]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/74xx_7xx/start.S
a37f92418db7bb1d325bdc27368fc24c87353f8f
[karo-tx-uboot.git] / cpu / 74xx_7xx / 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,2001,2002 Wolfgang Denk <wd@denx.de>
5  *  Copyright (C) 2001  Josh Huber <huber@mclx.com>
6  *
7  * See file CREDITS for list of people who contributed to this
8  * project.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23  * MA 02111-1307 USA
24  */
25
26 /*  U-Boot - Startup Code for PowerPC based Embedded Boards
27  *
28  *
29  *  The processor starts at 0xfff00100 and the code is executed
30  *  from flash. The code is organized to be at an other address
31  *  in memory, but as long we don't jump around before relocating.
32  *  board_init lies at a quite high address and when the cpu has
33  *  jumped there, everything is ok.
34  */
35 #include <config.h>
36 #include <74xx_7xx.h>
37 #include <version.h>
38
39 #include <ppc_asm.tmpl>
40 #include <ppc_defs.h>
41
42 #include <asm/cache.h>
43 #include <asm/mmu.h>
44
45 #include <galileo/gt64260R.h>
46
47 #ifndef  CONFIG_IDENT_STRING
48 #define  CONFIG_IDENT_STRING ""
49 #endif
50
51 /* We don't want the  MMU yet.
52 */
53 #undef  MSR_KERNEL
54 /* Machine Check and Recoverable Interr. */
55 #define MSR_KERNEL ( MSR_ME | MSR_RI )
56
57 /*
58  * Set up GOT: Global Offset Table
59  *
60  * Use r14 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  * r3 - 1st arg to board_init(): IMMP pointer
78  * r4 - 2nd arg to board_init(): boot flag
79  */
80         .text
81         .long   0x27051956              /* U-Boot Magic Number          */
82         .globl  version_string
83 version_string:
84         .ascii  U_BOOT_VERSION
85         .ascii  " (", __DATE__, " - ", __TIME__, ")"
86         .ascii  CONFIG_IDENT_STRING, "\0"
87
88         . = EXC_OFF_SYS_RESET
89         .globl  _start
90 _start:
91         li      r21, BOOTFLAG_COLD      /* Normal Power-On: Boot from FLASH */
92         b       boot_cold
93         sync
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         sync
102
103         /* the boot code is located below the exception table */
104
105         .globl  _start_of_vectors
106 _start_of_vectors:
107
108 /* Machine check */
109         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
110
111 /* Data Storage exception.  "Never" generated on the 860. */
112         STD_EXCEPTION(0x300, DataStorage, UnknownException)
113
114 /* Instruction Storage exception.  "Never" generated on the 860. */
115         STD_EXCEPTION(0x400, InstStorage, UnknownException)
116
117 /* External Interrupt exception. */
118         STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
119
120 /* Alignment exception. */
121         . = 0x600
122 Alignment:
123         EXCEPTION_PROLOG
124         mfspr   r4,DAR
125         stw     r4,_DAR(r21)
126         mfspr   r5,DSISR
127         stw     r5,_DSISR(r21)
128         addi    r3,r1,STACK_FRAME_OVERHEAD
129         li      r20,MSR_KERNEL
130         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
131         lwz     r6,GOT(transfer_to_handler)
132         mtlr    r6
133         blrl
134 .L_Alignment:
135         .long   AlignmentException - _start + EXC_OFF_SYS_RESET
136         .long   int_return - _start + EXC_OFF_SYS_RESET
137
138 /* Program check exception */
139         . = 0x700
140 ProgramCheck:
141         EXCEPTION_PROLOG
142         addi    r3,r1,STACK_FRAME_OVERHEAD
143         li      r20,MSR_KERNEL
144         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
145         lwz     r6,GOT(transfer_to_handler)
146         mtlr    r6
147         blrl
148 .L_ProgramCheck:
149         .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
150         .long   int_return - _start + EXC_OFF_SYS_RESET
151
152         /* No FPU on MPC8xx.  This exception is not supposed to happen.
153         */
154         STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
155
156         /* I guess we could implement decrementer, and may have
157          * to someday for timekeeping.
158          */
159         STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
160         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
161         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
162
163         . = 0xc00
164 /*
165  * r0 - SYSCALL number
166  * r3-... arguments
167  */
168 SystemCall:
169         addis   r11,r0,0                /* get functions table addr */
170         ori     r11,r11,0               /* Note: this code is patched in trap_init */
171         addis   r12,r0,0                /* get number of functions */
172         ori     r12,r12,0
173
174         cmplw   0, r0, r12
175         bge     1f
176
177         rlwinm  r0,r0,2,0,31            /* fn_addr = fn_tbl[r0] */
178         add     r11,r11,r0
179         lwz     r11,0(r11)
180
181         li      r20,0xd00-4             /* Get stack pointer */
182         lwz     r12,0(r20)
183         subi    r12,r12,12              /* Adjust stack pointer */
184         li      r0,0xc00+_end_back-SystemCall
185         cmplw   0, r0, r12              /* Check stack overflow */
186         bgt     1f
187         stw     r12,0(r20)
188
189         mflr    r0
190         stw     r0,0(r12)
191         mfspr   r0,SRR0
192         stw     r0,4(r12)
193         mfspr   r0,SRR1
194         stw     r0,8(r12)
195
196         li      r12,0xc00+_back-SystemCall
197         mtlr    r12
198         mtspr   SRR0,r11
199
200 1:      SYNC
201         rfi
202
203 _back:
204
205         mfmsr   r11                     /* Disable interrupts */
206         li      r12,0
207         ori     r12,r12,MSR_EE
208         andc    r11,r11,r12
209         SYNC                            /* Some chip revs need this... */
210         mtmsr   r11
211         SYNC
212
213         li      r12,0xd00-4             /* restore regs */
214         lwz     r12,0(r12)
215
216         lwz     r11,0(r12)
217         mtlr    r11
218         lwz     r11,4(r12)
219         mtspr   SRR0,r11
220         lwz     r11,8(r12)
221         mtspr   SRR1,r11
222
223         addi    r12,r12,12              /* Adjust stack pointer */
224         li      r20,0xd00-4
225         stw     r12,0(r20)
226
227         SYNC
228         rfi
229 _end_back:
230
231         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
232
233         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
234         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
235
236         /*
237          * On the MPC8xx, this is a software emulation interrupt. It
238          * occurs for all unimplemented and illegal instructions.
239          */
240         STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
241
242         STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
243         STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
244         STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
245         STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
246
247         STD_EXCEPTION(0x1500, Reserved5, UnknownException)
248         STD_EXCEPTION(0x1600, Reserved6, UnknownException)
249         STD_EXCEPTION(0x1700, Reserved7, UnknownException)
250         STD_EXCEPTION(0x1800, Reserved8, UnknownException)
251         STD_EXCEPTION(0x1900, Reserved9, UnknownException)
252         STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
253         STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
254
255         STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
256         STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
257         STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
258         STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
259
260         .globl  _end_of_vectors
261 _end_of_vectors:
262
263         . = 0x2000
264
265 boot_cold:
266 boot_warm:
267         /* disable everything */
268         li      r0, 0
269         mtspr   HID0, r0
270         sync
271         mtmsr   0
272         bl      invalidate_bats
273         sync
274
275 #ifdef CFG_L2
276         /* init the L2 cache */
277         addis   r3, r0, L2_INIT@h
278         ori     r3, r3, L2_INIT@l
279         sync
280         mtspr   l2cr, r3
281 #endif
282 #if defined(CONFIG_ALTIVEC) && defined(CONFIG_74xx)
283         .long   0x7e00066c
284                 /*
285                  * dssall instruction, gas doesn't have it yet
286                  * ...for altivec, data stream stop all this probably
287                  * isn't needed unless we warm (software) reboot U-Boot
288                  */
289 #endif
290
291 #ifdef CFG_L2
292         /* invalidate the L2 cache */
293         bl      l2cache_invalidate
294         sync
295 #endif
296 #ifdef CFG_BOARD_ASM_INIT
297         /* do early init */
298         bl      board_asm_init
299 #endif
300
301         /*
302          * Calculate absolute address in FLASH and jump there
303          *------------------------------------------------------*/
304         lis     r3, CFG_MONITOR_BASE@h
305         ori     r3, r3, CFG_MONITOR_BASE@l
306         addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
307         mtlr    r3
308         blr
309
310 in_flash:
311         /* let the C-code set up the rest                       */
312         /*                                                      */
313         /* Be careful to keep code relocatable !                */
314         /*------------------------------------------------------*/
315
316         /* perform low-level init */
317         /* sdram init, galileo init, etc */
318         /* r3:  NHR bit from HID0 */
319
320         /* setup the bats */
321         bl      setup_bats
322         sync
323
324         /*
325          * Cache must be enabled here for stack-in-cache trick.
326          * This means we need to enable the BATS.
327          * This means:
328          *   1) for the EVB, original gt regs need to be mapped
329          *   2) need to have an IBAT for the 0xf region,
330          *      we are running there!
331          * Cache should be turned on after BATs, since by default
332          * everything is write-through.
333          * The init-mem BAT can be reused after reloc. The old
334          * gt-regs BAT can be reused after board_init_f calls
335          * board_pre_init (EVB only).
336          */
337 #if !defined(CONFIG_BAB7xx) && !defined(CONFIG_ELPPC)
338         /* enable address translation */
339         bl      enable_addr_trans
340         sync
341
342         /* enable and invalidate the data cache */
343         bl      l1dcache_enable
344         sync
345 #endif
346 #ifdef CFG_INIT_RAM_LOCK
347         bl      lock_ram_in_cache
348         sync
349 #endif
350
351         /* set up the stack pointer in our newly created
352          * cache-ram (r1) */
353         lis     r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h
354         ori     r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
355
356         li      r0, 0           /* Make room for stack frame header and */
357         stwu    r0, -4(r1)      /* clear final stack frame so that      */
358         stwu    r0, -4(r1)      /* stack backtraces terminate cleanly   */
359
360         GET_GOT                 /* initialize GOT access        */
361
362         /* run low-level CPU init code     (from Flash) */
363         bl      cpu_init_f
364         sync
365
366         mr      r3, r21
367
368         /* r3: BOOTFLAG */
369         /* run 1st part of board init code (from Flash)   */
370         bl      board_init_f
371         sync
372
373         /* NOTREACHED */
374
375         .globl  invalidate_bats
376 invalidate_bats:
377         /* invalidate BATs */
378         mtspr   IBAT0U, r0
379         mtspr   IBAT1U, r0
380         mtspr   IBAT2U, r0
381         mtspr   IBAT3U, r0
382         isync
383         mtspr   DBAT0U, r0
384         mtspr   DBAT1U, r0
385         mtspr   DBAT2U, r0
386         mtspr   DBAT3U, r0
387         isync
388         sync
389         blr
390
391         /* setup_bats - set them up to some initial state */
392         .globl  setup_bats
393 setup_bats:
394         addis   r0, r0, 0x0000
395
396         /* IBAT 0 */
397         addis   r4, r0, CFG_IBAT0L@h
398         ori     r4, r4, CFG_IBAT0L@l
399         addis   r3, r0, CFG_IBAT0U@h
400         ori     r3, r3, CFG_IBAT0U@l
401         mtspr   IBAT0L, r4
402         mtspr   IBAT0U, r3
403         isync
404
405         /* DBAT 0 */
406         addis   r4, r0, CFG_DBAT0L@h
407         ori     r4, r4, CFG_DBAT0L@l
408         addis   r3, r0, CFG_DBAT0U@h
409         ori     r3, r3, CFG_DBAT0U@l
410         mtspr   DBAT0L, r4
411         mtspr   DBAT0U, r3
412         isync
413
414         /* IBAT 1 */
415         addis   r4, r0, CFG_IBAT1L@h
416         ori     r4, r4, CFG_IBAT1L@l
417         addis   r3, r0, CFG_IBAT1U@h
418         ori     r3, r3, CFG_IBAT1U@l
419         mtspr   IBAT1L, r4
420         mtspr   IBAT1U, r3
421         isync
422
423         /* DBAT 1 */
424         addis   r4, r0, CFG_DBAT1L@h
425         ori     r4, r4, CFG_DBAT1L@l
426         addis   r3, r0, CFG_DBAT1U@h
427         ori     r3, r3, CFG_DBAT1U@l
428         mtspr   DBAT1L, r4
429         mtspr   DBAT1U, r3
430         isync
431
432         /* IBAT 2 */
433         addis   r4, r0, CFG_IBAT2L@h
434         ori     r4, r4, CFG_IBAT2L@l
435         addis   r3, r0, CFG_IBAT2U@h
436         ori     r3, r3, CFG_IBAT2U@l
437         mtspr   IBAT2L, r4
438         mtspr   IBAT2U, r3
439         isync
440
441         /* DBAT 2 */
442         addis   r4, r0, CFG_DBAT2L@h
443         ori     r4, r4, CFG_DBAT2L@l
444         addis   r3, r0, CFG_DBAT2U@h
445         ori     r3, r3, CFG_DBAT2U@l
446         mtspr   DBAT2L, r4
447         mtspr   DBAT2U, r3
448         isync
449
450         /* IBAT 3 */
451         addis   r4, r0, CFG_IBAT3L@h
452         ori     r4, r4, CFG_IBAT3L@l
453         addis   r3, r0, CFG_IBAT3U@h
454         ori     r3, r3, CFG_IBAT3U@l
455         mtspr   IBAT3L, r4
456         mtspr   IBAT3U, r3
457         isync
458
459         /* DBAT 3 */
460         addis   r4, r0, CFG_DBAT3L@h
461         ori     r4, r4, CFG_DBAT3L@l
462         addis   r3, r0, CFG_DBAT3U@h
463         ori     r3, r3, CFG_DBAT3U@l
464         mtspr   DBAT3L, r4
465         mtspr   DBAT3U, r3
466         isync
467
468         /* bats are done, now invalidate the TLBs */
469
470         addis   r3, 0, 0x0000
471         addis   r5, 0, 0x4    /* upper bound of 0x00040000 for 7400/750 */
472
473         isync
474
475 tlblp:
476         tlbie   r3
477         sync
478         addi    r3, r3, 0x1000
479         cmp     0, 0, r3, r5
480         blt tlblp
481
482         blr
483
484         .globl enable_addr_trans
485 enable_addr_trans:
486         /* enable address translation */
487         mfmsr   r5
488         ori     r5, r5, (MSR_IR | MSR_DR)
489         mtmsr   r5
490         isync
491         blr
492
493         .globl disable_addr_trans
494 disable_addr_trans:
495         /* disable address translation */
496         mflr    r4
497         mfmsr   r3
498         andi.   r0, r3, (MSR_IR | MSR_DR)
499         beqlr
500         andc    r3, r3, r0
501         mtspr   SRR0, r4
502         mtspr   SRR1, r3
503         rfi
504
505 /*
506  * This code finishes saving the registers to the exception frame
507  * and jumps to the appropriate handler for the exception.
508  * Register r21 is pointer into trap frame, r1 has new stack pointer.
509  */
510         .globl  transfer_to_handler
511 transfer_to_handler:
512         stw     r22,_NIP(r21)
513         lis     r22,MSR_POW@h
514         andc    r23,r23,r22
515         stw     r23,_MSR(r21)
516         SAVE_GPR(7, r21)
517         SAVE_4GPRS(8, r21)
518         SAVE_8GPRS(12, r21)
519         SAVE_8GPRS(24, r21)
520         mflr    r23
521         andi.   r24,r23,0x3f00          /* get vector offset */
522         stw     r24,TRAP(r21)
523         li      r22,0
524         stw     r22,RESULT(r21)
525         mtspr   SPRG2,r22               /* r1 is now kernel sp */
526         lwz     r24,0(r23)              /* virtual address of handler */
527         lwz     r23,4(r23)              /* where to go when done */
528         mtspr   SRR0,r24
529         mtspr   SRR1,r20
530         mtlr    r23
531         SYNC
532         rfi                             /* jump to handler, enable MMU */
533
534 int_return:
535         mfmsr   r28             /* Disable interrupts */
536         li      r4,0
537         ori     r4,r4,MSR_EE
538         andc    r28,r28,r4
539         SYNC                    /* Some chip revs need this... */
540         mtmsr   r28
541         SYNC
542         lwz     r2,_CTR(r1)
543         lwz     r0,_LINK(r1)
544         mtctr   r2
545         mtlr    r0
546         lwz     r2,_XER(r1)
547         lwz     r0,_CCR(r1)
548         mtspr   XER,r2
549         mtcrf   0xFF,r0
550         REST_10GPRS(3, r1)
551         REST_10GPRS(13, r1)
552         REST_8GPRS(23, r1)
553         REST_GPR(31, r1)
554         lwz     r2,_NIP(r1)     /* Restore environment */
555         lwz     r0,_MSR(r1)
556         mtspr   SRR0,r2
557         mtspr   SRR1,r0
558         lwz     r0,GPR0(r1)
559         lwz     r2,GPR2(r1)
560         lwz     r1,GPR1(r1)
561         SYNC
562         rfi
563
564         .globl  dc_read
565 dc_read:
566         blr
567
568         .globl get_pvr
569 get_pvr:
570         mfspr   r3, PVR
571         blr
572
573 /*-----------------------------------------------------------------------*/
574 /*
575  * void relocate_code (addr_sp, gd, addr_moni)
576  *
577  * This "function" does not return, instead it continues in RAM
578  * after relocating the monitor code.
579  *
580  * r3 = dest
581  * r4 = src
582  * r5 = length in bytes
583  * r6 = cachelinesize
584  */
585         .globl  relocate_code
586 relocate_code:
587         mr      r1,  r3         /* Set new stack pointer                */
588         mr      r9,  r4         /* Save copy of Global Data pointer     */
589         mr      r10, r5         /* Save copy of Destination Address     */
590
591         mr      r3,  r5                         /* Destination Address  */
592         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
593         ori     r4, r4, CFG_MONITOR_BASE@l
594         lwz     r5, GOT(__init_end)
595         sub     r5, r5, r4
596         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
597
598         /*
599          * Fix GOT pointer:
600          *
601          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
602          *
603          * Offset:
604          */
605         sub     r15, r10, r4
606
607         /* First our own GOT */
608         add     r14, r14, r15
609         /* then the one used by the C code */
610         add     r30, r30, r15
611
612         /*
613          * Now relocate code
614          */
615 #ifdef CONFIG_ECC
616         bl      board_relocate_rom
617         sync
618         mr      r3, r10                         /* Destination Address  */
619         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
620         ori     r4, r4, CFG_MONITOR_BASE@l
621         lwz     r5, GOT(__init_end)
622         sub     r5, r5, r4
623         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
624 #else
625         cmplw   cr1,r3,r4
626         addi    r0,r5,3
627         srwi.   r0,r0,2
628         beq     cr1,4f          /* In place copy is not necessary       */
629         beq     7f              /* Protect against 0 count              */
630         mtctr   r0
631         bge     cr1,2f
632
633         la      r8,-4(r4)
634         la      r7,-4(r3)
635 1:      lwzu    r0,4(r8)
636         stwu    r0,4(r7)
637         bdnz    1b
638         b       4f
639
640 2:      slwi    r0,r0,2
641         add     r8,r4,r0
642         add     r7,r3,r0
643 3:      lwzu    r0,-4(r8)
644         stwu    r0,-4(r7)
645         bdnz    3b
646 #endif
647 /*
648  * Now flush the cache: note that we must start from a cache aligned
649  * address. Otherwise we might miss one cache line.
650  */
651 4:      cmpwi   r6,0
652         add     r5,r3,r5
653         beq     7f              /* Always flush prefetch queue in any case */
654         subi    r0,r6,1
655         andc    r3,r3,r0
656         mr      r4,r3
657 5:      dcbst   0,r4
658         add     r4,r4,r6
659         cmplw   r4,r5
660         blt     5b
661         sync                    /* Wait for all dcbst to complete on bus */
662         mr      r4,r3
663 6:      icbi    0,r4
664         add     r4,r4,r6
665         cmplw   r4,r5
666         blt     6b
667 7:      sync                    /* Wait for all icbi to complete on bus */
668         isync
669
670 /*
671  * We are done. Do not return, instead branch to second part of board
672  * initialization, now running from RAM.
673  */
674         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
675         mtlr    r0
676         blr
677
678 in_ram:
679 #ifdef CONFIG_ECC
680         bl      board_init_ecc
681 #endif
682         /*
683          * Relocation Function, r14 point to got2+0x8000
684          *
685          * Adjust got2 pointers, no need to check for 0, this code
686          * already puts a few entries in the table.
687          */
688         li      r0,__got2_entries@sectoff@l
689         la      r3,GOT(_GOT2_TABLE_)
690         lwz     r11,GOT(_GOT2_TABLE_)
691         mtctr   r0
692         sub     r11,r3,r11
693         addi    r3,r3,-4
694 1:      lwzu    r0,4(r3)
695         add     r0,r0,r11
696         stw     r0,0(r3)
697         bdnz    1b
698
699         /*
700          * Now adjust the fixups and the pointers to the fixups
701          * in case we need to move ourselves again.
702          */
703 2:      li      r0,__fixup_entries@sectoff@l
704         lwz     r3,GOT(_FIXUP_TABLE_)
705         cmpwi   r0,0
706         mtctr   r0
707         addi    r3,r3,-4
708         beq     4f
709 3:      lwzu    r4,4(r3)
710         lwzux   r0,r4,r11
711         add     r0,r0,r11
712         stw     r10,0(r3)
713         stw     r0,0(r4)
714         bdnz    3b
715 4:
716 /* clear_bss: */
717         /*
718          * Now clear BSS segment
719          */
720         lwz     r3,GOT(__bss_start)
721         lwz     r4,GOT(_end)
722
723         cmplw   0, r3, r4
724         beq     6f
725
726         li      r0, 0
727 5:
728         stw     r0, 0(r3)
729         addi    r3, r3, 4
730         cmplw   0, r3, r4
731         bne     5b
732 6:
733         mr      r3, r10         /* Destination Address          */
734 #ifdef CONFIG_AMIGAONEG3SE
735         mr      r4, r9          /* Use RAM copy of the global data */
736 #endif
737         bl      after_reloc
738
739         /* not reached - end relocate_code */
740 /*-----------------------------------------------------------------------*/
741
742         /*
743          * Copy exception vector code to low memory
744          *
745          * r3: dest_addr
746          * r7: source address, r8: end address, r9: target address
747          */
748         .globl  trap_init
749 trap_init:
750         lwz     r7, GOT(_start)
751         lwz     r8, GOT(_end_of_vectors)
752
753         li      r9, 0x100               /* reset vector always at 0x100 */
754
755         cmplw   0, r7, r8
756         bgelr                           /* return if r7>=r8 - just in case */
757
758         mflr    r4                      /* save link register           */
759 1:
760         lwz     r0, 0(r7)
761         stw     r0, 0(r9)
762         addi    r7, r7, 4
763         addi    r9, r9, 4
764         cmplw   0, r7, r8
765         bne     1b
766
767         /*
768          * relocate `hdlr' and `int_return' entries
769          */
770         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
771         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
772 2:
773         bl      trap_reloc
774         addi    r7, r7, 0x100           /* next exception vector        */
775         cmplw   0, r7, r8
776         blt     2b
777
778         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
779         bl      trap_reloc
780
781         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
782         bl      trap_reloc
783
784         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
785         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
786 3:
787         bl      trap_reloc
788         addi    r7, r7, 0x100           /* next exception vector        */
789         cmplw   0, r7, r8
790         blt     3b
791
792         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
793         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
794 4:
795         bl      trap_reloc
796         addi    r7, r7, 0x100           /* next exception vector        */
797         cmplw   0, r7, r8
798         blt     4b
799
800         /* enable execptions from RAM vectors */
801         mfmsr   r7
802         li      r8,MSR_IP
803         andc    r7,r7,r8
804         mtmsr   r7
805
806         mtlr    r4                      /* restore link register        */
807         blr
808
809         /*
810          * Function: relocate entries for one exception vector
811          */
812 trap_reloc:
813         lwz     r0, 0(r7)               /* hdlr ...                     */
814         add     r0, r0, r3              /*  ... += dest_addr            */
815         stw     r0, 0(r7)
816
817         lwz     r0, 4(r7)               /* int_return ...               */
818         add     r0, r0, r3              /*  ... += dest_addr            */
819         stw     r0, 4(r7)
820
821         sync
822         isync
823
824         blr
825
826 #ifdef CFG_INIT_RAM_LOCK
827 lock_ram_in_cache:
828         /* Allocate Initial RAM in data cache.
829          */
830         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
831         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
832         li      r2, ((CFG_INIT_RAM_END & ~31) + \
833                      (CFG_INIT_RAM_ADDR & 31) + 31) / 32
834         mtctr   r2
835 1:
836         dcbz    r0, r3
837         addi    r3, r3, 32
838         bdnz    1b
839
840         /* Lock the data cache */
841         mfspr   r0, HID0
842         ori     r0, r0, 0x1000
843         sync
844         mtspr   HID0, r0
845         sync
846         blr
847
848 .globl unlock_ram_in_cache
849 unlock_ram_in_cache:
850         /* invalidate the INIT_RAM section */
851         lis     r3, (CFG_INIT_RAM_ADDR & ~31)@h
852         ori     r3, r3, (CFG_INIT_RAM_ADDR & ~31)@l
853         li      r2, ((CFG_INIT_RAM_END & ~31) + \
854                      (CFG_INIT_RAM_ADDR & 31) + 31) / 32
855         mtctr   r2
856 1:      icbi    r0, r3
857         addi    r3, r3, 32
858         bdnz    1b
859         sync                    /* Wait for all icbi to complete on bus */
860         isync
861
862         /* Unlock the data cache and invalidate it */
863         mfspr   r0, HID0
864         li      r3,0x1000
865         andc    r0,r0,r3
866         li      r3,0x0400
867         or      r0,r0,r3
868         sync
869         mtspr   HID0, r0
870         sync
871         blr
872 #endif