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