* Implement new mechanism to export U-Boot's functions to standalone
[oweals/u-boot.git] / cpu / mpc5xxx / 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 MPC5xxx CPUs
27  */
28 #include <config.h>
29 #include <mpc5xxx.h>
30 #include <version.h>
31
32 #define CONFIG_MPC5XXX 1        /* needed for Linux kernel header files */
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 r14 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 " (", __DATE__, " - ", __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 #if defined(CFG_DEFAULT_MBAR)
107         lis     r3, CFG_MBAR@h
108         ori     r3, r3, CFG_MBAR@l
109 #if defined(CONFIG_MPC5200)
110         rlwinm  r3, r3, 16, 16, 31
111 #endif
112 #if defined(CONFIG_MGT5100)
113         rlwinm  r3, r3, 17, 15, 31
114 #endif
115         lis     r4, CFG_DEFAULT_MBAR@h
116         stw     r3, 0(r4)
117 #endif /* CFG_DEFAULT_MBAR */
118
119         /* Initialise the MPC5xxx processor core                        */
120         /*--------------------------------------------------------------*/
121
122         bl      init_5xxx_core
123
124         /* initialize some things that are hard to access from C        */
125         /*--------------------------------------------------------------*/
126
127         /* set up stack in on-chip SRAM */
128         lis     r3, CFG_INIT_RAM_ADDR@h
129         ori     r3, r3, CFG_INIT_RAM_ADDR@l
130         ori     r1, r3, CFG_INIT_SP_OFFSET
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 MPC5xxx processor core
339  * (conforms to PowerPC 603e spec)
340  * Note: expects original MSR contents to be in r5.
341  */
342
343         .globl  init_5xx_core
344 init_5xxx_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         /* clear all BAT's                                              */
374         /*--------------------------------------------------------------*/
375
376         li      r0, 0
377         mtspr   DBAT0U, r0
378         mtspr   DBAT0L, r0
379         mtspr   DBAT1U, r0
380         mtspr   DBAT1L, r0
381         mtspr   DBAT2U, r0
382         mtspr   DBAT2L, r0
383         mtspr   DBAT3U, r0
384         mtspr   DBAT3L, r0
385         mtspr   IBAT0U, r0
386         mtspr   IBAT0L, r0
387         mtspr   IBAT1U, r0
388         mtspr   IBAT1L, r0
389         mtspr   IBAT2U, r0
390         mtspr   IBAT2L, r0
391         mtspr   IBAT3U, r0
392         mtspr   IBAT3L, r0
393         SYNC
394
395         /* invalidate all tlb's                                         */
396         /*                                                              */
397         /* From the 603e User Manual: "The 603e provides the ability to */
398         /* invalidate a TLB entry. The TLB Invalidate Entry (tlbie)     */
399         /* instruction invalidates the TLB entry indexed by the EA, and */
400         /* operates on both the instruction and data TLBs simultaneously*/
401         /* invalidating four TLB entries (both sets in each TLB). The   */
402         /* index corresponds to bits 15-19 of the EA. To invalidate all */
403         /* entries within both TLBs, 32 tlbie instructions should be    */
404         /* issued, incrementing this field by one each time."           */
405         /*                                                              */
406         /* "Note that the tlbia instruction is not implemented on the   */
407         /* 603e."                                                       */
408         /*                                                              */
409         /* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000  */
410         /* incrementing by 0x1000 each time. The code below is sort of  */
411         /* based on code in "flush_tlbs" from arch/ppc/kernel/head.S    */
412         /*                                                              */
413         /*--------------------------------------------------------------*/
414
415         li      r3, 32
416         mtctr   r3
417         li      r3, 0
418 1:      tlbie   r3
419         addi    r3, r3, 0x1000
420         bdnz    1b
421         SYNC
422
423         /* Done!                                                        */
424         /*--------------------------------------------------------------*/
425
426         blr
427
428 /* Cache functions.
429  *
430  * Note: requires that all cache bits in
431  * HID0 are in the low half word.
432  */
433         .globl  icache_enable
434 icache_enable:
435         mfspr   r3, HID0
436         ori     r3, r3, HID0_ICE
437         lis     r4, 0
438         ori     r4, r4, HID0_ILOCK
439         andc    r3, r3, r4
440         ori     r4, r3, HID0_ICFI
441         isync
442         mtspr   HID0, r4        /* sets enable and invalidate, clears lock */
443         isync
444         mtspr   HID0, r3        /* clears invalidate */
445         blr
446
447         .globl  icache_disable
448 icache_disable:
449         mfspr   r3, HID0
450         lis     r4, 0
451         ori     r4, r4, HID0_ICE|HID0_ILOCK
452         andc    r3, r3, r4
453         ori     r4, r3, HID0_ICFI
454         isync
455         mtspr   HID0, r4        /* sets invalidate, clears enable and lock */
456         isync
457         mtspr   HID0, r3        /* clears invalidate */
458         blr
459
460         .globl  icache_status
461 icache_status:
462         mfspr   r3, HID0
463         rlwinm  r3, r3, HID0_ICE_BITPOS + 1, 31, 31
464         blr
465
466         .globl  dcache_enable
467 dcache_enable:
468         mfspr   r3, HID0
469         ori     r3, r3, HID0_DCE
470         lis     r4, 0
471         ori     r4, r4, HID0_DLOCK
472         andc    r3, r3, r4
473         ori     r4, r3, HID0_DCI
474         sync
475         mtspr   HID0, r4        /* sets enable and invalidate, clears lock */
476         sync
477         mtspr   HID0, r3        /* clears invalidate */
478         blr
479
480         .globl  dcache_disable
481 dcache_disable:
482         mfspr   r3, HID0
483         lis     r4, 0
484         ori     r4, r4, HID0_DCE|HID0_DLOCK
485         andc    r3, r3, r4
486         ori     r4, r3, HID0_DCI
487         sync
488         mtspr   HID0, r4        /* sets invalidate, clears enable and lock */
489         sync
490         mtspr   HID0, r3        /* clears invalidate */
491         blr
492
493         .globl  dcache_status
494 dcache_status:
495         mfspr   r3, HID0
496         rlwinm  r3, r3, HID0_DCE_BITPOS + 1, 31, 31
497         blr
498
499         .globl get_pvr
500 get_pvr:
501         mfspr   r3, PVR
502         blr
503
504 /*------------------------------------------------------------------------------*/
505
506 /*
507  * void relocate_code (addr_sp, gd, addr_moni)
508  *
509  * This "function" does not return, instead it continues in RAM
510  * after relocating the monitor code.
511  *
512  * r3 = dest
513  * r4 = src
514  * r5 = length in bytes
515  * r6 = cachelinesize
516  */
517         .globl  relocate_code
518 relocate_code:
519         mr      r1,  r3         /* Set new stack pointer                */
520         mr      r9,  r4         /* Save copy of Global Data pointer     */
521         mr      r10, r5         /* Save copy of Destination Address     */
522
523         mr      r3,  r5                         /* Destination Address  */
524         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
525         ori     r4, r4, CFG_MONITOR_BASE@l
526         lwz     r5, GOT(__init_end)
527         sub     r5, r5, r4
528         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
529
530         /*
531          * Fix GOT pointer:
532          *
533          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
534          *
535          * Offset:
536          */
537         sub     r15, r10, r4
538
539         /* First our own GOT */
540         add     r14, r14, 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, r14 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         add     r0,r0,r11
626         stw     r0,0(r3)
627         bdnz    1b
628
629         /*
630          * Now adjust the fixups and the pointers to the fixups
631          * in case we need to move ourselves again.
632          */
633 2:      li      r0,__fixup_entries@sectoff@l
634         lwz     r3,GOT(_FIXUP_TABLE_)
635         cmpwi   r0,0
636         mtctr   r0
637         addi    r3,r3,-4
638         beq     4f
639 3:      lwzu    r4,4(r3)
640         lwzux   r0,r4,r11
641         add     r0,r0,r11
642         stw     r10,0(r3)
643         stw     r0,0(r4)
644         bdnz    3b
645 4:
646 clear_bss:
647         /*
648          * Now clear BSS segment
649          */
650         lwz     r3,GOT(__bss_start)
651         lwz     r4,GOT(_end)
652
653         cmplw   0, r3, r4
654         beq     6f
655
656         li      r0, 0
657 5:
658         stw     r0, 0(r3)
659         addi    r3, r3, 4
660         cmplw   0, r3, r4
661         bne     5b
662 6:
663
664         mr      r3, r9          /* Global Data pointer          */
665         mr      r4, r10         /* Destination Address          */
666         bl      board_init_r
667
668         /*
669          * Copy exception vector code to low memory
670          *
671          * r3: dest_addr
672          * r7: source address, r8: end address, r9: target address
673          */
674         .globl  trap_init
675 trap_init:
676         lwz     r7, GOT(_start)
677         lwz     r8, GOT(_end_of_vectors)
678
679         li      r9, 0x100               /* reset vector always at 0x100 */
680
681         cmplw   0, r7, r8
682         bgelr                           /* return if r7>=r8 - just in case */
683
684         mflr    r4                      /* save link register           */
685 1:
686         lwz     r0, 0(r7)
687         stw     r0, 0(r9)
688         addi    r7, r7, 4
689         addi    r9, r9, 4
690         cmplw   0, r7, r8
691         bne     1b
692
693         /*
694          * relocate `hdlr' and `int_return' entries
695          */
696         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
697         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
698 2:
699         bl      trap_reloc
700         addi    r7, r7, 0x100           /* next exception vector        */
701         cmplw   0, r7, r8
702         blt     2b
703
704         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
705         bl      trap_reloc
706
707         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
708         bl      trap_reloc
709
710         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
711         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
712 3:
713         bl      trap_reloc
714         addi    r7, r7, 0x100           /* next exception vector        */
715         cmplw   0, r7, r8
716         blt     3b
717
718         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
719         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
720 4:
721         bl      trap_reloc
722         addi    r7, r7, 0x100           /* next exception vector        */
723         cmplw   0, r7, r8
724         blt     4b
725
726         mfmsr   r3                      /* now that the vectors have    */
727         lis     r7, MSR_IP@h            /* relocated into low memory    */
728         ori     r7, r7, MSR_IP@l        /* MSR[IP] can be turned off    */
729         andc    r3, r3, r7              /* (if it was on)               */
730         SYNC                            /* Some chip revs need this... */
731         mtmsr   r3
732         SYNC
733
734         mtlr    r4                      /* restore link register    */
735         blr
736
737         /*
738          * Function: relocate entries for one exception vector
739          */
740 trap_reloc:
741         lwz     r0, 0(r7)               /* hdlr ...                     */
742         add     r0, r0, r3              /*  ... += dest_addr            */
743         stw     r0, 0(r7)
744
745         lwz     r0, 4(r7)               /* int_return ...               */
746         add     r0, r0, r3              /*  ... += dest_addr            */
747         stw     r0, 4(r7)
748
749         blr