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
17 #include "asm/asmdefs.h"
18 #include "asm/processor.h"
20 /************************************************************************/
22 /************************************************************************/
24 #define ILLEGAL_VECTOR( v ) .org __vectors + v ; bl trap_error ;
25 #define VECTOR( v, dummystr ) .org __vectors + v ; vector__##v
27 /* We're trying to use the same code for the ppc32 and ppc64 handlers here.
28 * On ppc32 we only save/restore the registers, C considers volatile.
30 * On ppc64 on the other hand, we have to save/restore all registers, because
31 * all OF code is 32 bits, which only saves/restores the low 32 bits of the
32 * registers it clobbers.
35 #define EXCEPTION_PREAMBLE_TEMPLATE \
36 mtsprg1 r1 ; /* scratch */ \
37 mfmsr r1 ; /* unset MSR_SF */ \
40 mfsprg0 r1 ; /* exception stack in sprg0 */ \
41 .ifc ULONG_SIZE, 8 ; \
42 addi r1,r1,-(40 * ULONG_SIZE) ; /* push exception frame */ \
44 addi r1,r1,-(20 * ULONG_SIZE) ; /* push exception frame */ \
47 stl r0,(0 * ULONG_SIZE)(r1) ; /* save r0 */ \
49 stl r0,(1 * ULONG_SIZE)(r1) ; /* save r1 */ \
50 stl r2,(2 * ULONG_SIZE)(r1) ; /* save r2 */ \
51 stl r3,(3 * ULONG_SIZE)(r1) ; /* save r3 */ \
52 stl r4,(4 * ULONG_SIZE)(r1) ; \
53 stl r5,(5 * ULONG_SIZE)(r1) ; \
54 stl r6,(6 * ULONG_SIZE)(r1) ; \
55 stl r7,(7 * ULONG_SIZE)(r1) ; \
56 stl r8,(8 * ULONG_SIZE)(r1) ; \
57 stl r9,(9 * ULONG_SIZE)(r1) ; \
58 stl r10,(10 * ULONG_SIZE)(r1) ; \
59 stl r11,(11 * ULONG_SIZE)(r1) ; \
60 stl r12,(12 * ULONG_SIZE)(r1) ; \
61 .ifc ULONG_SIZE, 8 ; \
62 stl r13,(17 * ULONG_SIZE)(r1) ; \
63 stl r14,(18 * ULONG_SIZE)(r1) ; \
64 stl r15,(19 * ULONG_SIZE)(r1) ; \
65 stl r16,(20 * ULONG_SIZE)(r1) ; \
66 stl r17,(21 * ULONG_SIZE)(r1) ; \
67 stl r18,(22 * ULONG_SIZE)(r1) ; \
68 stl r19,(23 * ULONG_SIZE)(r1) ; \
69 stl r20,(24 * ULONG_SIZE)(r1) ; \
70 stl r21,(25 * ULONG_SIZE)(r1) ; \
71 stl r22,(26 * ULONG_SIZE)(r1) ; \
72 stl r23,(27 * ULONG_SIZE)(r1) ; \
73 stl r24,(28 * ULONG_SIZE)(r1) ; \
74 stl r25,(29 * ULONG_SIZE)(r1) ; \
75 stl r26,(30 * ULONG_SIZE)(r1) ; \
76 stl r27,(31 * ULONG_SIZE)(r1) ; \
77 stl r28,(32 * ULONG_SIZE)(r1) ; \
78 stl r29,(33 * ULONG_SIZE)(r1) ; \
79 stl r30,(34 * ULONG_SIZE)(r1) ; \
80 stl r31,(35 * ULONG_SIZE)(r1) ; \
84 stl r0,(13 * ULONG_SIZE)(r1) ; \
86 stl r0,(14 * ULONG_SIZE)(r1) ; \
88 stl r0,(15 * ULONG_SIZE)(r1) ; \
90 stl r0,(16 * ULONG_SIZE)(r1) ; \
93 addi r1,r1,-16 ; /* C ABI uses 0(r1) and 4(r1)... */
95 #define EXCEPTION_EPILOGUE_TEMPLATE \
96 addi r1,r1,16 ; /* pop ABI frame */ \
98 ll r0,(13 * ULONG_SIZE)(r1) ; \
100 ll r0,(14 * ULONG_SIZE)(r1) ; \
102 ll r0,(15 * ULONG_SIZE)(r1) ; \
104 ll r0,(16 * ULONG_SIZE)(r1) ; \
107 ll r0,(0 * ULONG_SIZE)(r1) ; \
108 ll r2,(2 * ULONG_SIZE)(r1) ; \
109 ll r3,(3 * ULONG_SIZE)(r1) ; \
110 ll r4,(4 * ULONG_SIZE)(r1) ; \
111 ll r5,(5 * ULONG_SIZE)(r1) ; \
112 ll r6,(6 * ULONG_SIZE)(r1) ; \
113 ll r7,(7 * ULONG_SIZE)(r1) ; \
114 ll r8,(8 * ULONG_SIZE)(r1) ; \
115 ll r9,(9 * ULONG_SIZE)(r1) ; \
116 ll r10,(10 * ULONG_SIZE)(r1) ; \
117 ll r11,(11 * ULONG_SIZE)(r1) ; \
118 ll r12,(12 * ULONG_SIZE)(r1) ; \
119 .ifc ULONG_SIZE, 8 ; \
120 ll r13,(17 * ULONG_SIZE)(r1) ; \
121 ll r14,(18 * ULONG_SIZE)(r1) ; \
122 ll r15,(19 * ULONG_SIZE)(r1) ; \
123 ll r16,(20 * ULONG_SIZE)(r1) ; \
124 ll r17,(21 * ULONG_SIZE)(r1) ; \
125 ll r18,(22 * ULONG_SIZE)(r1) ; \
126 ll r19,(23 * ULONG_SIZE)(r1) ; \
127 ll r20,(24 * ULONG_SIZE)(r1) ; \
128 ll r21,(25 * ULONG_SIZE)(r1) ; \
129 ll r22,(26 * ULONG_SIZE)(r1) ; \
130 ll r23,(27 * ULONG_SIZE)(r1) ; \
131 ll r24,(28 * ULONG_SIZE)(r1) ; \
132 ll r25,(29 * ULONG_SIZE)(r1) ; \
133 ll r26,(30 * ULONG_SIZE)(r1) ; \
134 ll r27,(31 * ULONG_SIZE)(r1) ; \
135 ll r28,(32 * ULONG_SIZE)(r1) ; \
136 ll r29,(33 * ULONG_SIZE)(r1) ; \
137 ll r30,(34 * ULONG_SIZE)(r1) ; \
138 ll r31,(35 * ULONG_SIZE)(r1) ; \
140 ll r1,(1 * ULONG_SIZE)(r1) ; /* restore stack at last */ \
149 .macro EXCEPTION_PREAMBLE
150 EXCEPTION_PREAMBLE_TEMPLATE
153 .macro EXCEPTION_EPILOGUE
154 EXCEPTION_EPILOGUE_TEMPLATE
167 .macro EXCEPTION_PREAMBLE_64
168 EXCEPTION_PREAMBLE_TEMPLATE
171 .macro EXCEPTION_EPILOGUE_64
172 EXCEPTION_EPILOGUE_TEMPLATE
179 /************************************************************************/
181 /************************************************************************/
183 .section .text.vectors, "ax"
192 .globl __divide_error
198 VECTOR( 0x100, "SRE" ):
201 ILLEGAL_VECTOR( 0x200 )
203 VECTOR( 0x300, "DSI" ):
205 lis r3,HA(dsi_exception)
206 addi r3,r3,LO(dsi_exception)
211 VECTOR( 0x400, "ISI" ):
213 lis r3,HA(isi_exception)
214 addi r3,r3,LO(isi_exception)
219 ILLEGAL_VECTOR( 0x500 )
220 ILLEGAL_VECTOR( 0x600 )
221 ILLEGAL_VECTOR( 0x700 )
223 VECTOR( 0x800, "FPU" ):
231 ILLEGAL_VECTOR( 0x900 )
232 ILLEGAL_VECTOR( 0xa00 )
233 ILLEGAL_VECTOR( 0xb00 )
234 ILLEGAL_VECTOR( 0xc00 )
235 ILLEGAL_VECTOR( 0xd00 )
236 ILLEGAL_VECTOR( 0xe00 )
237 ILLEGAL_VECTOR( 0xf00 )
238 ILLEGAL_VECTOR( 0xf20 )
239 ILLEGAL_VECTOR( 0x1000 )
240 ILLEGAL_VECTOR( 0x1100 )
241 ILLEGAL_VECTOR( 0x1200 )
242 ILLEGAL_VECTOR( 0x1300 )
243 ILLEGAL_VECTOR( 0x1400 )
244 ILLEGAL_VECTOR( 0x1500 )
245 ILLEGAL_VECTOR( 0x1600 )
246 ILLEGAL_VECTOR( 0x1700 )
248 VECTOR( 0x2000, "DSI_64" ):
249 EXCEPTION_PREAMBLE_64
250 lis r3,HA(dsi_exception)
251 addi r3,r3,LO(dsi_exception)
254 EXCEPTION_EPILOGUE_64
256 VECTOR( 0x2200, "ISI_64" ):
257 EXCEPTION_PREAMBLE_64
258 lis r3,HA(isi_exception)
259 addi r3,r3,LO(isi_exception)
262 EXCEPTION_EPILOGUE_64
264 GLOBL(__vectors_end):
266 /************************************************************************/
268 /************************************************************************/
271 /* clear MSR, disable MMU */
276 /* copy exception vectors */
279 addi r3,r3,LO(__vectors)
281 li r5,__vectors_end - __vectors + 16
306 * Top +-------------------------+
308 * | ROM into RAM (1 MB) |
310 * +-------------------------+
312 * | MMU Hash Table (64 kB) |
314 * +-------------------------+
316 * | Exception Stack (32 kB) |
318 * +-------------------------+
322 * +-------------------------+
324 * | Client Stack (64 kB) |
326 * +-------------------------+
328 * | Malloc Zone (2 MiB) |
330 * +-------------------------+
335 addis r1, r3, -16 /* ramsize - 1MB */
337 /* setup hash table */
339 addis r1, r1, -1 /* - 64 kB */
340 clrrwi r1, r1, 5*4 /* & ~0xfffff */
342 /* setup exception stack */
348 addi r1, r1, -32768 /* - 32 kB */
350 /* save memory size in stack */
358 /* According to IEEE 1275, PPC bindings:
360 * MSR = FP, ME + (DR|IR)
361 * r1 = stack (32 K + 32 bytes link area above)
362 * r5 = client interface handler
363 * r6 = address of client program arguments (unused)
364 * r7 = length of client program arguments (unused)
366 * Yaboot and Linux use r3 and r4 for initrd address and size
372 /* void call_elf( arg1, arg2, entry ) */
378 lis r8,HA(saved_stack)
379 addi r8,r8,LO(saved_stack) // save our stack pointer
382 addi r1, r1, -32768 /* - 32 KiB exception stack */
383 addis r1, r1, -1 /* - 64 KiB stack */
384 lis r5,HA(of_client_callback)
385 addi r5,r5,LO(of_client_callback) // r5 = callback
386 li r6,0 // r6 = address of client program arguments (unused)
387 li r7,0 // r7 = length of client program arguments (unused)
388 li r0,MSR_FP | MSR_ME | MSR_DR | MSR_IR
392 lis r8,HA(saved_stack)
393 addi r8,r8,LO(saved_stack) // restore stack pointer
398 // XXX: should restore r12-r31 etc..
399 // we should not really come here though
402 #define SAVE_SPACE 140
403 GLOBL(of_client_callback):
416 /* restore OF stack */
418 lis r4,HA(saved_stack)
419 addi r4,r4,LO(saved_stack)
422 stwu r4,-SAVE_SPACE(r4)
423 stw r1,8(r4) // save caller stack
429 /* save ctr, cr and xer */
468 bl of_client_interface
470 /* restore r5 - r31 */
500 /* restore ctr, cr and xer */
509 /* restore r0 and r2 */
514 /* restore caller stack */
525 /* rtas glue (must be reloctable) */
526 GLOBL(of_rtas_start):
527 /* r3 = argument buffer, r4 = of_rtas_start */
528 /* according to the CHRP standard, cr must be preserved (cr0/cr1 too?) */
533 #define CACHE_LINE_SIZE 32
534 #define LG_CACHE_LINE_SIZE 5
536 /* flush_icache_range( unsigned long start, unsigned long stop) */
537 GLOBL(flush_icache_range):
538 li r5,CACHE_LINE_SIZE-1
542 srwi. r4,r4,LG_CACHE_LINE_SIZE
547 addi r3,r3,CACHE_LINE_SIZE
549 sync /* wait for dcbst's to get to ram */
552 addi r6,r6,CACHE_LINE_SIZE
554 sync /* additional sync needed on g4 */
558 /* Get RAM size from Qemu configuration device */
560 #define CFG_ADDR 0xf0000510
561 #define FW_CFG_RAM_SIZE 0x03
565 ori r9,r9,LO(CFG_ADDR)
566 li r0,FW_CFG_RAM_SIZE
568 lis r9,HA(CFG_ADDR + 2)
569 ori r9,r9,LO(CFG_ADDR + 2)
582 /* Hard reset vector */
583 .section .romentry,"ax"