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.1 by gbeauche, 2003-09-07T14:25:01Z vs.
Revision 1.2 by gbeauche, 2003-09-28T21:27:34Z

# Line 27 | Line 27
27   #include "macos_util.h"
28   #include "block-alloc.hpp"
29   #include "sigsegv.h"
30 + #include "spcflags.h"
31   #include "cpu/ppc/ppc-cpu.hpp"
32   #include "cpu/ppc/ppc-operations.hpp"
33  
# Line 54 | Line 55 | static void enter_mon(void)
55   #endif
56   }
57  
58 + // Enable multicore (main/interrupts) cpu emulation?
59 + #define MULTICORE_CPU 0
60 +
61   // Enable Execute68k() safety checks?
62   #define SAFE_EXEC_68K 1
63  
# Line 99 | Line 103 | public:
103                  : powerpc_cpu()
104                  { init_decoder(); }
105  
102        // Stack pointer accessors
103        uint32 get_sp() const           { return gpr(1); }
104        void set_sp(uint32 v)           { gpr(1) = v; }
105
106          // Condition Register accessors
107          uint32 get_cr() const           { return cr().get(); }
108          void set_cr(uint32 v)           { cr().set(v); }
# Line 113 | Line 113 | public:
113          // Execute 68k routine
114          void execute_68k(uint32 entry, M68kRegisters *r);
115  
116 +        // Execute ppc routine
117 +        void execute_ppc(uint32 entry);
118 +
119          // Execute MacOS/PPC code
120          uint32 execute_macos_code(uint32 tvect, int nargs, uint32 const *args);
121  
# Line 120 | Line 123 | public:
123          void get_resource(uint32 old_get_resource);
124  
125          // Handle MacOS interrupt
126 <        void interrupt(uint32 entry, uint32 sp);
126 >        void interrupt(uint32 entry, sheepshaver_cpu *cpu);
127 >
128 >        // spcflags for interrupts handling
129 >        static uint32 spcflags;
130  
131          // Lazy memory allocator (one item at a time)
132          void *operator new(size_t size)
# Line 132 | Line 138 | public:
138          void operator delete[](void *p);
139   };
140  
141 + uint32 sheepshaver_cpu::spcflags = 0;
142   lazy_allocator< sheepshaver_cpu > allocator_helper< sheepshaver_cpu, lazy_allocator >::allocator;
143  
144   void sheepshaver_cpu::init_decoder()
# Line 163 | Line 170 | void sheepshaver_cpu::init_decoder()
170   // Forward declaration for native opcode handler
171   static void NativeOp(int selector);
172  
173 + /*              NativeOp instruction format:
174 +                +------------+--------------------------+--+----------+------------+
175 +                |      6     |                          |FN|    OP    |      2     |
176 +                +------------+--------------------------+--+----------+------------+
177 +                 0         5 |6                       19 20 21      25 26        31
178 + */
179 +
180 + typedef bit_field< 20, 20 > FN_field;
181 + typedef bit_field< 21, 25 > NATIVE_OP_field;
182 + typedef bit_field< 26, 31 > EMUL_OP_field;
183 +
184   // Execute SheepShaver instruction
185   void sheepshaver_cpu::execute_sheep(uint32 opcode)
186   {
# Line 179 | Line 197 | void sheepshaver_cpu::execute_sheep(uint
197                  break;
198  
199          case 2:         // EXEC_NATIVE
200 <                NativeOp((opcode >> 6) & 0x1f);
201 <                pc() = lr();
200 >                NativeOp(NATIVE_OP_field::extract(opcode));
201 >                if (FN_field::test(opcode))
202 >                        pc() = lr();
203 >                else
204 >                        pc() += 4;
205                  break;
206  
207          default: {      // EMUL_OP
# Line 192 | Line 213 | void sheepshaver_cpu::execute_sheep(uint
213                  for (int i = 0; i < 7; i++)
214                          r68.a[i] = gpr(16 + i);
215                  r68.a[7] = gpr(1);
216 <                EmulOp(&r68, gpr(24), (opcode & 0x3f) - 3);
216 >                EmulOp(&r68, gpr(24), EMUL_OP_field::extract(opcode) - 3);
217                  for (int i = 0; i < 8; i++)
218                          gpr(8 + i) = r68.d[i];
219                  for (int i = 0; i < 7; i++)
# Line 205 | Line 226 | void sheepshaver_cpu::execute_sheep(uint
226          }
227   }
228  
229 + // Checks for pending interrupts
230 + struct execute_nothing {
231 +        static inline void execute(powerpc_cpu *) { }
232 + };
233 +
234 + static void HandleInterrupt(void);
235 +
236 + struct execute_spcflags_check {
237 +        static inline void execute(powerpc_cpu *cpu) {
238 +                if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) {
239 +                        if (SPCFLAGS_TEST( SPCFLAG_ENTER_MON )) {
240 +                                SPCFLAGS_CLEAR( SPCFLAG_ENTER_MON );
241 +                                enter_mon();
242 +                        }
243 +                        if (SPCFLAGS_TEST( SPCFLAG_DOINT )) {
244 +                                SPCFLAGS_CLEAR( SPCFLAG_DOINT );
245 +                                HandleInterrupt();
246 +                        }
247 +                        if (SPCFLAGS_TEST( SPCFLAG_INT )) {
248 +                                SPCFLAGS_CLEAR( SPCFLAG_INT );
249 +                                SPCFLAGS_SET( SPCFLAG_DOINT );
250 +                        }
251 +                }
252 +        }
253 + };
254 +
255   // Execution loop
256   void sheepshaver_cpu::execute(uint32 entry)
257   {
258          try {
259                  pc() = entry;
260 <                powerpc_cpu::execute();
260 >                powerpc_cpu::do_execute<execute_nothing, execute_spcflags_check>();
261          }
262          catch (sheepshaver_exec_return const &) {
263                  // Nothing, simply return
# Line 222 | Line 269 | void sheepshaver_cpu::execute(uint32 ent
269   }
270  
271   // Handle MacOS interrupt
272 < void sheepshaver_cpu::interrupt(uint32 entry, uint32 sp)
272 > void sheepshaver_cpu::interrupt(uint32 entry, sheepshaver_cpu *cpu)
273   {
274 + #if MULTICORE_CPU
275 +        // Initialize stack pointer from previous CPU running
276 +        gpr(1) = cpu->gpr(1);
277 + #else
278 +        // Save program counters and branch registers
279 +        uint32 saved_pc = pc();
280 +        uint32 saved_lr = lr();
281 +        uint32 saved_ctr= ctr();
282 + #endif
283 +
284          // Create stack frame
285 <        gpr(1) = sp - 64;
285 >        gpr(1) -= 64;
286  
287          // Build trampoline to return from interrupt
288          uint32 trampoline[] = { POWERPC_EMUL_OP | 1 };
# Line 235 | Line 292 | void sheepshaver_cpu::interrupt(uint32 e
292          kernel_data->v[0x018 >> 2] = gpr(6);
293  
294          gpr(6) = kernel_data->v[0x65c >> 2];
295 +        assert(gpr(6) != 0);
296          WriteMacInt32(gpr(6) + 0x13c, gpr(7));
297          WriteMacInt32(gpr(6) + 0x144, gpr(8));
298          WriteMacInt32(gpr(6) + 0x14c, gpr(9));
# Line 263 | Line 321 | void sheepshaver_cpu::interrupt(uint32 e
321  
322          // Cleanup stack
323          gpr(1) += 64;
324 +
325 + #if !MULTICORE_CPU
326 +        // Restore program counters and branch registers
327 +        pc() = saved_pc;
328 +        lr() = saved_lr;
329 +        ctr()= saved_ctr;
330 + #endif
331   }
332  
333   // Execute 68k routine
# Line 290 | Line 355 | void sheepshaver_cpu::execute_68k(uint32
355   #endif
356  
357          // Setup registers for 68k emulator
358 <        cr().set(0);
294 <        cr().set(2, 1);                                                         // Supervisor mode
358 >        cr().set(CR_SO_field<2>::mask());                       // Supervisor mode
359          for (int i = 0; i < 8; i++)                                     // d[0]..d[7]
360            gpr(8 + i) = r->d[i];
361          for (int i = 0; i < 7; i++)                                     // a[0]..a[6]
# Line 392 | Line 456 | uint32 sheepshaver_cpu::execute_macos_co
456          return retval;
457   }
458  
459 + // Execute ppc routine
460 + inline void sheepshaver_cpu::execute_ppc(uint32 entry)
461 + {
462 +        // Save branch registers
463 +        uint32 saved_lr = lr();
464 +        uint32 saved_ctr= ctr();
465 +
466 +        const uint32 trampoline[] = { POWERPC_EMUL_OP | 1 };
467 +
468 +        lr() = (uint32)trampoline;
469 +        ctr()= entry;
470 +        execute(entry);
471 +
472 +        // Restore branch registers
473 +        lr() = saved_lr;
474 +        ctr()= saved_ctr;
475 + }
476 +
477   // Resource Manager thunk
478 + extern "C" void check_load_invoc(uint32 type, int16 id, uint16 **h);
479 +
480   inline void sheepshaver_cpu::get_resource(uint32 old_get_resource)
481   {
482 <        printf("ERROR: get_resource() unimplemented\n");
483 <        QuitEmulator();
482 >        uint32 type = gpr(3);
483 >        int16 id = gpr(4);
484 >
485 >        // Create stack frame
486 >        gpr(1) -= 56;
487 >
488 >        // Call old routine
489 >        execute_ppc(old_get_resource);
490 >        uint16 **handle = (uint16 **)gpr(3);
491 >
492 >        // Call CheckLoad()
493 >        check_load_invoc(type, id, handle);
494 >        gpr(3) = (uint32)handle;
495 >
496 >        // Cleanup stack
497 >        gpr(1) += 56;
498   }
499  
500  
# Line 408 | Line 506 | static sheepshaver_cpu *main_cpu = NULL;
506   static sheepshaver_cpu *interrupt_cpu = NULL;   // CPU emulator to handle interrupts
507   static sheepshaver_cpu *current_cpu = NULL;             // Current CPU emulator context
508  
509 + static inline void cpu_push(sheepshaver_cpu *new_cpu)
510 + {
511 + #if MULTICORE_CPU
512 +        current_cpu = new_cpu;
513 + #endif
514 + }
515 +
516 + static inline void cpu_pop()
517 + {
518 + #if MULTICORE_CPU
519 +        current_cpu = main_cpu;
520 + #endif
521 + }
522 +
523   // Dump PPC registers
524   static void dump_registers(void)
525   {
# Line 463 | Line 575 | static void sigsegv_handler(int sig, sig
575          interrupt_cpu->dump_registers();
576   #endif
577          current_cpu->dump_log();
466        WriteMacInt32(XLM_IRQ_NEST, 1);
578          enter_mon();
579          QuitEmulator();
580   }
# Line 475 | Line 586 | void init_emul_ppc(void)
586          main_cpu->set_register(powerpc_registers::GPR(3), any_register((uint32)ROM_BASE + 0x30d000));
587          WriteMacInt32(XLM_RUN_MODE, MODE_68K);
588  
589 + #if MULTICORE_CPU
590          // Initialize alternate CPU emulator to handle interrupts
591          interrupt_cpu = new sheepshaver_cpu();
592 + #endif
593  
594          // Install SIGSEGV handler
595          sigemptyset(&sigsegv_action.sa_mask);
# Line 512 | Line 625 | extern int atomic_add(int *var, int v);
625   extern int atomic_and(int *var, int v);
626   extern int atomic_or(int *var, int v);
627  
628 < void HandleInterrupt(void)
628 > void TriggerInterrupt(void)
629 > {
630 > #if 0
631 >  WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
632 > #else
633 >  SPCFLAGS_SET( SPCFLAG_INT );
634 > #endif
635 > }
636 >
637 > static void HandleInterrupt(void)
638   {
639          // Do nothing if interrupts are disabled
640 <        if (ReadMacInt32(XLM_IRQ_NEST) > 0 || InterruptFlags == 0)
640 >        if (int32(ReadMacInt32(XLM_IRQ_NEST)) > 0)
641                  return;
642  
643 <        // Do nothing if CPU objects are not initialized yet
644 <        if (current_cpu == NULL)
643 >        // Do nothing if there is no interrupt pending
644 >        if (InterruptFlags == 0)
645                  return;
646  
647          // Disable MacOS stack sniffer
# Line 546 | Line 668 | void HandleInterrupt(void)
668                                                    | tswap32(kernel_data->v[0x674 >> 2]));
669        
670                          // Execute nanokernel interrupt routine (this will activate the 68k emulator)
671 <                        atomic_add((int32 *)XLM_IRQ_NEST, htonl(1));
672 <                        current_cpu = interrupt_cpu;
671 >                        DisableInterrupt();
672 >                        cpu_push(interrupt_cpu);
673                          if (ROMType == ROMTYPE_NEWWORLD)
674 <                                current_cpu->interrupt(ROM_BASE + 0x312b1c, main_cpu->get_sp());
674 >                                current_cpu->interrupt(ROM_BASE + 0x312b1c, main_cpu);
675                          else
676 <                                current_cpu->interrupt(ROM_BASE + 0x312a3c, main_cpu->get_sp());
677 <                        current_cpu = main_cpu;
676 >                                current_cpu->interrupt(ROM_BASE + 0x312a3c, main_cpu);
677 >                        cpu_pop();
678                  }
679                  break;
680   #endif
# Line 566 | Line 688 | void HandleInterrupt(void)
688                          M68kRegisters r;
689                          uint32 old_r25 = ReadMacInt32(XLM_68K_R25);     // Save interrupt level
690                          WriteMacInt32(XLM_68K_R25, 0x21);                       // Execute with interrupt level 1
691 <                        static const uint16 proc[] = {
692 <                                0x3f3c, 0x0000,         // move.w       #$0000,-(sp)    (fake format word)
693 <                                0x487a, 0x000a,         // pea          @1(pc)                  (return address)
694 <                                0x40e7,                         // move         sr,-(sp)                (saved SR)
695 <                                0x2078, 0x0064,         // move.l       $64,a0
696 <                                0x4ed0,                         // jmp          (a0)
697 <                                M68K_RTS                        // @1
691 >                        static const uint8 proc[] = {
692 >                                0x3f, 0x3c, 0x00, 0x00,                 // move.w       #$0000,-(sp)    (fake format word)
693 >                                0x48, 0x7a, 0x00, 0x0a,                 // pea          @1(pc)                  (return address)
694 >                                0x40, 0xe7,                                             // move         sr,-(sp)                (saved SR)
695 >                                0x20, 0x78, 0x00, 0x064,                // move.l       $64,a0
696 >                                0x4e, 0xd0,                                             // jmp          (a0)
697 >                                M68K_RTS >> 8, M68K_RTS & 0xff  // @1
698                          };
699                          Execute68k((uint32)proc, &r);
700                          WriteMacInt32(XLM_68K_R25, old_r25);            // Restore interrupt level
# Line 596 | Line 718 | void HandleInterrupt(void)
718   *  Execute NATIVE_OP opcode (called by PowerPC emulator)
719   */
720  
721 < #define POWERPC_NATIVE_OP(selector) \
722 <                { tswap32(POWERPC_EMUL_OP | 2 | (((uint32)selector) << 6)) }
721 > #define POWERPC_NATIVE_OP_INIT(LR, OP) \
722 >                tswap32(POWERPC_EMUL_OP | ((LR) << 11) | (((uint32)OP) << 6) | 2)
723  
724   // FIXME: Make sure 32-bit relocations are used
725   const uint32 NativeOpTable[NATIVE_OP_MAX] = {
726 <        POWERPC_NATIVE_OP(NATIVE_PATCH_NAME_REGISTRY),
727 <        POWERPC_NATIVE_OP(NATIVE_VIDEO_INSTALL_ACCEL),
728 <        POWERPC_NATIVE_OP(NATIVE_VIDEO_VBL),
729 <        POWERPC_NATIVE_OP(NATIVE_VIDEO_DO_DRIVER_IO),
730 <        POWERPC_NATIVE_OP(NATIVE_ETHER_IRQ),
731 <        POWERPC_NATIVE_OP(NATIVE_ETHER_INIT),
732 <        POWERPC_NATIVE_OP(NATIVE_ETHER_TERM),
733 <        POWERPC_NATIVE_OP(NATIVE_ETHER_OPEN),
734 <        POWERPC_NATIVE_OP(NATIVE_ETHER_CLOSE),
735 <        POWERPC_NATIVE_OP(NATIVE_ETHER_WPUT),
736 <        POWERPC_NATIVE_OP(NATIVE_ETHER_RSRV),
737 <        POWERPC_NATIVE_OP(NATIVE_SERIAL_NOTHING),
738 <        POWERPC_NATIVE_OP(NATIVE_SERIAL_OPEN),
739 <        POWERPC_NATIVE_OP(NATIVE_SERIAL_PRIME_IN),
740 <        POWERPC_NATIVE_OP(NATIVE_SERIAL_PRIME_OUT),
741 <        POWERPC_NATIVE_OP(NATIVE_SERIAL_CONTROL),
742 <        POWERPC_NATIVE_OP(NATIVE_SERIAL_STATUS),
743 <        POWERPC_NATIVE_OP(NATIVE_SERIAL_CLOSE),
744 <        POWERPC_NATIVE_OP(NATIVE_GET_RESOURCE),
745 <        POWERPC_NATIVE_OP(NATIVE_GET_1_RESOURCE),
746 <        POWERPC_NATIVE_OP(NATIVE_GET_IND_RESOURCE),
747 <        POWERPC_NATIVE_OP(NATIVE_GET_1_IND_RESOURCE),
748 <        POWERPC_NATIVE_OP(NATIVE_R_GET_RESOURCE),
726 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_PATCH_NAME_REGISTRY),
727 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_VIDEO_INSTALL_ACCEL),
728 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_VIDEO_VBL),
729 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_VIDEO_DO_DRIVER_IO),
730 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_IRQ),
731 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_INIT),
732 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_TERM),
733 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_OPEN),
734 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_CLOSE),
735 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_WPUT),
736 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_RSRV),
737 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_NOTHING),
738 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_OPEN),
739 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_PRIME_IN),
740 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_PRIME_OUT),
741 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_CONTROL),
742 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_STATUS),
743 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_CLOSE),
744 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_GET_RESOURCE),
745 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_GET_1_RESOURCE),
746 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_GET_IND_RESOURCE),
747 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_GET_1_IND_RESOURCE),
748 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_R_GET_RESOURCE),
749 >        POWERPC_NATIVE_OP_INIT(0, NATIVE_DISABLE_INTERRUPT),
750 >        POWERPC_NATIVE_OP_INIT(0, NATIVE_ENABLE_INTERRUPT),
751   };
752  
753   static void get_resource(void);
# Line 685 | Line 809 | static void NativeOp(int selector)
809                  GPR(3) = serial_callbacks[selector - NATIVE_SERIAL_NOTHING](GPR(3), GPR(4));
810                  break;
811          }
812 +        case NATIVE_DISABLE_INTERRUPT:
813 +                DisableInterrupt();
814 +                break;
815 +        case NATIVE_ENABLE_INTERRUPT:
816 +                EnableInterrupt();
817 +                break;
818          default:
819                  printf("FATAL: NATIVE_OP called with bogus selector %d\n", selector);
820                  QuitEmulator();
# Line 808 | Line 938 | int atomic_or(int *var, int v)
938   *  Resource Manager thunks
939   */
940  
811 extern "C" void check_load_invoc(uint32 type, int16 id, uint16 **h);
812
941   void get_resource(void)
942   {
943          current_cpu->get_resource(ReadMacInt32(XLM_GET_RESOURCE));

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines