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