]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/mpc8xx/start.S
* Patch by Dave Ellis, 22 May 2003:
[karo-tx-uboot.git] / cpu / mpc8xx / 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  *
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 /*  U-Boot - Startup Code for PowerPC based Embedded Boards
26  *
27  *
28  *  The processor starts at 0x00000100 and the code is executed
29  *  from flash. The code is organized to be at an other address
30  *  in memory, but as long we don't jump around before relocating.
31  *  board_init lies at a quite high address and when the cpu has
32  *  jumped there, everything is ok.
33  *  This works because the cpu gives the FLASH (CS0) the whole
34  *  address space at startup, and board_init lies as a echo of
35  *  the flash somewhere up there in the memorymap.
36  *
37  *  board_init will change CS0 to be positioned at the correct
38  *  address and (s)dram will be positioned at address 0
39  */
40 #include <config.h>
41 #include <mpc8xx.h>
42 #include <version.h>
43
44 #define CONFIG_8xx 1            /* needed for Linux kernel header files */
45 #define _LINUX_CONFIG_H 1       /* avoid reading Linux autoconf.h file  */
46
47 #include <ppc_asm.tmpl>
48 #include <ppc_defs.h>
49
50 #include <asm/cache.h>
51 #include <asm/mmu.h>
52
53 #ifndef  CONFIG_IDENT_STRING
54 #define  CONFIG_IDENT_STRING ""
55 #endif
56
57 /* We don't want the  MMU yet.
58 */
59 #undef  MSR_KERNEL
60 #define MSR_KERNEL ( MSR_ME | MSR_RI )  /* Machine Check and Recoverable Interr. */
61
62 /*
63  * Set up GOT: Global Offset Table
64  *
65  * Use r14 to access the GOT
66  */
67         START_GOT
68         GOT_ENTRY(_GOT2_TABLE_)
69         GOT_ENTRY(_FIXUP_TABLE_)
70
71         GOT_ENTRY(_start)
72         GOT_ENTRY(_start_of_vectors)
73         GOT_ENTRY(_end_of_vectors)
74         GOT_ENTRY(transfer_to_handler)
75
76         GOT_ENTRY(_end)
77         GOT_ENTRY(__bss_start)
78 #if defined(CONFIG_FADS) || defined(CONFIG_ICU862)
79         GOT_ENTRY(environment)
80 #endif
81         END_GOT
82
83 /*
84  * r3 - 1st arg to board_init(): IMMP pointer
85  * r4 - 2nd arg to board_init(): boot flag
86  */
87         .text
88         .long   0x27051956              /* U-Boot Magic Number                  */
89         .globl  version_string
90 version_string:
91         .ascii U_BOOT_VERSION
92         .ascii " (", __DATE__, " - ", __TIME__, ")"
93         .ascii CONFIG_IDENT_STRING, "\0"
94
95         . = EXC_OFF_SYS_RESET
96         .globl  _start
97 _start:
98         lis     r3, CFG_IMMR@h          /* position IMMR */
99         mtspr   638, r3
100         li      r21, BOOTFLAG_COLD      /* Normal Power-On: Boot from FLASH     */
101         b       boot_cold
102
103         . = EXC_OFF_SYS_RESET + 0x10
104
105         .globl  _start_warm
106 _start_warm:
107         li      r21, BOOTFLAG_WARM      /* Software reboot                      */
108         b       boot_warm
109
110 boot_cold:
111 boot_warm:
112
113         /* Initialize machine status; enable machine check interrupt            */
114         /*----------------------------------------------------------------------*/
115         li      r3, MSR_KERNEL          /* Set ME, RI flags */
116         mtmsr   r3
117         mtspr   SRR1, r3                /* Make SRR1 match MSR */
118
119         mfspr   r3, ICR                 /* clear Interrupt Cause Register */
120
121         /* Initialize debug port registers                                      */
122         /*----------------------------------------------------------------------*/
123         xor     r0, r0, r0              /* Clear R0 */
124         mtspr   LCTRL1, r0              /* Initialize debug port regs */
125         mtspr   LCTRL2, r0
126         mtspr   COUNTA, r0
127         mtspr   COUNTB, r0
128
129         /* Reset the caches                                                     */
130         /*----------------------------------------------------------------------*/
131
132         mfspr   r3, IC_CST              /* Clear error bits */
133         mfspr   r3, DC_CST
134
135         lis     r3, IDC_UNALL@h         /* Unlock all */
136         mtspr   IC_CST, r3
137         mtspr   DC_CST, r3
138
139         lis     r3, IDC_INVALL@h        /* Invalidate all */
140         mtspr   IC_CST, r3
141         mtspr   DC_CST, r3
142
143         lis     r3, IDC_DISABLE@h       /* Disable data cache */
144         mtspr   DC_CST, r3
145
146 #if !(defined(CONFIG_IP860) || defined(CONFIG_PCU_E) || defined (CONFIG_FLAGADM))
147                                         /* On IP860 and PCU E,
148                                          * we cannot enable IC yet
149                                          */
150         lis     r3, IDC_ENABLE@h        /* Enable instruction cache */
151 #endif
152         mtspr   IC_CST, r3
153
154         /* invalidate all tlb's                                                 */
155         /*----------------------------------------------------------------------*/
156
157         tlbia
158         isync
159
160         /*
161          * Calculate absolute address in FLASH and jump there
162          *----------------------------------------------------------------------*/
163
164         lis     r3, CFG_MONITOR_BASE@h
165         ori     r3, r3, CFG_MONITOR_BASE@l
166         addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
167         mtlr    r3
168         blr
169
170 in_flash:
171
172         /* initialize some SPRs that are hard to access from C                  */
173         /*----------------------------------------------------------------------*/
174
175         lis     r3, CFG_IMMR@h          /* pass IMMR as arg1 to C routine */
176         ori     r1, r3, CFG_INIT_SP_OFFSET /* set up the stack in internal DPRAM */
177         /* Note: R0 is still 0 here */
178         stwu    r0, -4(r1)              /* clear final stack frame so that      */
179         stwu    r0, -4(r1)              /* stack backtraces terminate cleanly   */
180
181         /*
182          * Disable serialized ifetch and show cycles
183          * (i.e. set processor to normal mode).
184          * This is also a silicon bug workaround, see errata
185          */
186
187         li      r2, 0x0007
188         mtspr   ICTRL, r2
189
190         /* Set up debug mode entry */
191
192         lis     r2, CFG_DER@h
193         ori     r2, r2, CFG_DER@l
194         mtspr   DER, r2
195
196         /* let the C-code set up the rest                                       */
197         /*                                                                      */
198         /* Be careful to keep code relocatable !                                */
199         /*----------------------------------------------------------------------*/
200
201         GET_GOT                 /* initialize GOT access                        */
202
203         /* r3: IMMR */
204         bl      cpu_init_f      /* run low-level CPU init code     (from Flash) */
205
206         mr      r3, r21
207         /* r3: BOOTFLAG */
208         bl      board_init_f    /* run 1st part of board init code (from Flash) */
209
210
211
212         .globl  _start_of_vectors
213 _start_of_vectors:
214
215 /* Machine check */
216         STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
217
218 /* Data Storage exception.  "Never" generated on the 860. */
219         STD_EXCEPTION(0x300, DataStorage, UnknownException)
220
221 /* Instruction Storage exception.  "Never" generated on the 860. */
222         STD_EXCEPTION(0x400, InstStorage, UnknownException)
223
224 /* External Interrupt exception. */
225         STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
226
227 /* Alignment exception. */
228         . = 0x600
229 Alignment:
230         EXCEPTION_PROLOG
231         mfspr   r4,DAR
232         stw     r4,_DAR(r21)
233         mfspr   r5,DSISR
234         stw     r5,_DSISR(r21)
235         addi    r3,r1,STACK_FRAME_OVERHEAD
236         li      r20,MSR_KERNEL
237         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
238         lwz     r6,GOT(transfer_to_handler)
239         mtlr    r6
240         blrl
241 .L_Alignment:
242         .long   AlignmentException - _start + EXC_OFF_SYS_RESET
243         .long   int_return - _start + EXC_OFF_SYS_RESET
244
245 /* Program check exception */
246         . = 0x700
247 ProgramCheck:
248         EXCEPTION_PROLOG
249         addi    r3,r1,STACK_FRAME_OVERHEAD
250         li      r20,MSR_KERNEL
251         rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
252         lwz     r6,GOT(transfer_to_handler)
253         mtlr    r6
254         blrl
255 .L_ProgramCheck:
256         .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
257         .long   int_return - _start + EXC_OFF_SYS_RESET
258
259         /* No FPU on MPC8xx.  This exception is not supposed to happen.
260         */
261         STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
262
263         /* I guess we could implement decrementer, and may have
264          * to someday for timekeeping.
265          */
266         STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
267         STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
268         STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
269
270         . = 0xc00
271 /*
272  * r0 - SYSCALL number
273  * r3-... arguments
274  */
275 SystemCall:
276         addis   r11,r0,0                /* get functions table addr */
277         ori     r11,r11,0               /* Note: this code is patched in trap_init */
278         addis   r12,r0,0                /* get number of functions */
279         ori     r12,r12,0
280
281         cmplw   0, r0, r12
282         bge     1f
283
284         rlwinm  r0,r0,2,0,31            /* fn_addr = fn_tbl[r0] */
285         add     r11,r11,r0
286         lwz     r11,0(r11)
287
288         li      r20,0xd00-4             /* Get stack pointer */
289         lwz     r12,0(r20)
290         subi    r12,r12,12              /* Adjust stack pointer */
291         li      r0,0xc00+_end_back-SystemCall
292         cmplw   0, r0, r12              /* Check stack overflow */
293         bgt     1f
294         stw     r12,0(r20)
295
296         mflr    r0
297         stw     r0,0(r12)
298         mfspr   r0,SRR0
299         stw     r0,4(r12)
300         mfspr   r0,SRR1
301         stw     r0,8(r12)
302
303         li      r12,0xc00+_back-SystemCall
304         mtlr    r12
305         mtspr   SRR0,r11
306
307 1:      SYNC
308         rfi
309
310 _back:
311
312         mfmsr   r11                     /* Disable interrupts */
313         li      r12,0
314         ori     r12,r12,MSR_EE
315         andc    r11,r11,r12
316         SYNC                            /* Some chip revs need this... */
317         mtmsr   r11
318         SYNC
319
320         li      r12,0xd00-4             /* restore regs */
321         lwz     r12,0(r12)
322
323         lwz     r11,0(r12)
324         mtlr    r11
325         lwz     r11,4(r12)
326         mtspr   SRR0,r11
327         lwz     r11,8(r12)
328         mtspr   SRR1,r11
329
330         addi    r12,r12,12              /* Adjust stack pointer */
331         li      r20,0xd00-4
332         stw     r12,0(r20)
333
334         SYNC
335         rfi
336 _end_back:
337
338         STD_EXCEPTION(0xd00, SingleStep, UnknownException)
339
340         STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
341         STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
342
343         /* On the MPC8xx, this is a software emulation interrupt.  It occurs
344          * for all unimplemented and illegal instructions.
345          */
346         STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
347
348         STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
349         STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
350         STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
351         STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
352
353         STD_EXCEPTION(0x1500, Reserved5, UnknownException)
354         STD_EXCEPTION(0x1600, Reserved6, UnknownException)
355         STD_EXCEPTION(0x1700, Reserved7, UnknownException)
356         STD_EXCEPTION(0x1800, Reserved8, UnknownException)
357         STD_EXCEPTION(0x1900, Reserved9, UnknownException)
358         STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
359         STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
360
361         STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
362         STD_EXCEPTION(0x1d00, InstructionBreakpoint, DebugException)
363         STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
364         STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
365
366
367         .globl  _end_of_vectors
368 _end_of_vectors:
369
370
371         . = 0x2000
372
373 /*
374  * This code finishes saving the registers to the exception frame
375  * and jumps to the appropriate handler for the exception.
376  * Register r21 is pointer into trap frame, r1 has new stack pointer.
377  */
378         .globl  transfer_to_handler
379 transfer_to_handler:
380         stw     r22,_NIP(r21)
381         lis     r22,MSR_POW@h
382         andc    r23,r23,r22
383         stw     r23,_MSR(r21)
384         SAVE_GPR(7, r21)
385         SAVE_4GPRS(8, r21)
386         SAVE_8GPRS(12, r21)
387         SAVE_8GPRS(24, r21)
388         mflr    r23
389         andi.   r24,r23,0x3f00          /* get vector offset */
390         stw     r24,TRAP(r21)
391         li      r22,0
392         stw     r22,RESULT(r21)
393         mtspr   SPRG2,r22               /* r1 is now kernel sp */
394         lwz     r24,0(r23)              /* virtual address of handler */
395         lwz     r23,4(r23)              /* where to go when done */
396         mtspr   SRR0,r24
397         mtspr   SRR1,r20
398         mtlr    r23
399         SYNC
400         rfi                             /* jump to handler, enable MMU */
401
402 int_return:
403         mfmsr   r28                     /* Disable interrupts */
404         li      r4,0
405         ori     r4,r4,MSR_EE
406         andc    r28,r28,r4
407         SYNC                            /* Some chip revs need this... */
408         mtmsr   r28
409         SYNC
410         lwz     r2,_CTR(r1)
411         lwz     r0,_LINK(r1)
412         mtctr   r2
413         mtlr    r0
414         lwz     r2,_XER(r1)
415         lwz     r0,_CCR(r1)
416         mtspr   XER,r2
417         mtcrf   0xFF,r0
418         REST_10GPRS(3, r1)
419         REST_10GPRS(13, r1)
420         REST_8GPRS(23, r1)
421         REST_GPR(31, r1)
422         lwz     r2,_NIP(r1)             /* Restore environment */
423         lwz     r0,_MSR(r1)
424         mtspr   SRR0,r2
425         mtspr   SRR1,r0
426         lwz     r0,GPR0(r1)
427         lwz     r2,GPR2(r1)
428         lwz     r1,GPR1(r1)
429         SYNC
430         rfi
431
432 /* Cache functions.
433 */
434         .globl  icache_enable
435 icache_enable:
436         SYNC
437         lis     r3, IDC_INVALL@h
438         mtspr   IC_CST, r3
439         lis     r3, IDC_ENABLE@h
440         mtspr   IC_CST, r3
441         blr
442
443         .globl  icache_disable
444 icache_disable:
445         SYNC
446         lis     r3, IDC_DISABLE@h
447         mtspr   IC_CST, r3
448         blr
449
450         .globl  icache_status
451 icache_status:
452         mfspr   r3, IC_CST
453         srwi    r3, r3, 31      /* >>31 => select bit 0 */
454         blr
455
456         .globl  dcache_enable
457 dcache_enable:
458 #if 0
459         SYNC
460 #endif
461 #if 1
462         lis     r3, 0x0400              /* Set cache mode with MMU off */
463         mtspr   MD_CTR, r3
464 #endif
465
466         lis     r3, IDC_INVALL@h
467         mtspr   DC_CST, r3
468 #if 0
469         lis     r3, DC_SFWT@h
470         mtspr   DC_CST, r3
471 #endif
472         lis     r3, IDC_ENABLE@h
473         mtspr   DC_CST, r3
474         blr
475
476         .globl  dcache_disable
477 dcache_disable:
478         SYNC
479         lis     r3, IDC_DISABLE@h
480         mtspr   DC_CST, r3
481         lis     r3, IDC_INVALL@h
482         mtspr   DC_CST, r3
483         blr
484
485         .globl  dcache_status
486 dcache_status:
487         mfspr   r3, DC_CST
488         srwi    r3, r3, 31      /* >>31 => select bit 0 */
489         blr
490
491         .globl  dc_read
492 dc_read:
493         mtspr   DC_ADR, r3
494         mfspr   r3, DC_DAT
495         blr
496
497 /*
498  * unsigned int get_immr (unsigned int mask)
499  *
500  * return (mask ? (IMMR & mask) : IMMR);
501  */
502         .globl  get_immr
503 get_immr:
504         mr      r4,r3           /* save mask */
505         mfspr   r3, IMMR        /* IMMR */
506         cmpwi   0,r4,0          /* mask != 0 ? */
507         beq     4f
508         and     r3,r3,r4        /* IMMR & mask */
509 4:
510         blr
511
512         .globl get_pvr
513 get_pvr:
514         mfspr   r3, PVR
515         blr
516
517
518         .globl wr_ic_cst
519 wr_ic_cst:
520         mtspr   IC_CST, r3
521         blr
522
523         .globl rd_ic_cst
524 rd_ic_cst:
525         mfspr   r3, IC_CST
526         blr
527
528         .globl wr_ic_adr
529 wr_ic_adr:
530         mtspr   IC_ADR, r3
531         blr
532
533
534         .globl wr_dc_cst
535 wr_dc_cst:
536         mtspr   DC_CST, r3
537         blr
538
539         .globl rd_dc_cst
540 rd_dc_cst:
541         mfspr   r3, DC_CST
542         blr
543
544         .globl wr_dc_adr
545 wr_dc_adr:
546         mtspr   DC_ADR, r3
547         blr
548
549 /*------------------------------------------------------------------------------*/
550
551 /*
552  * void relocate_code (addr_sp, gd, addr_moni)
553  *
554  * This "function" does not return, instead it continues in RAM
555  * after relocating the monitor code.
556  *
557  * r3 = dest
558  * r4 = src
559  * r5 = length in bytes
560  * r6 = cachelinesize
561  */
562         .globl  relocate_code
563 relocate_code:
564         mr      r1,  r3         /* Set new stack pointer                */
565         mr      r9,  r4         /* Save copy of Global Data pointer     */
566         mr      r10, r5         /* Save copy of Destination Address     */
567
568         mr      r3,  r5                         /* Destination Address  */
569         lis     r4, CFG_MONITOR_BASE@h          /* Source      Address  */
570         ori     r4, r4, CFG_MONITOR_BASE@l
571         lis     r5, CFG_MONITOR_LEN@h           /* Length in Bytes      */
572         ori     r5, r5, CFG_MONITOR_LEN@l
573         li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
574
575         /*
576          * Fix GOT pointer:
577          *
578          * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
579          *
580          * Offset:
581          */
582         sub     r15, r10, r4
583
584         /* First our own GOT */
585         add     r14, r14, r15
586         /* then the one used by the C code */
587         add     r30, r30, r15
588
589         /*
590          * Now relocate code
591          */
592
593         cmplw   cr1,r3,r4
594         addi    r0,r5,3
595         srwi.   r0,r0,2
596         beq     cr1,4f          /* In place copy is not necessary       */
597         beq     7f              /* Protect against 0 count              */
598         mtctr   r0
599         bge     cr1,2f
600
601         la      r8,-4(r4)
602         la      r7,-4(r3)
603 1:      lwzu    r0,4(r8)
604         stwu    r0,4(r7)
605         bdnz    1b
606         b       4f
607
608 2:      slwi    r0,r0,2
609         add     r8,r4,r0
610         add     r7,r3,r0
611 3:      lwzu    r0,-4(r8)
612         stwu    r0,-4(r7)
613         bdnz    3b
614
615 /*
616  * Now flush the cache: note that we must start from a cache aligned
617  * address. Otherwise we might miss one cache line.
618  */
619 4:      cmpwi   r6,0
620         add     r5,r3,r5
621         beq     7f              /* Always flush prefetch queue in any case */
622         subi    r0,r6,1
623         andc    r3,r3,r0
624         mr      r4,r3
625 5:      dcbst   0,r4
626         add     r4,r4,r6
627         cmplw   r4,r5
628         blt     5b
629         sync                    /* Wait for all dcbst to complete on bus */
630         mr      r4,r3
631 6:      icbi    0,r4
632         add     r4,r4,r6
633         cmplw   r4,r5
634         blt     6b
635 7:      sync                    /* Wait for all icbi to complete on bus */
636         isync
637
638 /*
639  * We are done. Do not return, instead branch to second part of board
640  * initialization, now running from RAM.
641  */
642
643         addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
644         mtlr    r0
645         blr
646
647 in_ram:
648
649         /*
650          * Relocation Function, r14 point to got2+0x8000
651          *
652          * Adjust got2 pointers, no need to check for 0, this code
653          * already puts a few entries in the table.
654          */
655         li      r0,__got2_entries@sectoff@l
656         la      r3,GOT(_GOT2_TABLE_)
657         lwz     r11,GOT(_GOT2_TABLE_)
658         mtctr   r0
659         sub     r11,r3,r11
660         addi    r3,r3,-4
661 1:      lwzu    r0,4(r3)
662         add     r0,r0,r11
663         stw     r0,0(r3)
664         bdnz    1b
665
666         /*
667          * Now adjust the fixups and the pointers to the fixups
668          * in case we need to move ourselves again.
669          */
670 2:      li      r0,__fixup_entries@sectoff@l
671         lwz     r3,GOT(_FIXUP_TABLE_)
672         cmpwi   r0,0
673         mtctr   r0
674         addi    r3,r3,-4
675         beq     4f
676 3:      lwzu    r4,4(r3)
677         lwzux   r0,r4,r11
678         add     r0,r0,r11
679         stw     r10,0(r3)
680         stw     r0,0(r4)
681         bdnz    3b
682 4:
683 clear_bss:
684         /*
685          * Now clear BSS segment
686          */
687         lwz     r3,GOT(__bss_start)
688 #if defined(CONFIG_FADS) || defined(CONFIG_ICU862)
689         /*
690          * For the FADS - the environment is the very last item in flash.
691          * The real .bss stops just before environment starts, so only
692          * clear up to that point.
693          */
694         lwz     r4,GOT(environment)
695 #else
696         lwz     r4,GOT(_end)
697 #endif
698
699         cmplw   0, r3, r4
700         beq     6f
701
702         li      r0, 0
703 5:
704         stw     r0, 0(r3)
705         addi    r3, r3, 4
706         cmplw   0, r3, r4
707         bne     5b
708 6:
709
710         mr      r3, r9          /* Global Data pointer          */
711         mr      r4, r10         /* Destination Address          */
712         bl      board_init_r
713
714         /* Problems accessing "end" in C, so do it here */
715         .globl  get_endaddr
716 get_endaddr:
717         lwz     r3,GOT(_end)
718         blr
719
720         /*
721          * Copy exception vector code to low memory
722          *
723          * r3: dest_addr
724          * r7: source address, r8: end address, r9: target address
725          */
726         .globl  trap_init
727 trap_init:
728         lwz     r7, GOT(_start)
729         lwz     r8, GOT(_end_of_vectors)
730
731         rlwinm  r9, r7, 0, 22, 31       /* _start & 0x3FF       */
732
733         cmplw   0, r7, r8
734         bgelr                           /* return if r7>=r8 - just in case */
735
736         mflr    r4                      /* save link register           */
737 1:
738         lwz     r0, 0(r7)
739         stw     r0, 0(r9)
740         addi    r7, r7, 4
741         addi    r9, r9, 4
742         cmplw   0, r7, r8
743         bne     1b
744
745         /*
746          * relocate `hdlr' and `int_return' entries
747          */
748         li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
749         li      r8, Alignment - _start + EXC_OFF_SYS_RESET
750 2:
751         bl      trap_reloc
752         addi    r7, r7, 0x100           /* next exception vector        */
753         cmplw   0, r7, r8
754         blt     2b
755
756         li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
757         bl      trap_reloc
758
759         li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
760         bl      trap_reloc
761
762         li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
763         li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
764 3:
765         bl      trap_reloc
766         addi    r7, r7, 0x100           /* next exception vector        */
767         cmplw   0, r7, r8
768         blt     3b
769
770         li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
771         li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
772 4:
773         bl      trap_reloc
774         addi    r7, r7, 0x100           /* next exception vector        */
775         cmplw   0, r7, r8
776         blt     4b
777
778         mtlr    r4                      /* restore link register        */
779         blr
780
781         /*
782          * Function: relocate entries for one exception vector
783          */
784 trap_reloc:
785         lwz     r0, 0(r7)               /* hdlr ...                     */
786         add     r0, r0, r3              /*  ... += dest_addr            */
787         stw     r0, 0(r7)
788
789         lwz     r0, 4(r7)               /* int_return ...               */
790         add     r0, r0, r3              /*  ... += dest_addr            */
791         stw     r0, 4(r7)
792
793         sync
794         isync
795
796         blr