ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/ppc_asm.S
Revision: 1.8
Committed: 2005-06-28T16:50:30Z (19 years, 4 months ago) by gbeauche
Branch: MAIN
Changes since 1.7: +0 -1 lines
Log Message:
Clean-ups: comments, ticks per sec output, don't restore r13 twice.

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * asm_linux.S - Assembly routines
3     *
4     * SheepShaver (C) 1997-2005 Christian Bauer and Marc Hellwig
5     *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #include <ppc_asm.tmpl>
22     #include <xlowmem.h>
23    
24     #define SAVE_FP_EXEC_68K 1
25    
26    
27     /*
28 gbeauche 1.2 * void *get_sp(void) - Get stack pointer
29 gbeauche 1.1 */
30    
31 gbeauche 1.2 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_sp)
32     C_SYMBOL_NAME(get_sp):
33     mr r3,r1
34 gbeauche 1.1 blr
35    
36    
37     /*
38 gbeauche 1.2 * void *get_r2(void) - Get r2
39 gbeauche 1.1 */
40    
41 gbeauche 1.2 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_r2)
42     C_SYMBOL_NAME(get_r2):
43     mr r3,r2
44 gbeauche 1.1 blr
45    
46    
47     /*
48 gbeauche 1.2 * void set_r2(void *val {r3}) - Set r2
49 gbeauche 1.1 */
50    
51     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(set_r2)
52     C_SYMBOL_NAME(set_r2):
53     mr r2,r3
54     blr
55    
56    
57     /*
58 gbeauche 1.2 * void *get_r13(void) - Get r13 (small data pointer under Linux)
59     */
60    
61     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_r13)
62     C_SYMBOL_NAME(get_r13):
63     mr r3,r13
64     blr
65    
66     /*
67     * void set_r13(void *val {r3}) - Set r13 (small data pointer under Linux)
68     */
69    
70     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(set_r13)
71     C_SYMBOL_NAME(set_r13):
72     mr r13,r3
73     blr
74    
75    
76     /*
77 gbeauche 1.1 * void flush_icache_range(void *start {r3}, void *end {r3}) - Flush D and I cache
78     */
79    
80     CACHE_LINE_SIZE = 32
81     LG_CACHE_LINE_SIZE = 5
82    
83     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(flush_icache_range)
84     C_SYMBOL_NAME(flush_icache_range):
85     li r5,CACHE_LINE_SIZE-1
86     andc r3,r3,r5
87     subf r4,r3,r4
88     add r4,r4,r5
89     srwi. r4,r4,LG_CACHE_LINE_SIZE
90     beqlr
91     mtctr r4
92     mr r6,r3
93     1: dcbst 0,r3
94     addi r3,r3,CACHE_LINE_SIZE
95     bdnz 1b
96     sync /* wait for dcbst's to get to ram */
97     mtctr r4
98     2: icbi 0,r6
99     addi r6,r6,CACHE_LINE_SIZE
100     bdnz 2b
101     sync
102     isync
103     blr
104    
105    
106     /*
107     * long atomic_add(long *var{r3}, long add{r4}) - Atomic add operation
108     * long atomic_and(long *var{r3}, long and{r4}) - Atomic and operation
109     * long atomic_or(long *var{r3}, long or{r4}) - Atomic or operation
110     * int test_and_set(int *var{r3}, int val{r4}) - Atomic test-and-set
111     */
112    
113     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(atomic_add)
114     C_SYMBOL_NAME(atomic_add):
115     0: dcbf 0,r3
116     sync
117     ori r0,r0,1
118     ori r0,r0,1
119     ori r0,r0,1
120     ori r0,r0,1
121     ori r0,r0,1
122     ori r0,r0,1
123     isync
124     lwarx r5,0,r3
125     add r0,r4,r5
126     stwcx. r0,0,r3
127     bne- 0b
128     mr r3,r5
129     isync
130     blr
131    
132     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(atomic_and)
133     C_SYMBOL_NAME(atomic_and):
134     0: dcbf 0,r3
135     sync
136     ori r0,r0,1
137     ori r0,r0,1
138     ori r0,r0,1
139     ori r0,r0,1
140     ori r0,r0,1
141     ori r0,r0,1
142     isync
143     lwarx r5,0,r3
144     and r0,r4,r5
145     stwcx. r0,0,r3
146     bne- 0b
147     mr r3,r5
148     isync
149     blr
150    
151     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(atomic_or)
152     C_SYMBOL_NAME(atomic_or):
153     0: dcbf 0,r3
154     sync
155     ori r0,r0,1
156     ori r0,r0,1
157     ori r0,r0,1
158     ori r0,r0,1
159     ori r0,r0,1
160     ori r0,r0,1
161     isync
162     lwarx r5,0,r3
163     or r0,r4,r5
164     stwcx. r0,0,r3
165     bne- 0b
166     mr r3,r5
167     isync
168     blr
169    
170     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(test_and_set)
171     C_SYMBOL_NAME(test_and_set):
172     0: dcbf 0,r3
173     sync
174     ori r0,r0,1
175     ori r0,r0,1
176     ori r0,r0,1
177     ori r0,r0,1
178     ori r0,r0,1
179     ori r0,r0,1
180     isync
181     lwarx r5,0,r3
182     cmpi 0,r5,0x0000
183 gbeauche 1.6 bne 1f
184 gbeauche 1.1 stwcx. r4,0,r3
185     bne- 0b
186     1: isync
187     mr r3,r5
188     blr
189    
190    
191     /*
192     * void quit_emulator(void) - Jump to XLM_EMUL_RETURN_PROC
193     */
194    
195     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(quit_emulator)
196     C_SYMBOL_NAME(quit_emulator):
197     lwz r0,XLM_EMUL_RETURN_PROC(0)
198     mtlr r0
199     blr
200    
201    
202     /*
203     * void jump_to_rom(uint32 entry {r3}, uint32 emulator_data {r4}) - Jump to Mac ROM
204     */
205    
206     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(jump_to_rom)
207     C_SYMBOL_NAME(jump_to_rom):
208     // Create stack frame
209     mflr r0
210     stw r0,4(r1)
211     stwu r1,-(20+19*4+18*8)(r1) // maintain 16 byte alignment
212    
213     // Save PowerPC registers
214     stmw r13,20(r1)
215     stfd f14,20+19*4+0*8(r1)
216     stfd f15,20+19*4+1*8(r1)
217     stfd f16,20+19*4+2*8(r1)
218     stfd f17,20+19*4+3*8(r1)
219     stfd f18,20+19*4+4*8(r1)
220     stfd f19,20+19*4+5*8(r1)
221     stfd f20,20+19*4+6*8(r1)
222     stfd f21,20+19*4+7*8(r1)
223     stfd f22,20+19*4+8*8(r1)
224     stfd f23,20+19*4+9*8(r1)
225     stfd f24,20+19*4+10*8(r1)
226     stfd f25,20+19*4+11*8(r1)
227     stfd f26,20+19*4+12*8(r1)
228     stfd f27,20+19*4+13*8(r1)
229     stfd f28,20+19*4+14*8(r1)
230     stfd f29,20+19*4+15*8(r1)
231     stfd f30,20+19*4+16*8(r1)
232     stfd f31,20+19*4+17*8(r1)
233    
234     // Move entry address to ctr
235     mtctr r3
236    
237     // Skip over EMUL_RETURN routine and get its address
238     bl 1f
239    
240    
241     /*
242     * EMUL_RETURN: Returned from emulator
243     */
244    
245     // Restore PowerPC registers
246     lwz r1,XLM_EMUL_RETURN_STACK(0)
247 gbeauche 1.2 RESTORE_SYSTEM_R2
248 gbeauche 1.1 lmw r13,20(r1)
249     lfd f14,20+19*4+0*8(r1)
250     lfd f15,20+19*4+1*8(r1)
251     lfd f16,20+19*4+2*8(r1)
252     lfd f17,20+19*4+3*8(r1)
253     lfd f18,20+19*4+4*8(r1)
254     lfd f19,20+19*4+5*8(r1)
255     lfd f20,20+19*4+6*8(r1)
256     lfd f21,20+19*4+7*8(r1)
257     lfd f22,20+19*4+8*8(r1)
258     lfd f23,20+19*4+9*8(r1)
259     lfd f24,20+19*4+10*8(r1)
260     lfd f25,20+19*4+11*8(r1)
261     lfd f26,20+19*4+12*8(r1)
262     lfd f27,20+19*4+13*8(r1)
263     lfd f28,20+19*4+14*8(r1)
264     lfd f29,20+19*4+15*8(r1)
265     lfd f30,20+19*4+16*8(r1)
266     lfd f31,20+19*4+17*8(r1)
267    
268     // Exiting from 68k emulator
269     li r0,1
270     stw r0,XLM_IRQ_NEST(0)
271     li r0,MODE_NATIVE
272     stw r0,XLM_RUN_MODE(0)
273    
274     // Return to caller of jump_to_rom()
275     lwz r0,20+19*4+18*8+4(r1)
276     mtlr r0
277     addi r1,r1,20+19*4+18*8
278     blr
279    
280    
281     // Save address of EMUL_RETURN routine for 68k emulator patch
282     1: mflr r0
283     stw r0,XLM_EMUL_RETURN_PROC(0)
284    
285     // Skip over EXEC_RETURN routine and get its address
286     bl 2f
287    
288    
289     /*
290     * EXEC_RETURN: Returned from 68k routine executed with Execute68k()
291     */
292    
293     // Save r25 (contains current 68k interrupt level)
294     stw r25,XLM_68K_R25(0)
295    
296     // Reentering EMUL_OP mode
297     li r0,MODE_EMUL_OP
298     stw r0,XLM_RUN_MODE(0)
299    
300     // Save 68k registers
301     lwz r4,48(r1) // Pointer to M68kRegisters
302     stw r8,0*4(r4) // d[0]...d[7]
303     stw r9,1*4(r4)
304     stw r10,2*4(r4)
305     stw r11,3*4(r4)
306     stw r12,4*4(r4)
307     stw r13,5*4(r4)
308     stw r14,6*4(r4)
309     stw r15,7*4(r4)
310     stw r16,8*4(r4) // a[0]..a[6]
311     stw r17,9*4(r4)
312     stw r18,10*4(r4)
313     stw r19,11*4(r4)
314     stw r20,12*4(r4)
315     stw r21,13*4(r4)
316     stw r22,14*4(r4)
317    
318     // Restore PowerPC registers
319     lmw r13,56(r1)
320     #if SAVE_FP_EXEC_68K
321     lfd f14,56+19*4+0*8(r1)
322     lfd f15,56+19*4+1*8(r1)
323     lfd f16,56+19*4+2*8(r1)
324     lfd f17,56+19*4+3*8(r1)
325     lfd f18,56+19*4+4*8(r1)
326     lfd f19,56+19*4+5*8(r1)
327     lfd f20,56+19*4+6*8(r1)
328     lfd f21,56+19*4+7*8(r1)
329     lfd f22,56+19*4+8*8(r1)
330     lfd f23,56+19*4+9*8(r1)
331     lfd f24,56+19*4+10*8(r1)
332     lfd f25,56+19*4+11*8(r1)
333     lfd f26,56+19*4+12*8(r1)
334     lfd f27,56+19*4+13*8(r1)
335     lfd f28,56+19*4+14*8(r1)
336     lfd f29,56+19*4+15*8(r1)
337     lfd f30,56+19*4+16*8(r1)
338     lfd f31,56+19*4+17*8(r1)
339     #endif
340    
341     // Return to caller
342     lwz r0,52(r1)
343     mtcrf 0xff,r0
344     lwz r0,56+19*4+18*8+4(r1)
345     mtlr r0
346     addi r1,r1,56+19*4+18*8
347 gbeauche 1.4 RESTORE_SYSTEM_R2
348     RESTORE_SYSTEM_R13
349 gbeauche 1.1 blr
350    
351    
352     // Save address of EXEC_RETURN routine for 68k emulator patch
353     2: mflr r0
354     stw r0,XLM_EXEC_RETURN_PROC(0)
355    
356     // Skip over EMUL_BREAK/EMUL_OP routine and get its address
357     bl 3f
358    
359    
360     /*
361     * EMUL_BREAK/EMUL_OP: Execute native routine, selector in r5 (my own private mode switch)
362     *
363     * 68k registers are stored in a M68kRegisters struct on the stack
364     * which the native routine may read and modify
365     */
366    
367     // Save r25 (contains current 68k interrupt level)
368     stw r25,XLM_68K_R25(0)
369    
370     // Entering EMUL_OP mode within 68k emulator
371     li r0,MODE_EMUL_OP
372     stw r0,XLM_RUN_MODE(0)
373    
374     // Create PowerPC stack frame, reserve space for M68kRegisters
375     mr r3,r1
376     subi r1,r1,64 // Fake "caller" frame
377     rlwinm r1,r1,0,0,27 // Align stack
378    
379     mfcr r0
380     rlwinm r0,r0,0,11,8
381     stw r0,4(r1)
382     mfxer r0
383     stw r0,16(r1)
384     stw r2,12(r1)
385 gbeauche 1.4 stwu r1,-(56+16*4+15*8)(r1)
386 gbeauche 1.1
387     // Save 68k registers (M68kRegisters)
388 gbeauche 1.4 stw r8,56+0*4(r1) // d[0]..d[7]
389     stw r9,56+1*4(r1)
390     stw r10,56+2*4(r1)
391     stw r11,56+3*4(r1)
392     stw r12,56+4*4(r1)
393     stw r13,56+5*4(r1)
394     stw r14,56+6*4(r1)
395     stw r15,56+7*4(r1)
396     stw r16,56+8*4(r1) // a[0]..a[7]
397     stw r17,56+9*4(r1)
398     stw r18,56+10*4(r1)
399     stw r19,56+11*4(r1)
400     stw r20,56+12*4(r1)
401     stw r21,56+13*4(r1)
402     stw r22,56+14*4(r1)
403     stw r3,56+15*4(r1)
404     stfd f0,56+16*4+0*8(r1)
405     stfd f1,56+16*4+1*8(r1)
406     stfd f2,56+16*4+2*8(r1)
407     stfd f3,56+16*4+3*8(r1)
408     stfd f4,56+16*4+4*8(r1)
409     stfd f5,56+16*4+5*8(r1)
410     stfd f6,56+16*4+6*8(r1)
411     stfd f7,56+16*4+7*8(r1)
412 gbeauche 1.1 mffs f0
413 gbeauche 1.4 stfd f8,56+16*4+8*8(r1)
414     stfd f9,56+16*4+9*8(r1)
415     stfd f10,56+16*4+10*8(r1)
416     stfd f11,56+16*4+11*8(r1)
417     stfd f12,56+16*4+12*8(r1)
418     stfd f13,56+16*4+13*8(r1)
419     stfd f0,56+16*4+14*8(r1)
420 gbeauche 1.1
421     // Execute native routine
422 gbeauche 1.2 RESTORE_SYSTEM_R2
423     RESTORE_SYSTEM_R13
424 gbeauche 1.4 addi r3,r1,56
425 gbeauche 1.1 mr r4,r24
426     bl C_SYMBOL_NAME(EmulOp)
427    
428     // Restore 68k registers (M68kRegisters)
429 gbeauche 1.4 lwz r8,56+0*4(r1) // d[0]..d[7]
430     lwz r9,56+1*4(r1)
431     lwz r10,56+2*4(r1)
432     lwz r11,56+3*4(r1)
433     lwz r12,56+4*4(r1)
434     lwz r13,56+5*4(r1)
435     lwz r14,56+6*4(r1)
436     lwz r15,56+7*4(r1)
437     lwz r16,56+8*4(r1) // a[0]..a[7]
438     lwz r17,56+9*4(r1)
439     lwz r18,56+10*4(r1)
440     lwz r19,56+11*4(r1)
441     lwz r20,56+12*4(r1)
442     lwz r21,56+13*4(r1)
443     lwz r22,56+14*4(r1)
444     lwz r3,56+15*4(r1)
445     lfd f13,56+16*4+14*8(r1)
446     lfd f0,56+16*4+0*8(r1)
447     lfd f1,56+16*4+1*8(r1)
448     lfd f2,56+16*4+2*8(r1)
449     lfd f3,56+16*4+3*8(r1)
450     lfd f4,56+16*4+4*8(r1)
451     lfd f5,56+16*4+5*8(r1)
452     lfd f6,56+16*4+6*8(r1)
453     lfd f7,56+16*4+7*8(r1)
454 gbeauche 1.1 mtfsf 0xff,f13
455 gbeauche 1.4 lfd f8,56+16*4+8*8(r1)
456     lfd f9,56+16*4+9*8(r1)
457     lfd f10,56+16*4+10*8(r1)
458     lfd f11,56+16*4+11*8(r1)
459     lfd f12,56+16*4+12*8(r1)
460     lfd f13,56+16*4+13*8(r1)
461 gbeauche 1.1
462     // Delete PowerPC stack frame
463 gbeauche 1.4 lwz r2,56+16*4+15*8+12(r1)
464     lwz r0,56+16*4+15*8+16(r1)
465 gbeauche 1.1 mtxer r0
466 gbeauche 1.4 lwz r0,56+16*4+15*8+4(r1)
467 gbeauche 1.1 mtcrf 0xff,r0
468     mr r1,r3
469    
470     // Reentering 68k emulator
471     li r0,MODE_68K
472     stw r0,XLM_RUN_MODE(0)
473    
474     // Set r0 to 0 for 68k emulator
475     li r0,0
476    
477     // Execute next 68k opcode
478     rlwimi r29,r27,3,13,28
479     lhau r27,2(r24)
480     mtlr r29
481     blr
482    
483    
484     // Save address of EMUL_BREAK/EMUL_OP routine for 68k emulator patch
485     3: mflr r0
486     stw r0,XLM_EMUL_OP_PROC(0)
487    
488     // Save stack pointer for EMUL_RETURN
489     stw r1,XLM_EMUL_RETURN_STACK(0)
490    
491     // Preset registers for ROM boot routine
492     lis r3,0x40b0 // Pointer to ROM boot structure
493     ori r3,r3,0xd000
494    
495     // 68k emulator is now active
496     li r0,MODE_68K
497     stw r0,XLM_RUN_MODE(0)
498    
499     // Jump to ROM
500     bctr
501    
502    
503     /*
504     * void execute_68k(uint32 pc {r3}, M68kRegisters *r {r4}) - Execute 68k routine
505     */
506    
507     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(execute_68k)
508     C_SYMBOL_NAME(execute_68k):
509     // Create MacOS stack frame
510     mflr r0
511     stw r0,4(r1)
512     stwu r1,-(56+19*4+18*8)(r1)
513     mfcr r0
514     stw r4,48(r1) // save pointer to M68kRegisters for EXEC_RETURN
515     stw r0,52(r1) // save CR
516    
517     // Save PowerPC registers
518     stmw r13,56(r1)
519     #if SAVE_FP_EXEC_68K
520     stfd f14,56+19*4+0*8(r1)
521     stfd f15,56+19*4+1*8(r1)
522     stfd f16,56+19*4+2*8(r1)
523     stfd f17,56+19*4+3*8(r1)
524     stfd f18,56+19*4+4*8(r1)
525     stfd f19,56+19*4+5*8(r1)
526     stfd f20,56+19*4+6*8(r1)
527     stfd f21,56+19*4+7*8(r1)
528     stfd f22,56+19*4+8*8(r1)
529     stfd f23,56+19*4+9*8(r1)
530     stfd f24,56+19*4+10*8(r1)
531     stfd f25,56+19*4+11*8(r1)
532     stfd f26,56+19*4+12*8(r1)
533     stfd f27,56+19*4+13*8(r1)
534     stfd f28,56+19*4+14*8(r1)
535     stfd f29,56+19*4+15*8(r1)
536     stfd f30,56+19*4+16*8(r1)
537     stfd f31,56+19*4+17*8(r1)
538     #endif
539    
540     // Set up registers for 68k emulator
541     lwz r31,XLM_KERNEL_DATA(0) // Pointer to Kernel Data
542     addi r31,r31,0x1000
543     li r0,0
544     mtcrf 0xff,r0
545     creqv 11,11,11 // Supervisor mode
546     lwz r8,0*4(r4) // d[0]..d[7]
547     lwz r9,1*4(r4)
548     lwz r10,2*4(r4)
549     lwz r11,3*4(r4)
550     lwz r12,4*4(r4)
551     lwz r13,5*4(r4)
552     lwz r14,6*4(r4)
553     lwz r15,7*4(r4)
554     lwz r16,8*4(r4) // a[0]..a[6]
555     lwz r17,9*4(r4)
556     lwz r18,10*4(r4)
557     lwz r19,11*4(r4)
558     lwz r20,12*4(r4)
559     lwz r21,13*4(r4)
560     lwz r22,14*4(r4)
561     li r23,0
562     mr r24,r3
563     lwz r25,XLM_68K_R25(0) // MSB of SR
564     li r26,0
565     li r28,0 // VBR
566     lwz r29,0x74(r31) // Pointer to opcode table
567     lwz r30,0x78(r31) // Address of emulator
568    
569     // Push return address (points to EXEC_RETURN opcode) on stack
570     li r0,XLM_EXEC_RETURN_OPCODE
571     stwu r0,-4(r1)
572    
573     // Reentering 68k emulator
574     li r0,MODE_68K
575     stw r0,XLM_RUN_MODE(0)
576    
577     // Set r0 to 0 for 68k emulator
578     li r0,0
579    
580     // Execute 68k opcode
581     lha r27,0(r24)
582     rlwimi r29,r27,3,13,28
583     lhau r27,2(r24)
584     mtlr r29
585     blr
586    
587    
588     /*
589     * uint32 call_macos1(uint32 tvect{r3}, uint32 arg1{r4}) ... - Call MacOS routines
590     */
591    
592     ASM_MACRO_START prolog
593     mflr r0
594     stw r0,4(r1)
595     stwu r1,-64(r1)
596     ASM_MACRO_END
597    
598     ASM_MACRO_START epilog
599     lwz r0,64+4(r1)
600     mtlr r0
601     addi r1,r1,64
602 gbeauche 1.4 RESTORE_SYSTEM_R2
603     RESTORE_SYSTEM_R13
604 gbeauche 1.1 blr
605     ASM_MACRO_END
606    
607     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos)
608     C_SYMBOL_NAME(call_macos):
609     prolog
610     lwz r0,0(r3) // Get routine address
611     lwz r2,4(r3) // Load TOC pointer
612     mtctr r0
613     bctrl
614     epilog
615    
616     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos1)
617     C_SYMBOL_NAME(call_macos1):
618     prolog
619     lwz r0,0(r3) // Get routine address
620     lwz r2,4(r3) // Load TOC pointer
621     mtctr r0
622     mr r3,r4
623     bctrl
624     epilog
625    
626     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos2)
627     C_SYMBOL_NAME(call_macos2):
628     prolog
629     lwz r0,0(r3) // Get routine address
630     lwz r2,4(r3) // Load TOC pointer
631     mtctr r0
632     mr r3,r4
633     mr r4,r5
634     bctrl
635     epilog
636    
637     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos3)
638     C_SYMBOL_NAME(call_macos3):
639     prolog
640     lwz r0,0(r3) // Get routine address
641     lwz r2,4(r3) // Load TOC pointer
642     mtctr r0
643     mr r3,r4
644     mr r4,r5
645     mr r5,r6
646     bctrl
647     epilog
648    
649     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos4)
650     C_SYMBOL_NAME(call_macos4):
651     prolog
652     lwz r0,0(r3) // Get routine address
653     lwz r2,4(r3) // Load TOC pointer
654     mtctr r0
655     mr r3,r4
656     mr r4,r5
657     mr r5,r6
658     mr r6,r7
659     bctrl
660     epilog
661    
662     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos5)
663     C_SYMBOL_NAME(call_macos5):
664     prolog
665     lwz r0,0(r3) // Get routine address
666     lwz r2,4(r3) // Load TOC pointer
667     mtctr r0
668     mr r3,r4
669     mr r4,r5
670     mr r5,r6
671     mr r6,r7
672     mr r7,r8
673     bctrl
674     epilog
675    
676     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos6)
677     C_SYMBOL_NAME(call_macos6):
678     prolog
679     lwz r0,0(r3) // Get routine address
680     lwz r2,4(r3) // Load TOC pointer
681     mtctr r0
682     mr r3,r4
683     mr r4,r5
684     mr r5,r6
685     mr r6,r7
686     mr r7,r8
687     mr r8,r9
688     bctrl
689     epilog
690    
691     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos7)
692     C_SYMBOL_NAME(call_macos7):
693     prolog
694     lwz r0,0(r3) // Get routine address
695     lwz r2,4(r3) // Load TOC pointer
696     mtctr r0
697     mr r3,r4
698     mr r4,r5
699     mr r5,r6
700     mr r6,r7
701     mr r7,r8
702     mr r8,r9
703     mr r9,r10
704     bctrl
705     epilog
706    
707    
708     /*
709     * Native resource manager patches
710     */
711    
712 gbeauche 1.5 ASM_MACRO_START do_get_resource ASM_MACRO_ARG0_DEF
713 gbeauche 1.1 // Create stack frame
714     mflr r0
715     stw r0,8(r1)
716     stwu r1,-(56+12)(r1)
717    
718     // Save type/ID
719     stw r3,56(r1)
720     stw r4,56+4(r1)
721    
722     // Call old routine
723 gbeauche 1.5 lwz r0,ASM_MACRO_ARG0(0)
724 gbeauche 1.1 lwz r2,XLM_RES_LIB_TOC(0)
725     mtctr r0
726     bctrl
727     stw r3,56+8(r1) // Save handle
728    
729     // Call CheckLoad
730 gbeauche 1.4 RESTORE_SYSTEM_R2
731     RESTORE_SYSTEM_R13
732 gbeauche 1.1 lwz r3,56(r1)
733     lha r4,56+6(r1)
734     lwz r5,56+8(r1)
735     bl C_SYMBOL_NAME(check_load_invoc)
736     lwz r3,56+8(r1) // Restore handle
737    
738     // Return to caller
739     lwz r0,56+12+8(r1)
740     mtlr r0
741     addi r1,r1,56+12
742     blr
743 gbeauche 1.4 ASM_MACRO_END
744    
745     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_resource)
746     C_SYMBOL_NAME(get_resource):
747     do_get_resource XLM_GET_RESOURCE
748 gbeauche 1.1
749     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_resource)
750     C_SYMBOL_NAME(get_1_resource):
751 gbeauche 1.4 do_get_resource XLM_GET_1_RESOURCE
752 gbeauche 1.1
753     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_ind_resource)
754     C_SYMBOL_NAME(get_ind_resource):
755 gbeauche 1.4 do_get_resource XLM_GET_IND_RESOURCE
756 gbeauche 1.1
757     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_ind_resource)
758     C_SYMBOL_NAME(get_1_ind_resource):
759 gbeauche 1.4 do_get_resource XLM_GET_1_IND_RESOURCE
760 gbeauche 1.1
761     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(r_get_resource)
762     C_SYMBOL_NAME(r_get_resource):
763 gbeauche 1.4 do_get_resource XLM_R_GET_RESOURCE
764 gbeauche 1.1
765    
766     /*
767     * void ppc_interrupt(uint32 entry{r3}, uint32 kernel_data{r4}) - Execute PPC interrupt
768     */
769    
770     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(ppc_interrupt)
771     C_SYMBOL_NAME(ppc_interrupt):
772     mflr r0
773     stw r0,4(r1)
774     stwu r1,-64(r1)
775    
776     // Get address of return routine
777     bl 1f
778    
779     // Return routine
780     lwz r0,64+4(r1)
781     mtlr r0
782     addi r1,r1,64
783     blr
784    
785     // Prepare registers for nanokernel interrupt routine
786     1: mtctr r1
787     mr r1,r4
788     stw r6,0x018(r1)
789     mfctr r6
790     stw r6,0x004(r1)
791     lwz r6,0x65c(r1)
792     stw r7,0x13c(r6)
793     stw r8,0x144(r6)
794     stw r9,0x14c(r6)
795     stw r10,0x154(r6)
796     stw r11,0x15c(r6)
797     stw r12,0x164(r6)
798     stw r13,0x16c(r6)
799    
800     mflr r10
801     mfcr r13
802     lwz r7,0x660(r1)
803     mflr r12
804     rlwimi. r7,r7,8,0,0
805     li r11,0
806     ori r11,r11,0xf072 // MSR (SRR1)
807     mtcrf 0x70,r11
808     li r8,0
809    
810     // Enter nanokernel
811     mtlr r3
812     blr
813 gbeauche 1.7
814    
815     /*
816     * Define signal handlers with alternate stack initialization magic
817     */
818    
819     #define SIG_STACK_SIZE 0x10000
820    
821     ASM_MACRO_START do_define_signal_handler \
822     ASM_MACRO_ARG0_DEF /* name */ \
823     ASM_MACRO_ARG1_DEF /* stack */ \
824     ASM_MACRO_ARG2_DEF /* stack id */ \
825     ASM_MACRO_ARG3_DEF /* signal handler */
826    
827     // Alternate stack lower base for this signal handler
828     .lcomm ASM_MACRO_ARG1,SIG_STACK_SIZE,ASM_ALIGN_2(4)
829     ASM_TYPE(ASM_MACRO_ARG1,@object)
830    
831     // Represents the current nest level for this signal handler
832     // Note that in SheepShaver, SIGUSR2 signals are blocked while
833     // handling other signals so, it's unlikely we ever get a nest
834     // level greater than 1
835     .lcomm ASM_MACRO_ARG2,4,ASM_ALIGN_2(2)
836     ASM_TYPE(ASM_MACRO_ARG2,@object)
837    
838     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(ASM_MACRO_ARG0)
839     C_SYMBOL_NAME(ASM_MACRO_ARG0):
840     // Preserve args in scratch registers
841     mflr r14
842     mr r15,r3
843     mr r16,r4
844     mr r17,r5
845     mr r18,r1
846    
847     // Atomically increase stack_id
848     lis r19,ASM_HA16(ASM_MACRO_ARG2)
849     la r19,ASM_LO16(ASM_MACRO_ARG2,r19)
850     li r4,1
851     mr r3,r19
852     bl C_SYMBOL_NAME(atomic_add)
853     cmpwi r3,0
854     bne- 1f
855    
856     // ID was 0, we can use the local stack
857     lis r9,ASM_HA16(ASM_MACRO_ARG1)
858     lis r3,(SIG_STACK_SIZE>>16)
859     la r9,ASM_LO16(ASM_MACRO_ARG1,r9)
860     addi r3,r3,((SIG_STACK_SIZE&0xffff)-64)
861     add r1,r9,r3
862    
863     1: // Invoke signal handler
864     stwu r1,-16(r1)
865     mr r3,r15
866     mr r4,r16
867     mr r5,r17
868     bl C_SYMBOL_NAME(ASM_MACRO_ARG3)
869     addi r1,r1,16
870    
871     // Atomically decrease stack id
872     mr r3,r19
873     li r4,-1
874     bl C_SYMBOL_NAME(atomic_add)
875    
876     // Restore kernel stack and return
877     mtlr r14
878     mr r1,r18
879     blr
880     ASM_MACRO_END
881    
882     #define DEFINE_SIGNAL_HANDLER(NAME) \
883     do_define_signal_handler \
884     NAME##_handler_init ASM_MACRO_ARG_SEP \
885     NAME##_stack ASM_MACRO_ARG_SEP \
886     NAME##_stack_id ASM_MACRO_ARG_SEP \
887     NAME##_handler
888    
889     DEFINE_SIGNAL_HANDLER(sigusr2)