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.17 by gbeauche, 2003-11-10T16:23:58Z

# 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 36 | Line 35
35   #include "video.h"
36   #include "name_registry.h"
37   #include "serial.h"
38 + #include "ether.h"
39  
40   #include <stdio.h>
41  
# Line 44 | Line 44
44   #include "mon_disass.h"
45   #endif
46  
47 < #define DEBUG 1
47 > #define DEBUG 0
48   #include "debug.h"
49  
50 + // Emulation time statistics
51 + #define EMUL_TIME_STATS 1
52 +
53 + #if EMUL_TIME_STATS
54 + static clock_t emul_start_time;
55 + static uint32 interrupt_count = 0;
56 + static clock_t interrupt_time = 0;
57 + static uint32 exec68k_count = 0;
58 + static clock_t exec68k_time = 0;
59 + static uint32 native_exec_count = 0;
60 + static clock_t native_exec_time = 0;
61 + static uint32 macos_exec_count = 0;
62 + static clock_t macos_exec_time = 0;
63 + #endif
64 +
65   static void enter_mon(void)
66   {
67          // Start up mon in real-mode
# Line 57 | Line 72 | static void enter_mon(void)
72   }
73  
74   // Enable multicore (main/interrupts) cpu emulation?
75 < #define MULTICORE_CPU 0
75 > #define MULTICORE_CPU (ASYNC_IRQ ? 1 : 0)
76  
77   // Enable Execute68k() safety checks?
78   #define SAFE_EXEC_68K 1
# Line 71 | Line 86 | static void enter_mon(void)
86   // Interrupts in native mode?
87   #define INTERRUPTS_IN_NATIVE_MODE 1
88  
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
89   // Pointer to Kernel Data
90 < static KernelData * const kernel_data = (KernelData *)0x68ffe000;
90 > static KernelData * const kernel_data = (KernelData *)KERNEL_DATA_BASE;
91 >
92 > // SIGSEGV handler
93 > static sigsegv_return_t sigsegv_handler(sigsegv_address_t, sigsegv_address_t);
94  
95  
96   /**
97   *              PowerPC emulator glue with special 'sheep' opcodes
98   **/
99  
93 struct sheepshaver_exec_return { };
94
100   class sheepshaver_cpu
101          : public powerpc_cpu
102   {
# Line 100 | Line 105 | class sheepshaver_cpu
105  
106   public:
107  
108 <        sheepshaver_cpu()
109 <                : powerpc_cpu()
105 <                { init_decoder(); }
108 >        // Constructor
109 >        sheepshaver_cpu();
110  
111          // Condition Register accessors
112          uint32 get_cr() const           { return cr().get(); }
113          void set_cr(uint32 v)           { cr().set(v); }
114  
115          // Execution loop
116 <        void execute(uint32 pc);
116 >        void execute(uint32 entry, bool enable_cache = false);
117  
118          // Execute 68k routine
119          void execute_68k(uint32 entry, M68kRegisters *r);
# Line 124 | Line 128 | public:
128          void get_resource(uint32 old_get_resource);
129  
130          // Handle MacOS interrupt
131 <        void interrupt(uint32 entry, sheepshaver_cpu *cpu);
132 <
129 <        // spcflags for interrupts handling
130 <        static uint32 spcflags;
131 >        void interrupt(uint32 entry);
132 >        void handle_interrupt();
133  
134          // Lazy memory allocator (one item at a time)
135          void *operator new(size_t size)
# Line 137 | Line 139 | public:
139          // FIXME: really make surre array allocation fail at link time?
140          void *operator new[](size_t);
141          void operator delete[](void *p);
142 +
143 +        // Make sure the SIGSEGV handler can access CPU registers
144 +        friend sigsegv_return_t sigsegv_handler(sigsegv_address_t, sigsegv_address_t);
145   };
146  
142 uint32 sheepshaver_cpu::spcflags = 0;
147   lazy_allocator< sheepshaver_cpu > allocator_helper< sheepshaver_cpu, lazy_allocator >::allocator;
148  
149 + sheepshaver_cpu::sheepshaver_cpu()
150 +        : powerpc_cpu()
151 + {
152 +        init_decoder();
153 + }
154 +
155   void sheepshaver_cpu::init_decoder()
156   {
157   #ifndef PPC_NO_STATIC_II_INDEX_TABLE
# Line 153 | Line 163 | void sheepshaver_cpu::init_decoder()
163  
164          static const instr_info_t sheep_ii_table[] = {
165                  { "sheep",
166 <                  (execute_fn)&sheepshaver_cpu::execute_sheep,
166 >                  (execute_pmf)&sheepshaver_cpu::execute_sheep,
167                    NULL,
168 <                  D_form, 6, 0, CFLOW_TRAP
168 >                  D_form, 6, 0, CFLOW_JUMP | CFLOW_TRAP
169                  }
170          };
171  
# Line 192 | Line 202 | void sheepshaver_cpu::execute_sheep(uint
202          case 0:         // EMUL_RETURN
203                  QuitEmulator();
204                  break;
205 <                
205 >
206          case 1:         // EXEC_RETURN
207 <                throw sheepshaver_exec_return();
207 >                spcflags().set(SPCFLAG_CPU_EXEC_RETURN);
208                  break;
209  
210          case 2:         // EXEC_NATIVE
# Line 227 | Line 237 | void sheepshaver_cpu::execute_sheep(uint
237          }
238   }
239  
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
240   // Execution loop
241 < void sheepshaver_cpu::execute(uint32 entry)
241 > void sheepshaver_cpu::execute(uint32 entry, bool enable_cache)
242   {
243 <        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 <        }
243 >        powerpc_cpu::execute(entry, enable_cache);
244   }
245  
246   // Handle MacOS interrupt
247 < void sheepshaver_cpu::interrupt(uint32 entry, sheepshaver_cpu *cpu)
247 > void sheepshaver_cpu::interrupt(uint32 entry)
248   {
249 < #if MULTICORE_CPU
250 <        // Initialize stack pointer from previous CPU running
251 <        gpr(1) = cpu->gpr(1);
252 < #else
249 > #if EMUL_TIME_STATS
250 >        interrupt_count++;
251 >        const clock_t interrupt_start = clock();
252 > #endif
253 >
254 > #if !MULTICORE_CPU
255          // Save program counters and branch registers
256          uint32 saved_pc = pc();
257          uint32 saved_lr = lr();
258          uint32 saved_ctr= ctr();
259 +        uint32 saved_sp = gpr(1);
260   #endif
261  
262 <        // Create stack frame
263 <        gpr(1) -= 64;
262 >        // Initialize stack pointer to SheepShaver alternate stack base
263 >        gpr(1) = SheepStack1Base - 64;
264  
265          // Build trampoline to return from interrupt
266 <        uint32 trampoline[] = { POWERPC_EMUL_OP | 1 };
266 >        uint32 trampoline[] = { htonl(POWERPC_EMUL_OP | 1) };
267  
268          // Prepare registers for nanokernel interrupt routine
269 <        kernel_data->v[0x004 >> 2] = gpr(1);
270 <        kernel_data->v[0x018 >> 2] = gpr(6);
269 >        kernel_data->v[0x004 >> 2] = htonl(gpr(1));
270 >        kernel_data->v[0x018 >> 2] = htonl(gpr(6));
271  
272 <        gpr(6) = kernel_data->v[0x65c >> 2];
272 >        gpr(6) = ntohl(kernel_data->v[0x65c >> 2]);
273          assert(gpr(6) != 0);
274          WriteMacInt32(gpr(6) + 0x13c, gpr(7));
275          WriteMacInt32(gpr(6) + 0x144, gpr(8));
# Line 303 | Line 280 | void sheepshaver_cpu::interrupt(uint32 e
280          WriteMacInt32(gpr(6) + 0x16c, gpr(13));
281  
282          gpr(1)  = KernelDataAddr;
283 <        gpr(7)  = kernel_data->v[0x660 >> 2];
283 >        gpr(7)  = ntohl(kernel_data->v[0x660 >> 2]);
284          gpr(8)  = 0;
285          gpr(10) = (uint32)trampoline;
286          gpr(12) = (uint32)trampoline;
287 <        gpr(13) = cr().get();
287 >        gpr(13) = get_cr();
288  
289          // rlwimi. r7,r7,8,0,0
290          uint32 result = op_ppc_rlwimi::apply(gpr(7), 8, 0x80000000, gpr(7));
# Line 315 | Line 292 | void sheepshaver_cpu::interrupt(uint32 e
292          gpr(7) = result;
293  
294          gpr(11) = 0xf072; // MSR (SRR1)
295 <        cr().set((gpr(11) & 0x0fff0000) | (cr().get() & ~0x0fff0000));
295 >        cr().set((gpr(11) & 0x0fff0000) | (get_cr() & ~0x0fff0000));
296  
297          // Enter nanokernel
298          execute(entry);
299  
323        // Cleanup stack
324        gpr(1) += 64;
325
300   #if !MULTICORE_CPU
301          // Restore program counters and branch registers
302          pc() = saved_pc;
303          lr() = saved_lr;
304          ctr()= saved_ctr;
305 +        gpr(1) = saved_sp;
306 + #endif
307 +
308 + #if EMUL_TIME_STATS
309 +        interrupt_time += (clock() - interrupt_start);
310   #endif
311   }
312  
313   // Execute 68k routine
314   void sheepshaver_cpu::execute_68k(uint32 entry, M68kRegisters *r)
315   {
316 + #if EMUL_TIME_STATS
317 +        exec68k_count++;
318 +        const clock_t exec68k_start = clock();
319 + #endif
320 +
321   #if SAFE_EXEC_68K
322          if (ReadMacInt32(XLM_RUN_MODE) != MODE_EMUL_OP)
323                  printf("FATAL: Execute68k() not called from EMUL_OP mode\n");
# Line 343 | Line 327 | void sheepshaver_cpu::execute_68k(uint32
327          uint32 saved_pc = pc();
328          uint32 saved_lr = lr();
329          uint32 saved_ctr= ctr();
330 +        uint32 saved_cr = get_cr();
331  
332          // Create MacOS stack frame
333 +        // FIXME: make sure MacOS doesn't expect PPC registers to live on top
334          uint32 sp = gpr(1);
335 <        gpr(1) -= 56 + 19*4 + 18*8;
335 >        gpr(1) -= 56;
336          WriteMacInt32(gpr(1), sp);
337  
338          // Save PowerPC registers
339 <        memcpy(Mac2HostAddr(gpr(1)+56), &gpr(13), sizeof(uint32)*(32-13));
339 >        uint32 saved_GPRs[19];
340 >        memcpy(&saved_GPRs[0], &gpr(13), sizeof(uint32)*(32-13));
341   #if SAVE_FP_EXEC_68K
342 <        memcpy(Mac2HostAddr(gpr(1)+56+19*4), &fpr(14), sizeof(double)*(32-14));
342 >        double saved_FPRs[18];
343 >        memcpy(&saved_FPRs[0], &fpr(14), sizeof(double)*(32-14));
344   #endif
345  
346          // Setup registers for 68k emulator
# Line 366 | Line 354 | void sheepshaver_cpu::execute_68k(uint32
354          gpr(25) = ReadMacInt32(XLM_68K_R25);            // MSB of SR
355          gpr(26) = 0;
356          gpr(28) = 0;                                                            // VBR
357 <        gpr(29) = kernel_data->ed.v[0x74 >> 2];         // Pointer to opcode table
358 <        gpr(30) = kernel_data->ed.v[0x78 >> 2];         // Address of emulator
357 >        gpr(29) = ntohl(kernel_data->ed.v[0x74 >> 2]);          // Pointer to opcode table
358 >        gpr(30) = ntohl(kernel_data->ed.v[0x78 >> 2]);          // Address of emulator
359          gpr(31) = KernelDataAddr + 0x1000;
360  
361          // Push return address (points to EXEC_RETURN opcode) on stack
# Line 399 | Line 387 | void sheepshaver_cpu::execute_68k(uint32
387            r->a[i] = gpr(16 + i);
388  
389          // Restore PowerPC registers
390 <        memcpy(&gpr(13), Mac2HostAddr(gpr(1)+56), sizeof(uint32)*(32-13));
390 >        memcpy(&gpr(13), &saved_GPRs[0], sizeof(uint32)*(32-13));
391   #if SAVE_FP_EXEC_68K
392 <        memcpy(&fpr(14), Mac2HostAddr(gpr(1)+56+19*4), sizeof(double)*(32-14));
392 >        memcpy(&fpr(14), &saved_FPRs[0], sizeof(double)*(32-14));
393   #endif
394  
395          // Cleanup stack
396 <        gpr(1) += 56 + 19*4 + 18*8;
396 >        gpr(1) += 56;
397  
398          // Restore program counters and branch registers
399          pc() = saved_pc;
400          lr() = saved_lr;
401          ctr()= saved_ctr;
402 +        set_cr(saved_cr);
403 +
404 + #if EMUL_TIME_STATS
405 +        exec68k_time += (clock() - exec68k_start);
406 + #endif
407   }
408  
409   // Call MacOS PPC code
410   uint32 sheepshaver_cpu::execute_macos_code(uint32 tvect, int nargs, uint32 const *args)
411   {
412 + #if EMUL_TIME_STATS
413 +        macos_exec_count++;
414 +        const clock_t macos_exec_start = clock();
415 + #endif
416 +
417          // Save program counters and branch registers
418          uint32 saved_pc = pc();
419          uint32 saved_lr = lr();
420          uint32 saved_ctr= ctr();
421  
422          // Build trampoline with EXEC_RETURN
423 <        uint32 trampoline[] = { POWERPC_EMUL_OP | 1 };
423 >        uint32 trampoline[] = { htonl(POWERPC_EMUL_OP | 1) };
424          lr() = (uint32)trampoline;
425  
426          gpr(1) -= 64;                                                           // Create stack frame
# Line 454 | Line 452 | uint32 sheepshaver_cpu::execute_macos_co
452          lr() = saved_lr;
453          ctr()= saved_ctr;
454  
455 + #if EMUL_TIME_STATS
456 +        macos_exec_time += (clock() - macos_exec_start);
457 + #endif
458 +
459          return retval;
460   }
461  
# Line 462 | Line 464 | inline void sheepshaver_cpu::execute_ppc
464   {
465          // Save branch registers
466          uint32 saved_lr = lr();
465        uint32 saved_ctr= ctr();
466
467        const uint32 trampoline[] = { POWERPC_EMUL_OP | 1 };
467  
468 +        const uint32 trampoline[] = { htonl(POWERPC_EMUL_OP | 1) };
469          lr() = (uint32)trampoline;
470 <        ctr()= entry;
470 >
471          execute(entry);
472  
473          // Restore branch registers
474          lr() = saved_lr;
475        ctr()= saved_ctr;
475   }
476  
477   // Resource Manager thunk
478 < extern "C" void check_load_invoc(uint32 type, int16 id, uint16 **h);
478 > extern "C" void check_load_invoc(uint32 type, int16 id, uint32 h);
479  
480   inline void sheepshaver_cpu::get_resource(uint32 old_get_resource)
481   {
# Line 488 | Line 487 | inline void sheepshaver_cpu::get_resourc
487  
488          // Call old routine
489          execute_ppc(old_get_resource);
491        uint16 **handle = (uint16 **)gpr(3);
490  
491          // Call CheckLoad()
492 +        uint32 handle = gpr(3);
493          check_load_invoc(type, id, handle);
494 <        gpr(3) = (uint32)handle;
494 >        gpr(3) = handle;
495  
496          // Cleanup stack
497          gpr(1) += 56;
# Line 507 | 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 + void FlushCodeCache(uintptr start, uintptr end)
510 + {
511 +        D(bug("FlushCodeCache(%08x, %08x)\n", start, end));
512 +        main_cpu->invalidate_cache_range(start, end);
513 + #if MULTICORE_CPU
514 +        interrupt_cpu->invalidate_cache_range(start, end);
515 + #endif
516 + }
517 +
518   static inline void cpu_push(sheepshaver_cpu *new_cpu)
519   {
520   #if MULTICORE_CPU
# Line 552 | Line 560 | static sigsegv_return_t sigsegv_handler(
560          if ((addr - ROM_BASE) < ROM_SIZE)
561                  return SIGSEGV_RETURN_SKIP_INSTRUCTION;
562  
563 <        // Ignore all other faults, if requested
564 <        if (PrefsFindBool("ignoresegv"))
565 <                return SIGSEGV_RETURN_FAILURE;
563 >        // Get program counter of target CPU
564 >        sheepshaver_cpu * const cpu = current_cpu;
565 >        const uint32 pc = cpu->pc();
566 >        
567 >        // Fault in Mac ROM or RAM?
568 >        bool mac_fault = (pc >= ROM_BASE) && (pc < (ROM_BASE + ROM_AREA_SIZE)) || (pc >= RAMBase) && (pc < (RAMBase + RAMSize));
569 >        if (mac_fault) {
570 >
571 >                // "VM settings" during MacOS 8 installation
572 >                if (pc == ROM_BASE + 0x488160 && cpu->gpr(20) == 0xf8000000)
573 >                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
574 >        
575 >                // MacOS 8.5 installation
576 >                else if (pc == ROM_BASE + 0x488140 && cpu->gpr(16) == 0xf8000000)
577 >                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
578 >        
579 >                // MacOS 8 serial drivers on startup
580 >                else if (pc == ROM_BASE + 0x48e080 && (cpu->gpr(8) == 0xf3012002 || cpu->gpr(8) == 0xf3012000))
581 >                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
582 >        
583 >                // MacOS 8.1 serial drivers on startup
584 >                else if (pc == ROM_BASE + 0x48c5e0 && (cpu->gpr(20) == 0xf3012002 || cpu->gpr(20) == 0xf3012000))
585 >                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
586 >                else if (pc == ROM_BASE + 0x4a10a0 && (cpu->gpr(20) == 0xf3012002 || cpu->gpr(20) == 0xf3012000))
587 >                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
588 >
589 >                // Ignore all other faults, if requested
590 >                if (PrefsFindBool("ignoresegv"))
591 >                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
592 >        }
593   #else
594   #error "FIXME: You don't have the capability to skip instruction within signal handlers"
595   #endif
# Line 585 | Line 620 | void init_emul_ppc(void)
620  
621          // Install the handler for SIGSEGV
622          sigsegv_install_handler(sigsegv_handler);
623 <        
623 >
624   #if ENABLE_MON
625          // Install "regs" command in cxmon
626          mon_add_command("regs", dump_registers, "regs                     Dump PowerPC registers\n");
627          mon_add_command("log", dump_log, "log                      Dump PowerPC emulation log\n");
628   #endif
629 +
630 + #if EMUL_TIME_STATS
631 +        emul_start_time = clock();
632 + #endif
633 + }
634 +
635 + /*
636 + *  Deinitialize emulation
637 + */
638 +
639 + void exit_emul_ppc(void)
640 + {
641 + #if EMUL_TIME_STATS
642 +        clock_t emul_end_time = clock();
643 +
644 +        printf("### Statistics for SheepShaver emulation parts\n");
645 +        const clock_t emul_time = emul_end_time - emul_start_time;
646 +        printf("Total emulation time : %.1f sec\n", double(emul_time) / double(CLOCKS_PER_SEC));
647 +        printf("Total interrupt count: %d (%2.1f Hz)\n", interrupt_count,
648 +                   (double(interrupt_count) * CLOCKS_PER_SEC) / double(emul_time));
649 +
650 + #define PRINT_STATS(LABEL, VAR_PREFIX) do {                                                             \
651 +                printf("Total " LABEL " count : %d\n", VAR_PREFIX##_count);             \
652 +                printf("Total " LABEL " time  : %.1f sec (%.1f%%)\n",                   \
653 +                           double(VAR_PREFIX##_time) / double(CLOCKS_PER_SEC),          \
654 +                           100.0 * double(VAR_PREFIX##_time) / double(emul_time));      \
655 +        } while (0)
656 +
657 +        PRINT_STATS("Execute68k[Trap] execution", exec68k);
658 +        PRINT_STATS("NativeOp execution", native_exec);
659 +        PRINT_STATS("MacOS routine execution", macos_exec);
660 +
661 + #undef PRINT_STATS
662 +        printf("\n");
663 + #endif
664 +
665 +        delete main_cpu;
666 + #if MULTICORE_CPU
667 +        delete interrupt_cpu;
668 + #endif
669   }
670  
671   /*
# Line 600 | Line 675 | void init_emul_ppc(void)
675   void emul_ppc(uint32 entry)
676   {
677          current_cpu = main_cpu;
678 + #if DEBUG
679          current_cpu->start_log();
680 <        current_cpu->execute(entry);
680 > #endif
681 >        // start emulation loop and enable code translation or caching
682 >        current_cpu->execute(entry, true);
683   }
684  
685   /*
686   *  Handle PowerPC interrupt
687   */
688  
689 < // Atomic operations
690 < extern int atomic_add(int *var, int v);
691 < extern int atomic_and(int *var, int v);
692 < extern int atomic_or(int *var, int v);
693 <
689 > #if ASYNC_IRQ
690 > void HandleInterrupt(void)
691 > {
692 >        main_cpu->handle_interrupt();
693 > }
694 > #else
695   void TriggerInterrupt(void)
696   {
697   #if 0
698    WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
699   #else
700 <  SPCFLAGS_SET( SPCFLAG_INT );
700 >  // Trigger interrupt to main cpu only
701 >  if (main_cpu)
702 >          main_cpu->trigger_interrupt();
703   #endif
704   }
705 + #endif
706  
707 < static void HandleInterrupt(void)
707 > void sheepshaver_cpu::handle_interrupt(void)
708   {
709          // Do nothing if interrupts are disabled
710 <        if (int32(ReadMacInt32(XLM_IRQ_NEST)) > 0)
710 >        if (*(int32 *)XLM_IRQ_NEST > 0)
711                  return;
712  
713          // Do nothing if there is no interrupt pending
# Line 641 | Line 723 | static void HandleInterrupt(void)
723                  // 68k emulator active, trigger 68k interrupt level 1
724                  assert(current_cpu == main_cpu);
725                  WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1);
726 <                main_cpu->set_cr(main_cpu->get_cr() | tswap32(kernel_data->v[0x674 >> 2]));
726 >                set_cr(get_cr() | tswap32(kernel_data->v[0x674 >> 2]));
727                  break;
728      
729   #if INTERRUPTS_IN_NATIVE_MODE
730          case MODE_NATIVE:
731                  // 68k emulator inactive, in nanokernel?
732                  assert(current_cpu == main_cpu);
733 <                if (main_cpu->gpr(1) != KernelDataAddr) {
733 >                if (gpr(1) != KernelDataAddr) {
734                          // Prepare for 68k interrupt level 1
735                          WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1);
736                          WriteMacInt32(tswap32(kernel_data->v[0x658 >> 2]) + 0xdc,
# Line 659 | Line 741 | static void HandleInterrupt(void)
741                          DisableInterrupt();
742                          cpu_push(interrupt_cpu);
743                          if (ROMType == ROMTYPE_NEWWORLD)
744 <                                current_cpu->interrupt(ROM_BASE + 0x312b1c, main_cpu);
744 >                                current_cpu->interrupt(ROM_BASE + 0x312b1c);
745                          else
746 <                                current_cpu->interrupt(ROM_BASE + 0x312a3c, main_cpu);
746 >                                current_cpu->interrupt(ROM_BASE + 0x312a3c);
747                          cpu_pop();
748                  }
749                  break;
# Line 736 | Line 818 | const uint32 NativeOpTable[NATIVE_OP_MAX
818          POWERPC_NATIVE_OP_INIT(1, NATIVE_R_GET_RESOURCE),
819          POWERPC_NATIVE_OP_INIT(0, NATIVE_DISABLE_INTERRUPT),
820          POWERPC_NATIVE_OP_INIT(0, NATIVE_ENABLE_INTERRUPT),
821 +        POWERPC_NATIVE_OP_INIT(1, NATIVE_MAKE_EXECUTABLE),
822   };
823  
824   static void get_resource(void);
# Line 748 | Line 831 | static void r_get_resource(void);
831  
832   static void NativeOp(int selector)
833   {
834 + #if EMUL_TIME_STATS
835 +        native_exec_count++;
836 +        const clock_t native_exec_start = clock();
837 + #endif
838 +
839          switch (selector) {
840          case NATIVE_PATCH_NAME_REGISTRY:
841                  DoPatchNameRegistry();
# Line 762 | Line 850 | static void NativeOp(int selector)
850                  GPR(3) = (int32)(int16)VideoDoDriverIO((void *)GPR(3), (void *)GPR(4),
851                                                                                             (void *)GPR(5), GPR(6), GPR(7));
852                  break;
853 <        case NATIVE_GET_RESOURCE:
854 <                get_resource();
853 > #ifdef WORDS_BIGENDIAN
854 >        case NATIVE_ETHER_IRQ:
855 >                EtherIRQ();
856                  break;
857 <        case NATIVE_GET_1_RESOURCE:
858 <                get_1_resource();
857 >        case NATIVE_ETHER_INIT:
858 >                GPR(3) = InitStreamModule((void *)GPR(3));
859                  break;
860 <        case NATIVE_GET_IND_RESOURCE:
861 <                get_ind_resource();
860 >        case NATIVE_ETHER_TERM:
861 >                TerminateStreamModule();
862                  break;
863 <        case NATIVE_GET_1_IND_RESOURCE:
864 <                get_1_ind_resource();
863 >        case NATIVE_ETHER_OPEN:
864 >                GPR(3) = ether_open((queue_t *)GPR(3), (void *)GPR(4), GPR(5), GPR(6), (void*)GPR(7));
865 >                break;
866 >        case NATIVE_ETHER_CLOSE:
867 >                GPR(3) = ether_close((queue_t *)GPR(3), GPR(4), (void *)GPR(5));
868                  break;
869 <        case NATIVE_R_GET_RESOURCE:
870 <                r_get_resource();
869 >        case NATIVE_ETHER_WPUT:
870 >                GPR(3) = ether_wput((queue_t *)GPR(3), (mblk_t *)GPR(4));
871                  break;
872 +        case NATIVE_ETHER_RSRV:
873 +                GPR(3) = ether_rsrv((queue_t *)GPR(3));
874 +                break;
875 + #else
876 +        case NATIVE_ETHER_INIT:
877 +                // FIXME: needs more complicated thunks
878 +                GPR(3) = false;
879 +                break;
880 + #endif
881          case NATIVE_SERIAL_NOTHING:
882          case NATIVE_SERIAL_OPEN:
883          case NATIVE_SERIAL_PRIME_IN:
# Line 797 | Line 898 | static void NativeOp(int selector)
898                  GPR(3) = serial_callbacks[selector - NATIVE_SERIAL_NOTHING](GPR(3), GPR(4));
899                  break;
900          }
901 +        case NATIVE_GET_RESOURCE:
902 +        case NATIVE_GET_1_RESOURCE:
903 +        case NATIVE_GET_IND_RESOURCE:
904 +        case NATIVE_GET_1_IND_RESOURCE:
905 +        case NATIVE_R_GET_RESOURCE: {
906 +                typedef void (*GetResourceCallback)(void);
907 +                static const GetResourceCallback get_resource_callbacks[] = {
908 +                        get_resource,
909 +                        get_1_resource,
910 +                        get_ind_resource,
911 +                        get_1_ind_resource,
912 +                        r_get_resource
913 +                };
914 +                get_resource_callbacks[selector - NATIVE_GET_RESOURCE]();
915 +                break;
916 +        }
917          case NATIVE_DISABLE_INTERRUPT:
918                  DisableInterrupt();
919                  break;
920          case NATIVE_ENABLE_INTERRUPT:
921                  EnableInterrupt();
922                  break;
923 +        case NATIVE_MAKE_EXECUTABLE:
924 +                MakeExecutable(0, (void *)GPR(4), GPR(5));
925 +                break;
926          default:
927                  printf("FATAL: NATIVE_OP called with bogus selector %d\n", selector);
928                  QuitEmulator();
929                  break;
930          }
931 +
932 + #if EMUL_TIME_STATS
933 +        native_exec_time += (clock() - native_exec_start);
934 + #endif
935   }
936  
937   /*
# Line 842 | Line 966 | void Execute68k(uint32 pc, M68kRegisters
966  
967   void Execute68kTrap(uint16 trap, M68kRegisters *r)
968   {
969 <        uint16 proc[2] = {trap, M68K_RTS};
969 >        uint16 proc[2];
970 >        proc[0] = htons(trap);
971 >        proc[1] = htons(M68K_RTS);
972          Execute68k((uint32)proc, r);
973   }
974  
# Line 898 | Line 1024 | uint32 call_macos7(uint32 tvect, uint32
1024   }
1025  
1026   /*
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 /*
1027   *  Resource Manager thunks
1028   */
1029  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines