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