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