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, 9 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

# 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 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 RESTORE_SYSTEM_R2
248 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 RESTORE_SYSTEM_R2
385
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 RESTORE_SYSTEM_R2
422 RESTORE_SYSTEM_R13
423 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 RESTORE_SYSTEM_R2
599 RESTORE_SYSTEM_R13
600 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 RESTORE_SYSTEM_R2
728 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 RESTORE_SYSTEM_R2
760 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 RESTORE_SYSTEM_R2
792 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 RESTORE_SYSTEM_R2
824 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 RESTORE_SYSTEM_R2
856 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
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