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