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