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.5 by gbeauche, 2003-09-29T22:50:31Z vs.
Revision 1.14 by gbeauche, 2003-11-03T21:28:29Z

# 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 79 | Line 78 | static KernelData * const kernel_data =
78   *              PowerPC emulator glue with special 'sheep' opcodes
79   **/
80  
82 struct sheepshaver_exec_return { };
83
81   class sheepshaver_cpu
82          : public powerpc_cpu
83   {
# Line 89 | Line 86 | class sheepshaver_cpu
86  
87   public:
88  
89 <        sheepshaver_cpu()
90 <                : powerpc_cpu()
94 <                { 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 114 | Line 110 | public:
110  
111          // Handle MacOS interrupt
112          void interrupt(uint32 entry);
113 <
118 <        // spcflags for interrupts handling
119 <        static uint32 spcflags;
113 >        void handle_interrupt();
114  
115          // Lazy memory allocator (one item at a time)
116          void *operator new(size_t size)
# Line 128 | Line 122 | public:
122          void operator delete[](void *p);
123   };
124  
131 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 142 | Line 141 | void sheepshaver_cpu::init_decoder()
141  
142          static const instr_info_t sheep_ii_table[] = {
143                  { "sheep",
144 <                  (execute_fn)&sheepshaver_cpu::execute_sheep,
144 >                  (execute_pmf)&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 181 | 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 216 | Line 215 | void sheepshaver_cpu::execute_sheep(uint
215          }
216   }
217  
219 // Checks for pending interrupts
220 struct execute_nothing {
221        static inline void execute(powerpc_cpu *) { }
222 };
223
224 struct execute_spcflags_check {
225        static inline void execute(powerpc_cpu *cpu) {
226 #if !ASYNC_IRQ
227                if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) {
228                        if (SPCFLAGS_TEST( SPCFLAG_ENTER_MON )) {
229                                SPCFLAGS_CLEAR( SPCFLAG_ENTER_MON );
230                                enter_mon();
231                        }
232                        if (SPCFLAGS_TEST( SPCFLAG_DOINT )) {
233                                SPCFLAGS_CLEAR( SPCFLAG_DOINT );
234                                HandleInterrupt();
235                        }
236                        if (SPCFLAGS_TEST( SPCFLAG_INT )) {
237                                SPCFLAGS_CLEAR( SPCFLAG_INT );
238                                SPCFLAGS_SET( SPCFLAG_DOINT );
239                        }
240                }
241 #endif
242        }
243 };
244
218   // Execution loop
219 < void sheepshaver_cpu::execute(uint32 entry)
219 > void sheepshaver_cpu::execute(uint32 entry, bool enable_cache)
220   {
221 <        try {
249 <                pc() = entry;
250 <                powerpc_cpu::do_execute<execute_nothing, execute_spcflags_check>();
251 <        }
252 <        catch (sheepshaver_exec_return const &) {
253 <                // Nothing, simply return
254 <        }
255 <        catch (...) {
256 <                printf("ERROR: execute() received an unknown exception!\n");
257 <                QuitEmulator();
258 <        }
221 >        powerpc_cpu::execute(entry, enable_cache);
222   }
223  
224   // Handle MacOS interrupt
# Line 294 | Line 257 | void sheepshaver_cpu::interrupt(uint32 e
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 302 | 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);
# Line 328 | 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 <        for (int i = 13; i < 32; i++)
304 <                WriteMacInt32(gpr(1) + 56 + i*4, gpr(i));
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 385 | Line 351 | void sheepshaver_cpu::execute_68k(uint32
351            r->a[i] = gpr(16 + i);
352  
353          // Restore PowerPC registers
354 <        for (int i = 13; i < 32; i++)
389 <                gpr(i) = ReadMacInt32(gpr(1) + 56 + i*4);
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 449 | Line 415 | inline void sheepshaver_cpu::execute_ppc
415   {
416          // Save branch registers
417          uint32 saved_lr = lr();
452        uint32 saved_ctr= ctr();
418  
419          const uint32 trampoline[] = { htonl(POWERPC_EMUL_OP | 1) };
455
420          lr() = (uint32)trampoline;
421 <        ctr()= entry;
421 >
422          execute(entry);
423  
424          // Restore branch registers
425          lr() = saved_lr;
462        ctr()= saved_ctr;
426   }
427  
428   // Resource Manager thunk
# Line 494 | 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 581 | Line 553 | void init_emul_ppc(void)
553   }
554  
555   /*
556 + *  Deinitialize emulation
557 + */
558 +
559 + void exit_emul_ppc(void)
560 + {
561 +        delete main_cpu;
562 + #if MULTICORE_CPU
563 +        delete interrupt_cpu;
564 + #endif
565 + }
566 +
567 + /*
568   *  Emulation loop
569   */
570  
571   void emul_ppc(uint32 entry)
572   {
573          current_cpu = main_cpu;
574 + #if DEBUG
575          current_cpu->start_log();
576 <        current_cpu->execute(entry);
576 > #endif
577 >        // start emulation loop and enable code translation or caching
578 >        current_cpu->execute(entry, true);
579   }
580  
581   /*
582   *  Handle PowerPC interrupt
583   */
584  
585 < // Atomic operations
586 < extern int atomic_add(int *var, int v);
587 < extern int atomic_and(int *var, int v);
588 < extern int atomic_or(int *var, int v);
589 <
590 < #if !ASYNC_IRQ
585 > #if ASYNC_IRQ
586 > void HandleInterrupt(void)
587 > {
588 >        main_cpu->handle_interrupt();
589 > }
590 > #else
591   void TriggerInterrupt(void)
592   {
593   #if 0
594    WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
595   #else
596 <  SPCFLAGS_SET( SPCFLAG_INT );
596 >  // Trigger interrupt to main cpu only
597 >  if (main_cpu)
598 >          main_cpu->trigger_interrupt();
599   #endif
600   }
601   #endif
602  
603 < void HandleInterrupt(void)
603 > void sheepshaver_cpu::handle_interrupt(void)
604   {
605          // Do nothing if interrupts are disabled
606          if (int32(ReadMacInt32(XLM_IRQ_NEST)) > 0)
# Line 630 | Line 619 | void HandleInterrupt(void)
619                  // 68k emulator active, trigger 68k interrupt level 1
620                  assert(current_cpu == main_cpu);
621                  WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1);
622 <                main_cpu->set_cr(main_cpu->get_cr() | tswap32(kernel_data->v[0x674 >> 2]));
622 >                set_cr(get_cr() | tswap32(kernel_data->v[0x674 >> 2]));
623                  break;
624      
625   #if INTERRUPTS_IN_NATIVE_MODE
626          case MODE_NATIVE:
627                  // 68k emulator inactive, in nanokernel?
628                  assert(current_cpu == main_cpu);
629 <                if (main_cpu->gpr(1) != KernelDataAddr) {
629 >                if (gpr(1) != KernelDataAddr) {
630                          // Prepare for 68k interrupt level 1
631                          WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1);
632                          WriteMacInt32(tswap32(kernel_data->v[0x658 >> 2]) + 0xdc,
# Line 725 | Line 714 | const uint32 NativeOpTable[NATIVE_OP_MAX
714          POWERPC_NATIVE_OP_INIT(1, NATIVE_R_GET_RESOURCE),
715          POWERPC_NATIVE_OP_INIT(0, NATIVE_DISABLE_INTERRUPT),
716          POWERPC_NATIVE_OP_INIT(0, NATIVE_ENABLE_INTERRUPT),
717 +        POWERPC_NATIVE_OP_INIT(1, NATIVE_MAKE_EXECUTABLE),
718   };
719  
720   static void get_resource(void);
# Line 792 | Line 782 | static void NativeOp(int selector)
782          case NATIVE_ENABLE_INTERRUPT:
783                  EnableInterrupt();
784                  break;
785 +        case NATIVE_MAKE_EXECUTABLE:
786 +                MakeExecutable(0, (void *)GPR(4), GPR(5));
787 +                break;
788          default:
789                  printf("FATAL: NATIVE_OP called with bogus selector %d\n", selector);
790                  QuitEmulator();
# Line 889 | Line 882 | uint32 call_macos7(uint32 tvect, uint32
882   }
883  
884   /*
892 *  Atomic operations
893 */
894
895 int atomic_add(int *var, int v)
896 {
897        int ret = *var;
898        *var += v;
899        return ret;
900 }
901
902 int atomic_and(int *var, int v)
903 {
904        int ret = *var;
905        *var &= v;
906        return ret;
907 }
908
909 int atomic_or(int *var, int v)
910 {
911        int ret = *var;
912        *var |= v;
913        return ret;
914 }
915
916 /*
885   *  Resource Manager thunks
886   */
887  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines