ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/ppc_asm.S
Revision: 1.10
Committed: 2009-08-18T18:26:11Z (15 years, 2 months ago) by asvitkine
Branch: MAIN
CVS Tags: HEAD
Changes since 1.9: +6 -4 lines
Log Message:
[Michael Schmitt]
Attached is a patch to SheepShaver to fix memory allocation problems when OS X 10.5 is the host. It also relaxes the 512 MB RAM limit on OS X hosts.


Problem
-------
Some users have been unable to run SheepShaver on OS X 10.5 (Leopard) hosts. The symptom is error "ERROR: Cannot map RAM: File already exists".

SheepShaver allocates RAM at fixed addresses. If it is running in "Real" addressing mode, and can't allocate at address 0, then it was hard-coded to allocate the RAM area at 0x20000000. The ROM area as allocated at 0x40800000.

The normal configuration is for SheepShaver to run under SDL, which is a Cocoa wrapper. By the time SheepShaver does its memory allocations, the Cocoa application has already started. The result is the SheepShaver memory address space already contains libraries, fonts, Input Managers, and IOKit areas.

On Leopard hosts these areas can land on the same addresses SheepShaver needs, so SheepShaver's memory allocation fails.


Solution
--------
The approach is to change SheepShaver (on Unix & OS X hosts) to allocate the RAM area anywhere it can find the space, rather than at a fixed address.

This could result in the RAM allocated higher than the ROM area, which causes a crash. To prevent this from occurring, the RAM and ROM areas are allocated contiguously.

Previously the ROM starting address was a constant ROM_BASE, which was used throughout the source files. The ROM start address is now a variable ROMBase. ROMBase is allocated and set by main_*.cpp just like RAMBase.

A side-effect of this change is that it lifts the 512 MB RAM limit for OS X hosts. The limit was because the fixed RAM and ROM addresses were such that the RAM could only be 512 MB before it overlapped the ROM area.


Impact
------
The change to make ROMBase a variable is throughout all hosts & addressing modes.

The RAM and ROM areas will only shift when run on Unix & OS X hosts, otherwise the same fixed allocation address is used as before.

This change is limited to "Real" addressing mode. Unlike Basilisk II, SheepShaver *pre-calculates* the offset for "Direct" addressing mode; the offset is compiled into the program. If the RAM address were allowed to shift, it could result in the RAM area wrapping around address 0.


Changes to main_unix.cpp
------------------------
1. Real addressing mode no longer defines a RAM_BASE constant.

2. The base address of the Mac ROM (ROMBase) is defined and exported by this program.

3. Memory management helper vm_mac_acquire is renamed to vm_mac_acquire_fixed. Added a new memory management helper vm_mac_acquire, which allocates memory at any address.

4. Changed and rearranged the allocation of RAM and ROM areas.

Before it worked like this:

  - Allocate ROM area
  - If can, attempt to allocate RAM at address zero
  - If RAM not allocated at 0, allocate at fixed address

We still want to try allocating the RAM at zero, and if using DIRECT addressing we're still going to use the fixed addresses. So we don't know where the ROM should be until after we do the RAM. The new logic is:

  - If can, attempt to allocate RAM at address zero
  - If RAM not allocated at 0
      if REAL addressing
         allocate RAM and ROM together. The ROM address is aligned to a 1 MB boundary
      else (direct addressing)
         allocate RAM at fixed address
  - If ROM hasn't been allocated yet, allocate at fixed address

5. Calculate ROMBase and ROMBaseHost based on where the ROM was loaded.

6. There is a crash if the RAM is allocated too high. To try and catch this, check if it was allocated higher than the kernel data address.

7. Change subsequent code from using constant ROM_BASE to variable ROMBase.


Changes to Other Programs
-------------------------
emul_op.cpp, main.cpp, name_registery.cpp, rom_patches.cpp, rsrc_patches.cpp, emul_ppc.cpp, sheepshaver_glue.cpp, ppc-translate-cpp:
Change from constant ROM_BASE to variable ROMBase.

ppc_asm.S: It was setting register to a hard-coded literal address: 0x40b0d000. Changed to set it to ROMBase + 0x30d000.

ppc_asm.tmpl: It defined a macro ASM_LO16 but it assumed that the macro would always be used with operands that included a register specification. This is not true. Moved the register specification from the macro to the macro invocations.

main_beos.cpp, main_windows.cpp: Since the subprograms are all expecting a variable ROMBase, all the main_*.cpp pgrams have to define and export it. The ROM_BASE constant is moved here for consistency. The mains for beos and windows just allocate the ROM at the same fixed address as before, set ROMBaseHost and ROMBase to that address, and then use ROMBase for the subsequent code.

cpu_emulation.h: removed ROM_BASE constant. This value is moved to the main_*.cpp modules, to be consistent with RAM_BASE.

user_strings_unix.cpp, user_strings_unix.h: Added new error messages related to errors that occur when the RAM and ROM are allocated anywhere.

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 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 RESTORE_SYSTEM_R2
348 RESTORE_SYSTEM_R13
349 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 stwu r1,-(56+16*4+15*8)(r1)
386
387 // Save 68k registers (M68kRegisters)
388 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 mffs f0
413 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
421 // Execute native routine
422 RESTORE_SYSTEM_R2
423 RESTORE_SYSTEM_R13
424 addi r3,r1,56
425 mr r4,r24
426 bl C_SYMBOL_NAME(EmulOp)
427
428 // Restore 68k registers (M68kRegisters)
429 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 mtfsf 0xff,f13
455 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
462 // Delete PowerPC stack frame
463 lwz r2,56+16*4+15*8+12(r1)
464 lwz r0,56+16*4+15*8+16(r1)
465 mtxer r0
466 lwz r0,56+16*4+15*8+4(r1)
467 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,ASM_HA16(C_SYMBOL_NAME(ROMBase)) // Pointer to ROM boot structure:
493 lwz r3,ASM_LO16(C_SYMBOL_NAME(ROMBase))(r3) // r3 = ROMBase + 0x30d000
494 addis r3,r3,ASM_HA16(0x30d000)
495 addi r3,r3,ASM_LO16(0x30d000)
496
497 // 68k emulator is now active
498 li r0,MODE_68K
499 stw r0,XLM_RUN_MODE(0)
500
501 // Jump to ROM
502 bctr
503
504
505 /*
506 * void execute_68k(uint32 pc {r3}, M68kRegisters *r {r4}) - Execute 68k routine
507 */
508
509 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(execute_68k)
510 C_SYMBOL_NAME(execute_68k):
511 // Create MacOS stack frame
512 mflr r0
513 stw r0,4(r1)
514 stwu r1,-(56+19*4+18*8)(r1)
515 mfcr r0
516 stw r4,48(r1) // save pointer to M68kRegisters for EXEC_RETURN
517 stw r0,52(r1) // save CR
518
519 // Save PowerPC registers
520 stmw r13,56(r1)
521 #if SAVE_FP_EXEC_68K
522 stfd f14,56+19*4+0*8(r1)
523 stfd f15,56+19*4+1*8(r1)
524 stfd f16,56+19*4+2*8(r1)
525 stfd f17,56+19*4+3*8(r1)
526 stfd f18,56+19*4+4*8(r1)
527 stfd f19,56+19*4+5*8(r1)
528 stfd f20,56+19*4+6*8(r1)
529 stfd f21,56+19*4+7*8(r1)
530 stfd f22,56+19*4+8*8(r1)
531 stfd f23,56+19*4+9*8(r1)
532 stfd f24,56+19*4+10*8(r1)
533 stfd f25,56+19*4+11*8(r1)
534 stfd f26,56+19*4+12*8(r1)
535 stfd f27,56+19*4+13*8(r1)
536 stfd f28,56+19*4+14*8(r1)
537 stfd f29,56+19*4+15*8(r1)
538 stfd f30,56+19*4+16*8(r1)
539 stfd f31,56+19*4+17*8(r1)
540 #endif
541
542 // Set up registers for 68k emulator
543 lwz r31,XLM_KERNEL_DATA(0) // Pointer to Kernel Data
544 addi r31,r31,0x1000
545 li r0,0
546 mtcrf 0xff,r0
547 creqv 11,11,11 // Supervisor mode
548 lwz r8,0*4(r4) // d[0]..d[7]
549 lwz r9,1*4(r4)
550 lwz r10,2*4(r4)
551 lwz r11,3*4(r4)
552 lwz r12,4*4(r4)
553 lwz r13,5*4(r4)
554 lwz r14,6*4(r4)
555 lwz r15,7*4(r4)
556 lwz r16,8*4(r4) // a[0]..a[6]
557 lwz r17,9*4(r4)
558 lwz r18,10*4(r4)
559 lwz r19,11*4(r4)
560 lwz r20,12*4(r4)
561 lwz r21,13*4(r4)
562 lwz r22,14*4(r4)
563 li r23,0
564 mr r24,r3
565 lwz r25,XLM_68K_R25(0) // MSB of SR
566 li r26,0
567 li r28,0 // VBR
568 lwz r29,0x74(r31) // Pointer to opcode table
569 lwz r30,0x78(r31) // Address of emulator
570
571 // Push return address (points to EXEC_RETURN opcode) on stack
572 li r0,XLM_EXEC_RETURN_OPCODE
573 stwu r0,-4(r1)
574
575 // Reentering 68k emulator
576 li r0,MODE_68K
577 stw r0,XLM_RUN_MODE(0)
578
579 // Set r0 to 0 for 68k emulator
580 li r0,0
581
582 // Execute 68k opcode
583 lha r27,0(r24)
584 rlwimi r29,r27,3,13,28
585 lhau r27,2(r24)
586 mtlr r29
587 blr
588
589
590 /*
591 * uint32 call_macos1(uint32 tvect{r3}, uint32 arg1{r4}) ... - Call MacOS routines
592 */
593
594 ASM_MACRO_START prolog
595 mflr r0
596 stw r0,4(r1)
597 stwu r1,-64(r1)
598 ASM_MACRO_END
599
600 ASM_MACRO_START epilog
601 lwz r0,64+4(r1)
602 mtlr r0
603 addi r1,r1,64
604 RESTORE_SYSTEM_R2
605 RESTORE_SYSTEM_R13
606 blr
607 ASM_MACRO_END
608
609 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos)
610 C_SYMBOL_NAME(call_macos):
611 prolog
612 lwz r0,0(r3) // Get routine address
613 lwz r2,4(r3) // Load TOC pointer
614 mtctr r0
615 bctrl
616 epilog
617
618 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos1)
619 C_SYMBOL_NAME(call_macos1):
620 prolog
621 lwz r0,0(r3) // Get routine address
622 lwz r2,4(r3) // Load TOC pointer
623 mtctr r0
624 mr r3,r4
625 bctrl
626 epilog
627
628 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos2)
629 C_SYMBOL_NAME(call_macos2):
630 prolog
631 lwz r0,0(r3) // Get routine address
632 lwz r2,4(r3) // Load TOC pointer
633 mtctr r0
634 mr r3,r4
635 mr r4,r5
636 bctrl
637 epilog
638
639 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos3)
640 C_SYMBOL_NAME(call_macos3):
641 prolog
642 lwz r0,0(r3) // Get routine address
643 lwz r2,4(r3) // Load TOC pointer
644 mtctr r0
645 mr r3,r4
646 mr r4,r5
647 mr r5,r6
648 bctrl
649 epilog
650
651 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos4)
652 C_SYMBOL_NAME(call_macos4):
653 prolog
654 lwz r0,0(r3) // Get routine address
655 lwz r2,4(r3) // Load TOC pointer
656 mtctr r0
657 mr r3,r4
658 mr r4,r5
659 mr r5,r6
660 mr r6,r7
661 bctrl
662 epilog
663
664 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos5)
665 C_SYMBOL_NAME(call_macos5):
666 prolog
667 lwz r0,0(r3) // Get routine address
668 lwz r2,4(r3) // Load TOC pointer
669 mtctr r0
670 mr r3,r4
671 mr r4,r5
672 mr r5,r6
673 mr r6,r7
674 mr r7,r8
675 bctrl
676 epilog
677
678 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos6)
679 C_SYMBOL_NAME(call_macos6):
680 prolog
681 lwz r0,0(r3) // Get routine address
682 lwz r2,4(r3) // Load TOC pointer
683 mtctr r0
684 mr r3,r4
685 mr r4,r5
686 mr r5,r6
687 mr r6,r7
688 mr r7,r8
689 mr r8,r9
690 bctrl
691 epilog
692
693 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(call_macos7)
694 C_SYMBOL_NAME(call_macos7):
695 prolog
696 lwz r0,0(r3) // Get routine address
697 lwz r2,4(r3) // Load TOC pointer
698 mtctr r0
699 mr r3,r4
700 mr r4,r5
701 mr r5,r6
702 mr r6,r7
703 mr r7,r8
704 mr r8,r9
705 mr r9,r10
706 bctrl
707 epilog
708
709
710 /*
711 * Native resource manager patches
712 */
713
714 ASM_MACRO_START do_get_resource ASM_MACRO_ARG0_DEF
715 // Create stack frame
716 mflr r0
717 stw r0,8(r1)
718 stwu r1,-(56+12)(r1)
719
720 // Save type/ID
721 stw r3,56(r1)
722 stw r4,56+4(r1)
723
724 // Call old routine
725 lwz r0,ASM_MACRO_ARG0(0)
726 lwz r2,XLM_RES_LIB_TOC(0)
727 mtctr r0
728 bctrl
729 stw r3,56+8(r1) // Save handle
730
731 // Call CheckLoad
732 RESTORE_SYSTEM_R2
733 RESTORE_SYSTEM_R13
734 lwz r3,56(r1)
735 lha r4,56+6(r1)
736 lwz r5,56+8(r1)
737 bl C_SYMBOL_NAME(check_load_invoc)
738 lwz r3,56+8(r1) // Restore handle
739
740 // Return to caller
741 lwz r0,56+12+8(r1)
742 mtlr r0
743 addi r1,r1,56+12
744 blr
745 ASM_MACRO_END
746
747 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_resource)
748 C_SYMBOL_NAME(get_resource):
749 do_get_resource XLM_GET_RESOURCE
750
751 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_resource)
752 C_SYMBOL_NAME(get_1_resource):
753 do_get_resource XLM_GET_1_RESOURCE
754
755 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_ind_resource)
756 C_SYMBOL_NAME(get_ind_resource):
757 do_get_resource XLM_GET_IND_RESOURCE
758
759 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_ind_resource)
760 C_SYMBOL_NAME(get_1_ind_resource):
761 do_get_resource XLM_GET_1_IND_RESOURCE
762
763 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(r_get_resource)
764 C_SYMBOL_NAME(r_get_resource):
765 do_get_resource XLM_R_GET_RESOURCE
766
767 ASM_MACRO_START do_get_named_resource ASM_MACRO_ARG0_DEF
768 // Create stack frame
769 mflr r0
770 stw r0,8(r1)
771 stwu r1,-(56+12)(r1)
772
773 // Save type/ID
774 stw r3,56(r1)
775 stw r4,56+4(r1)
776
777 // Call old routine
778 lwz r0,ASM_MACRO_ARG0(0)
779 lwz r2,XLM_RES_LIB_TOC(0)
780 mtctr r0
781 bctrl
782 stw r3,56+8(r1) // Save handle
783
784 // Call CheckLoad
785 RESTORE_SYSTEM_R2
786 RESTORE_SYSTEM_R13
787 lwz r3,56(r1)
788 lwz r4,56+4(r1)
789 lwz r5,56+8(r1)
790 bl C_SYMBOL_NAME(named_check_load_invoc)
791 lwz r3,56+8(r1) // Restore handle
792
793 // Return to caller
794 lwz r0,56+12+8(r1)
795 mtlr r0
796 addi r1,r1,56+12
797 blr
798 ASM_MACRO_END
799
800 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_named_resource)
801 C_SYMBOL_NAME(get_named_resource):
802 do_get_named_resource XLM_GET_NAMED_RESOURCE
803
804 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(get_1_named_resource)
805 C_SYMBOL_NAME(get_1_named_resource):
806 do_get_named_resource XLM_GET_1_NAMED_RESOURCE
807
808
809 /*
810 * void ppc_interrupt(uint32 entry{r3}, uint32 kernel_data{r4}) - Execute PPC interrupt
811 */
812
813 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(ppc_interrupt)
814 C_SYMBOL_NAME(ppc_interrupt):
815 mflr r0
816 stw r0,4(r1)
817 stwu r1,-64(r1)
818
819 // Get address of return routine
820 bl 1f
821
822 // Return routine
823 lwz r0,64+4(r1)
824 mtlr r0
825 addi r1,r1,64
826 blr
827
828 // Prepare registers for nanokernel interrupt routine
829 1: mtctr r1
830 mr r1,r4
831 stw r6,0x018(r1)
832 mfctr r6
833 stw r6,0x004(r1)
834 lwz r6,0x65c(r1)
835 stw r7,0x13c(r6)
836 stw r8,0x144(r6)
837 stw r9,0x14c(r6)
838 stw r10,0x154(r6)
839 stw r11,0x15c(r6)
840 stw r12,0x164(r6)
841 stw r13,0x16c(r6)
842
843 mflr r10
844 mfcr r13
845 lwz r7,0x660(r1)
846 mflr r12
847 rlwimi. r7,r7,8,0,0
848 li r11,0
849 ori r11,r11,0xf072 // MSR (SRR1)
850 mtcrf 0x70,r11
851 li r8,0
852
853 // Enter nanokernel
854 mtlr r3
855 blr
856
857
858 /*
859 * Define signal handlers with alternate stack initialization magic
860 */
861
862 #define SIG_STACK_SIZE 0x10000
863
864 ASM_MACRO_START do_define_signal_handler \
865 ASM_MACRO_ARG0_DEF /* name */ \
866 ASM_MACRO_ARG1_DEF /* stack */ \
867 ASM_MACRO_ARG2_DEF /* stack id */ \
868 ASM_MACRO_ARG3_DEF /* signal handler */
869
870 // Alternate stack lower base for this signal handler
871 .lcomm ASM_MACRO_ARG1,SIG_STACK_SIZE,ASM_ALIGN_2(4)
872 ASM_TYPE(ASM_MACRO_ARG1,@object)
873
874 // Represents the current nest level for this signal handler
875 // Note that in SheepShaver, SIGUSR2 signals are blocked while
876 // handling other signals so, it's unlikely we ever get a nest
877 // level greater than 1
878 .lcomm ASM_MACRO_ARG2,4,ASM_ALIGN_2(2)
879 ASM_TYPE(ASM_MACRO_ARG2,@object)
880
881 ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(ASM_MACRO_ARG0)
882 C_SYMBOL_NAME(ASM_MACRO_ARG0):
883 // Preserve args in scratch registers
884 mflr r14
885 mr r15,r3
886 mr r16,r4
887 mr r17,r5
888 mr r18,r1
889
890 // Atomically increase stack_id
891 lis r19,ASM_HA16(ASM_MACRO_ARG2)
892 la r19,ASM_LO16(ASM_MACRO_ARG2)(r19)
893 li r4,1
894 mr r3,r19
895 bl C_SYMBOL_NAME(atomic_add)
896 cmpwi r3,0
897 bne- 1f
898
899 // ID was 0, we can use the local stack
900 lis r9,ASM_HA16(ASM_MACRO_ARG1)
901 lis r3,(SIG_STACK_SIZE>>16)
902 la r9,ASM_LO16(ASM_MACRO_ARG1)(r9)
903 addi r3,r3,((SIG_STACK_SIZE&0xffff)-64)
904 add r1,r9,r3
905
906 1: // Invoke signal handler
907 stwu r1,-16(r1)
908 mr r3,r15
909 mr r4,r16
910 mr r5,r17
911 bl C_SYMBOL_NAME(ASM_MACRO_ARG3)
912 addi r1,r1,16
913
914 // Atomically decrease stack id
915 mr r3,r19
916 li r4,-1
917 bl C_SYMBOL_NAME(atomic_add)
918
919 // Restore kernel stack and return
920 mtlr r14
921 mr r1,r18
922 blr
923 ASM_MACRO_END
924
925 #define DEFINE_SIGNAL_HANDLER(NAME) \
926 do_define_signal_handler \
927 NAME##_handler_init ASM_MACRO_ARG_SEP \
928 NAME##_stack ASM_MACRO_ARG_SEP \
929 NAME##_stack_id ASM_MACRO_ARG_SEP \
930 NAME##_handler
931
932 DEFINE_SIGNAL_HANDLER(sigusr2)