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