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.3 by gbeauche, 2003-09-29T07:05:15Z

# Line 21 | Line 21
21   #include "sysdeps.h"
22   #include "cpu_emulation.h"
23   #include "main.h"
24 + #include "prefs.h"
25   #include "xlowmem.h"
26   #include "emul_op.h"
27   #include "rom_patches.h"
28   #include "macos_util.h"
29   #include "block-alloc.hpp"
30   #include "sigsegv.h"
31 + #include "spcflags.h"
32   #include "cpu/ppc/ppc-cpu.hpp"
33   #include "cpu/ppc/ppc-operations.hpp"
34  
# Line 54 | Line 56 | static void enter_mon(void)
56   #endif
57   }
58  
59 + // Enable multicore (main/interrupts) cpu emulation?
60 + #define MULTICORE_CPU 0
61 +
62   // Enable Execute68k() safety checks?
63   #define SAFE_EXEC_68K 1
64  
# Line 99 | Line 104 | public:
104                  : powerpc_cpu()
105                  { init_decoder(); }
106  
102        // Stack pointer accessors
103        uint32 get_sp() const           { return gpr(1); }
104        void set_sp(uint32 v)           { gpr(1) = v; }
105
107          // Condition Register accessors
108          uint32 get_cr() const           { return cr().get(); }
109          void set_cr(uint32 v)           { cr().set(v); }
# Line 113 | Line 114 | public:
114          // Execute 68k routine
115          void execute_68k(uint32 entry, M68kRegisters *r);
116  
117 +        // Execute ppc routine
118 +        void execute_ppc(uint32 entry);
119 +
120          // Execute MacOS/PPC code
121          uint32 execute_macos_code(uint32 tvect, int nargs, uint32 const *args);
122  
# Line 120 | Line 124 | public:
124          void get_resource(uint32 old_get_resource);
125  
126          // Handle MacOS interrupt
127 <        void interrupt(uint32 entry, uint32 sp);
127 >        void interrupt(uint32 entry, sheepshaver_cpu *cpu);
128 >
129 >        // spcflags for interrupts handling
130 >        static uint32 spcflags;
131  
132          // Lazy memory allocator (one item at a time)
133          void *operator new(size_t size)
# Line 132 | Line 139 | public:
139          void operator delete[](void *p);
140   };
141  
142 + uint32 sheepshaver_cpu::spcflags = 0;
143   lazy_allocator< sheepshaver_cpu > allocator_helper< sheepshaver_cpu, lazy_allocator >::allocator;
144  
145   void sheepshaver_cpu::init_decoder()
# Line 163 | Line 171 | void sheepshaver_cpu::init_decoder()
171   // Forward declaration for native opcode handler
172   static void NativeOp(int selector);
173  
174 + /*              NativeOp instruction format:
175 +                +------------+--------------------------+--+----------+------------+
176 +                |      6     |                          |FN|    OP    |      2     |
177 +                +------------+--------------------------+--+----------+------------+
178 +                 0         5 |6                       19 20 21      25 26        31
179 + */
180 +
181 + typedef bit_field< 20, 20 > FN_field;
182 + typedef bit_field< 21, 25 > NATIVE_OP_field;
183 + typedef bit_field< 26, 31 > EMUL_OP_field;
184 +
185   // Execute SheepShaver instruction
186   void sheepshaver_cpu::execute_sheep(uint32 opcode)
187   {
# Line 179 | Line 198 | void sheepshaver_cpu::execute_sheep(uint
198                  break;
199  
200          case 2:         // EXEC_NATIVE
201 <                NativeOp((opcode >> 6) & 0x1f);
202 <                pc() = lr();
201 >                NativeOp(NATIVE_OP_field::extract(opcode));
202 >                if (FN_field::test(opcode))
203 >                        pc() = lr();
204 >                else
205 >                        pc() += 4;
206                  break;
207  
208          default: {      // EMUL_OP
# Line 192 | Line 214 | void sheepshaver_cpu::execute_sheep(uint
214                  for (int i = 0; i < 7; i++)
215                          r68.a[i] = gpr(16 + i);
216                  r68.a[7] = gpr(1);
217 <                EmulOp(&r68, gpr(24), (opcode & 0x3f) - 3);
217 >                EmulOp(&r68, gpr(24), EMUL_OP_field::extract(opcode) - 3);
218                  for (int i = 0; i < 8; i++)
219                          gpr(8 + i) = r68.d[i];
220                  for (int i = 0; i < 7; i++)
# Line 205 | Line 227 | void sheepshaver_cpu::execute_sheep(uint
227          }
228   }
229  
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 +
256   // Execution loop
257   void sheepshaver_cpu::execute(uint32 entry)
258   {
259          try {
260                  pc() = entry;
261 <                powerpc_cpu::execute();
261 >                powerpc_cpu::do_execute<execute_nothing, execute_spcflags_check>();
262          }
263          catch (sheepshaver_exec_return const &) {
264                  // Nothing, simply return
# Line 222 | Line 270 | void sheepshaver_cpu::execute(uint32 ent
270   }
271  
272   // Handle MacOS interrupt
273 < void sheepshaver_cpu::interrupt(uint32 entry, uint32 sp)
273 > void sheepshaver_cpu::interrupt(uint32 entry, sheepshaver_cpu *cpu)
274   {
275 + #if MULTICORE_CPU
276 +        // Initialize stack pointer from previous CPU running
277 +        gpr(1) = cpu->gpr(1);
278 + #else
279 +        // Save program counters and branch registers
280 +        uint32 saved_pc = pc();
281 +        uint32 saved_lr = lr();
282 +        uint32 saved_ctr= ctr();
283 + #endif
284 +
285          // Create stack frame
286 <        gpr(1) = sp - 64;
286 >        gpr(1) -= 64;
287  
288          // Build trampoline to return from interrupt
289          uint32 trampoline[] = { POWERPC_EMUL_OP | 1 };
# Line 235 | Line 293 | void sheepshaver_cpu::interrupt(uint32 e
293          kernel_data->v[0x018 >> 2] = gpr(6);
294  
295          gpr(6) = kernel_data->v[0x65c >> 2];
296 +        assert(gpr(6) != 0);
297          WriteMacInt32(gpr(6) + 0x13c, gpr(7));
298          WriteMacInt32(gpr(6) + 0x144, gpr(8));
299          WriteMacInt32(gpr(6) + 0x14c, gpr(9));
# Line 263 | Line 322 | void sheepshaver_cpu::interrupt(uint32 e
322  
323          // Cleanup stack
324          gpr(1) += 64;
325 +
326 + #if !MULTICORE_CPU
327 +        // Restore program counters and branch registers
328 +        pc() = saved_pc;
329 +        lr() = saved_lr;
330 +        ctr()= saved_ctr;
331 + #endif
332   }
333  
334   // Execute 68k routine
# Line 290 | Line 356 | void sheepshaver_cpu::execute_68k(uint32
356   #endif
357  
358          // Setup registers for 68k emulator
359 <        cr().set(0);
294 <        cr().set(2, 1);                                                         // Supervisor mode
359 >        cr().set(CR_SO_field<2>::mask());                       // Supervisor mode
360          for (int i = 0; i < 8; i++)                                     // d[0]..d[7]
361            gpr(8 + i) = r->d[i];
362          for (int i = 0; i < 7; i++)                                     // a[0]..a[6]
# Line 392 | Line 457 | uint32 sheepshaver_cpu::execute_macos_co
457          return retval;
458   }
459  
460 + // Execute ppc routine
461 + inline void sheepshaver_cpu::execute_ppc(uint32 entry)
462 + {
463 +        // Save branch registers
464 +        uint32 saved_lr = lr();
465 +        uint32 saved_ctr= ctr();
466 +
467 +        const uint32 trampoline[] = { POWERPC_EMUL_OP | 1 };
468 +
469 +        lr() = (uint32)trampoline;
470 +        ctr()= entry;
471 +        execute(entry);
472 +
473 +        // Restore branch registers
474 +        lr() = saved_lr;
475 +        ctr()= saved_ctr;
476 + }
477 +
478   // Resource Manager thunk
479 + extern "C" void check_load_invoc(uint32 type, int16 id, uint16 **h);
480 +
481   inline void sheepshaver_cpu::get_resource(uint32 old_get_resource)
482   {
483 <        printf("ERROR: get_resource() unimplemented\n");
484 <        QuitEmulator();
483 >        uint32 type = gpr(3);
484 >        int16 id = gpr(4);
485 >
486 >        // Create stack frame
487 >        gpr(1) -= 56;
488 >
489 >        // Call old routine
490 >        execute_ppc(old_get_resource);
491 >        uint16 **handle = (uint16 **)gpr(3);
492 >
493 >        // Call CheckLoad()
494 >        check_load_invoc(type, id, handle);
495 >        gpr(3) = (uint32)handle;
496 >
497 >        // Cleanup stack
498 >        gpr(1) += 56;
499   }
500  
501  
# Line 408 | Line 507 | static sheepshaver_cpu *main_cpu = NULL;
507   static sheepshaver_cpu *interrupt_cpu = NULL;   // CPU emulator to handle interrupts
508   static sheepshaver_cpu *current_cpu = NULL;             // Current CPU emulator context
509  
510 + static inline void cpu_push(sheepshaver_cpu *new_cpu)
511 + {
512 + #if MULTICORE_CPU
513 +        current_cpu = new_cpu;
514 + #endif
515 + }
516 +
517 + static inline void cpu_pop()
518 + {
519 + #if MULTICORE_CPU
520 +        current_cpu = main_cpu;
521 + #endif
522 + }
523 +
524   // Dump PPC registers
525   static void dump_registers(void)
526   {
# Line 424 | Line 537 | static void dump_log(void)
537   *  Initialize CPU emulation
538   */
539  
540 < static struct sigaction sigsegv_action;
428 <
429 < #if defined(__powerpc__)
430 < #include <sys/ucontext.h>
431 < #endif
432 <
433 < static void sigsegv_handler(int sig, siginfo_t *sip, void *scp)
540 > static sigsegv_return_t sigsegv_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction)
541   {
435        const uintptr addr = (uintptr)sip->si_addr;
542   #if ENABLE_VOSF
543 <        // Handle screen fault.
544 <        extern bool Screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction);
545 <        if (Screen_fault_handler((sigsegv_address_t)addr, SIGSEGV_INVALID_PC))
546 <                return;
441 < #endif
442 < #if defined(__powerpc__)
443 <        if (addr >= ROM_BASE && addr < ROM_BASE + ROM_SIZE) {
444 <                printf("IGNORE write access to ROM at %08x\n", addr);
445 <                (((ucontext_t *)scp)->uc_mcontext.regs)->nip += 4;
446 <                return;
447 <        }
448 <        if (addr >= 0xf3012000 && addr < 0xf3014000 && 0) {
449 <                printf("IGNORE write access to ROM at %08x\n", addr);
450 <                (((ucontext_t *)scp)->uc_mcontext.regs)->nip += 4;
451 <                return;
452 <        }
543 >        // Handle screen fault
544 >        extern bool Screen_fault_handler(sigsegv_address_t, sigsegv_address_t);
545 >        if (Screen_fault_handler(fault_address, fault_instruction))
546 >                return SIGSEGV_RETURN_SUCCESS;
547   #endif
548 <        printf("Caught SIGSEGV at address %p\n", sip->si_addr);
549 <        printf("Native PC: %08x\n", (((ucontext_t *)scp)->uc_mcontext.regs)->nip);
550 <        printf("Current CPU: %s\n", current_cpu == main_cpu ? "main" : "interrupts");
551 < #if 1
552 <        dump_registers();
548 >
549 >        const uintptr addr = (uintptr)fault_address;
550 > #if HAVE_SIGSEGV_SKIP_INSTRUCTION
551 >        // Ignore writes to ROM
552 >        if ((addr - ROM_BASE) < ROM_SIZE)
553 >                return SIGSEGV_RETURN_SKIP_INSTRUCTION;
554 >
555 >        // Ignore all other faults, if requested
556 >        if (PrefsFindBool("ignoresegv"))
557 >                return SIGSEGV_RETURN_FAILURE;
558   #else
559 <        printf("Main CPU context\n");
461 <        main_cpu->dump_registers();
462 <        printf("Interrupts CPU context\n");
463 <        interrupt_cpu->dump_registers();
559 > #error "FIXME: You don't have the capability to skip instruction within signal handlers"
560   #endif
561 +
562 +        printf("SIGSEGV\n");
563 +        printf("  pc %p\n", fault_instruction);
564 +        printf("  ea %p\n", fault_address);
565 +        printf(" cpu %s\n", current_cpu == main_cpu ? "main" : "interrupts");
566 +        dump_registers();
567          current_cpu->dump_log();
466        WriteMacInt32(XLM_IRQ_NEST, 1);
568          enter_mon();
569          QuitEmulator();
570 +
571 +        return SIGSEGV_RETURN_FAILURE;
572   }
573  
574   void init_emul_ppc(void)
# Line 475 | Line 578 | void init_emul_ppc(void)
578          main_cpu->set_register(powerpc_registers::GPR(3), any_register((uint32)ROM_BASE + 0x30d000));
579          WriteMacInt32(XLM_RUN_MODE, MODE_68K);
580  
581 + #if MULTICORE_CPU
582          // Initialize alternate CPU emulator to handle interrupts
583          interrupt_cpu = new sheepshaver_cpu();
584 + #endif
585  
586 <        // Install SIGSEGV handler
587 <        sigemptyset(&sigsegv_action.sa_mask);
588 <        sigsegv_action.sa_sigaction = sigsegv_handler;
484 <        sigsegv_action.sa_flags = SA_SIGINFO;
485 <        sigsegv_action.sa_restorer = NULL;
486 <        sigaction(SIGSEGV, &sigsegv_action, NULL);
487 <
586 >        // Install the handler for SIGSEGV
587 >        sigsegv_install_handler(sigsegv_handler);
588 >        
589   #if ENABLE_MON
590          // Install "regs" command in cxmon
591          mon_add_command("regs", dump_registers, "regs                     Dump PowerPC registers\n");
# Line 512 | Line 613 | extern int atomic_add(int *var, int v);
613   extern int atomic_and(int *var, int v);
614   extern int atomic_or(int *var, int v);
615  
616 < void HandleInterrupt(void)
616 > void TriggerInterrupt(void)
617 > {
618 > #if 0
619 >  WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
620 > #else
621 >  SPCFLAGS_SET( SPCFLAG_INT );
622 > #endif
623 > }
624 >
625 > static void HandleInterrupt(void)
626   {
627          // Do nothing if interrupts are disabled
628 <        if (ReadMacInt32(XLM_IRQ_NEST) > 0 || InterruptFlags == 0)
628 >        if (int32(ReadMacInt32(XLM_IRQ_NEST)) > 0)
629                  return;
630  
631 <        // Do nothing if CPU objects are not initialized yet
632 <        if (current_cpu == NULL)
631 >        // Do nothing if there is no interrupt pending
632 >        if (InterruptFlags == 0)
633                  return;
634  
635          // Disable MacOS stack sniffer
# Line 546 | Line 656 | void HandleInterrupt(void)
656                                                    | tswap32(kernel_data->v[0x674 >> 2]));
657        
658                          // Execute nanokernel interrupt routine (this will activate the 68k emulator)
659 <                        atomic_add((int32 *)XLM_IRQ_NEST, htonl(1));
660 <                        current_cpu = interrupt_cpu;
659 >                        DisableInterrupt();
660 >                        cpu_push(interrupt_cpu);
661                          if (ROMType == ROMTYPE_NEWWORLD)
662 <                                current_cpu->interrupt(ROM_BASE + 0x312b1c, main_cpu->get_sp());
662 >                                current_cpu->interrupt(ROM_BASE + 0x312b1c, main_cpu);
663                          else
664 <                                current_cpu->interrupt(ROM_BASE + 0x312a3c, main_cpu->get_sp());
665 <                        current_cpu = main_cpu;
664 >                                current_cpu->interrupt(ROM_BASE + 0x312a3c, main_cpu);
665 >                        cpu_pop();
666                  }
667                  break;
668   #endif
# Line 566 | Line 676 | void HandleInterrupt(void)
676                          M68kRegisters r;
677                          uint32 old_r25 = ReadMacInt32(XLM_68K_R25);     // Save interrupt level
678                          WriteMacInt32(XLM_68K_R25, 0x21);                       // Execute with interrupt level 1
679 <                        static const uint16 proc[] = {
680 <                                0x3f3c, 0x0000,         // move.w       #$0000,-(sp)    (fake format word)
681 <                                0x487a, 0x000a,         // pea          @1(pc)                  (return address)
682 <                                0x40e7,                         // move         sr,-(sp)                (saved SR)
683 <                                0x2078, 0x0064,         // move.l       $64,a0
684 <                                0x4ed0,                         // jmp          (a0)
685 <                                M68K_RTS                        // @1
679 >                        static const uint8 proc[] = {
680 >                                0x3f, 0x3c, 0x00, 0x00,                 // move.w       #$0000,-(sp)    (fake format word)
681 >                                0x48, 0x7a, 0x00, 0x0a,                 // pea          @1(pc)                  (return address)
682 >                                0x40, 0xe7,                                             // move         sr,-(sp)                (saved SR)
683 >                                0x20, 0x78, 0x00, 0x064,                // move.l       $64,a0
684 >                                0x4e, 0xd0,                                             // jmp          (a0)
685 >                                M68K_RTS >> 8, M68K_RTS & 0xff  // @1
686                          };
687                          Execute68k((uint32)proc, &r);
688                          WriteMacInt32(XLM_68K_R25, old_r25);            // Restore interrupt level
# Line 596 | Line 706 | void HandleInterrupt(void)
706   *  Execute NATIVE_OP opcode (called by PowerPC emulator)
707   */
708  
709 < #define POWERPC_NATIVE_OP(selector) \
710 <                { tswap32(POWERPC_EMUL_OP | 2 | (((uint32)selector) << 6)) }
709 > #define POWERPC_NATIVE_OP_INIT(LR, OP) \
710 >                tswap32(POWERPC_EMUL_OP | ((LR) << 11) | (((uint32)OP) << 6) | 2)
711  
712   // FIXME: Make sure 32-bit relocations are used
713   const uint32 NativeOpTable[NATIVE_OP_MAX] = {
714 <        POWERPC_NATIVE_OP(NATIVE_PATCH_NAME_REGISTRY),
715 <        POWERPC_NATIVE_OP(NATIVE_VIDEO_INSTALL_ACCEL),
716 <        POWERPC_NATIVE_OP(NATIVE_VIDEO_VBL),
717 <        POWERPC_NATIVE_OP(NATIVE_VIDEO_DO_DRIVER_IO),
718 <        POWERPC_NATIVE_OP(NATIVE_ETHER_IRQ),
719 <        POWERPC_NATIVE_OP(NATIVE_ETHER_INIT),
720 <        POWERPC_NATIVE_OP(NATIVE_ETHER_TERM),
721 <        POWERPC_NATIVE_OP(NATIVE_ETHER_OPEN),
722 <        POWERPC_NATIVE_OP(NATIVE_ETHER_CLOSE),
723 <        POWERPC_NATIVE_OP(NATIVE_ETHER_WPUT),
724 <        POWERPC_NATIVE_OP(NATIVE_ETHER_RSRV),
725 <        POWERPC_NATIVE_OP(NATIVE_SERIAL_NOTHING),
726 <        POWERPC_NATIVE_OP(NATIVE_SERIAL_OPEN),
727 <        POWERPC_NATIVE_OP(NATIVE_SERIAL_PRIME_IN),
728 <        POWERPC_NATIVE_OP(NATIVE_SERIAL_PRIME_OUT),
729 <        POWERPC_NATIVE_OP(NATIVE_SERIAL_CONTROL),
730 <        POWERPC_NATIVE_OP(NATIVE_SERIAL_STATUS),
731 <        POWERPC_NATIVE_OP(NATIVE_SERIAL_CLOSE),
732 <        POWERPC_NATIVE_OP(NATIVE_GET_RESOURCE),
733 <        POWERPC_NATIVE_OP(NATIVE_GET_1_RESOURCE),
734 <        POWERPC_NATIVE_OP(NATIVE_GET_IND_RESOURCE),
735 <        POWERPC_NATIVE_OP(NATIVE_GET_1_IND_RESOURCE),
736 <        POWERPC_NATIVE_OP(NATIVE_R_GET_RESOURCE),
714 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_PATCH_NAME_REGISTRY),
715 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_VIDEO_INSTALL_ACCEL),
716 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_VIDEO_VBL),
717 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_VIDEO_DO_DRIVER_IO),
718 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_IRQ),
719 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_INIT),
720 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_TERM),
721 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_OPEN),
722 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_CLOSE),
723 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_WPUT),
724 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_ETHER_RSRV),
725 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_NOTHING),
726 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_OPEN),
727 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_PRIME_IN),
728 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_PRIME_OUT),
729 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_CONTROL),
730 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_STATUS),
731 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_SERIAL_CLOSE),
732 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_GET_RESOURCE),
733 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_GET_1_RESOURCE),
734 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_GET_IND_RESOURCE),
735 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_GET_1_IND_RESOURCE),
736 >        POWERPC_NATIVE_OP_INIT(1, NATIVE_R_GET_RESOURCE),
737 >        POWERPC_NATIVE_OP_INIT(0, NATIVE_DISABLE_INTERRUPT),
738 >        POWERPC_NATIVE_OP_INIT(0, NATIVE_ENABLE_INTERRUPT),
739   };
740  
741   static void get_resource(void);
# Line 685 | Line 797 | static void NativeOp(int selector)
797                  GPR(3) = serial_callbacks[selector - NATIVE_SERIAL_NOTHING](GPR(3), GPR(4));
798                  break;
799          }
800 +        case NATIVE_DISABLE_INTERRUPT:
801 +                DisableInterrupt();
802 +                break;
803 +        case NATIVE_ENABLE_INTERRUPT:
804 +                EnableInterrupt();
805 +                break;
806          default:
807                  printf("FATAL: NATIVE_OP called with bogus selector %d\n", selector);
808                  QuitEmulator();
# Line 808 | Line 926 | int atomic_or(int *var, int v)
926   *  Resource Manager thunks
927   */
928  
811 extern "C" void check_load_invoc(uint32 type, int16 id, uint16 **h);
812
929   void get_resource(void)
930   {
931          current_cpu->get_resource(ReadMacInt32(XLM_GET_RESOURCE));

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines