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.13 by gbeauche, 2003-11-02T14:48:17Z vs.
Revision 1.20 by gbeauche, 2003-12-03T10:52:49Z

# Line 30 | Line 30
30   #include "sigsegv.h"
31   #include "cpu/ppc/ppc-cpu.hpp"
32   #include "cpu/ppc/ppc-operations.hpp"
33 + #include "cpu/ppc/ppc-instructions.hpp"
34  
35   // Used for NativeOp trampolines
36   #include "video.h"
37   #include "name_registry.h"
38   #include "serial.h"
39 + #include "ether.h"
40  
41   #include <stdio.h>
42  
# Line 46 | Line 48
48   #define DEBUG 0
49   #include "debug.h"
50  
51 + // Emulation time statistics
52 + #define EMUL_TIME_STATS 1
53 +
54 + #if EMUL_TIME_STATS
55 + static clock_t emul_start_time;
56 + static uint32 interrupt_count = 0;
57 + static clock_t interrupt_time = 0;
58 + static uint32 exec68k_count = 0;
59 + static clock_t exec68k_time = 0;
60 + static uint32 native_exec_count = 0;
61 + static clock_t native_exec_time = 0;
62 + static uint32 macos_exec_count = 0;
63 + static clock_t macos_exec_time = 0;
64 + #endif
65 +
66   static void enter_mon(void)
67   {
68          // Start up mon in real-mode
# Line 73 | Line 90 | static void enter_mon(void)
90   // Pointer to Kernel Data
91   static KernelData * const kernel_data = (KernelData *)KERNEL_DATA_BASE;
92  
93 + // SIGSEGV handler
94 + static sigsegv_return_t sigsegv_handler(sigsegv_address_t, sigsegv_address_t);
95 +
96 + // JIT Compiler enabled?
97 + static inline bool enable_jit_p()
98 + {
99 +        return PrefsFindBool("jit");
100 + }
101 +
102  
103   /**
104   *              PowerPC emulator glue with special 'sheep' opcodes
105   **/
106  
107 + enum {
108 +        PPC_I(SHEEP) = PPC_I(MAX),
109 +        PPC_I(SHEEP_MAX)
110 + };
111 +
112   class sheepshaver_cpu
113          : public powerpc_cpu
114   {
# Line 93 | Line 124 | public:
124          uint32 get_cr() const           { return cr().get(); }
125          void set_cr(uint32 v)           { cr().set(v); }
126  
96        // Execution loop
97        void execute(uint32 entry, bool enable_cache = false);
98
127          // Execute 68k routine
128          void execute_68k(uint32 entry, M68kRegisters *r);
129  
# Line 120 | Line 148 | public:
148          // FIXME: really make surre array allocation fail at link time?
149          void *operator new[](size_t);
150          void operator delete[](void *p);
151 +
152 +        // Make sure the SIGSEGV handler can access CPU registers
153 +        friend sigsegv_return_t sigsegv_handler(sigsegv_address_t, sigsegv_address_t);
154   };
155  
156   lazy_allocator< sheepshaver_cpu > allocator_helper< sheepshaver_cpu, lazy_allocator >::allocator;
157  
158   sheepshaver_cpu::sheepshaver_cpu()
159 <        : powerpc_cpu()
159 >        : powerpc_cpu(enable_jit_p())
160   {
161          init_decoder();
162   }
# Line 143 | Line 174 | void sheepshaver_cpu::init_decoder()
174                  { "sheep",
175                    (execute_pmf)&sheepshaver_cpu::execute_sheep,
176                    NULL,
177 +                  PPC_I(SHEEP),
178                    D_form, 6, 0, CFLOW_JUMP | CFLOW_TRAP
179                  }
180          };
# Line 215 | Line 247 | void sheepshaver_cpu::execute_sheep(uint
247          }
248   }
249  
218 // Execution loop
219 void sheepshaver_cpu::execute(uint32 entry, bool enable_cache)
220 {
221        powerpc_cpu::execute(entry, enable_cache);
222 }
223
250   // Handle MacOS interrupt
251   void sheepshaver_cpu::interrupt(uint32 entry)
252   {
253 + #if EMUL_TIME_STATS
254 +        interrupt_count++;
255 +        const clock_t interrupt_start = clock();
256 + #endif
257 +
258   #if !MULTICORE_CPU
259          // Save program counters and branch registers
260          uint32 saved_pc = pc();
# Line 277 | Line 308 | void sheepshaver_cpu::interrupt(uint32 e
308          ctr()= saved_ctr;
309          gpr(1) = saved_sp;
310   #endif
311 +
312 + #if EMUL_TIME_STATS
313 +        interrupt_time += (clock() - interrupt_start);
314 + #endif
315   }
316  
317   // Execute 68k routine
318   void sheepshaver_cpu::execute_68k(uint32 entry, M68kRegisters *r)
319   {
320 + #if EMUL_TIME_STATS
321 +        exec68k_count++;
322 +        const clock_t exec68k_start = clock();
323 + #endif
324 +
325   #if SAFE_EXEC_68K
326          if (ReadMacInt32(XLM_RUN_MODE) != MODE_EMUL_OP)
327                  printf("FATAL: Execute68k() not called from EMUL_OP mode\n");
# Line 364 | Line 404 | void sheepshaver_cpu::execute_68k(uint32
404          lr() = saved_lr;
405          ctr()= saved_ctr;
406          set_cr(saved_cr);
407 +
408 + #if EMUL_TIME_STATS
409 +        exec68k_time += (clock() - exec68k_start);
410 + #endif
411   }
412  
413   // Call MacOS PPC code
414   uint32 sheepshaver_cpu::execute_macos_code(uint32 tvect, int nargs, uint32 const *args)
415   {
416 + #if EMUL_TIME_STATS
417 +        macos_exec_count++;
418 +        const clock_t macos_exec_start = clock();
419 + #endif
420 +
421          // Save program counters and branch registers
422          uint32 saved_pc = pc();
423          uint32 saved_lr = lr();
# Line 407 | Line 456 | uint32 sheepshaver_cpu::execute_macos_co
456          lr() = saved_lr;
457          ctr()= saved_ctr;
458  
459 + #if EMUL_TIME_STATS
460 +        macos_exec_time += (clock() - macos_exec_start);
461 + #endif
462 +
463          return retval;
464   }
465  
# Line 511 | Line 564 | static sigsegv_return_t sigsegv_handler(
564          if ((addr - ROM_BASE) < ROM_SIZE)
565                  return SIGSEGV_RETURN_SKIP_INSTRUCTION;
566  
567 <        // Ignore all other faults, if requested
568 <        if (PrefsFindBool("ignoresegv"))
569 <                return SIGSEGV_RETURN_FAILURE;
567 >        // Get program counter of target CPU
568 >        sheepshaver_cpu * const cpu = current_cpu;
569 >        const uint32 pc = cpu->pc();
570 >        
571 >        // Fault in Mac ROM or RAM?
572 >        bool mac_fault = (pc >= ROM_BASE) && (pc < (ROM_BASE + ROM_AREA_SIZE)) || (pc >= RAMBase) && (pc < (RAMBase + RAMSize));
573 >        if (mac_fault) {
574 >
575 >                // "VM settings" during MacOS 8 installation
576 >                if (pc == ROM_BASE + 0x488160 && cpu->gpr(20) == 0xf8000000)
577 >                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
578 >        
579 >                // MacOS 8.5 installation
580 >                else if (pc == ROM_BASE + 0x488140 && cpu->gpr(16) == 0xf8000000)
581 >                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
582 >        
583 >                // MacOS 8 serial drivers on startup
584 >                else if (pc == ROM_BASE + 0x48e080 && (cpu->gpr(8) == 0xf3012002 || cpu->gpr(8) == 0xf3012000))
585 >                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
586 >        
587 >                // MacOS 8.1 serial drivers on startup
588 >                else if (pc == ROM_BASE + 0x48c5e0 && (cpu->gpr(20) == 0xf3012002 || cpu->gpr(20) == 0xf3012000))
589 >                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
590 >                else if (pc == ROM_BASE + 0x4a10a0 && (cpu->gpr(20) == 0xf3012002 || cpu->gpr(20) == 0xf3012000))
591 >                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
592 >
593 >                // Ignore all other faults, if requested
594 >                if (PrefsFindBool("ignoresegv"))
595 >                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
596 >        }
597   #else
598   #error "FIXME: You don't have the capability to skip instruction within signal handlers"
599   #endif
# Line 550 | Line 630 | void init_emul_ppc(void)
630          mon_add_command("regs", dump_registers, "regs                     Dump PowerPC registers\n");
631          mon_add_command("log", dump_log, "log                      Dump PowerPC emulation log\n");
632   #endif
633 +
634 + #if EMUL_TIME_STATS
635 +        emul_start_time = clock();
636 + #endif
637 + }
638 +
639 + /*
640 + *  Deinitialize emulation
641 + */
642 +
643 + void exit_emul_ppc(void)
644 + {
645 + #if EMUL_TIME_STATS
646 +        clock_t emul_end_time = clock();
647 +
648 +        printf("### Statistics for SheepShaver emulation parts\n");
649 +        const clock_t emul_time = emul_end_time - emul_start_time;
650 +        printf("Total emulation time : %.1f sec\n", double(emul_time) / double(CLOCKS_PER_SEC));
651 +        printf("Total interrupt count: %d (%2.1f Hz)\n", interrupt_count,
652 +                   (double(interrupt_count) * CLOCKS_PER_SEC) / double(emul_time));
653 +
654 + #define PRINT_STATS(LABEL, VAR_PREFIX) do {                                                             \
655 +                printf("Total " LABEL " count : %d\n", VAR_PREFIX##_count);             \
656 +                printf("Total " LABEL " time  : %.1f sec (%.1f%%)\n",                   \
657 +                           double(VAR_PREFIX##_time) / double(CLOCKS_PER_SEC),          \
658 +                           100.0 * double(VAR_PREFIX##_time) / double(emul_time));      \
659 +        } while (0)
660 +
661 +        PRINT_STATS("Execute68k[Trap] execution", exec68k);
662 +        PRINT_STATS("NativeOp execution", native_exec);
663 +        PRINT_STATS("MacOS routine execution", macos_exec);
664 +
665 + #undef PRINT_STATS
666 +        printf("\n");
667 + #endif
668 +
669 +        delete main_cpu;
670 + #if MULTICORE_CPU
671 +        delete interrupt_cpu;
672 + #endif
673   }
674  
675   /*
# Line 563 | Line 683 | void emul_ppc(uint32 entry)
683          current_cpu->start_log();
684   #endif
685          // start emulation loop and enable code translation or caching
686 <        current_cpu->execute(entry, true);
686 >        current_cpu->execute(entry);
687   }
688  
689   /*
# Line 591 | Line 711 | void TriggerInterrupt(void)
711   void sheepshaver_cpu::handle_interrupt(void)
712   {
713          // Do nothing if interrupts are disabled
714 <        if (int32(ReadMacInt32(XLM_IRQ_NEST)) > 0)
714 >        if (*(int32 *)XLM_IRQ_NEST > 0)
715                  return;
716  
717          // Do nothing if there is no interrupt pending
# Line 715 | Line 835 | static void r_get_resource(void);
835  
836   static void NativeOp(int selector)
837   {
838 + #if EMUL_TIME_STATS
839 +        native_exec_count++;
840 +        const clock_t native_exec_start = clock();
841 + #endif
842 +
843          switch (selector) {
844          case NATIVE_PATCH_NAME_REGISTRY:
845                  DoPatchNameRegistry();
# Line 729 | Line 854 | static void NativeOp(int selector)
854                  GPR(3) = (int32)(int16)VideoDoDriverIO((void *)GPR(3), (void *)GPR(4),
855                                                                                             (void *)GPR(5), GPR(6), GPR(7));
856                  break;
857 <        case NATIVE_GET_RESOURCE:
858 <                get_resource();
857 > #ifdef WORDS_BIGENDIAN
858 >        case NATIVE_ETHER_IRQ:
859 >                EtherIRQ();
860                  break;
861 <        case NATIVE_GET_1_RESOURCE:
862 <                get_1_resource();
861 >        case NATIVE_ETHER_INIT:
862 >                GPR(3) = InitStreamModule((void *)GPR(3));
863                  break;
864 <        case NATIVE_GET_IND_RESOURCE:
865 <                get_ind_resource();
864 >        case NATIVE_ETHER_TERM:
865 >                TerminateStreamModule();
866                  break;
867 <        case NATIVE_GET_1_IND_RESOURCE:
868 <                get_1_ind_resource();
867 >        case NATIVE_ETHER_OPEN:
868 >                GPR(3) = ether_open((queue_t *)GPR(3), (void *)GPR(4), GPR(5), GPR(6), (void*)GPR(7));
869 >                break;
870 >        case NATIVE_ETHER_CLOSE:
871 >                GPR(3) = ether_close((queue_t *)GPR(3), GPR(4), (void *)GPR(5));
872 >                break;
873 >        case NATIVE_ETHER_WPUT:
874 >                GPR(3) = ether_wput((queue_t *)GPR(3), (mblk_t *)GPR(4));
875                  break;
876 <        case NATIVE_R_GET_RESOURCE:
877 <                r_get_resource();
876 >        case NATIVE_ETHER_RSRV:
877 >                GPR(3) = ether_rsrv((queue_t *)GPR(3));
878                  break;
879 + #else
880 +        case NATIVE_ETHER_INIT:
881 +                // FIXME: needs more complicated thunks
882 +                GPR(3) = false;
883 +                break;
884 + #endif
885          case NATIVE_SERIAL_NOTHING:
886          case NATIVE_SERIAL_OPEN:
887          case NATIVE_SERIAL_PRIME_IN:
# Line 764 | Line 902 | static void NativeOp(int selector)
902                  GPR(3) = serial_callbacks[selector - NATIVE_SERIAL_NOTHING](GPR(3), GPR(4));
903                  break;
904          }
905 +        case NATIVE_GET_RESOURCE:
906 +        case NATIVE_GET_1_RESOURCE:
907 +        case NATIVE_GET_IND_RESOURCE:
908 +        case NATIVE_GET_1_IND_RESOURCE:
909 +        case NATIVE_R_GET_RESOURCE: {
910 +                typedef void (*GetResourceCallback)(void);
911 +                static const GetResourceCallback get_resource_callbacks[] = {
912 +                        get_resource,
913 +                        get_1_resource,
914 +                        get_ind_resource,
915 +                        get_1_ind_resource,
916 +                        r_get_resource
917 +                };
918 +                get_resource_callbacks[selector - NATIVE_GET_RESOURCE]();
919 +                break;
920 +        }
921          case NATIVE_DISABLE_INTERRUPT:
922                  DisableInterrupt();
923                  break;
# Line 778 | Line 932 | static void NativeOp(int selector)
932                  QuitEmulator();
933                  break;
934          }
935 +
936 + #if EMUL_TIME_STATS
937 +        native_exec_time += (clock() - native_exec_start);
938 + #endif
939   }
940  
941   /*

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines