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