]> git.sur5r.net Git - u-boot/blob - cpu/mpc8220/start.S
Patch by TsiChung Liew, 23 Sep 2004:
[u-boot] / cpu / mpc8220 / start.S
1 /*
2  *  Copyright (C) 1998  Dan Malek <dmalek@jlc.net>
3  *  Copyright (C) 1999  Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
4  *  Copyright (C) 2000 - 2003 Wolfgang Denk <wd@denx.de>
5  *
6  * See file CREDITS for list of people who contributed to this
7  * project.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22  * MA 02111-1307 USA
23  */
24
25 /*
26  *  U-Boot - Startup Code for MPC8220 CPUs
27  */
28 #include <config.h>
29 #include <mpc8220.h>
30 #include <version.h>
31
32 #define _LINUX_CONFIG_H 1   /* avoid reading Linux autoconf.h file  */
33
34 #include <ppc_asm.tmpl>
35 #include <ppc_defs.h>
36
37 #include <asm/cache.h>
38 #include <asm/mmu.h>
39
40 #ifndef  CONFIG_IDENT_STRING
41 #define  CONFIG_IDENT_STRING ""
42 #endif
43
44 /* We don't want the  MMU yet.
45 */
46 #undef  MSR_KERNEL
47 /* Floating Point enable, Machine Check and Recoverable Interr. */
48 #ifdef DEBUG
49 #define MSR_KERNEL (MSR_FP|MSR_RI)
50 #else
51 #define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
52 #endif
53
54 /*
55  * Set up GOT: Global Offset Table
56  *
57  * Use r14 to access the GOT
58  */
59         START_GOT
60         GOT_ENTRY(_GOT2_TABLE_)
61         GOT_ENTRY(_FIXUP_TABLE_)
62
63         GOT_ENTRY(_start)
64         GOT_ENTRY(_start_of_vectors)
65         GOT_ENTRY(_end_of_vectors)
66         GOT_ENTRY(transfer_to_handler)
67
68         GOT_ENTRY(__init_end)
69         GOT_ENTRY(_end)
70         GOT_ENTRY(__bss_start)
71         END_GOT
72
73 /*
74  * Version string
75  */
76         .data
77         .globl  version_string
78 version_string:
79         .ascii U_BOOT_VERSION
80         .ascii " (", __DATE__, " - ", __TIME__, ")"
81         .ascii CONFIG_IDENT_STRING, "\0"
82
83 /*
84  * Exception vectors
85  */
86         .text
87         . = EXC_OFF_SYS_RESET
88         .globl  _start
89 _start:
90         li      r21, BOOTFLAG_COLD  /* Normal Power-On      */
91         nop
92         b       boot_cold
93
94         . = EXC_OFF_SYS_RESET + 0x10
95
96         .globl  _start_warm
97 _start_warm:
98         li      r21, BOOTFLAG_WARM  /* Software reboot      */
99         b       boot_warm
100
101 boot_cold:
102 boot_warm:
103         mfmsr   r5                  /* save msr contents    */
104
105         /* replace default MBAR base address from 0x80000000
106             to 0xf0000000 */
107
108 #if defined(CFG_DEFAULT_MBAR) && !defined(CFG_RAMBOOT)
109         lis     r3, CFG_MBAR@h
110         ori     r3, r3, CFG_MBAR@l
111
112         /* MBAR is mirrored into the MBAR SPR */
113         mtspr   MBAR,r3
114         lis     r4, CFG_DEFAULT_MBAR@h
115         stw     r3, 0(r4)
116 #endif /* CFG_DEFAULT_MBAR */
117
118         /* Initialise the MPC8220 processor core                        */
119         /*--------------------------------------------------------------*/
120
121         bl  init_8220_core
122
123         /* initialize some things that are hard to access from C        */
124         /*--------------------------------------------------------------*/
125
126         /* set up stack in on-chip SRAM */
127         lis     r3, CFG_INIT_RAM_ADDR@h
128         ori     r3, r3, CFG_INIT_RAM_ADDR@l
129         ori     r1, r3, CFG_INIT_SP_OFFSET
130
131         li      r0, 0           /* Make room for stack frame header and */
132         stwu    r0, -4(r1)      /* clear final stack frame so that      */
133         stwu    r0, -4(r1)      /* stack backtraces terminate cleanly   */
134
135         /* let the C-code set up the rest                               */
136         /*                                                              */
137         /* Be careful to keep code relocatable !                        */
138         /*--------------------------------------------------------------*/
139
140         GET_GOT                 /* initialize GOT access                */
141
142         /* r3: IMMR */
143         bl      cpu_init_f      /* run low-level CPU init code (in Flash)*/
144
145         mr      r3, r21
146         /* r3: BOOTFLAG */
147         bl      board_init_f    /* run 1st part of board init code (in Flash)*/
148
149 /*
150  * Vector Table
151  */
152
153         .globl  _start_of_vectors
154 _start_of_vectors:
155
156 /* Machine check */
157         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
158
159 /* Data Storage exception. */
160         STD_EXCEPTION(0x300, DataStorage, UnknownException)
161
162 /* Instruction Storage exception. */
163         STD_EXCEPTION(0x400, InstStorage, UnknownException)
164
165 /* External Interrupt exception. */
166         STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
167
168 /* Alignment exception. */
169         . = 0x600
170 Alignment:
171         EXCEPTION_PROLOG
172         mfspr   r4,DAR
173         stw     r4,_DAR(r21)
174         mfspr   r5,DSISR
175         stw     r5,_DSISR(r21)
176         addi    r3,r1,STACK_FRAME_OVERHEAD
177         li      r20,MSR_KERNEL
178         rlwimi  r20,r23,0,16,16     /* copy EE bit from saved MSR */
179         rlwimi  r20,r23,0,25,25     /* copy IP bit from saved MSR */
180         lwz     r6,GOT(transfer_to_handler)
181         mtlr    r6
182         blrl
183 .L_Alignment:
184         .long   AlignmentException - _start + EXC_OFF_SYS_RESET
185         .long   int_return - _start + EXC_OFF_SYS_RESET
186
187 /* Program check exception */
188         . = 0x700
189 ProgramCheck:
190         EXCEPTION_PROLOG
191         addi    r3,r1,STACK_FRAME_OVERHEAD
192         li      r20,MSR_KERNEL
193         rlwimi  r20,r23,0,16,16     /* copy EE bit from saved MSR */
194         rlwimi  r20,r23,0,25,25     /* copy IP bit from saved MSR */
195         lwz     r6,GOT(transfer_to_handler)
196         mtlr    r6
197         blrl
198 .L_ProgramCheck:
199         .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
200         .long   int_return - _start + EXC_OFF_SYS_RESET
201
202         STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
203
204         /* I guess we could implement decrementer, and may have
205          * to someday for timekeeping.
206          */
207         STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
208
209         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
210         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
211         STD_EXCEPTION(0xc00, SystemCall, UnknownException)
212         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
213
214         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
215         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
216
217         STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
218         STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
219         STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
220 #ifdef DEBUG
221         . = 0x1300
222         /*
223          * This exception occurs when the program counter matches the
224          * Instruction Address Breakpoint Register (IABR).
225          *
226          * I want the cpu to halt if this occurs so I can hunt around
227          * with the debugger and look at things.
228          *
229          * When DEBUG is defined, both machine check enable (in the MSR)
230          * and checkstop reset enable (in the reset mode register) are
231          * turned off and so a checkstop condition will result in the cpu
232          * halting.
233          *
234          * I force the cpu into a checkstop condition by putting an illegal
235          * instruction here (at least this is the theory).
236          *
237          * well - that didnt work, so just do an infinite loop!
238          */
239 1:      b       1b
240 #else
241         STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
242 #endif
243         STD_EXCEPTION(0x1400, SMI, UnknownException)
244
245         STD_EXCEPTION(0x1500, Trap_15, UnknownException)
246         STD_EXCEPTION(0x1600, Trap_16, UnknownException)
247         STD_EXCEPTION(0x1700, Trap_17, UnknownException)
248         STD_EXCEPTION(0x1800, Trap_18, UnknownException)
249         STD_EXCEPTION(0x1900, Trap_19, UnknownException)
250         STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
251         STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
252         STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
253         STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
254         STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
255         STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
256         STD_EXCEPTION(0x2000, Trap_20, UnknownException)
257         STD_EXCEPTION(0x2100, Trap_21, UnknownException)
258         STD_EXCEPTION(0x2200, Trap_22, UnknownException)
259         STD_EXCEPTION(0x2300, Trap_23, UnknownException)
260         STD_EXCEPTION(0x2400, Trap_24, UnknownException)
261         STD_EXCEPTION(0x2500, Trap_25, UnknownException)
262         STD_EXCEPTION(0x2600, Trap_26, UnknownException)
263         STD_EXCEPTION(0x2700, Trap_27, UnknownException)
264         STD_EXCEPTION(0x2800, Trap_28, UnknownException)
265         STD_EXCEPTION(0x2900, Trap_29, UnknownException)
266         STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
267         STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
268         STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
269         STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
270         STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
271         STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
272
273
274         .globl  _end_of_vectors
275 _end_of_vectors:
276
277         . = 0x3000
278
279 /*
280  * This code finishes saving the registers to the exception frame
281  * and jumps to the appropriate handler for the exception.
282  * Register r21 is pointer into trap frame, r1 has new stack pointer.
283  */
284         .globl  transfer_to_handler
285 transfer_to_handler:
286         stw     r22,_NIP(r21)
287         lis     r22,MSR_POW@h
288         andc    r23,r23,r22
289         stw     r23,_MSR(r21)
290         SAVE_GPR(7, r21)
291         SAVE_4GPRS(8, r21)
292         SAVE_8GPRS(12, r21)
293         SAVE_8GPRS(24, r21)
294         mflr    r23
295         andi.   r24,r23,0x3f00      /* get vector offset */
296         stw     r24,TRAP(r21)
297         li      r22,0
298         stw     r22,RESULT(r21)
299         lwz     r24,0(r23)              /* virtual address of handler */
300         lwz     r23,4(r23)              /* where to go when done */
301         mtspr   SRR0,r24
302         mtspr   SRR1,r20
303         mtlr    r23
304         SYNC
305         rfi                         /* jump to handler, enable MMU */
306
307 int_return:
308         mfmsr   r28                 /* Disable interrupts */
309         li      r4,0
310         ori     r4,r4,MSR_EE
311         andc    r28,r28,r4
312         SYNC                        /* Some chip revs need this... */
313         mtmsr   r28
314         SYNC
315         lwz     r2,_CTR(r1)
316         lwz     r0,_LINK(r1)
317         mtctr   r2
318         mtlr    r0
319         lwz     r2,_XER(r1)
320         lwz     r0,_CCR(r1)
321         mtspr   XER,r2
322         mtcrf   0xFF,r0
323         REST_10GPRS(3, r1)
324         REST_10GPRS(13, r1)
325         REST_8GPRS(23, r1)
326         REST_GPR(31, r1)
327         lwz     r2,_NIP(r1)         /* Restore environment */
328         lwz     r0,_MSR(r1)
329         mtspr   SRR0,r2
330         mtspr   SRR1,r0
331         lwz     r0,GPR0(r1)
332         lwz     r2,GPR2(r1)
333         lwz     r1,GPR1(r1)
334         SYNC
335         rfi
336
337 /*
338  * This code initialises the MPC8220 processor core
339  * (conforms to PowerPC 603e spec)
340  * Note: expects original MSR contents to be in r5.
341  */
342
343         .globl  init_8220_core
344 init_8220_core:
345
346         /* Initialize machine status; enable machine check interrupt    */
347         /*--------------------------------------------------------------*/
348
349         li      r3, MSR_KERNEL      /* Set ME and RI flags              */
350         rlwimi  r3, r5, 0, 25, 25   /* preserve IP bit set by HRCW      */
351 #ifdef DEBUG
352         rlwimi  r3, r5, 0, 21, 22   /* debugger might set SE & BE bits  */
353 #endif
354         SYNC                        /* Some chip revs need this...      */
355         mtmsr   r3
356         SYNC
357         mtspr   SRR1, r3            /* Make SRR1 match MSR              */
358
359         /* Initialize the Hardware Implementation-dependent Registers   */
360         /* HID0 also contains cache control                             */
361         /*--------------------------------------------------------------*/
362
363         lis     r3, CFG_HID0_INIT@h
364         ori     r3, r3, CFG_HID0_INIT@l
365         SYNC
366         mtspr   HID0, r3
367
368         lis     r3, CFG_HID0_FINAL@h
369         ori     r3, r3, CFG_HID0_FINAL@l
370         SYNC
371         mtspr   HID0, r3
372
373         /* Enable Extra BATs */
374         mfspr   r3, 1011    /* HID2 */
375         lis     r4, 0x0004
376         ori     r4, r4, 0x0000
377         or      r4, r4, r3
378         mtspr   1011, r4
379         sync
380
381         /* clear all BAT's                                              */
382         /*--------------------------------------------------------------*/
383
384         li      r0, 0
385         mtspr   DBAT0U, r0
386         mtspr   DBAT0L, r0
387         mtspr   DBAT1U, r0
388         mtspr   DBAT1L, r0
389         mtspr   DBAT2U, r0
390         mtspr   DBAT2L, r0
391         mtspr   DBAT3U, r0
392         mtspr   DBAT3L, r0
393         mtspr   DBAT4U, r0
394         mtspr   DBAT4L, r0
395         mtspr   DBAT5U, r0
396         mtspr   DBAT5L, r0
397         mtspr   DBAT6U, r0
398         mtspr   DBAT6L, r0
399         mtspr   DBAT7U, r0
400         mtspr   DBAT7L, r0
401         mtspr   IBAT0U, r0
402         mtspr   IBAT0L, r0
403         mtspr   IBAT1U, r0
404         mtspr   IBAT1L, r0
405         mtspr   IBAT2U, r0
406         mtspr   IBAT2L, r0
407         mtspr   IBAT3U, r0
408         mtspr   IBAT3L, r0
409         mtspr   IBAT4U, r0
410         mtspr   IBAT4L, r0
411         mtspr   IBAT5U, r0
412         mtspr   IBAT5L, r0
413         mtspr   IBAT6U, r0
414         mtspr   IBAT6L, r0
415         mtspr   IBAT7U, r0
416         mtspr   IBAT7L, r0
417         SYNC
418
419         /* invalidate all tlb's                                         */
420         /*                                                              */
421         /* From the 603e User Manual: "The 603e provides the ability to */
422         /* invalidate a TLB entry. The TLB Invalidate Entry (tlbie)     */
423         /* instruction invalidates the TLB entry indexed by the EA, and */
424         /* operates on both the instruction and data TLBs simultaneously*/
425         /* invalidating four TLB entries (both sets in each TLB). The   */
426         /* index corresponds to bits 15-19 of the EA. To invalidate all */
427         /* entries within both TLBs, 32 tlbie instructions should be    */
428         /* issued, incrementing this field by one each time."           */
429         /*                                                              */
430         /* "Note that the tlbia instruction is not implemented on the   */
431         /* 603e."                                                       */
432         /*                                                              */
433         /* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000  */
434         /* incrementing by 0x1000 each time. The code below is sort of  */
435         /* based on code in "flush_tlbs" from arch/ppc/kernel/head.S    */
436         /*                                                              */
437         /*--------------------------------------------------------------*/
438
439         li      r3, 32
440         mtctr   r3
441         li      r3, 0
442 1:      tlbie   r3
443         addi    r3, r3, 0x1000
444         bdnz    1b
445         SYNC
446
447         /* Done!                                                        */
448         /*--------------------------------------------------------------*/
449
450         blr
451
452 /* Cache functions.
453  *
454  * Note: requires that all cache bits in
455  * HID0 are in the low half word.
456  */
457         .globl  icache_enable
458 icache_enable:
459         lis     r4, 0
460         ori     r4, r4, CFG_HID0_INIT /* set ICE & ICFI bit             */
461         rlwinm  r3, r4, 0, 21, 19     /* clear the ICFI bit             */
462
463         /*
464          * The setting of the instruction cache enable (ICE) bit must be
465          * preceded by an isync instruction to prevent the cache from being
466          * enabled or disabled while an instruction access is in progress.
467          */
468         isync
469         mtspr   HID0, r4              /* Enable Instr Cache & Inval cache */
470         mtspr   HID0, r3              /* using 2 consec instructions    */
471         isync
472         blr
473
474         .globl  icache_disable
475 icache_disable:
476         mfspr   r3, HID0
477         rlwinm  r3, r3, 0, 17, 15     /* clear the ICE bit              */
478         mtspr   HID0, r3
479         isync
480         blr
481
482         .globl  icache_status
483 icache_status:
484         mfspr   r3, HID0
485         rlwinm  r3, r3, HID0_ICE_BITPOS + 1, 31, 31
486         blr
487
488         .globl  dcache_enable
489 dcache_enable:
490         lis     r4, 0
491         ori     r4, r4, HID0_DCE|HID0_DCFI /* set DCE & DCFI bit        */
492         rlwinm  r3, r4, 0, 22, 20     /* clear the DCFI bit             */
493
494         /* Enable address translation in MSR bit */
495         mfmsr   r5
496         ori     r5, r5, 0x
497
498
499         /*
500          * The setting of the instruction cache enable (ICE) bit must be
501          * preceded by an isync instruction to prevent the cache from being
502          * enabled or disabled while an instruction access is in progress.
503          */
504         isync
505         mtspr   HID0, r4              /* Enable Data Cache & Inval cache*/
506         mtspr   HID0, r3              /* using 2 consec instructions    */
507         isync
508         blr
509
510         .globl  dcache_disable
511 dcache_disable:
512         mfspr   r3, HID0
513         rlwinm  r3, r3, 0, 18, 16     /* clear the DCE bit */
514         mtspr   HID0, r3
515         isync
516         blr
517
518         .globl  dcache_status
519 dcache_status:
520         mfspr   r3, HID0
521         rlwinm  r3, r3, HID0_DCE_BITPOS + 1, 31, 31
522         blr
523
524         .globl  get_pvr
525 get_pvr:
526         mfspr   r3, PVR
527         blr
528
529 /*------------------------------------------------------------------------------*/
530
531 /*
532  * void relocate_code (addr_sp, gd, addr_moni)
533  *
534  * This "function" does not return, instead it continues in RAM
535  * after relocating the monitor code.
536  *
537  * r3 = dest
538  * r4 = src
539  * r5 = length in bytes
540  * r6 = cachelinesize
541  */
542         .globl  relocate_code
543 relocate_code:
544         mr      r1,  r3     /* Set new stack pointer            */
545         mr      r9,  r4     /* Save copy of Global Data pointer */
546         mr      r10, r5     /* Save copy of Destination Address */
547
548         mr      r3,  r5     /* Destination Address              */
549         lis     r4, CFG_MONITOR_BASE@h  /* Source Address       */
550         ori     r4, r4, CFG_MONITOR_BASE@l
551         lwz     r5, GOT(__init_end)
552         sub     r5, r5, r4
553         li      r6, CFG_CACHELINE_SIZE  /* Cache Line Size      */
554
555         /*
556          * Fix GOT pointer:
557          *
558          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
559          *
560          * Offset:
561          */
562         sub     r15, r10, r4
563
564         /* First our own GOT */
565         add     r14, r14, r15
566         /* then the one used by the C code */
567         add     r30, r30, r15
568
569         /*
570          * Now relocate code
571          */
572
573         cmplw   cr1,r3,r4
574         addi    r0,r5,3
575         srwi.   r0,r0,2
576         beq     cr1,4f      /* In place copy is not necessary   */
577         beq     7f          /* Protect against 0 count          */
578         mtctr   r0
579         bge     cr1,2f
580
581         la      r8,-4(r4)
582         la      r7,-4(r3)
583 1:      lwzu    r0,4(r8)
584         stwu    r0,4(r7)
585         bdnz    1b
586         b       4f
587
588 2:      slwi    r0,r0,2
589         add     r8,r4,r0
590         add     r7,r3,r0
591 3:      lwzu    r0,-4(r8)
592         stwu    r0,-4(r7)
593         bdnz    3b
594
595 /*
596  * Now flush the cache: note that we must start from a cache aligned
597  * address. Otherwise we might miss one cache line.
598  */
599 4:      cmpwi   r6,0
600         add     r5,r3,r5
601         beq     7f          /* Always flush prefetch queue in any case  */
602         subi    r0,r6,1
603         andc    r3,r3,r0
604         mfspr   r7,HID0     /* don't do dcbst if dcache is disabled     */
605         rlwinm  r7,r7,HID0_DCE_BITPOS+1,31,31
606         cmpwi   r7,0
607         beq     9f
608         mr      r4,r3
609 5:      dcbst   0,r4
610         add     r4,r4,r6
611         cmplw   r4,r5
612         blt     5b
613         sync                /* Wait for all dcbst to complete on bus    */
614 9:      mfspr   r7,HID0     /* don't do icbi if icache is disabled      */
615         rlwinm  r7,r7,HID0_ICE_BITPOS+1,31,31
616         cmpwi   r7,0
617         beq     7f
618         mr      r4,r3
619 6:      icbi    0,r4
620         add     r4,r4,r6
621         cmplw   r4,r5
622         blt     6b
623 7:      sync                /* Wait for all icbi to complete on bus     */
624         isync
625
626 /*
627  * We are done. Do not return, instead branch to second part of board
628  * initialization, now running from RAM.
629  */
630
631         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
632         mtlr    r0
633         blr
634
635 in_ram:
636
637         /*
638          * Relocation Function, r14 point to got2+0x8000
639          *
640          * Adjust got2 pointers, no need to check for 0, this code
641          * already puts a few entries in the table.
642          */
643         li      r0,__got2_entries@sectoff@l
644         la      r3,GOT(_GOT2_TABLE_)
645         lwz     r11,GOT(_GOT2_TABLE_)
646         mtctr   r0
647         sub     r11,r3,r11
648         addi    r3,r3,-4
649 1:      lwzu    r0,4(r3)
650         add     r0,r0,r11
651         stw     r0,0(r3)
652         bdnz    1b
653
654         /*
655          * Now adjust the fixups and the pointers to the fixups
656          * in case we need to move ourselves again.
657          */
658 2:      li      r0,__fixup_entries@sectoff@l
659         lwz     r3,GOT(_FIXUP_TABLE_)
660         cmpwi   r0,0
661         mtctr   r0
662         addi    r3,r3,-4
663         beq     4f
664 3:      lwzu    r4,4(r3)
665         lwzux   r0,r4,r11
666         add     r0,r0,r11
667         stw     r10,0(r3)
668         stw     r0,0(r4)
669         bdnz    3b
670 4:
671 clear_bss:
672         /*
673          * Now clear BSS segment
674          */
675         lwz     r3,GOT(__bss_start)
676         lwz     r4,GOT(_end)
677
678         cmplw   0, r3, r4
679         beq     6f
680
681         li      r0, 0
682 5:
683         stw     r0, 0(r3)
684         addi    r3, r3, 4
685         cmplw   0, r3, r4
686         bne     5b
687 6:
688
689         mr      r3, r9      /* Global Data pointer      */
690         mr      r4, r10     /* Destination Address      */
691         bl      board_init_r
692
693         /*
694          * Copy exception vector code to low memory
695          *
696          * r3: dest_addr
697          * r7: source address, r8: end address, r9: target address
698          */
699         .globl  trap_init
700 trap_init:
701         lwz     r7, GOT(_start)
702         lwz     r8, GOT(_end_of_vectors)
703
704         li      r9, 0x100   /* reset vector always at 0x100     */
705
706         cmplw   0, r7, r8
707         bgelr               /* return if r7>=r8 - just in case  */
708
709         mflr    r4          /* save link register               */
710 1:
711         lwz     r0, 0(r7)
712         stw     r0, 0(r9)
713         addi    r7, r7, 4
714         addi    r9, r9, 4
715         cmplw   0, r7, r8
716         bne     1b
717
718         /*
719          * relocate `hdlr' and `int_return' entries
720          */
721         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
722         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
723 2:
724         bl      trap_reloc
725         addi    r7, r7, 0x100       /* next exception vector        */
726         cmplw   0, r7, r8
727         blt     2b
728
729         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
730         bl      trap_reloc
731
732         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
733         bl      trap_reloc
734
735         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
736         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
737 3:
738         bl      trap_reloc
739         addi    r7, r7, 0x100       /* next exception vector        */
740         cmplw   0, r7, r8
741         blt     3b
742
743         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
744         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
745 4:
746         bl      trap_reloc
747         addi    r7, r7, 0x100       /* next exception vector        */
748         cmplw   0, r7, r8
749         blt     4b
750
751         mfmsr   r3                  /* now that the vectors have    */
752         lis     r7, MSR_IP@h        /* relocated into low memory    */
753         ori     r7, r7, MSR_IP@l    /* MSR[IP] can be turned off    */
754         andc    r3, r3, r7          /* (if it was on)               */
755         SYNC                        /* Some chip revs need this...  */
756         mtmsr   r3
757         SYNC
758
759         mtlr    r4                  /* restore link register        */
760         blr
761
762         /*
763          * Function: relocate entries for one exception vector
764          */
765 trap_reloc:
766         lwz     r0, 0(r7)           /* hdlr ...                     */
767         add     r0, r0, r3          /*  ... += dest_addr            */
768         stw     r0, 0(r7)
769
770         lwz     r0, 4(r7)           /* int_return ...               */
771         add     r0, r0, r3          /*  ... += dest_addr            */
772         stw     r0, 4(r7)
773
774         blr