blob: 6072374a618f29959e68fc682e63d9af63972190 [file] [log] [blame]
wdenk983fda82004-10-28 00:09:35 +00001/*
2 * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
3 * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
4 * Copyright (C) 2000 - 2003 Wolfgang Denk <wd@denx.de>
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 */
24
25/*
26 * U-Boot - Startup Code for MPC8220 CPUs
27 */
28#include <config.h>
29#include <mpc8220.h>
30#include <version.h>
31
32#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
33
34#include <ppc_asm.tmpl>
35#include <ppc_defs.h>
36
37#include <asm/cache.h>
38#include <asm/mmu.h>
39
40#ifndef CONFIG_IDENT_STRING
41#define CONFIG_IDENT_STRING ""
42#endif
43
44/* We don't want the MMU yet.
45*/
46#undef MSR_KERNEL
47/* Floating Point enable, Machine Check and Recoverable Interr. */
48#ifdef DEBUG
49#define MSR_KERNEL (MSR_FP|MSR_RI)
50#else
51#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
52#endif
53
54/*
55 * Set up GOT: Global Offset Table
56 *
57 * Use r14 to access the GOT
58 */
59 START_GOT
60 GOT_ENTRY(_GOT2_TABLE_)
61 GOT_ENTRY(_FIXUP_TABLE_)
62
63 GOT_ENTRY(_start)
64 GOT_ENTRY(_start_of_vectors)
65 GOT_ENTRY(_end_of_vectors)
66 GOT_ENTRY(transfer_to_handler)
67
68 GOT_ENTRY(__init_end)
69 GOT_ENTRY(_end)
70 GOT_ENTRY(__bss_start)
71 END_GOT
72
73/*
74 * Version string
75 */
76 .data
77 .globl version_string
78version_string:
79 .ascii U_BOOT_VERSION
80 .ascii " (", __DATE__, " - ", __TIME__, ")"
81 .ascii CONFIG_IDENT_STRING, "\0"
82
83/*
84 * Exception vectors
85 */
86 .text
87 . = EXC_OFF_SYS_RESET
88 .globl _start
89_start:
90 li r21, BOOTFLAG_COLD /* Normal Power-On */
91 nop
92 b boot_cold
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
101boot_cold:
102boot_warm:
103 mfmsr r5 /* save msr contents */
104
105 /* replace default MBAR base address from 0x80000000
106 to 0xf0000000 */
107
108#if defined(CFG_DEFAULT_MBAR) && !defined(CFG_RAMBOOT)
109 lis r3, CFG_MBAR@h
110 ori r3, r3, CFG_MBAR@l
111
112 /* MBAR is mirrored into the MBAR SPR */
113 mtspr MBAR,r3
114 lis r4, CFG_DEFAULT_MBAR@h
115 stw r3, 0(r4)
116#endif /* CFG_DEFAULT_MBAR */
117
118 /* Initialise the MPC8220 processor core */
119 /*--------------------------------------------------------------*/
120
121 bl init_8220_core
122
123 /* initialize some things that are hard to access from C */
124 /*--------------------------------------------------------------*/
125
126 /* set up stack in on-chip SRAM */
127 lis r3, CFG_INIT_RAM_ADDR@h
128 ori r3, r3, CFG_INIT_RAM_ADDR@l
129 ori r1, r3, CFG_INIT_SP_OFFSET
130
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
170Alignment:
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
189ProgramCheck:
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 STD_EXCEPTION(0xc00, SystemCall, UnknownException)
212 STD_EXCEPTION(0xd00, SingleStep, UnknownException)
213
214 STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
215 STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
216
217 STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
218 STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
219 STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
220#ifdef DEBUG
221 . = 0x1300
222 /*
223 * This exception occurs when the program counter matches the
224 * Instruction Address Breakpoint Register (IABR).
225 *
226 * I want the cpu to halt if this occurs so I can hunt around
227 * with the debugger and look at things.
228 *
229 * When DEBUG is defined, both machine check enable (in the MSR)
230 * and checkstop reset enable (in the reset mode register) are
231 * turned off and so a checkstop condition will result in the cpu
232 * halting.
233 *
234 * I force the cpu into a checkstop condition by putting an illegal
235 * instruction here (at least this is the theory).
236 *
237 * well - that didnt work, so just do an infinite loop!
238 */
2391: b 1b
240#else
241 STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
242#endif
243 STD_EXCEPTION(0x1400, SMI, UnknownException)
244
245 STD_EXCEPTION(0x1500, Trap_15, UnknownException)
246 STD_EXCEPTION(0x1600, Trap_16, UnknownException)
247 STD_EXCEPTION(0x1700, Trap_17, UnknownException)
248 STD_EXCEPTION(0x1800, Trap_18, UnknownException)
249 STD_EXCEPTION(0x1900, Trap_19, UnknownException)
250 STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
251 STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
252 STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
253 STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
254 STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
255 STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
256 STD_EXCEPTION(0x2000, Trap_20, UnknownException)
257 STD_EXCEPTION(0x2100, Trap_21, UnknownException)
258 STD_EXCEPTION(0x2200, Trap_22, UnknownException)
259 STD_EXCEPTION(0x2300, Trap_23, UnknownException)
260 STD_EXCEPTION(0x2400, Trap_24, UnknownException)
261 STD_EXCEPTION(0x2500, Trap_25, UnknownException)
262 STD_EXCEPTION(0x2600, Trap_26, UnknownException)
263 STD_EXCEPTION(0x2700, Trap_27, UnknownException)
264 STD_EXCEPTION(0x2800, Trap_28, UnknownException)
265 STD_EXCEPTION(0x2900, Trap_29, UnknownException)
266 STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
267 STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
268 STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
269 STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
270 STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
271 STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
272
273
274 .globl _end_of_vectors
275_end_of_vectors:
276
277 . = 0x3000
278
279/*
280 * This code finishes saving the registers to the exception frame
281 * and jumps to the appropriate handler for the exception.
282 * Register r21 is pointer into trap frame, r1 has new stack pointer.
283 */
284 .globl transfer_to_handler
285transfer_to_handler:
286 stw r22,_NIP(r21)
287 lis r22,MSR_POW@h
288 andc r23,r23,r22
289 stw r23,_MSR(r21)
290 SAVE_GPR(7, r21)
291 SAVE_4GPRS(8, r21)
292 SAVE_8GPRS(12, r21)
293 SAVE_8GPRS(24, r21)
294 mflr r23
295 andi. r24,r23,0x3f00 /* get vector offset */
296 stw r24,TRAP(r21)
297 li r22,0
298 stw r22,RESULT(r21)
299 lwz r24,0(r23) /* virtual address of handler */
300 lwz r23,4(r23) /* where to go when done */
301 mtspr SRR0,r24
302 mtspr SRR1,r20
303 mtlr r23
304 SYNC
305 rfi /* jump to handler, enable MMU */
306
307int_return:
308 mfmsr r28 /* Disable interrupts */
309 li r4,0
310 ori r4,r4,MSR_EE
311 andc r28,r28,r4
312 SYNC /* Some chip revs need this... */
313 mtmsr r28
314 SYNC
315 lwz r2,_CTR(r1)
316 lwz r0,_LINK(r1)
317 mtctr r2
318 mtlr r0
319 lwz r2,_XER(r1)
320 lwz r0,_CCR(r1)
321 mtspr XER,r2
322 mtcrf 0xFF,r0
323 REST_10GPRS(3, r1)
324 REST_10GPRS(13, r1)
325 REST_8GPRS(23, r1)
326 REST_GPR(31, r1)
327 lwz r2,_NIP(r1) /* Restore environment */
328 lwz r0,_MSR(r1)
329 mtspr SRR0,r2
330 mtspr SRR1,r0
331 lwz r0,GPR0(r1)
332 lwz r2,GPR2(r1)
333 lwz r1,GPR1(r1)
334 SYNC
335 rfi
336
337/*
338 * This code initialises the MPC8220 processor core
339 * (conforms to PowerPC 603e spec)
340 * Note: expects original MSR contents to be in r5.
341 */
342
343 .globl init_8220_core
344init_8220_core:
345
346 /* Initialize machine status; enable machine check interrupt */
347 /*--------------------------------------------------------------*/
348
349 li r3, MSR_KERNEL /* Set ME and RI flags */
350 rlwimi r3, r5, 0, 25, 25 /* preserve IP bit set by HRCW */
351#ifdef DEBUG
352 rlwimi r3, r5, 0, 21, 22 /* debugger might set SE & BE bits */
353#endif
354 SYNC /* Some chip revs need this... */
355 mtmsr r3
356 SYNC
357 mtspr SRR1, r3 /* Make SRR1 match MSR */
358
359 /* Initialize the Hardware Implementation-dependent Registers */
360 /* HID0 also contains cache control */
361 /*--------------------------------------------------------------*/
362
363 lis r3, CFG_HID0_INIT@h
364 ori r3, r3, CFG_HID0_INIT@l
365 SYNC
366 mtspr HID0, r3
367
368 lis r3, CFG_HID0_FINAL@h
369 ori r3, r3, CFG_HID0_FINAL@l
370 SYNC
371 mtspr HID0, r3
372
373 /* Enable Extra BATs */
374 mfspr r3, 1011 /* HID2 */
375 lis r4, 0x0004
376 ori r4, r4, 0x0000
377 or r4, r4, r3
378 mtspr 1011, r4
379 sync
380
381 /* clear all BAT's */
382 /*--------------------------------------------------------------*/
383
384 li r0, 0
385 mtspr DBAT0U, r0
386 mtspr DBAT0L, r0
387 mtspr DBAT1U, r0
388 mtspr DBAT1L, r0
389 mtspr DBAT2U, r0
390 mtspr DBAT2L, r0
391 mtspr DBAT3U, r0
392 mtspr DBAT3L, r0
393 mtspr DBAT4U, r0
394 mtspr DBAT4L, r0
395 mtspr DBAT5U, r0
396 mtspr DBAT5L, r0
397 mtspr DBAT6U, r0
398 mtspr DBAT6L, r0
399 mtspr DBAT7U, r0
400 mtspr DBAT7L, r0
401 mtspr IBAT0U, r0
402 mtspr IBAT0L, r0
403 mtspr IBAT1U, r0
404 mtspr IBAT1L, r0
405 mtspr IBAT2U, r0
406 mtspr IBAT2L, r0
407 mtspr IBAT3U, r0
408 mtspr IBAT3L, r0
409 mtspr IBAT4U, r0
410 mtspr IBAT4L, r0
411 mtspr IBAT5U, r0
412 mtspr IBAT5L, r0
413 mtspr IBAT6U, r0
414 mtspr IBAT6L, r0
415 mtspr IBAT7U, r0
416 mtspr IBAT7L, r0
417 SYNC
418
419 /* invalidate all tlb's */
420 /* */
421 /* From the 603e User Manual: "The 603e provides the ability to */
422 /* invalidate a TLB entry. The TLB Invalidate Entry (tlbie) */
423 /* instruction invalidates the TLB entry indexed by the EA, and */
424 /* operates on both the instruction and data TLBs simultaneously*/
425 /* invalidating four TLB entries (both sets in each TLB). The */
426 /* index corresponds to bits 15-19 of the EA. To invalidate all */
427 /* entries within both TLBs, 32 tlbie instructions should be */
428 /* issued, incrementing this field by one each time." */
429 /* */
430 /* "Note that the tlbia instruction is not implemented on the */
431 /* 603e." */
432 /* */
433 /* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000 */
434 /* incrementing by 0x1000 each time. The code below is sort of */
435 /* based on code in "flush_tlbs" from arch/ppc/kernel/head.S */
436 /* */
437 /*--------------------------------------------------------------*/
438
439 li r3, 32
440 mtctr r3
441 li r3, 0
4421: tlbie r3
443 addi r3, r3, 0x1000
444 bdnz 1b
445 SYNC
446
447 /* Done! */
448 /*--------------------------------------------------------------*/
449
450 blr
451
452/* Cache functions.
453 *
454 * Note: requires that all cache bits in
455 * HID0 are in the low half word.
456 */
457 .globl icache_enable
458icache_enable:
459 lis r4, 0
460 ori r4, r4, CFG_HID0_INIT /* set ICE & ICFI bit */
461 rlwinm r3, r4, 0, 21, 19 /* clear the ICFI bit */
462
463 /*
464 * The setting of the instruction cache enable (ICE) bit must be
465 * preceded by an isync instruction to prevent the cache from being
466 * enabled or disabled while an instruction access is in progress.
467 */
468 isync
469 mtspr HID0, r4 /* Enable Instr Cache & Inval cache */
470 mtspr HID0, r3 /* using 2 consec instructions */
471 isync
472 blr
473
474 .globl icache_disable
475icache_disable:
476 mfspr r3, HID0
477 rlwinm r3, r3, 0, 17, 15 /* clear the ICE bit */
478 mtspr HID0, r3
479 isync
480 blr
481
482 .globl icache_status
483icache_status:
484 mfspr r3, HID0
485 rlwinm r3, r3, HID0_ICE_BITPOS + 1, 31, 31
486 blr
487
488 .globl dcache_enable
489dcache_enable:
490 lis r4, 0
491 ori r4, r4, HID0_DCE|HID0_DCFI /* set DCE & DCFI bit */
492 rlwinm r3, r4, 0, 22, 20 /* clear the DCFI bit */
493
494 /* Enable address translation in MSR bit */
495 mfmsr r5
496 ori r5, r5, 0x
497
498
499 /*
500 * The setting of the instruction cache enable (ICE) bit must be
501 * preceded by an isync instruction to prevent the cache from being
502 * enabled or disabled while an instruction access is in progress.
503 */
504 isync
505 mtspr HID0, r4 /* Enable Data Cache & Inval cache*/
506 mtspr HID0, r3 /* using 2 consec instructions */
507 isync
508 blr
509
510 .globl dcache_disable
511dcache_disable:
512 mfspr r3, HID0
513 rlwinm r3, r3, 0, 18, 16 /* clear the DCE bit */
514 mtspr HID0, r3
515 isync
516 blr
517
518 .globl dcache_status
519dcache_status:
520 mfspr r3, HID0
521 rlwinm r3, r3, HID0_DCE_BITPOS + 1, 31, 31
522 blr
523
524 .globl get_pvr
525get_pvr:
526 mfspr r3, PVR
527 blr
528
529/*------------------------------------------------------------------------------*/
530
531/*
532 * void relocate_code (addr_sp, gd, addr_moni)
533 *
534 * This "function" does not return, instead it continues in RAM
535 * after relocating the monitor code.
536 *
537 * r3 = dest
538 * r4 = src
539 * r5 = length in bytes
540 * r6 = cachelinesize
541 */
542 .globl relocate_code
543relocate_code:
544 mr r1, r3 /* Set new stack pointer */
545 mr r9, r4 /* Save copy of Global Data pointer */
546 mr r10, r5 /* Save copy of Destination Address */
547
548 mr r3, r5 /* Destination Address */
549 lis r4, CFG_MONITOR_BASE@h /* Source Address */
550 ori r4, r4, CFG_MONITOR_BASE@l
551 lwz r5, GOT(__init_end)
552 sub r5, r5, r4
553 li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
554
555 /*
556 * Fix GOT pointer:
557 *
558 * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
559 *
560 * Offset:
561 */
562 sub r15, r10, r4
563
564 /* First our own GOT */
565 add r14, r14, r15
566 /* then the one used by the C code */
567 add r30, r30, r15
568
569 /*
570 * Now relocate code
571 */
572
573 cmplw cr1,r3,r4
574 addi r0,r5,3
575 srwi. r0,r0,2
576 beq cr1,4f /* In place copy is not necessary */
577 beq 7f /* Protect against 0 count */
578 mtctr r0
579 bge cr1,2f
580
581 la r8,-4(r4)
582 la r7,-4(r3)
5831: lwzu r0,4(r8)
584 stwu r0,4(r7)
585 bdnz 1b
586 b 4f
587
5882: slwi r0,r0,2
589 add r8,r4,r0
590 add r7,r3,r0
5913: lwzu r0,-4(r8)
592 stwu r0,-4(r7)
593 bdnz 3b
594
595/*
596 * Now flush the cache: note that we must start from a cache aligned
597 * address. Otherwise we might miss one cache line.
598 */
5994: cmpwi r6,0
600 add r5,r3,r5
601 beq 7f /* Always flush prefetch queue in any case */
602 subi r0,r6,1
603 andc r3,r3,r0
604 mfspr r7,HID0 /* don't do dcbst if dcache is disabled */
605 rlwinm r7,r7,HID0_DCE_BITPOS+1,31,31
606 cmpwi r7,0
607 beq 9f
608 mr r4,r3
6095: dcbst 0,r4
610 add r4,r4,r6
611 cmplw r4,r5
612 blt 5b
613 sync /* Wait for all dcbst to complete on bus */
6149: mfspr r7,HID0 /* don't do icbi if icache is disabled */
615 rlwinm r7,r7,HID0_ICE_BITPOS+1,31,31
616 cmpwi r7,0
617 beq 7f
618 mr r4,r3
6196: icbi 0,r4
620 add r4,r4,r6
621 cmplw r4,r5
622 blt 6b
6237: sync /* Wait for all icbi to complete on bus */
624 isync
625
626/*
627 * We are done. Do not return, instead branch to second part of board
628 * initialization, now running from RAM.
629 */
630
631 addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
632 mtlr r0
633 blr
634
635in_ram:
636
637 /*
638 * Relocation Function, r14 point to got2+0x8000
639 *
640 * Adjust got2 pointers, no need to check for 0, this code
641 * already puts a few entries in the table.
642 */
643 li r0,__got2_entries@sectoff@l
644 la r3,GOT(_GOT2_TABLE_)
645 lwz r11,GOT(_GOT2_TABLE_)
646 mtctr r0
647 sub r11,r3,r11
648 addi r3,r3,-4
6491: lwzu r0,4(r3)
650 add r0,r0,r11
651 stw r0,0(r3)
652 bdnz 1b
653
654 /*
655 * Now adjust the fixups and the pointers to the fixups
656 * in case we need to move ourselves again.
657 */
6582: li r0,__fixup_entries@sectoff@l
659 lwz r3,GOT(_FIXUP_TABLE_)
660 cmpwi r0,0
661 mtctr r0
662 addi r3,r3,-4
663 beq 4f
6643: lwzu r4,4(r3)
665 lwzux r0,r4,r11
666 add r0,r0,r11
667 stw r10,0(r3)
668 stw r0,0(r4)
669 bdnz 3b
6704:
671clear_bss:
672 /*
673 * Now clear BSS segment
674 */
675 lwz r3,GOT(__bss_start)
676 lwz r4,GOT(_end)
677
678 cmplw 0, r3, r4
679 beq 6f
680
681 li r0, 0
6825:
683 stw r0, 0(r3)
684 addi r3, r3, 4
685 cmplw 0, r3, r4
686 bne 5b
6876:
688
689 mr r3, r9 /* Global Data pointer */
690 mr r4, r10 /* Destination Address */
691 bl board_init_r
692
693 /*
694 * Copy exception vector code to low memory
695 *
696 * r3: dest_addr
697 * r7: source address, r8: end address, r9: target address
698 */
699 .globl trap_init
700trap_init:
701 lwz r7, GOT(_start)
702 lwz r8, GOT(_end_of_vectors)
703
704 li r9, 0x100 /* reset vector always at 0x100 */
705
706 cmplw 0, r7, r8
707 bgelr /* return if r7>=r8 - just in case */
708
709 mflr r4 /* save link register */
7101:
711 lwz r0, 0(r7)
712 stw r0, 0(r9)
713 addi r7, r7, 4
714 addi r9, r9, 4
715 cmplw 0, r7, r8
716 bne 1b
717
718 /*
719 * relocate `hdlr' and `int_return' entries
720 */
721 li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
722 li r8, Alignment - _start + EXC_OFF_SYS_RESET
7232:
724 bl trap_reloc
725 addi r7, r7, 0x100 /* next exception vector */
726 cmplw 0, r7, r8
727 blt 2b
728
729 li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
730 bl trap_reloc
731
732 li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
733 bl trap_reloc
734
735 li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
736 li r8, SystemCall - _start + EXC_OFF_SYS_RESET
7373:
738 bl trap_reloc
739 addi r7, r7, 0x100 /* next exception vector */
740 cmplw 0, r7, r8
741 blt 3b
742
743 li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
744 li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
7454:
746 bl trap_reloc
747 addi r7, r7, 0x100 /* next exception vector */
748 cmplw 0, r7, r8
749 blt 4b
750
751 mfmsr r3 /* now that the vectors have */
752 lis r7, MSR_IP@h /* relocated into low memory */
753 ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
754 andc r3, r3, r7 /* (if it was on) */
755 SYNC /* Some chip revs need this... */
756 mtmsr r3
757 SYNC
758
759 mtlr r4 /* restore link register */
760 blr
761
762 /*
763 * Function: relocate entries for one exception vector
764 */
765trap_reloc:
766 lwz r0, 0(r7) /* hdlr ... */
767 add r0, r0, r3 /* ... += dest_addr */
768 stw r0, 0(r7)
769
770 lwz r0, 4(r7) /* int_return ... */
771 add r0, r0, r3 /* ... += dest_addr */
772 stw r0, 4(r7)
773
774 blr