ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp
(Generate patch)

Comparing SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp (file contents):
Revision 1.3 by gbeauche, 2003-09-29T07:05:15Z vs.
Revision 1.12 by gbeauche, 2003-11-01T15:15:27Z

# Line 28 | Line 28
28   #include "macos_util.h"
29   #include "block-alloc.hpp"
30   #include "sigsegv.h"
31 #include "spcflags.h"
31   #include "cpu/ppc/ppc-cpu.hpp"
32   #include "cpu/ppc/ppc-operations.hpp"
33  
# Line 44 | Line 43
43   #include "mon_disass.h"
44   #endif
45  
46 < #define DEBUG 1
46 > #define DEBUG 0
47   #include "debug.h"
48  
49   static void enter_mon(void)
# Line 57 | Line 56 | static void enter_mon(void)
56   }
57  
58   // Enable multicore (main/interrupts) cpu emulation?
59 < #define MULTICORE_CPU 0
59 > #define MULTICORE_CPU (ASYNC_IRQ ? 1 : 0)
60  
61   // Enable Execute68k() safety checks?
62   #define SAFE_EXEC_68K 1
# Line 71 | Line 70 | static void enter_mon(void)
70   // Interrupts in native mode?
71   #define INTERRUPTS_IN_NATIVE_MODE 1
72  
74 // 68k Emulator Data
75 struct EmulatorData {
76        uint32  v[0x400];      
77 };
78
79 // Kernel Data
80 struct KernelData {
81        uint32  v[0x400];
82        EmulatorData ed;
83 };
84
73   // Pointer to Kernel Data
74 < static KernelData * const kernel_data = (KernelData *)0x68ffe000;
74 > static KernelData * const kernel_data = (KernelData *)KERNEL_DATA_BASE;
75  
76  
77   /**
78   *              PowerPC emulator glue with special 'sheep' opcodes
79   **/
80  
93 struct sheepshaver_exec_return { };
94
81   class sheepshaver_cpu
82          : public powerpc_cpu
83   {
# Line 100 | Line 86 | class sheepshaver_cpu
86  
87   public:
88  
89 <        sheepshaver_cpu()
90 <                : powerpc_cpu()
105 <                { init_decoder(); }
89 >        // Constructor
90 >        sheepshaver_cpu();
91  
92          // Condition Register accessors
93          uint32 get_cr() const           { return cr().get(); }
94          void set_cr(uint32 v)           { cr().set(v); }
95  
96          // Execution loop
97 <        void execute(uint32 pc);
97 >        void execute(uint32 entry, bool enable_cache = false);
98  
99          // Execute 68k routine
100          void execute_68k(uint32 entry, M68kRegisters *r);
# Line 124 | Line 109 | public:
109          void get_resource(uint32 old_get_resource);
110  
111          // Handle MacOS interrupt
112 <        void interrupt(uint32 entry, sheepshaver_cpu *cpu);
113 <
129 <        // spcflags for interrupts handling
130 <        static uint32 spcflags;
112 >        void interrupt(uint32 entry);
113 >        void handle_interrupt();
114  
115          // Lazy memory allocator (one item at a time)
116          void *operator new(size_t size)
# Line 139 | Line 122 | public:
122          void operator delete[](void *p);
123   };
124  
142 uint32 sheepshaver_cpu::spcflags = 0;
125   lazy_allocator< sheepshaver_cpu > allocator_helper< sheepshaver_cpu, lazy_allocator >::allocator;
126  
127 + sheepshaver_cpu::sheepshaver_cpu()
128 +        : powerpc_cpu()
129 + {
130 +        init_decoder();
131 + }
132 +
133   void sheepshaver_cpu::init_decoder()
134   {
135   #ifndef PPC_NO_STATIC_II_INDEX_TABLE
# Line 155 | Line 143 | void sheepshaver_cpu::init_decoder()
143                  { "sheep",
144                    (execute_fn)&sheepshaver_cpu::execute_sheep,
145                    NULL,
146 <                  D_form, 6, 0, CFLOW_TRAP
146 >                  D_form, 6, 0, CFLOW_JUMP | CFLOW_TRAP
147                  }
148          };
149  
# Line 192 | Line 180 | void sheepshaver_cpu::execute_sheep(uint
180          case 0:         // EMUL_RETURN
181                  QuitEmulator();
182                  break;
183 <                
183 >
184          case 1:         // EXEC_RETURN
185 <                throw sheepshaver_exec_return();
185 >                spcflags().set(SPCFLAG_CPU_EXEC_RETURN);
186                  break;
187  
188          case 2:         // EXEC_NATIVE
# Line 227 | Line 215 | void sheepshaver_cpu::execute_sheep(uint
215          }
216   }
217  
230 // Checks for pending interrupts
231 struct execute_nothing {
232        static inline void execute(powerpc_cpu *) { }
233 };
234
235 static void HandleInterrupt(void);
236
237 struct execute_spcflags_check {
238        static inline void execute(powerpc_cpu *cpu) {
239                if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) {
240                        if (SPCFLAGS_TEST( SPCFLAG_ENTER_MON )) {
241                                SPCFLAGS_CLEAR( SPCFLAG_ENTER_MON );
242                                enter_mon();
243                        }
244                        if (SPCFLAGS_TEST( SPCFLAG_DOINT )) {
245                                SPCFLAGS_CLEAR( SPCFLAG_DOINT );
246                                HandleInterrupt();
247                        }
248                        if (SPCFLAGS_TEST( SPCFLAG_INT )) {
249                                SPCFLAGS_CLEAR( SPCFLAG_INT );
250                                SPCFLAGS_SET( SPCFLAG_DOINT );
251                        }
252                }
253        }
254 };
255
218   // Execution loop
219 < void sheepshaver_cpu::execute(uint32 entry)
219 > void sheepshaver_cpu::execute(uint32 entry, bool enable_cache)
220   {
221 <        try {
260 <                pc() = entry;
261 <                powerpc_cpu::do_execute<execute_nothing, execute_spcflags_check>();
262 <        }
263 <        catch (sheepshaver_exec_return const &) {
264 <                // Nothing, simply return
265 <        }
266 <        catch (...) {
267 <                printf("ERROR: execute() received an unknown exception!\n");
268 <                QuitEmulator();
269 <        }
221 >        powerpc_cpu::execute(entry, enable_cache);
222   }
223  
224   // Handle MacOS interrupt
225 < void sheepshaver_cpu::interrupt(uint32 entry, sheepshaver_cpu *cpu)
225 > void sheepshaver_cpu::interrupt(uint32 entry)
226   {
227 < #if MULTICORE_CPU
276 <        // Initialize stack pointer from previous CPU running
277 <        gpr(1) = cpu->gpr(1);
278 < #else
227 > #if !MULTICORE_CPU
228          // Save program counters and branch registers
229          uint32 saved_pc = pc();
230          uint32 saved_lr = lr();
231          uint32 saved_ctr= ctr();
232 +        uint32 saved_sp = gpr(1);
233   #endif
234  
235 <        // Create stack frame
236 <        gpr(1) -= 64;
235 >        // Initialize stack pointer to SheepShaver alternate stack base
236 >        gpr(1) = SheepStack1Base - 64;
237  
238          // Build trampoline to return from interrupt
239 <        uint32 trampoline[] = { POWERPC_EMUL_OP | 1 };
239 >        uint32 trampoline[] = { htonl(POWERPC_EMUL_OP | 1) };
240  
241          // Prepare registers for nanokernel interrupt routine
242 <        kernel_data->v[0x004 >> 2] = gpr(1);
243 <        kernel_data->v[0x018 >> 2] = gpr(6);
242 >        kernel_data->v[0x004 >> 2] = htonl(gpr(1));
243 >        kernel_data->v[0x018 >> 2] = htonl(gpr(6));
244  
245 <        gpr(6) = kernel_data->v[0x65c >> 2];
245 >        gpr(6) = ntohl(kernel_data->v[0x65c >> 2]);
246          assert(gpr(6) != 0);
247          WriteMacInt32(gpr(6) + 0x13c, gpr(7));
248          WriteMacInt32(gpr(6) + 0x144, gpr(8));
# Line 303 | Line 253 | void sheepshaver_cpu::interrupt(uint32 e
253          WriteMacInt32(gpr(6) + 0x16c, gpr(13));
254  
255          gpr(1)  = KernelDataAddr;
256 <        gpr(7)  = kernel_data->v[0x660 >> 2];
256 >        gpr(7)  = ntohl(kernel_data->v[0x660 >> 2]);
257          gpr(8)  = 0;
258          gpr(10) = (uint32)trampoline;
259          gpr(12) = (uint32)trampoline;
260 <        gpr(13) = cr().get();
260 >        gpr(13) = get_cr();
261  
262          // rlwimi. r7,r7,8,0,0
263          uint32 result = op_ppc_rlwimi::apply(gpr(7), 8, 0x80000000, gpr(7));
# Line 315 | Line 265 | void sheepshaver_cpu::interrupt(uint32 e
265          gpr(7) = result;
266  
267          gpr(11) = 0xf072; // MSR (SRR1)
268 <        cr().set((gpr(11) & 0x0fff0000) | (cr().get() & ~0x0fff0000));
268 >        cr().set((gpr(11) & 0x0fff0000) | (get_cr() & ~0x0fff0000));
269  
270          // Enter nanokernel
271          execute(entry);
272  
323        // Cleanup stack
324        gpr(1) += 64;
325
273   #if !MULTICORE_CPU
274          // Restore program counters and branch registers
275          pc() = saved_pc;
276          lr() = saved_lr;
277          ctr()= saved_ctr;
278 +        gpr(1) = saved_sp;
279   #endif
280   }
281  
# Line 343 | Line 291 | void sheepshaver_cpu::execute_68k(uint32
291          uint32 saved_pc = pc();
292          uint32 saved_lr = lr();
293          uint32 saved_ctr= ctr();
294 +        uint32 saved_cr = get_cr();
295  
296          // Create MacOS stack frame
297 +        // FIXME: make sure MacOS doesn't expect PPC registers to live on top
298          uint32 sp = gpr(1);
299 <        gpr(1) -= 56 + 19*4 + 18*8;
299 >        gpr(1) -= 56;
300          WriteMacInt32(gpr(1), sp);
301  
302          // Save PowerPC registers
303 <        memcpy(Mac2HostAddr(gpr(1)+56), &gpr(13), sizeof(uint32)*(32-13));
303 >        uint32 saved_GPRs[19];
304 >        memcpy(&saved_GPRs[0], &gpr(13), sizeof(uint32)*(32-13));
305   #if SAVE_FP_EXEC_68K
306 <        memcpy(Mac2HostAddr(gpr(1)+56+19*4), &fpr(14), sizeof(double)*(32-14));
306 >        double saved_FPRs[18];
307 >        memcpy(&saved_FPRs[0], &fpr(14), sizeof(double)*(32-14));
308   #endif
309  
310          // Setup registers for 68k emulator
# Line 366 | Line 318 | void sheepshaver_cpu::execute_68k(uint32
318          gpr(25) = ReadMacInt32(XLM_68K_R25);            // MSB of SR
319          gpr(26) = 0;
320          gpr(28) = 0;                                                            // VBR
321 <        gpr(29) = kernel_data->ed.v[0x74 >> 2];         // Pointer to opcode table
322 <        gpr(30) = kernel_data->ed.v[0x78 >> 2];         // Address of emulator
321 >        gpr(29) = ntohl(kernel_data->ed.v[0x74 >> 2]);          // Pointer to opcode table
322 >        gpr(30) = ntohl(kernel_data->ed.v[0x78 >> 2]);          // Address of emulator
323          gpr(31) = KernelDataAddr + 0x1000;
324  
325          // Push return address (points to EXEC_RETURN opcode) on stack
# Line 399 | Line 351 | void sheepshaver_cpu::execute_68k(uint32
351            r->a[i] = gpr(16 + i);
352  
353          // Restore PowerPC registers
354 <        memcpy(&gpr(13), Mac2HostAddr(gpr(1)+56), sizeof(uint32)*(32-13));
354 >        memcpy(&gpr(13), &saved_GPRs[0], sizeof(uint32)*(32-13));
355   #if SAVE_FP_EXEC_68K
356 <        memcpy(&fpr(14), Mac2HostAddr(gpr(1)+56+19*4), sizeof(double)*(32-14));
356 >        memcpy(&fpr(14), &saved_FPRs[0], sizeof(double)*(32-14));
357   #endif
358  
359          // Cleanup stack
360 <        gpr(1) += 56 + 19*4 + 18*8;
360 >        gpr(1) += 56;
361  
362          // Restore program counters and branch registers
363          pc() = saved_pc;
364          lr() = saved_lr;
365          ctr()= saved_ctr;
366 +        set_cr(saved_cr);
367   }
368  
369   // Call MacOS PPC code
# Line 422 | Line 375 | uint32 sheepshaver_cpu::execute_macos_co
375          uint32 saved_ctr= ctr();
376  
377          // Build trampoline with EXEC_RETURN
378 <        uint32 trampoline[] = { POWERPC_EMUL_OP | 1 };
378 >        uint32 trampoline[] = { htonl(POWERPC_EMUL_OP | 1) };
379          lr() = (uint32)trampoline;
380  
381          gpr(1) -= 64;                                                           // Create stack frame
# Line 462 | Line 415 | inline void sheepshaver_cpu::execute_ppc
415   {
416          // Save branch registers
417          uint32 saved_lr = lr();
465        uint32 saved_ctr= ctr();
466
467        const uint32 trampoline[] = { POWERPC_EMUL_OP | 1 };
418  
419 +        const uint32 trampoline[] = { htonl(POWERPC_EMUL_OP | 1) };
420          lr() = (uint32)trampoline;
421 <        ctr()= entry;
421 >
422          execute(entry);
423  
424          // Restore branch registers
425          lr() = saved_lr;
475        ctr()= saved_ctr;
426   }
427  
428   // Resource Manager thunk
429 < extern "C" void check_load_invoc(uint32 type, int16 id, uint16 **h);
429 > extern "C" void check_load_invoc(uint32 type, int16 id, uint32 h);
430  
431   inline void sheepshaver_cpu::get_resource(uint32 old_get_resource)
432   {
# Line 488 | Line 438 | inline void sheepshaver_cpu::get_resourc
438  
439          // Call old routine
440          execute_ppc(old_get_resource);
491        uint16 **handle = (uint16 **)gpr(3);
441  
442          // Call CheckLoad()
443 +        uint32 handle = gpr(3);
444          check_load_invoc(type, id, handle);
445 <        gpr(3) = (uint32)handle;
445 >        gpr(3) = handle;
446  
447          // Cleanup stack
448          gpr(1) += 56;
# Line 507 | Line 457 | static sheepshaver_cpu *main_cpu = NULL;
457   static sheepshaver_cpu *interrupt_cpu = NULL;   // CPU emulator to handle interrupts
458   static sheepshaver_cpu *current_cpu = NULL;             // Current CPU emulator context
459  
460 + void FlushCodeCache(uintptr start, uintptr end)
461 + {
462 +        D(bug("FlushCodeCache(%08x, %08x)\n", start, end));
463 +        main_cpu->invalidate_cache_range(start, end);
464 + #if MULTICORE_CPU
465 +        interrupt_cpu->invalidate_cache_range(start, end);
466 + #endif
467 + }
468 +
469   static inline void cpu_push(sheepshaver_cpu *new_cpu)
470   {
471   #if MULTICORE_CPU
# Line 585 | Line 544 | void init_emul_ppc(void)
544  
545          // Install the handler for SIGSEGV
546          sigsegv_install_handler(sigsegv_handler);
547 <        
547 >
548   #if ENABLE_MON
549          // Install "regs" command in cxmon
550          mon_add_command("regs", dump_registers, "regs                     Dump PowerPC registers\n");
# Line 600 | Line 559 | void init_emul_ppc(void)
559   void emul_ppc(uint32 entry)
560   {
561          current_cpu = main_cpu;
562 + #if DEBUG
563          current_cpu->start_log();
564 <        current_cpu->execute(entry);
564 > #endif
565 >        // start emulation loop and enable code translation or caching
566 >        current_cpu->execute(entry, true);
567   }
568  
569   /*
570   *  Handle PowerPC interrupt
571   */
572  
573 < // Atomic operations
574 < extern int atomic_add(int *var, int v);
575 < extern int atomic_and(int *var, int v);
576 < extern int atomic_or(int *var, int v);
577 <
573 > #if ASYNC_IRQ
574 > void HandleInterrupt(void)
575 > {
576 >        main_cpu->handle_interrupt();
577 > }
578 > #else
579   void TriggerInterrupt(void)
580   {
581   #if 0
582    WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
583   #else
584 <  SPCFLAGS_SET( SPCFLAG_INT );
584 >  // Trigger interrupt to main cpu only
585 >  if (main_cpu)
586 >          main_cpu->trigger_interrupt();
587   #endif
588   }
589 + #endif
590  
591 < static void HandleInterrupt(void)
591 > void sheepshaver_cpu::handle_interrupt(void)
592   {
593          // Do nothing if interrupts are disabled
594          if (int32(ReadMacInt32(XLM_IRQ_NEST)) > 0)
# Line 641 | Line 607 | static void HandleInterrupt(void)
607                  // 68k emulator active, trigger 68k interrupt level 1
608                  assert(current_cpu == main_cpu);
609                  WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1);
610 <                main_cpu->set_cr(main_cpu->get_cr() | tswap32(kernel_data->v[0x674 >> 2]));
610 >                set_cr(get_cr() | tswap32(kernel_data->v[0x674 >> 2]));
611                  break;
612      
613   #if INTERRUPTS_IN_NATIVE_MODE
614          case MODE_NATIVE:
615                  // 68k emulator inactive, in nanokernel?
616                  assert(current_cpu == main_cpu);
617 <                if (main_cpu->gpr(1) != KernelDataAddr) {
617 >                if (gpr(1) != KernelDataAddr) {
618                          // Prepare for 68k interrupt level 1
619                          WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1);
620                          WriteMacInt32(tswap32(kernel_data->v[0x658 >> 2]) + 0xdc,
# Line 659 | Line 625 | static void HandleInterrupt(void)
625                          DisableInterrupt();
626                          cpu_push(interrupt_cpu);
627                          if (ROMType == ROMTYPE_NEWWORLD)
628 <                                current_cpu->interrupt(ROM_BASE + 0x312b1c, main_cpu);
628 >                                current_cpu->interrupt(ROM_BASE + 0x312b1c);
629                          else
630 <                                current_cpu->interrupt(ROM_BASE + 0x312a3c, main_cpu);
630 >                                current_cpu->interrupt(ROM_BASE + 0x312a3c);
631                          cpu_pop();
632                  }
633                  break;
# Line 736 | Line 702 | const uint32 NativeOpTable[NATIVE_OP_MAX
702          POWERPC_NATIVE_OP_INIT(1, NATIVE_R_GET_RESOURCE),
703          POWERPC_NATIVE_OP_INIT(0, NATIVE_DISABLE_INTERRUPT),
704          POWERPC_NATIVE_OP_INIT(0, NATIVE_ENABLE_INTERRUPT),
705 +        POWERPC_NATIVE_OP_INIT(1, NATIVE_MAKE_EXECUTABLE),
706   };
707  
708   static void get_resource(void);
# Line 803 | Line 770 | static void NativeOp(int selector)
770          case NATIVE_ENABLE_INTERRUPT:
771                  EnableInterrupt();
772                  break;
773 +        case NATIVE_MAKE_EXECUTABLE:
774 +                MakeExecutable(0, (void *)GPR(4), GPR(5));
775 +                break;
776          default:
777                  printf("FATAL: NATIVE_OP called with bogus selector %d\n", selector);
778                  QuitEmulator();
# Line 842 | Line 812 | void Execute68k(uint32 pc, M68kRegisters
812  
813   void Execute68kTrap(uint16 trap, M68kRegisters *r)
814   {
815 <        uint16 proc[2] = {trap, M68K_RTS};
815 >        uint16 proc[2];
816 >        proc[0] = htons(trap);
817 >        proc[1] = htons(M68K_RTS);
818          Execute68k((uint32)proc, r);
819   }
820  
# Line 898 | Line 870 | uint32 call_macos7(uint32 tvect, uint32
870   }
871  
872   /*
901 *  Atomic operations
902 */
903
904 int atomic_add(int *var, int v)
905 {
906        int ret = *var;
907        *var += v;
908        return ret;
909 }
910
911 int atomic_and(int *var, int v)
912 {
913        int ret = *var;
914        *var &= v;
915        return ret;
916 }
917
918 int atomic_or(int *var, int v)
919 {
920        int ret = *var;
921        *var |= v;
922        return ret;
923 }
924
925 /*
873   *  Resource Manager thunks
874   */
875  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines