ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/ppc_asm.S
Revision: 1.7
Committed: 2005-06-28T16:47:32Z (18 years, 11 months ago) by gbeauche
Branch: MAIN
Changes since 1.6: +77 -0 lines
Log Message:
The alternate stack trick never worked as you can't modify an active stack.
i.e. it returned EPERM and ran into stack corruption to eventually crash the
emulator. This is noticeable in !hw_mac_cursor_accl mode (e.g. fullscreen DGA).

In order to the sigalstack() to be effective, we must kludge the kernel to
think it's running on another stack. In practise, we provide another stack
for the SIGUSR2 handler. sigusr2_handler_init() fulfills that purpose.

I hope this fixes remaining issues forever. At some point, I had multiple
*_init() handlers in case this is necessary.

File Contents

# Content
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 * void *get_sp(void) - Get stack pointer
29 */
30
31 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_sp)
32 C_SYMBOL_NAME(get_sp):
33 mr r3,r1
34 blr
35
36
37 /*
38 * void *get_r2(void) - Get r2
39 */
40
41 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_r2)
42 C_SYMBOL_NAME(get_r2):
43 mr r3,r2
44 blr
45
46
47 /*
48 * void set_r2(void *val {r3}) - Set r2
49 */
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 * 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 * 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 bne 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 RESTORE_SYSTEM_R2
248 RESTORE_SYSTEM_R13
249 lmw r13,20(r1)
250 lfd f14,20+19*4+0*8(r1)
251 lfd f15,20+19*4+1*8(r1)
252 lfd f16,20+19*4+2*8(r1)
253 lfd f17,20+19*4+3*8(r1)
254 lfd f18,20+19*4+4*8(r1)
255 lfd f19,20+19*4+5*8(r1)
256 lfd f20,20+19*4+6*8(r1)
257 lfd f21,20+19*4+7*8(r1)
258 lfd f22,20+19*4+8*8(r1)
259 lfd f23,20+19*4+9*8(r1)
260 lfd f24,20+19*4+10*8(r1)
261 lfd f25,20+19*4+11*8(r1)
262 lfd f26,20+19*4+12*8(r1)
263 lfd f27,20+19*4+13*8(r1)
264 lfd f28,20+19*4+14*8(r1)
265 lfd f29,20+19*4+15*8(r1)
266 lfd f30,20+19*4+16*8(r1)
267 lfd f31,20+19*4+17*8(r1)
268
269 // Exiting from 68k emulator
270 li r0,1
271 stw r0,XLM_IRQ_NEST(0)
272 li r0,MODE_NATIVE
273 stw r0,XLM_RUN_MODE(0)
274
275 // Return to caller of jump_to_rom()
276 lwz r0,20+19*4+18*8+4(r1)
277 mtlr r0
278 addi r1,r1,20+19*4+18*8
279 blr
280
281
282 // Save address of EMUL_RETURN routine for 68k emulator patch
283 1: mflr r0
284 stw r0,XLM_EMUL_RETURN_PROC(0)
285
286 // Skip over EXEC_RETURN routine and get its address
287 bl 2f
288
289
290 /*
291 * EXEC_RETURN: Returned from 68k routine executed with Execute68k()
292 */
293
294 // Save r25 (contains current 68k interrupt level)
295 stw r25,XLM_68K_R25(0)
296
297 // Reentering EMUL_OP mode
298 li r0,MODE_EMUL_OP
299 stw r0,XLM_RUN_MODE(0)
300
301 // Save 68k registers
302 lwz r4,48(r1) // Pointer to M68kRegisters
303 stw r8,0*4(r4) // d[0]...d[7]
304 stw r9,1*4(r4)
305 stw r10,2*4(r4)
306 stw r11,3*4(r4)
307 stw r12,4*4(r4)
308 stw r13,5*4(r4)
309 stw r14,6*4(r4)
310 stw r15,7*4(r4)
311 stw r16,8*4(r4) // a[0]..a[6]
312 stw r17,9*4(r4)
313 stw r18,10*4(r4)
314 stw r19,11*4(r4)
315 stw r20,12*4(r4)
316 stw r21,13*4(r4)
317 stw r22,14*4(r4)
318
319 // Restore PowerPC registers
320 lmw r13,56(r1)
321 #if SAVE_FP_EXEC_68K
322 lfd f14,56+19*4+0*8(r1)
323 lfd f15,56+19*4+1*8(r1)
324 lfd f16,56+19*4+2*8(r1)
325 lfd f17,56+19*4+3*8(r1)
326 lfd f18,56+19*4+4*8(r1)
327 lfd f19,56+19*4+5*8(r1)
328 lfd f20,56+19*4+6*8(r1)
329 lfd f21,56+19*4+7*8(r1)
330 lfd f22,56+19*4+8*8(r1)
331 lfd f23,56+19*4+9*8(r1)
332 lfd f24,56+19*4+10*8(r1)
333 lfd f25,56+19*4+11*8(r1)
334 lfd f26,56+19*4+12*8(r1)
335 lfd f27,56+19*4+13*8(r1)
336 lfd f28,56+19*4+14*8(r1)
337 lfd f29,56+19*4+15*8(r1)
338 lfd f30,56+19*4+16*8(r1)
339 lfd f31,56+19*4+17*8(r1)
340 #endif
341
342 // Return to caller
343 lwz r0,52(r1)
344 mtcrf 0xff,r0
345 lwz r0,56+19*4+18*8+4(r1)
346 mtlr r0
347 addi r1,r1,56+19*4+18*8
348 RESTORE_SYSTEM_R2
349 RESTORE_SYSTEM_R13
350 blr
351
352
353 // Save address of EXEC_RETURN routine for 68k emulator patch
354 2: mflr r0
355 stw r0,XLM_EXEC_RETURN_PROC(0)
356
357 // Skip over EMUL_BREAK/EMUL_OP routine and get its address
358 bl 3f
359
360
361 /*
362 * EMUL_BREAK/EMUL_OP: Execute native routine, selector in r5 (my own private mode switch)
363 *
364 * 68k registers are stored in a M68kRegisters struct on the stack
365 * which the native routine may read and modify
366 */
367
368 // Save r25 (contains current 68k interrupt level)
369 stw r25,XLM_68K_R25(0)
370
371 // Entering EMUL_OP mode within 68k emulator
372 li r0,MODE_EMUL_OP
373 stw r0,XLM_RUN_MODE(0)
374
375 // Create PowerPC stack frame, reserve space for M68kRegisters
376 mr r3,r1
377 subi r1,r1,64 // Fake "caller" frame
378 rlwinm r1,r1,0,0,27 // Align stack
379
380 mfcr r0
381 rlwinm r0,r0,0,11,8
382 stw r0,4(r1)
383 mfxer r0
384 stw r0,16(r1)
385 stw r2,12(r1)
386 stwu r1,-(56+16*4+15*8)(r1)
387
388 // Save 68k registers (M68kRegisters)
389 stw r8,56+0*4(r1) // d[0]..d[7]
390 stw r9,56+1*4(r1)
391 stw r10,56+2*4(r1)
392 stw r11,56+3*4(r1)
393 stw r12,56+4*4(r1)
394 stw r13,56+5*4(r1)
395 stw r14,56+6*4(r1)
396 stw r15,56+7*4(r1)
397 stw r16,56+8*4(r1) // a[0]..a[7]
398 stw r17,56+9*4(r1)
399 stw r18,56+10*4(r1)
400 stw r19,56+11*4(r1)
401 stw r20,56+12*4(r1)
402 stw r21,56+13*4(r1)
403 stw r22,56+14*4(r1)
404 stw r3,56+15*4(r1)
405 stfd f0,56+16*4+0*8(r1)
406 stfd f1,56+16*4+1*8(r1)
407 stfd f2,56+16*4+2*8(r1)
408 stfd f3,56+16*4+3*8(r1)
409 stfd f4,56+16*4+4*8(r1)
410 stfd f5,56+16*4+5*8(r1)
411 stfd f6,56+16*4+6*8(r1)
412 stfd f7,56+16*4+7*8(r1)
413 mffs f0
414 stfd f8,56+16*4+8*8(r1)
415 stfd f9,56+16*4+9*8(r1)
416 stfd f10,56+16*4+10*8(r1)
417 stfd f11,56+16*4+11*8(r1)
418 stfd f12,56+16*4+12*8(r1)
419 stfd f13,56+16*4+13*8(r1)
420 stfd f0,56+16*4+14*8(r1)
421
422 // Execute native routine
423 RESTORE_SYSTEM_R2
424 RESTORE_SYSTEM_R13
425 addi r3,r1,56
426 mr r4,r24
427 bl C_SYMBOL_NAME(EmulOp)
428
429 // Restore 68k registers (M68kRegisters)
430 lwz r8,56+0*4(r1) // d[0]..d[7]
431 lwz r9,56+1*4(r1)
432 lwz r10,56+2*4(r1)
433 lwz r11,56+3*4(r1)
434 lwz r12,56+4*4(r1)
435 lwz r13,56+5*4(r1)
436 lwz r14,56+6*4(r1)
437 lwz r15,56+7*4(r1)
438 lwz r16,56+8*4(r1) // a[0]..a[7]
439 lwz r17,56+9*4(r1)
440 lwz r18,56+10*4(r1)
441 lwz r19,56+11*4(r1)
442 lwz r20,56+12*4(r1)
443 lwz r21,56+13*4(r1)
444 lwz r22,56+14*4(r1)
445 lwz r3,56+15*4(r1)
446 lfd f13,56+16*4+14*8(r1)
447 lfd f0,56+16*4+0*8(r1)
448 lfd f1,56+16*4+1*8(r1)
449 lfd f2,56+16*4+2*8(r1)
450 lfd f3,56+16*4+3*8(r1)
451 lfd f4,56+16*4+4*8(r1)
452 lfd f5,56+16*4+5*8(r1)
453 lfd f6,56+16*4+6*8(r1)
454 lfd f7,56+16*4+7*8(r1)
455 mtfsf 0xff,f13
456 lfd f8,56+16*4+8*8(r1)
457 lfd f9,56+16*4+9*8(r1)
458 lfd f10,56+16*4+10*8(r1)
459 lfd f11,56+16*4+11*8(r1)
460 lfd f12,56+16*4+12*8(r1)
461 lfd f13,56+16*4+13*8(r1)
462
463 // Delete PowerPC stack frame
464 lwz r2,56+16*4+15*8+12(r1)
465 lwz r0,56+16*4+15*8+16(r1)
466 mtxer r0
467 lwz r0,56+16*4+15*8+4(r1)
468 mtcrf 0xff,r0
469 mr r1,r3
470
471 // Reentering 68k emulator
472 li r0,MODE_68K
473 stw r0,XLM_RUN_MODE(0)
474
475 // Set r0 to 0 for 68k emulator
476 li r0,0
477
478 // Execute next 68k opcode
479 rlwimi r29,r27,3,13,28
480 lhau r27,2(r24)
481 mtlr r29
482 blr
483
484
485 // Save address of EMUL_BREAK/EMUL_OP routine for 68k emulator patch
486 3: mflr r0
487 stw r0,XLM_EMUL_OP_PROC(0)
488
489 // Save stack pointer for EMUL_RETURN
490 stw r1,XLM_EMUL_RETURN_STACK(0)
491
492 // Preset registers for ROM boot routine
493 lis r3,0x40b0 // Pointer to ROM boot structure
494 ori r3,r3,0xd000
495
496 // 68k emulator is now active
497 li r0,MODE_68K
498 stw r0,XLM_RUN_MODE(0)
499
500 // Jump to ROM
501 bctr
502
503
504 /*
505 * void execute_68k(uint32 pc {r3}, M68kRegisters *r {r4}) - Execute 68k routine
506 */
507
508 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(execute_68k)
509 C_SYMBOL_NAME(execute_68k):
510 // Create MacOS stack frame
511 mflr r0
512 stw r0,4(r1)
513 stwu r1,-(56+19*4+18*8)(r1)
514 mfcr r0
515 stw r4,48(r1) // save pointer to M68kRegisters for EXEC_RETURN
516 stw r0,52(r1) // save CR
517
518 // Save PowerPC registers
519 stmw r13,56(r1)
520 #if SAVE_FP_EXEC_68K
521 stfd f14,56+19*4+0*8(r1)
522 stfd f15,56+19*4+1*8(r1)
523 stfd f16,56+19*4+2*8(r1)
524 stfd f17,56+19*4+3*8(r1)
525 stfd f18,56+19*4+4*8(r1)
526 stfd f19,56+19*4+5*8(r1)
527 stfd f20,56+19*4+6*8(r1)
528 stfd f21,56+19*4+7*8(r1)
529 stfd f22,56+19*4+8*8(r1)
530 stfd f23,56+19*4+9*8(r1)
531 stfd f24,56+19*4+10*8(r1)
532 stfd f25,56+19*4+11*8(r1)
533 stfd f26,56+19*4+12*8(r1)
534 stfd f27,56+19*4+13*8(r1)
535 stfd f28,56+19*4+14*8(r1)
536 stfd f29,56+19*4+15*8(r1)
537 stfd f30,56+19*4+16*8(r1)
538 stfd f31,56+19*4+17*8(r1)
539 #endif
540
541 // Set up registers for 68k emulator
542 lwz r31,XLM_KERNEL_DATA(0) // Pointer to Kernel Data
543 addi r31,r31,0x1000
544 li r0,0
545 mtcrf 0xff,r0
546 creqv 11,11,11 // Supervisor mode
547 lwz r8,0*4(r4) // d[0]..d[7]
548 lwz r9,1*4(r4)
549 lwz r10,2*4(r4)
550 lwz r11,3*4(r4)
551 lwz r12,4*4(r4)
552 lwz r13,5*4(r4)
553 lwz r14,6*4(r4)
554 lwz r15,7*4(r4)
555 lwz r16,8*4(r4) // a[0]..a[6]
556 lwz r17,9*4(r4)
557 lwz r18,10*4(r4)
558 lwz r19,11*4(r4)
559 lwz r20,12*4(r4)
560 lwz r21,13*4(r4)
561 lwz r22,14*4(r4)
562 li r23,0
563 mr r24,r3
564 lwz r25,XLM_68K_R25(0) // MSB of SR
565 li r26,0
566 li r28,0 // VBR
567 lwz r29,0x74(r31) // Pointer to opcode table
568 lwz r30,0x78(r31) // Address of emulator
569
570 // Push return address (points to EXEC_RETURN opcode) on stack
571 li r0,XLM_EXEC_RETURN_OPCODE
572 stwu r0,-4(r1)
573
574 // Reentering 68k emulator
575 li r0,MODE_68K
576 stw r0,XLM_RUN_MODE(0)
577
578 // Set r0 to 0 for 68k emulator
579 li r0,0
580
581 // Execute 68k opcode
582 lha r27,0(r24)
583 rlwimi r29,r27,3,13,28
584 lhau r27,2(r24)
585 mtlr r29
586 blr
587
588
589 /*
590 * uint32 call_macos1(uint32 tvect{r3}, uint32 arg1{r4}) ... - Call MacOS routines
591 */
592
593 ASM_MACRO_START prolog
594 mflr r0
595 stw r0,4(r1)
596 stwu r1,-64(r1)
597 ASM_MACRO_END
598
599 ASM_MACRO_START epilog
600 lwz r0,64+4(r1)
601 mtlr r0
602 addi r1,r1,64
603 RESTORE_SYSTEM_R2
604 RESTORE_SYSTEM_R13
605 blr
606 ASM_MACRO_END
607
608 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos)
609 C_SYMBOL_NAME(call_macos):
610 prolog
611 lwz r0,0(r3) // Get routine address
612 lwz r2,4(r3) // Load TOC pointer
613 mtctr r0
614 bctrl
615 epilog
616
617 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos1)
618 C_SYMBOL_NAME(call_macos1):
619 prolog
620 lwz r0,0(r3) // Get routine address
621 lwz r2,4(r3) // Load TOC pointer
622 mtctr r0
623 mr r3,r4
624 bctrl
625 epilog
626
627 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos2)
628 C_SYMBOL_NAME(call_macos2):
629 prolog
630 lwz r0,0(r3) // Get routine address
631 lwz r2,4(r3) // Load TOC pointer
632 mtctr r0
633 mr r3,r4
634 mr r4,r5
635 bctrl
636 epilog
637
638 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos3)
639 C_SYMBOL_NAME(call_macos3):
640 prolog
641 lwz r0,0(r3) // Get routine address
642 lwz r2,4(r3) // Load TOC pointer
643 mtctr r0
644 mr r3,r4
645 mr r4,r5
646 mr r5,r6
647 bctrl
648 epilog
649
650 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos4)
651 C_SYMBOL_NAME(call_macos4):
652 prolog
653 lwz r0,0(r3) // Get routine address
654 lwz r2,4(r3) // Load TOC pointer
655 mtctr r0
656 mr r3,r4
657 mr r4,r5
658 mr r5,r6
659 mr r6,r7
660 bctrl
661 epilog
662
663 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos5)
664 C_SYMBOL_NAME(call_macos5):
665 prolog
666 lwz r0,0(r3) // Get routine address
667 lwz r2,4(r3) // Load TOC pointer
668 mtctr r0
669 mr r3,r4
670 mr r4,r5
671 mr r5,r6
672 mr r6,r7
673 mr r7,r8
674 bctrl
675 epilog
676
677 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos6)
678 C_SYMBOL_NAME(call_macos6):
679 prolog
680 lwz r0,0(r3) // Get routine address
681 lwz r2,4(r3) // Load TOC pointer
682 mtctr r0
683 mr r3,r4
684 mr r4,r5
685 mr r5,r6
686 mr r6,r7
687 mr r7,r8
688 mr r8,r9
689 bctrl
690 epilog
691
692 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos7)
693 C_SYMBOL_NAME(call_macos7):
694 prolog
695 lwz r0,0(r3) // Get routine address
696 lwz r2,4(r3) // Load TOC pointer
697 mtctr r0
698 mr r3,r4
699 mr r4,r5
700 mr r5,r6
701 mr r6,r7
702 mr r7,r8
703 mr r8,r9
704 mr r9,r10
705 bctrl
706 epilog
707
708
709 /*
710 * Native resource manager patches
711 */
712
713 ASM_MACRO_START do_get_resource ASM_MACRO_ARG0_DEF
714 // Create stack frame
715 mflr r0
716 stw r0,8(r1)
717 stwu r1,-(56+12)(r1)
718
719 // Save type/ID
720 stw r3,56(r1)
721 stw r4,56+4(r1)
722
723 // Call old routine
724 lwz r0,ASM_MACRO_ARG0(0)
725 lwz r2,XLM_RES_LIB_TOC(0)
726 mtctr r0
727 bctrl
728 stw r3,56+8(r1) // Save handle
729
730 // Call CheckLoad
731 RESTORE_SYSTEM_R2
732 RESTORE_SYSTEM_R13
733 lwz r3,56(r1)
734 lha r4,56+6(r1)
735 lwz r5,56+8(r1)
736 bl C_SYMBOL_NAME(check_load_invoc)
737 lwz r3,56+8(r1) // Restore handle
738
739 // Return to caller
740 lwz r0,56+12+8(r1)
741 mtlr r0
742 addi r1,r1,56+12
743 blr
744 ASM_MACRO_END
745
746 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_resource)
747 C_SYMBOL_NAME(get_resource):
748 do_get_resource XLM_GET_RESOURCE
749
750 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_resource)
751 C_SYMBOL_NAME(get_1_resource):
752 do_get_resource XLM_GET_1_RESOURCE
753
754 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_ind_resource)
755 C_SYMBOL_NAME(get_ind_resource):
756 do_get_resource XLM_GET_IND_RESOURCE
757
758 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_ind_resource)
759 C_SYMBOL_NAME(get_1_ind_resource):
760 do_get_resource XLM_GET_1_IND_RESOURCE
761
762 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(r_get_resource)
763 C_SYMBOL_NAME(r_get_resource):
764 do_get_resource XLM_R_GET_RESOURCE
765
766
767 /*
768 * void ppc_interrupt(uint32 entry{r3}, uint32 kernel_data{r4}) - Execute PPC interrupt
769 */
770
771 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(ppc_interrupt)
772 C_SYMBOL_NAME(ppc_interrupt):
773 mflr r0
774 stw r0,4(r1)
775 stwu r1,-64(r1)
776
777 // Get address of return routine
778 bl 1f
779
780 // Return routine
781 lwz r0,64+4(r1)
782 mtlr r0
783 addi r1,r1,64
784 blr
785
786 // Prepare registers for nanokernel interrupt routine
787 1: mtctr r1
788 mr r1,r4
789 stw r6,0x018(r1)
790 mfctr r6
791 stw r6,0x004(r1)
792 lwz r6,0x65c(r1)
793 stw r7,0x13c(r6)
794 stw r8,0x144(r6)
795 stw r9,0x14c(r6)
796 stw r10,0x154(r6)
797 stw r11,0x15c(r6)
798 stw r12,0x164(r6)
799 stw r13,0x16c(r6)
800
801 mflr r10
802 mfcr r13
803 lwz r7,0x660(r1)
804 mflr r12
805 rlwimi. r7,r7,8,0,0
806 li r11,0
807 ori r11,r11,0xf072 // MSR (SRR1)
808 mtcrf 0x70,r11
809 li r8,0
810
811 // Enter nanokernel
812 mtlr r3
813 blr
814
815
816 /*
817 * Define signal handlers with alternate stack initialization magic
818 */
819
820 #define SIG_STACK_SIZE 0x10000
821
822 ASM_MACRO_START do_define_signal_handler \
823 ASM_MACRO_ARG0_DEF /* name */ \
824 ASM_MACRO_ARG1_DEF /* stack */ \
825 ASM_MACRO_ARG2_DEF /* stack id */ \
826 ASM_MACRO_ARG3_DEF /* signal handler */
827
828 // Alternate stack lower base for this signal handler
829 .lcomm ASM_MACRO_ARG1,SIG_STACK_SIZE,ASM_ALIGN_2(4)
830 ASM_TYPE(ASM_MACRO_ARG1,@object)
831
832 // Represents the current nest level for this signal handler
833 // Note that in SheepShaver, SIGUSR2 signals are blocked while
834 // handling other signals so, it's unlikely we ever get a nest
835 // level greater than 1
836 .lcomm ASM_MACRO_ARG2,4,ASM_ALIGN_2(2)
837 ASM_TYPE(ASM_MACRO_ARG2,@object)
838
839 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(ASM_MACRO_ARG0)
840 C_SYMBOL_NAME(ASM_MACRO_ARG0):
841 // Preserve args in scratch registers
842 mflr r14
843 mr r15,r3
844 mr r16,r4
845 mr r17,r5
846 mr r18,r1
847
848 // Atomically increase stack_id
849 lis r19,ASM_HA16(ASM_MACRO_ARG2)
850 la r19,ASM_LO16(ASM_MACRO_ARG2,r19)
851 li r4,1
852 mr r3,r19
853 bl C_SYMBOL_NAME(atomic_add)
854 cmpwi r3,0
855 bne- 1f
856
857 // ID was 0, we can use the local stack
858 lis r9,ASM_HA16(ASM_MACRO_ARG1)
859 lis r3,(SIG_STACK_SIZE>>16)
860 la r9,ASM_LO16(ASM_MACRO_ARG1,r9)
861 addi r3,r3,((SIG_STACK_SIZE&0xffff)-64)
862 add r1,r9,r3
863
864 1: // Invoke signal handler
865 stwu r1,-16(r1)
866 mr r3,r15
867 mr r4,r16
868 mr r5,r17
869 bl C_SYMBOL_NAME(ASM_MACRO_ARG3)
870 addi r1,r1,16
871
872 // Atomically decrease stack id
873 mr r3,r19
874 li r4,-1
875 bl C_SYMBOL_NAME(atomic_add)
876
877 // Restore kernel stack and return
878 mtlr r14
879 mr r1,r18
880 blr
881 ASM_MACRO_END
882
883 #define DEFINE_SIGNAL_HANDLER(NAME) \
884 do_define_signal_handler \
885 NAME##_handler_init ASM_MACRO_ARG_SEP \
886 NAME##_stack ASM_MACRO_ARG_SEP \
887 NAME##_stack_id ASM_MACRO_ARG_SEP \
888 NAME##_handler
889
890 DEFINE_SIGNAL_HANDLER(sigusr2)