2 * Creation Date: <2001/06/16 21:30:18 samuel>
3 * Time-stamp: <2003/04/04 16:32:06 samuel>
7 * Asm glue for ELF images
9 * Copyright (C) 2001, 2002, 2003 Samuel Rydh (samuel@ibrium.se)
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation
18 #include "asm/asmdefs.h"
19 #include "asm/processor.h"
21 /************************************************************************/
23 /************************************************************************/
25 #define ILLEGAL_VECTOR( v ) .org __vectors + v ; vector__##v: bl trap_error ;
26 #define VECTOR( v, dummystr ) .org __vectors + v ; vector__##v
28 #ifdef CONFIG_PPC_64BITSUPPORT
30 /* We're trying to use the same code for the ppc32 and ppc64 handlers here.
31 * On ppc32 we only save/restore the registers, C considers volatile.
33 * On ppc64 on the other hand, we have to save/restore all registers, because
34 * all OF code is 32 bits, which only saves/restores the low 32 bits of the
35 * registers it clobbers.
38 #define EXCEPTION_PREAMBLE_TEMPLATE \
39 mtsprg1 r1 ; /* scratch */ \
41 mtsprg2 r1 ; /* scratch */ \
42 lis r1, 0x8000 ; /* r1=0x80000000 */ \
43 add. r1,r1,r1 ; /* r1=r1+r1 (high 32bit !0) */ \
46 mfmsr r1 ; /* unset MSR_SF */ \
50 mfsprg0 r1 ; /* exception stack in sprg0 */ \
51 .ifc ULONG_SIZE, 8 ; \
52 addi r1,r1,-(40 * ULONG_SIZE) ; /* push exception frame */ \
54 addi r1,r1,-(20 * ULONG_SIZE) ; /* push exception frame */ \
57 stl r0,(0 * ULONG_SIZE)(r1) ; /* save r0 */ \
59 stl r0,(1 * ULONG_SIZE)(r1) ; /* save r1 */ \
60 stl r2,(2 * ULONG_SIZE)(r1) ; /* save r2 */ \
61 stl r3,(3 * ULONG_SIZE)(r1) ; /* save r3 */ \
62 stl r4,(4 * ULONG_SIZE)(r1) ; \
63 stl r5,(5 * ULONG_SIZE)(r1) ; \
64 stl r6,(6 * ULONG_SIZE)(r1) ; \
65 stl r7,(7 * ULONG_SIZE)(r1) ; \
66 stl r8,(8 * ULONG_SIZE)(r1) ; \
67 stl r9,(9 * ULONG_SIZE)(r1) ; \
68 stl r10,(10 * ULONG_SIZE)(r1) ; \
69 stl r11,(11 * ULONG_SIZE)(r1) ; \
70 stl r12,(12 * ULONG_SIZE)(r1) ; \
71 .ifc ULONG_SIZE, 8 ; \
72 stl r13,(17 * ULONG_SIZE)(r1) ; \
73 stl r14,(18 * ULONG_SIZE)(r1) ; \
74 stl r15,(19 * ULONG_SIZE)(r1) ; \
75 stl r16,(20 * ULONG_SIZE)(r1) ; \
76 stl r17,(21 * ULONG_SIZE)(r1) ; \
77 stl r18,(22 * ULONG_SIZE)(r1) ; \
78 stl r19,(23 * ULONG_SIZE)(r1) ; \
79 stl r20,(24 * ULONG_SIZE)(r1) ; \
80 stl r21,(25 * ULONG_SIZE)(r1) ; \
81 stl r22,(26 * ULONG_SIZE)(r1) ; \
82 stl r23,(27 * ULONG_SIZE)(r1) ; \
83 stl r24,(28 * ULONG_SIZE)(r1) ; \
84 stl r25,(29 * ULONG_SIZE)(r1) ; \
85 stl r26,(30 * ULONG_SIZE)(r1) ; \
86 stl r27,(31 * ULONG_SIZE)(r1) ; \
87 stl r28,(32 * ULONG_SIZE)(r1) ; \
88 stl r29,(33 * ULONG_SIZE)(r1) ; \
89 stl r30,(34 * ULONG_SIZE)(r1) ; \
90 stl r31,(35 * ULONG_SIZE)(r1) ; \
94 stl r0,(13 * ULONG_SIZE)(r1) ; \
96 stl r0,(14 * ULONG_SIZE)(r1) ; \
98 stl r0,(15 * ULONG_SIZE)(r1) ; \
100 stl r0,(16 * ULONG_SIZE)(r1) ; \
102 /* 76(r1) unused */ \
103 addi r1,r1,-16 ; /* C ABI uses 0(r1) and 4(r1)... */
105 #define EXCEPTION_EPILOGUE_TEMPLATE \
106 addi r1,r1,16 ; /* pop ABI frame */ \
108 ll r0,(13 * ULONG_SIZE)(r1) ; \
110 ll r0,(14 * ULONG_SIZE)(r1) ; \
112 ll r0,(15 * ULONG_SIZE)(r1) ; \
114 ll r0,(16 * ULONG_SIZE)(r1) ; \
117 ll r0,(0 * ULONG_SIZE)(r1) ; \
118 ll r2,(2 * ULONG_SIZE)(r1) ; \
119 ll r3,(3 * ULONG_SIZE)(r1) ; \
120 ll r4,(4 * ULONG_SIZE)(r1) ; \
121 ll r5,(5 * ULONG_SIZE)(r1) ; \
122 ll r6,(6 * ULONG_SIZE)(r1) ; \
123 ll r7,(7 * ULONG_SIZE)(r1) ; \
124 ll r8,(8 * ULONG_SIZE)(r1) ; \
125 ll r9,(9 * ULONG_SIZE)(r1) ; \
126 ll r10,(10 * ULONG_SIZE)(r1) ; \
127 ll r11,(11 * ULONG_SIZE)(r1) ; \
128 ll r12,(12 * ULONG_SIZE)(r1) ; \
129 .ifc ULONG_SIZE, 8 ; \
130 ll r13,(17 * ULONG_SIZE)(r1) ; \
131 ll r14,(18 * ULONG_SIZE)(r1) ; \
132 ll r15,(19 * ULONG_SIZE)(r1) ; \
133 ll r16,(20 * ULONG_SIZE)(r1) ; \
134 ll r17,(21 * ULONG_SIZE)(r1) ; \
135 ll r18,(22 * ULONG_SIZE)(r1) ; \
136 ll r19,(23 * ULONG_SIZE)(r1) ; \
137 ll r20,(24 * ULONG_SIZE)(r1) ; \
138 ll r21,(25 * ULONG_SIZE)(r1) ; \
139 ll r22,(26 * ULONG_SIZE)(r1) ; \
140 ll r23,(27 * ULONG_SIZE)(r1) ; \
141 ll r24,(28 * ULONG_SIZE)(r1) ; \
142 ll r25,(29 * ULONG_SIZE)(r1) ; \
143 ll r26,(30 * ULONG_SIZE)(r1) ; \
144 ll r27,(31 * ULONG_SIZE)(r1) ; \
145 ll r28,(32 * ULONG_SIZE)(r1) ; \
146 ll r29,(33 * ULONG_SIZE)(r1) ; \
147 ll r30,(34 * ULONG_SIZE)(r1) ; \
148 ll r31,(35 * ULONG_SIZE)(r1) ; \
150 ll r1,(1 * ULONG_SIZE)(r1) ; /* restore stack at last */ \
159 .macro EXCEPTION_PREAMBLE
160 EXCEPTION_PREAMBLE_TEMPLATE
163 .macro EXCEPTION_EPILOGUE
164 EXCEPTION_EPILOGUE_TEMPLATE
177 .macro EXCEPTION_PREAMBLE_64
178 EXCEPTION_PREAMBLE_TEMPLATE
181 .macro EXCEPTION_EPILOGUE_64
182 EXCEPTION_EPILOGUE_TEMPLATE
190 #define STACKFRAME_MINSIZE 16
192 #else /* !CONFIG_PPC_64BITSUPPORT */
197 #define STACKFRAME_MINSIZE 48
204 #define STACKFRAME_MINSIZE 16
210 .macro EXCEPTION_PREAMBLE
211 mtsprg1 r1 /* scratch */
212 mfsprg0 r1 /* exception stack in sprg0 */
213 addi r1, r1, -(20 * ULONG_SIZE) /* push exception frame */
215 stl r0, ( 0 * ULONG_SIZE)(r1) /* save r0 */
217 stl r0, ( 1 * ULONG_SIZE)(r1) /* save r1 */
218 stl r2, ( 2 * ULONG_SIZE)(r1) /* save r2 */
219 stl r3, ( 3 * ULONG_SIZE)(r1) /* save r3 */
220 stl r4, ( 4 * ULONG_SIZE)(r1)
221 stl r5, ( 5 * ULONG_SIZE)(r1)
222 stl r6, ( 6 * ULONG_SIZE)(r1)
223 stl r7, ( 7 * ULONG_SIZE)(r1)
224 stl r8, ( 8 * ULONG_SIZE)(r1)
225 stl r9, ( 9 * ULONG_SIZE)(r1)
226 stl r10, (10 * ULONG_SIZE)(r1)
227 stl r11, (11 * ULONG_SIZE)(r1)
228 stl r12, (12 * ULONG_SIZE)(r1)
231 stl r0, (13 * ULONG_SIZE)(r1)
233 stl r0, (14 * ULONG_SIZE)(r1)
235 stl r0, (15 * ULONG_SIZE)(r1)
237 stl r0, (16 * ULONG_SIZE)(r1)
239 addi r1, r1, -STACKFRAME_MINSIZE /* C ABI saves LR and SP */
242 .macro EXCEPTION_EPILOGUE
243 addi r1, r1, STACKFRAME_MINSIZE /* pop ABI frame */
245 ll r0, (13 * ULONG_SIZE)(r1)
247 ll r0, (14 * ULONG_SIZE)(r1)
249 ll r0, (15 * ULONG_SIZE)(r1)
251 ll r0, (16 * ULONG_SIZE)(r1)
254 ll r0, ( 0 * ULONG_SIZE)(r1)
255 ll r2, ( 2 * ULONG_SIZE)(r1)
256 ll r3, ( 3 * ULONG_SIZE)(r1)
257 ll r4, ( 4 * ULONG_SIZE)(r1)
258 ll r5, ( 5 * ULONG_SIZE)(r1)
259 ll r6, ( 6 * ULONG_SIZE)(r1)
260 ll r7, ( 7 * ULONG_SIZE)(r1)
261 ll r8, ( 8 * ULONG_SIZE)(r1)
262 ll r9, ( 9 * ULONG_SIZE)(r1)
263 ll r10, (10 * ULONG_SIZE)(r1)
264 ll r11, (11 * ULONG_SIZE)(r1)
265 ll r12, (12 * ULONG_SIZE)(r1)
267 ll r1, ( 1 * ULONG_SIZE)(r1) /* restore stack at last */
271 #endif /* !CONFIG_PPC_64BITSUPPORT */
273 /************************************************************************/
275 /************************************************************************/
277 .section .text.vectors, "ax"
283 VECTOR( 0x100, "SRE" ):
287 lis r1, 0x8000 /* r1=0x80000000 */
288 add. r1,r1,r1 /* r1=r1+r1 (high 32bit !0) */
291 mfmsr r1 /* unset MSR_SF */
296 LOAD_REG_FUNC(r4, unexpected_excep)
300 ILLEGAL_VECTOR( 0x200 )
302 VECTOR( 0x300, "DSI" ):
305 ILLEGAL_VECTOR( 0x380 )
307 VECTOR( 0x400, "ISI" ):
310 ILLEGAL_VECTOR( 0x480 )
312 ILLEGAL_VECTOR( 0x500 )
313 ILLEGAL_VECTOR( 0x600 )
314 ILLEGAL_VECTOR( 0x700 )
316 VECTOR( 0x800, "FPU" ):
324 ILLEGAL_VECTOR( 0x900 )
325 ILLEGAL_VECTOR( 0xa00 )
326 ILLEGAL_VECTOR( 0xb00 )
327 ILLEGAL_VECTOR( 0xc00 )
328 ILLEGAL_VECTOR( 0xd00 )
329 ILLEGAL_VECTOR( 0xe00 )
330 ILLEGAL_VECTOR( 0xf00 )
331 ILLEGAL_VECTOR( 0xf20 )
332 ILLEGAL_VECTOR( 0x1000 )
333 ILLEGAL_VECTOR( 0x1100 )
334 ILLEGAL_VECTOR( 0x1200 )
335 ILLEGAL_VECTOR( 0x1300 )
336 ILLEGAL_VECTOR( 0x1400 )
337 ILLEGAL_VECTOR( 0x1500 )
338 ILLEGAL_VECTOR( 0x1600 )
339 ILLEGAL_VECTOR( 0x1700 )
341 #ifdef CONFIG_PPC_64BITSUPPORT
343 VECTOR( 0x2000, "DSI_64" ):
344 EXCEPTION_PREAMBLE_64
345 LOAD_REG_IMMEDIATE(r3, dsi_exception)
348 EXCEPTION_EPILOGUE_64
350 VECTOR( 0x2200, "ISI_64" ):
351 EXCEPTION_PREAMBLE_64
352 LOAD_REG_IMMEDIATE(r3, isi_exception)
355 EXCEPTION_EPILOGUE_64
361 LOAD_REG_FUNC(r3, dsi_exception)
368 LOAD_REG_FUNC(r3, isi_exception)
376 GLOBL(__vectors_end):
378 /************************************************************************/
380 /************************************************************************/
384 #ifdef CONFIG_PPC_64BITSUPPORT
387 lis r3, 0x8000 /* r1=0x80000000 */
388 add. r3,r3,r3 /* r1=r1+r1 (high 32bit !0) */
389 beq no_64bit /* only true when !MSR_SF */
391 /* clear MSR, disable MMU, SF */
396 /* clear MSR, disable MMU */
402 /* copy exception vectors */
404 LOAD_REG_IMMEDIATE(r3, __vectors)
406 li r5,__vectors_end - __vectors + 16
431 * Top +-------------------------+
433 * | ROM into RAM (1 MB) |
435 * +-------------------------+
437 * | MMU Hash Table (64 kB) |
439 * +-------------------------+
441 * | Exception Stack (32 kB) |
443 * +-------------------------+
447 * +-------------------------+
449 * | Client Stack (64 kB) |
451 * +-------------------------+
453 * | Malloc Zone (2 MiB) |
455 * +-------------------------+
460 addis r1, r3, -16 /* ramsize - 1MB */
462 /* setup hash table */
464 addis r1, r1, -1 /* - 64 kB */
465 clrrwi r1, r1, 5*4 /* & ~0xfffff */
467 /* setup exception stack */
473 addi r1, r1, -32768 /* - 32 kB */
475 /* save memory size in stack */
478 /* set up TOC pointer */
480 LOAD_REG_IMMEDIATE(r2, setup_mmu)
484 bl BRANCH_LABEL(setup_mmu)
485 bl BRANCH_LABEL(entry)
490 /* According to IEEE 1275, PPC bindings:
492 * MSR = FP, ME + (DR|IR)
493 * r1 = stack (32 K + 32 bytes link area above)
494 * r5 = client interface handler
495 * r6 = address of client program arguments (unused)
496 * r7 = length of client program arguments (unused)
498 * Yaboot and Linux use r3 and r4 for initrd address and size
504 /* void call_elf( arg1, arg2, entry ) */
507 PPC_STLU r1, -STACKFRAME_MINSIZE(r1)
508 PPC_STL r0, (STACKFRAME_MINSIZE + PPC_LR_STKOFF)(r1)
510 LOAD_REG_IMMEDIATE(r8, saved_stack) // save our stack pointer
513 addi r1, r1, -32768 /* - 32 KiB exception stack */
514 addis r1, r1, -1 /* - 64 KiB stack */
515 LOAD_REG_IMMEDIATE(r5, of_client_callback) // r5 = callback
516 li r6,0 // r6 = address of client program arguments (unused)
517 li r7,0 // r7 = length of client program arguments (unused)
518 li r0,MSR_FP | MSR_ME | MSR_DR | MSR_IR
524 LOAD_REG_IMMEDIATE(r0, MSR_SF | MSR_FP | MSR_ME | MSR_DR | MSR_IR)
527 LOAD_REG_IMMEDIATE(r8, saved_stack) // restore stack pointer
529 PPC_LL r0, (STACKFRAME_MINSIZE + PPC_LR_STKOFF)(r1)
531 addi r1, r1, STACKFRAME_MINSIZE
532 // XXX: should restore r12-r31 etc..
533 // we should not really come here though
537 #define STKOFF STACKFRAME_MINSIZE
538 #define SAVE_SPACE 320
541 #define SAVE_SPACE 144
543 GLOBL(of_client_callback):
546 PPC_STLU r1, -(STACKFRAME_MINSIZE + 16)(r1)
548 PPC_STLU r1, -STACKFRAME_MINSIZE(r1) /* fits within alignment */
553 PPC_STL r4, STKOFF(r1)
558 PPC_STL r4, PPC_LR_STKOFF(r1)
560 /* restore OF stack */
562 LOAD_REG_IMMEDIATE(r4, saved_stack)
565 PPC_STLU r4,-SAVE_SPACE(r4)
566 PPC_STL r1,(STKOFF)(r4) // save caller stack
569 PPC_STL r2, (STKOFF + 1 * ULONG_SIZE)(r1)
570 PPC_STL r0, (STKOFF + 2 * ULONG_SIZE)(r1)
572 /* save ctr, cr and xer */
575 PPC_STL r2, (STKOFF + 3 * ULONG_SIZE)(r1)
577 PPC_STL r2, (STKOFF + 4 * ULONG_SIZE)(r1)
579 PPC_STL r2, (STKOFF + 5 * ULONG_SIZE)(r1)
583 PPC_STL r5, (STKOFF + 6 * ULONG_SIZE)(r1)
584 PPC_STL r6, (STKOFF + 7 * ULONG_SIZE)(r1)
585 PPC_STL r7, (STKOFF + 8 * ULONG_SIZE)(r1)
586 PPC_STL r8, (STKOFF + 9 * ULONG_SIZE)(r1)
587 PPC_STL r9, (STKOFF + 10 * ULONG_SIZE)(r1)
588 PPC_STL r10, (STKOFF + 11 * ULONG_SIZE)(r1)
589 PPC_STL r11, (STKOFF + 12 * ULONG_SIZE)(r1)
590 PPC_STL r12, (STKOFF + 13 * ULONG_SIZE)(r1)
591 PPC_STL r13, (STKOFF + 14 * ULONG_SIZE)(r1)
592 PPC_STL r14, (STKOFF + 15 * ULONG_SIZE)(r1)
593 PPC_STL r15, (STKOFF + 16 * ULONG_SIZE)(r1)
594 PPC_STL r16, (STKOFF + 17 * ULONG_SIZE)(r1)
595 PPC_STL r17, (STKOFF + 18 * ULONG_SIZE)(r1)
596 PPC_STL r18, (STKOFF + 19 * ULONG_SIZE)(r1)
597 PPC_STL r19, (STKOFF + 20 * ULONG_SIZE)(r1)
598 PPC_STL r20, (STKOFF + 21 * ULONG_SIZE)(r1)
599 PPC_STL r21, (STKOFF + 22 * ULONG_SIZE)(r1)
600 PPC_STL r22, (STKOFF + 23 * ULONG_SIZE)(r1)
601 PPC_STL r23, (STKOFF + 24 * ULONG_SIZE)(r1)
602 PPC_STL r24, (STKOFF + 25 * ULONG_SIZE)(r1)
603 PPC_STL r25, (STKOFF + 26 * ULONG_SIZE)(r1)
604 PPC_STL r26, (STKOFF + 27 * ULONG_SIZE)(r1)
605 PPC_STL r27, (STKOFF + 28 * ULONG_SIZE)(r1)
606 PPC_STL r28, (STKOFF + 29 * ULONG_SIZE)(r1)
607 PPC_STL r29, (STKOFF + 30 * ULONG_SIZE)(r1)
608 PPC_STL r30, (STKOFF + 31 * ULONG_SIZE)(r1)
609 PPC_STL r31, (STKOFF + 32 * ULONG_SIZE)(r1)
612 LOAD_REG_IMMEDIATE(r2, of_client_interface)
615 bl BRANCH_LABEL(of_client_interface)
617 /* restore r5 - r31 */
619 PPC_LL r5, (STKOFF + 6 * ULONG_SIZE)(r1)
620 PPC_LL r6, (STKOFF + 7 * ULONG_SIZE)(r1)
621 PPC_LL r7, (STKOFF + 8 * ULONG_SIZE)(r1)
622 PPC_LL r8, (STKOFF + 9 * ULONG_SIZE)(r1)
623 PPC_LL r9, (STKOFF + 10 * ULONG_SIZE)(r1)
624 PPC_LL r10, (STKOFF + 11 * ULONG_SIZE)(r1)
625 PPC_LL r11, (STKOFF + 12 * ULONG_SIZE)(r1)
626 PPC_LL r12, (STKOFF + 13 * ULONG_SIZE)(r1)
627 PPC_LL r13, (STKOFF + 14 * ULONG_SIZE)(r1)
628 PPC_LL r14, (STKOFF + 15 * ULONG_SIZE)(r1)
629 PPC_LL r15, (STKOFF + 16 * ULONG_SIZE)(r1)
630 PPC_LL r16, (STKOFF + 17 * ULONG_SIZE)(r1)
631 PPC_LL r17, (STKOFF + 18 * ULONG_SIZE)(r1)
632 PPC_LL r18, (STKOFF + 19 * ULONG_SIZE)(r1)
633 PPC_LL r19, (STKOFF + 20 * ULONG_SIZE)(r1)
634 PPC_LL r20, (STKOFF + 21 * ULONG_SIZE)(r1)
635 PPC_LL r21, (STKOFF + 22 * ULONG_SIZE)(r1)
636 PPC_LL r22, (STKOFF + 23 * ULONG_SIZE)(r1)
637 PPC_LL r23, (STKOFF + 24 * ULONG_SIZE)(r1)
638 PPC_LL r24, (STKOFF + 25 * ULONG_SIZE)(r1)
639 PPC_LL r25, (STKOFF + 26 * ULONG_SIZE)(r1)
640 PPC_LL r26, (STKOFF + 27 * ULONG_SIZE)(r1)
641 PPC_LL r27, (STKOFF + 28 * ULONG_SIZE)(r1)
642 PPC_LL r28, (STKOFF + 29 * ULONG_SIZE)(r1)
643 PPC_LL r29, (STKOFF + 30 * ULONG_SIZE)(r1)
644 PPC_LL r30, (STKOFF + 31 * ULONG_SIZE)(r1)
645 PPC_LL r31, (STKOFF + 32 * ULONG_SIZE)(r1)
647 /* restore ctr, cr and xer */
649 PPC_LL r2, (STKOFF + 3 * ULONG_SIZE)(r1)
651 PPC_LL r2, (STKOFF + 4 * ULONG_SIZE)(r1)
653 PPC_LL r2, (STKOFF + 5 * ULONG_SIZE)(r1)
656 /* restore r0 and r2 */
658 PPC_LL r2, (STKOFF + 1 * ULONG_SIZE)(r1)
659 PPC_LL r0, (STKOFF + 2 * ULONG_SIZE)(r1)
661 /* restore caller stack */
663 PPC_LL r1, (STKOFF)(r1)
665 PPC_LL r4, PPC_LR_STKOFF(r1)
667 PPC_LL r4, STKOFF(r1)
672 /* rtas glue (must be reloctable) */
673 GLOBL(of_rtas_start):
674 /* r3 = argument buffer, r4 = of_rtas_start */
675 /* according to the CHRP standard, cr must be preserved (cr0/cr1 too?) */
680 #define CACHE_LINE_SIZE 32
681 #define LG_CACHE_LINE_SIZE 5
683 /* flush_icache_range( unsigned long start, unsigned long stop) */
684 _GLOBAL(flush_icache_range):
685 li r5,CACHE_LINE_SIZE-1
689 srwi. r4,r4,LG_CACHE_LINE_SIZE
694 addi r3,r3,CACHE_LINE_SIZE
696 sync /* wait for dcbst's to get to ram */
699 addi r6,r6,CACHE_LINE_SIZE
701 sync /* additional sync needed on g4 */
705 /* Get RAM size from QEMU configuration device */
707 #define CFG_ADDR 0xf0000510
708 #define FW_CFG_RAM_SIZE 0x03
711 LOAD_REG_IMMEDIATE(r9, CFG_ADDR)
712 li r0,FW_CFG_RAM_SIZE
714 LOAD_REG_IMMEDIATE(r9, CFG_ADDR + 2)
727 /* Hard reset vector */
728 .section .romentry,"ax"