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