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