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.11 by gbeauche, 2003-10-26T14:16:39Z 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 47 | Line 47
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 74 | Line 89 | static void enter_mon(void)
89   // Pointer to Kernel Data
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  
82 struct sheepshaver_exec_return { };
83
100   class sheepshaver_cpu
101          : public powerpc_cpu
102   {
# Line 115 | Line 131 | public:
131          void interrupt(uint32 entry);
132          void handle_interrupt();
133  
118        // spcflags for interrupts handling
119        static uint32 spcflags;
120
134          // Lazy memory allocator (one item at a time)
135          void *operator new(size_t size)
136                  { return allocator_helper< sheepshaver_cpu, lazy_allocator >::allocate(); }
# Line 126 | 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  
131 uint32 sheepshaver_cpu::spcflags = 0;
147   lazy_allocator< sheepshaver_cpu > allocator_helper< sheepshaver_cpu, lazy_allocator >::allocator;
148  
149   sheepshaver_cpu::sheepshaver_cpu()
# Line 148 | 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_JUMP | CFLOW_TRAP
169                  }
# Line 189 | Line 204 | void sheepshaver_cpu::execute_sheep(uint
204                  break;
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 225 | Line 240 | void sheepshaver_cpu::execute_sheep(uint
240   // Execution loop
241   void sheepshaver_cpu::execute(uint32 entry, bool enable_cache)
242   {
243 <        try {
229 <                powerpc_cpu::execute(entry, enable_cache);
230 <        }
231 <        catch (sheepshaver_exec_return const &) {
232 <                // Nothing, simply return
233 <        }
234 <        catch (...) {
235 <                printf("ERROR: execute() received an unknown exception!\n");
236 <                QuitEmulator();
237 <        }
243 >        powerpc_cpu::execute(entry, enable_cache);
244   }
245  
246   // Handle MacOS interrupt
247   void sheepshaver_cpu::interrupt(uint32 entry)
248   {
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();
# Line 293 | Line 304 | void sheepshaver_cpu::interrupt(uint32 e
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 380 | Line 400 | void sheepshaver_cpu::execute_68k(uint32
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();
# Line 423 | 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 527 | 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 566 | Line 626 | void init_emul_ppc(void)
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 607 | Line 707 | void TriggerInterrupt(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 731 | 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 745 | 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_ETHER_WPUT:
870 >                GPR(3) = ether_wput((queue_t *)GPR(3), (mblk_t *)GPR(4));
871                  break;
872 <        case NATIVE_R_GET_RESOURCE:
873 <                r_get_resource();
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 780 | 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;
# Line 794 | Line 928 | static void NativeOp(int 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   /*

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines