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