ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/ppc_asm.S
Revision: 1.2
Committed: 2005-02-27T21:52:06Z (19 years, 8 months ago) by gbeauche
Branch: MAIN
Changes since 1.1: +93 -11 lines
Log Message:
Fix native Linux/ppc with recent enough glibc that supports TLS; r2 is used
in that case. Tell me if I broke other arches, e.g. r13 is no longer saved
in Video and Ethernet stubs, though it seems to be OK.

Colateral feature: SheepShaver should now run on Linux/ppc64 with relevant
32-bit runtime. Native Linux/ppc64 support is harder as low mem globals are
32-bit in mind and e.g. the TLS register there is %r13, %r2 is the TOC
(PowerOpen/AIX ABI)

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     beq 1f
184     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     blr
348    
349    
350     // Save address of EXEC_RETURN routine for 68k emulator patch
351     2: mflr r0
352     stw r0,XLM_EXEC_RETURN_PROC(0)
353    
354     // Skip over EMUL_BREAK/EMUL_OP routine and get its address
355     bl 3f
356    
357    
358     /*
359     * EMUL_BREAK/EMUL_OP: Execute native routine, selector in r5 (my own private mode switch)
360     *
361     * 68k registers are stored in a M68kRegisters struct on the stack
362     * which the native routine may read and modify
363     */
364    
365     // Save r25 (contains current 68k interrupt level)
366     stw r25,XLM_68K_R25(0)
367    
368     // Entering EMUL_OP mode within 68k emulator
369     li r0,MODE_EMUL_OP
370     stw r0,XLM_RUN_MODE(0)
371    
372     // Create PowerPC stack frame, reserve space for M68kRegisters
373     mr r3,r1
374     subi r1,r1,64 // Fake "caller" frame
375     rlwinm r1,r1,0,0,27 // Align stack
376    
377     mfcr r0
378     rlwinm r0,r0,0,11,8
379     stw r0,4(r1)
380     mfxer r0
381     stw r0,16(r1)
382     stw r2,12(r1)
383     stwu r1,-(24+16*4+15*8)(r1)
384 gbeauche 1.2 RESTORE_SYSTEM_R2
385 gbeauche 1.1
386     // Save 68k registers (M68kRegisters)
387     stw r8,24+0*4(r1) // d[0]..d[7]
388     stw r9,24+1*4(r1)
389     stw r10,24+2*4(r1)
390     stw r11,24+3*4(r1)
391     stw r12,24+4*4(r1)
392     stw r13,24+5*4(r1)
393     stw r14,24+6*4(r1)
394     stw r15,24+7*4(r1)
395     stw r16,24+8*4(r1) // a[0]..a[7]
396     stw r17,24+9*4(r1)
397     stw r18,24+10*4(r1)
398     stw r19,24+11*4(r1)
399     stw r20,24+12*4(r1)
400     stw r21,24+13*4(r1)
401     stw r22,24+14*4(r1)
402     stw r3,24+15*4(r1)
403     stfd f0,24+16*4+0*8(r1)
404     stfd f1,24+16*4+1*8(r1)
405     stfd f2,24+16*4+2*8(r1)
406     stfd f3,24+16*4+3*8(r1)
407     stfd f4,24+16*4+4*8(r1)
408     stfd f5,24+16*4+5*8(r1)
409     stfd f6,24+16*4+6*8(r1)
410     stfd f7,24+16*4+7*8(r1)
411     mffs f0
412     stfd f8,24+16*4+8*8(r1)
413     stfd f9,24+16*4+9*8(r1)
414     stfd f10,24+16*4+10*8(r1)
415     stfd f11,24+16*4+11*8(r1)
416     stfd f12,24+16*4+12*8(r1)
417     stfd f13,24+16*4+13*8(r1)
418     stfd f0,24+16*4+14*8(r1)
419    
420     // Execute native routine
421 gbeauche 1.2 RESTORE_SYSTEM_R2
422     RESTORE_SYSTEM_R13
423 gbeauche 1.1 addi r3,r1,24
424     mr r4,r24
425     bl C_SYMBOL_NAME(EmulOp)
426    
427     // Restore 68k registers (M68kRegisters)
428     lwz r8,24+0*4(r1) // d[0]..d[7]
429     lwz r9,24+1*4(r1)
430     lwz r10,24+2*4(r1)
431     lwz r11,24+3*4(r1)
432     lwz r12,24+4*4(r1)
433     lwz r13,24+5*4(r1)
434     lwz r14,24+6*4(r1)
435     lwz r15,24+7*4(r1)
436     lwz r16,24+8*4(r1) // a[0]..a[7]
437     lwz r17,24+9*4(r1)
438     lwz r18,24+10*4(r1)
439     lwz r19,24+11*4(r1)
440     lwz r20,24+12*4(r1)
441     lwz r21,24+13*4(r1)
442     lwz r22,24+14*4(r1)
443     lwz r3,24+15*4(r1)
444     lfd f13,24+16*4+14*8(r1)
445     lfd f0,24+16*4+0*8(r1)
446     lfd f1,24+16*4+1*8(r1)
447     lfd f2,24+16*4+2*8(r1)
448     lfd f3,24+16*4+3*8(r1)
449     lfd f4,24+16*4+4*8(r1)
450     lfd f5,24+16*4+5*8(r1)
451     lfd f6,24+16*4+6*8(r1)
452     lfd f7,24+16*4+7*8(r1)
453     mtfsf 0xff,f13
454     lfd f8,24+16*4+8*8(r1)
455     lfd f9,24+16*4+9*8(r1)
456     lfd f10,24+16*4+10*8(r1)
457     lfd f11,24+16*4+11*8(r1)
458     lfd f12,24+16*4+12*8(r1)
459     lfd f13,24+16*4+13*8(r1)
460    
461     // Delete PowerPC stack frame
462     lwz r2,24+16*4+15*8+12(r1)
463     lwz r0,24+16*4+15*8+16(r1)
464     mtxer r0
465     lwz r0,24+16*4+15*8+4(r1)
466     mtcrf 0xff,r0
467     mr r1,r3
468    
469     // Reentering 68k emulator
470     li r0,MODE_68K
471     stw r0,XLM_RUN_MODE(0)
472    
473     // Set r0 to 0 for 68k emulator
474     li r0,0
475    
476     // Execute next 68k opcode
477     rlwimi r29,r27,3,13,28
478     lhau r27,2(r24)
479     mtlr r29
480     blr
481    
482    
483     // Save address of EMUL_BREAK/EMUL_OP routine for 68k emulator patch
484     3: mflr r0
485     stw r0,XLM_EMUL_OP_PROC(0)
486    
487     // Save stack pointer for EMUL_RETURN
488     stw r1,XLM_EMUL_RETURN_STACK(0)
489    
490     // Preset registers for ROM boot routine
491     lis r3,0x40b0 // Pointer to ROM boot structure
492     ori r3,r3,0xd000
493    
494     // 68k emulator is now active
495     li r0,MODE_68K
496     stw r0,XLM_RUN_MODE(0)
497    
498     // Jump to ROM
499     bctr
500    
501    
502     /*
503     * void execute_68k(uint32 pc {r3}, M68kRegisters *r {r4}) - Execute 68k routine
504     */
505    
506     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(execute_68k)
507     C_SYMBOL_NAME(execute_68k):
508     // Create MacOS stack frame
509     mflr r0
510     stw r0,4(r1)
511     stwu r1,-(56+19*4+18*8)(r1)
512     mfcr r0
513     stw r4,48(r1) // save pointer to M68kRegisters for EXEC_RETURN
514     stw r0,52(r1) // save CR
515    
516     // Save PowerPC registers
517     stmw r13,56(r1)
518     #if SAVE_FP_EXEC_68K
519     stfd f14,56+19*4+0*8(r1)
520     stfd f15,56+19*4+1*8(r1)
521     stfd f16,56+19*4+2*8(r1)
522     stfd f17,56+19*4+3*8(r1)
523     stfd f18,56+19*4+4*8(r1)
524     stfd f19,56+19*4+5*8(r1)
525     stfd f20,56+19*4+6*8(r1)
526     stfd f21,56+19*4+7*8(r1)
527     stfd f22,56+19*4+8*8(r1)
528     stfd f23,56+19*4+9*8(r1)
529     stfd f24,56+19*4+10*8(r1)
530     stfd f25,56+19*4+11*8(r1)
531     stfd f26,56+19*4+12*8(r1)
532     stfd f27,56+19*4+13*8(r1)
533     stfd f28,56+19*4+14*8(r1)
534     stfd f29,56+19*4+15*8(r1)
535     stfd f30,56+19*4+16*8(r1)
536     stfd f31,56+19*4+17*8(r1)
537     #endif
538    
539     // Set up registers for 68k emulator
540     lwz r31,XLM_KERNEL_DATA(0) // Pointer to Kernel Data
541     addi r31,r31,0x1000
542     li r0,0
543     mtcrf 0xff,r0
544     creqv 11,11,11 // Supervisor mode
545     lwz r8,0*4(r4) // d[0]..d[7]
546     lwz r9,1*4(r4)
547     lwz r10,2*4(r4)
548     lwz r11,3*4(r4)
549     lwz r12,4*4(r4)
550     lwz r13,5*4(r4)
551     lwz r14,6*4(r4)
552     lwz r15,7*4(r4)
553     lwz r16,8*4(r4) // a[0]..a[6]
554     lwz r17,9*4(r4)
555     lwz r18,10*4(r4)
556     lwz r19,11*4(r4)
557     lwz r20,12*4(r4)
558     lwz r21,13*4(r4)
559     lwz r22,14*4(r4)
560     li r23,0
561     mr r24,r3
562     lwz r25,XLM_68K_R25(0) // MSB of SR
563     li r26,0
564     li r28,0 // VBR
565     lwz r29,0x74(r31) // Pointer to opcode table
566     lwz r30,0x78(r31) // Address of emulator
567    
568     // Push return address (points to EXEC_RETURN opcode) on stack
569     li r0,XLM_EXEC_RETURN_OPCODE
570     stwu r0,-4(r1)
571    
572     // Reentering 68k emulator
573     li r0,MODE_68K
574     stw r0,XLM_RUN_MODE(0)
575    
576     // Set r0 to 0 for 68k emulator
577     li r0,0
578    
579     // Execute 68k opcode
580     lha r27,0(r24)
581     rlwimi r29,r27,3,13,28
582     lhau r27,2(r24)
583     mtlr r29
584     blr
585    
586    
587     /*
588     * uint32 call_macos1(uint32 tvect{r3}, uint32 arg1{r4}) ... - Call MacOS routines
589     */
590    
591     ASM_MACRO_START prolog
592     mflr r0
593     stw r0,4(r1)
594     stwu r1,-64(r1)
595     ASM_MACRO_END
596    
597     ASM_MACRO_START epilog
598 gbeauche 1.2 RESTORE_SYSTEM_R2
599     RESTORE_SYSTEM_R13
600 gbeauche 1.1 lwz r0,64+4(r1)
601     mtlr r0
602     addi r1,r1,64
603     blr
604     ASM_MACRO_END
605    
606     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos)
607     C_SYMBOL_NAME(call_macos):
608     prolog
609     lwz r0,0(r3) // Get routine address
610     lwz r2,4(r3) // Load TOC pointer
611     mtctr r0
612     bctrl
613     epilog
614    
615     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos1)
616     C_SYMBOL_NAME(call_macos1):
617     prolog
618     lwz r0,0(r3) // Get routine address
619     lwz r2,4(r3) // Load TOC pointer
620     mtctr r0
621     mr r3,r4
622     bctrl
623     epilog
624    
625     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos2)
626     C_SYMBOL_NAME(call_macos2):
627     prolog
628     lwz r0,0(r3) // Get routine address
629     lwz r2,4(r3) // Load TOC pointer
630     mtctr r0
631     mr r3,r4
632     mr r4,r5
633     bctrl
634     epilog
635    
636     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos3)
637     C_SYMBOL_NAME(call_macos3):
638     prolog
639     lwz r0,0(r3) // Get routine address
640     lwz r2,4(r3) // Load TOC pointer
641     mtctr r0
642     mr r3,r4
643     mr r4,r5
644     mr r5,r6
645     bctrl
646     epilog
647    
648     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos4)
649     C_SYMBOL_NAME(call_macos4):
650     prolog
651     lwz r0,0(r3) // Get routine address
652     lwz r2,4(r3) // Load TOC pointer
653     mtctr r0
654     mr r3,r4
655     mr r4,r5
656     mr r5,r6
657     mr r6,r7
658     bctrl
659     epilog
660    
661     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos5)
662     C_SYMBOL_NAME(call_macos5):
663     prolog
664     lwz r0,0(r3) // Get routine address
665     lwz r2,4(r3) // Load TOC pointer
666     mtctr r0
667     mr r3,r4
668     mr r4,r5
669     mr r5,r6
670     mr r6,r7
671     mr r7,r8
672     bctrl
673     epilog
674    
675     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos6)
676     C_SYMBOL_NAME(call_macos6):
677     prolog
678     lwz r0,0(r3) // Get routine address
679     lwz r2,4(r3) // Load TOC pointer
680     mtctr r0
681     mr r3,r4
682     mr r4,r5
683     mr r5,r6
684     mr r6,r7
685     mr r7,r8
686     mr r8,r9
687     bctrl
688     epilog
689    
690     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos7)
691     C_SYMBOL_NAME(call_macos7):
692     prolog
693     lwz r0,0(r3) // Get routine address
694     lwz r2,4(r3) // Load TOC pointer
695     mtctr r0
696     mr r3,r4
697     mr r4,r5
698     mr r5,r6
699     mr r6,r7
700     mr r7,r8
701     mr r8,r9
702     mr r9,r10
703     bctrl
704     epilog
705    
706    
707     /*
708     * Native resource manager patches
709     */
710    
711     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_resource)
712     C_SYMBOL_NAME(get_resource):
713     // 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     lwz r0,XLM_GET_RESOURCE(0)
724     lwz r2,XLM_RES_LIB_TOC(0)
725     mtctr r0
726     bctrl
727 gbeauche 1.2 RESTORE_SYSTEM_R2
728 gbeauche 1.1 stw r3,56+8(r1) // Save handle
729    
730     // Call CheckLoad
731     lwz r3,56(r1)
732     lha r4,56+6(r1)
733     lwz r5,56+8(r1)
734     bl C_SYMBOL_NAME(check_load_invoc)
735     lwz r3,56+8(r1) // Restore handle
736    
737     // Return to caller
738     lwz r0,56+12+8(r1)
739     mtlr r0
740     addi r1,r1,56+12
741     blr
742    
743     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_resource)
744     C_SYMBOL_NAME(get_1_resource):
745     // Create stack frame
746     mflr r0
747     stw r0,8(r1)
748     stwu r1,-(56+12)(r1)
749    
750     // Save type/ID
751     stw r3,56(r1)
752     stw r4,56+4(r1)
753    
754     // Call old routine
755     lwz r0,XLM_GET_1_RESOURCE(0)
756     lwz r2,XLM_RES_LIB_TOC(0)
757     mtctr r0
758     bctrl
759 gbeauche 1.2 RESTORE_SYSTEM_R2
760 gbeauche 1.1 stw r3,56+8(r1) // Save handle
761    
762     // Call CheckLoad
763     lwz r3,56(r1)
764     lha r4,56+6(r1)
765     lwz r5,56+8(r1)
766     bl C_SYMBOL_NAME(check_load_invoc)
767     lwz r3,56+8(r1) // Restore handle
768    
769     // Return to caller
770     lwz r0,56+12+8(r1)
771     mtlr r0
772     addi r1,r1,56+12
773     blr
774    
775     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_ind_resource)
776     C_SYMBOL_NAME(get_ind_resource):
777     // Create stack frame
778     mflr r0
779     stw r0,8(r1)
780     stwu r1,-(56+12)(r1)
781    
782     // Save type/index
783     stw r3,56(r1)
784     stw r4,56+4(r1)
785    
786     // Call old routine
787     lwz r0,XLM_GET_IND_RESOURCE(0)
788     lwz r2,XLM_RES_LIB_TOC(0)
789     mtctr r0
790     bctrl
791 gbeauche 1.2 RESTORE_SYSTEM_R2
792 gbeauche 1.1 stw r3,56+8(r1) // Save handle
793    
794     // Call CheckLoad
795     lwz r3,56(r1)
796     lha r4,56+6(r1)
797     lwz r5,56+8(r1)
798     bl C_SYMBOL_NAME(check_load_invoc)
799     lwz r3,56+8(r1) // Restore handle
800    
801     // Return to caller
802     lwz r0,56+12+8(r1)
803     mtlr r0
804     addi r1,r1,56+12
805     blr
806    
807     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_ind_resource)
808     C_SYMBOL_NAME(get_1_ind_resource):
809     // Create stack frame
810     mflr r0
811     stw r0,8(r1)
812     stwu r1,-(56+12)(r1)
813    
814     // Save type/index
815     stw r3,56(r1)
816     stw r4,56+4(r1)
817    
818     // Call old routine
819     lwz r0,XLM_GET_1_IND_RESOURCE(0)
820     lwz r2,XLM_RES_LIB_TOC(0)
821     mtctr r0
822     bctrl
823 gbeauche 1.2 RESTORE_SYSTEM_R2
824 gbeauche 1.1 stw r3,56+8(r1) // Save handle
825    
826     // Call CheckLoad
827     lwz r3,56(r1)
828     lha r4,56+6(r1)
829     lwz r5,56+8(r1)
830     bl C_SYMBOL_NAME(check_load_invoc)
831     lwz r3,56+8(r1) // Restore handle
832    
833     // Return to caller
834     lwz r0,56+12+8(r1)
835     mtlr r0
836     addi r1,r1,56+12
837     blr
838    
839     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(r_get_resource)
840     C_SYMBOL_NAME(r_get_resource):
841     // Create stack frame
842     mflr r0
843     stw r0,8(r1)
844     stwu r1,-(56+12)(r1)
845    
846     // Save type/ID
847     stw r3,56(r1)
848     stw r4,56+4(r1)
849    
850     // Call old routine
851     lwz r0,XLM_R_GET_RESOURCE(0)
852     lwz r2,XLM_RES_LIB_TOC(0)
853     mtctr r0
854     bctrl
855 gbeauche 1.2 RESTORE_SYSTEM_R2
856 gbeauche 1.1 stw r3,56+8(r1) // Save handle
857    
858     // Call CheckLoad
859     lwz r3,56(r1)
860     lha r4,56+6(r1)
861     lwz r5,56+8(r1)
862     bl C_SYMBOL_NAME(check_load_invoc)
863     lwz r3,56+8(r1) // Restore handle
864    
865     // Return to caller
866     lwz r0,56+12+8(r1)
867     mtlr r0
868     addi r1,r1,56+12
869     blr
870    
871    
872     /*
873     * void ppc_interrupt(uint32 entry{r3}, uint32 kernel_data{r4}) - Execute PPC interrupt
874     */
875    
876     ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(ppc_interrupt)
877     C_SYMBOL_NAME(ppc_interrupt):
878     mflr r0
879     stw r0,4(r1)
880     stwu r1,-64(r1)
881    
882     // Get address of return routine
883     bl 1f
884    
885     // Return routine
886     lwz r0,64+4(r1)
887     mtlr r0
888     addi r1,r1,64
889     blr
890    
891     // Prepare registers for nanokernel interrupt routine
892     1: mtctr r1
893     mr r1,r4
894     stw r6,0x018(r1)
895     mfctr r6
896     stw r6,0x004(r1)
897     lwz r6,0x65c(r1)
898     stw r7,0x13c(r6)
899     stw r8,0x144(r6)
900     stw r9,0x14c(r6)
901     stw r10,0x154(r6)
902     stw r11,0x15c(r6)
903     stw r12,0x164(r6)
904     stw r13,0x16c(r6)
905    
906     mflr r10
907     mfcr r13
908     lwz r7,0x660(r1)
909     mflr r12
910     rlwimi. r7,r7,8,0,0
911     li r11,0
912     ori r11,r11,0xf072 // MSR (SRR1)
913     mtcrf 0x70,r11
914     li r8,0
915    
916     // Enter nanokernel
917     mtlr r3
918     blr
919 gbeauche 1.2
920    
921     /*
922     * Glue for glibc with TLS support which clobbers r2
923     *
924     * The following is derived from dietlibc and only provides
925     * pass-through to kernel syscalls. You also lose asynchronous
926     * cancellation support.
927     */
928    
929     #if defined(__linux__)
930     #define __NR_getpid 20
931     #define __NR__newselect 142
932    
933     #define syscall_weak(name,wsym,sym) \
934     .text; \
935     .type wsym,@function; \
936     .weak wsym; \
937     wsym: ; \
938     .type sym,@function; \
939     .global sym; \
940     sym: \
941     li 0,__NR_##name; \
942     b __unified_syscall
943    
944     #define syscall(name,sym) \
945     .text; \
946     .type sym,@function; \
947     .global sym; \
948     sym: \
949     li 0,__NR_##name; \
950     b __unified_syscall
951    
952    
953     .type __unified_syscall,@function
954     __unified_syscall:
955     sc
956     bnslr+
957     stwu 1,-16(1)
958     mflr 0
959     stw 0,20(1)
960     stw 3,12(1)
961     bl __errno_location
962     lwz 0,12(1)
963     stw 0,0(3)
964     lwz 0,20(1)
965     mtlr 0
966     addi 1,1,16
967     blr
968    
969     /* name weak symbol symbol */
970     syscall( getpid, getpid)
971     syscall_weak( _newselect, select, __select)
972     #endif