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.39 by gbeauche, 2004-05-20T11:05:30Z vs.
Revision 1.46 by gbeauche, 2004-06-22T17:10:08Z

# Line 52 | Line 52
52   #include "debug.h"
53  
54   // Emulation time statistics
55 < #define EMUL_TIME_STATS 1
55 > #ifndef EMUL_TIME_STATS
56 > #define EMUL_TIME_STATS 0
57 > #endif
58  
59   #if EMUL_TIME_STATS
60   static clock_t emul_start_time;
61 < static uint32 interrupt_count = 0;
61 > static uint32 interrupt_count = 0, ppc_interrupt_count = 0;
62   static clock_t interrupt_time = 0;
63   static uint32 exec68k_count = 0;
64   static clock_t exec68k_time = 0;
# Line 84 | Line 86 | extern "C" void check_load_invoc(uint32
86   // PowerPC EmulOp to exit from emulation looop
87   const uint32 POWERPC_EXEC_RETURN = POWERPC_EMUL_OP | 1;
88  
87 // Enable multicore (main/interrupts) cpu emulation?
88 #define MULTICORE_CPU (ASYNC_IRQ ? 1 : 0)
89
89   // Enable interrupt routine safety checks?
90   #define SAFE_INTERRUPT_PPC 1
91  
# Line 447 | Line 446 | int sheepshaver_cpu::compile1(codegen_co
446                          status = COMPILE_CODE_OK;
447                          break;
448   #endif
450                case NATIVE_DISABLE_INTERRUPT:
451                        dg.gen_invoke(DisableInterrupt);
452                        status = COMPILE_CODE_OK;
453                        break;
454                case NATIVE_ENABLE_INTERRUPT:
455                        dg.gen_invoke(EnableInterrupt);
456                        status = COMPILE_CODE_OK;
457                        break;
449                  case NATIVE_BITBLT:
450                          dg.gen_load_T0_GPR(3);
451                          dg.gen_invoke_T0((void (*)(uint32))NQD_bitblt);
# Line 472 | Line 463 | int sheepshaver_cpu::compile1(codegen_co
463                          break;
464                  }
465                  // Could we fully translate this NativeOp?
466 <                if (FN_field::test(opcode)) {
467 <                        if (status != COMPILE_FAILURE) {
466 >                if (status == COMPILE_CODE_OK) {
467 >                        if (!FN_field::test(opcode))
468 >                                cg_context.done_compile = false;
469 >                        else {
470                                  dg.gen_load_A0_LR();
471                                  dg.gen_set_PC_A0();
472 +                                cg_context.done_compile = true;
473                          }
480                        cg_context.done_compile = true;
481                        break;
482                }
483                else if (status != COMPILE_FAILURE) {
484                        cg_context.done_compile = false;
474                          break;
475                  }
476   #if PPC_REENTRANT_JIT
477                  // Try to execute NativeOp trampoline
478 <                dg.gen_set_PC_im(cg_context.pc + 4);
478 >                if (!FN_field::test(opcode))
479 >                        dg.gen_set_PC_im(cg_context.pc + 4);
480 >                else {
481 >                        dg.gen_load_A0_LR();
482 >                        dg.gen_set_PC_A0();
483 >                }
484                  dg.gen_mov_32_T0_im(selector);
485                  dg.gen_jmp(native_op_trampoline);
486                  cg_context.done_compile = true;
# Line 494 | Line 488 | int sheepshaver_cpu::compile1(codegen_co
488                  break;
489   #endif
490                  // Invoke NativeOp handler
491 <                typedef void (*func_t)(dyngen_cpu_base, uint32);
492 <                func_t func = (func_t)nv_mem_fun(&sheepshaver_cpu::execute_native_op).ptr();
493 <                dg.gen_invoke_CPU_im(func, selector);
494 <                cg_context.done_compile = false;
495 <                status = COMPILE_CODE_OK;
491 >                if (!FN_field::test(opcode)) {
492 >                        typedef void (*func_t)(dyngen_cpu_base, uint32);
493 >                        func_t func = (func_t)nv_mem_fun(&sheepshaver_cpu::execute_native_op).ptr();
494 >                        dg.gen_invoke_CPU_im(func, selector);
495 >                        cg_context.done_compile = false;
496 >                        status = COMPILE_CODE_OK;
497 >                }
498 >                // Otherwise, let it generate a call to execute_sheep() which
499 >                // will cause necessary updates to the program counter
500                  break;
501          }
502  
# Line 592 | Line 590 | sheepshaver_cpu::interrupt_context::~int
590   void sheepshaver_cpu::interrupt(uint32 entry)
591   {
592   #if EMUL_TIME_STATS
593 <        interrupt_count++;
593 >        ppc_interrupt_count++;
594          const clock_t interrupt_start = clock();
595   #endif
596  
# Line 603 | Line 601 | void sheepshaver_cpu::interrupt(uint32 e
601          depth++;
602   #endif
603  
606 #if !MULTICORE_CPU
604          // Save program counters and branch registers
605          uint32 saved_pc = pc();
606          uint32 saved_lr = lr();
607          uint32 saved_ctr= ctr();
608          uint32 saved_sp = gpr(1);
612 #endif
609  
610          // Initialize stack pointer to SheepShaver alternate stack base
611          gpr(1) = SignalStackBase() - 64;
# Line 649 | Line 645 | void sheepshaver_cpu::interrupt(uint32 e
645          // Enter nanokernel
646          execute(entry);
647  
652 #if !MULTICORE_CPU
648          // Restore program counters and branch registers
649          pc() = saved_pc;
650          lr() = saved_lr;
651          ctr()= saved_ctr;
652          gpr(1) = saved_sp;
658 #endif
653  
654   #if EMUL_TIME_STATS
655          interrupt_time += (clock() - interrupt_start);
# Line 857 | Line 851 | inline void sheepshaver_cpu::get_resourc
851   *              SheepShaver CPU engine interface
852   **/
853  
854 < static sheepshaver_cpu *main_cpu = NULL;                // CPU emulator to handle usual control flow
855 < static sheepshaver_cpu *interrupt_cpu = NULL;   // CPU emulator to handle interrupts
862 < static sheepshaver_cpu *current_cpu = NULL;             // Current CPU emulator context
854 > // PowerPC CPU emulator
855 > static sheepshaver_cpu *ppc_cpu = NULL;
856  
857   void FlushCodeCache(uintptr start, uintptr end)
858   {
859          D(bug("FlushCodeCache(%08x, %08x)\n", start, end));
860 <        main_cpu->invalidate_cache_range(start, end);
868 < #if MULTICORE_CPU
869 <        interrupt_cpu->invalidate_cache_range(start, end);
870 < #endif
871 < }
872 <
873 < static inline void cpu_push(sheepshaver_cpu *new_cpu)
874 < {
875 < #if MULTICORE_CPU
876 <        current_cpu = new_cpu;
877 < #endif
878 < }
879 <
880 < static inline void cpu_pop()
881 < {
882 < #if MULTICORE_CPU
883 <        current_cpu = main_cpu;
884 < #endif
860 >        ppc_cpu->invalidate_cache_range(start, end);
861   }
862  
863   // Dump PPC registers
864   static void dump_registers(void)
865   {
866 <        current_cpu->dump_registers();
866 >        ppc_cpu->dump_registers();
867   }
868  
869   // Dump log
870   static void dump_log(void)
871   {
872 <        current_cpu->dump_log();
872 >        ppc_cpu->dump_log();
873   }
874  
875   /*
# Line 916 | Line 892 | static sigsegv_return_t sigsegv_handler(
892                  return SIGSEGV_RETURN_SKIP_INSTRUCTION;
893  
894          // Get program counter of target CPU
895 <        sheepshaver_cpu * const cpu = current_cpu;
895 >        sheepshaver_cpu * const cpu = ppc_cpu;
896          const uint32 pc = cpu->pc();
897          
898          // Fault in Mac ROM or RAM?
899 <        bool mac_fault = (pc >= ROM_BASE) && (pc < (ROM_BASE + ROM_AREA_SIZE)) || (pc >= RAMBase) && (pc < (RAMBase + RAMSize));
899 >        bool mac_fault = (pc >= ROM_BASE) && (pc < (ROM_BASE + ROM_AREA_SIZE)) || (pc >= RAMBase) && (pc < (RAMBase + RAMSize)) || (pc >= DR_CACHE_BASE && pc < (DR_CACHE_BASE + DR_CACHE_SIZE));
900          if (mac_fault) {
901  
902                  // "VM settings" during MacOS 8 installation
# Line 940 | Line 916 | static sigsegv_return_t sigsegv_handler(
916                          return SIGSEGV_RETURN_SKIP_INSTRUCTION;
917                  else if (pc == ROM_BASE + 0x4a10a0 && (cpu->gpr(20) == 0xf3012002 || cpu->gpr(20) == 0xf3012000))
918                          return SIGSEGV_RETURN_SKIP_INSTRUCTION;
919 +        
920 +                // MacOS 8.6 serial drivers on startup (with DR Cache and OldWorld ROM)
921 +                else if ((pc - DR_CACHE_BASE) < DR_CACHE_SIZE && (cpu->gpr(16) == 0xf3012002 || cpu->gpr(16) == 0xf3012000))
922 +                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
923 +                else if ((pc - DR_CACHE_BASE) < DR_CACHE_SIZE && (cpu->gpr(20) == 0xf3012002 || cpu->gpr(20) == 0xf3012000))
924 +                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
925  
926                  // Ignore writes to the zero page
927                  else if ((uint32)(addr - SheepMem::ZeroPage()) < (uint32)SheepMem::PageSize())
# Line 956 | Line 938 | static sigsegv_return_t sigsegv_handler(
938          printf("SIGSEGV\n");
939          printf("  pc %p\n", fault_instruction);
940          printf("  ea %p\n", fault_address);
959        printf(" cpu %s\n", current_cpu == main_cpu ? "main" : "interrupts");
941          dump_registers();
942 <        current_cpu->dump_log();
942 >        ppc_cpu->dump_log();
943          enter_mon();
944          QuitEmulator();
945  
# Line 968 | Line 949 | static sigsegv_return_t sigsegv_handler(
949   void init_emul_ppc(void)
950   {
951          // Initialize main CPU emulator
952 <        main_cpu = new sheepshaver_cpu();
953 <        main_cpu->set_register(powerpc_registers::GPR(3), any_register((uint32)ROM_BASE + 0x30d000));
954 <        main_cpu->set_register(powerpc_registers::GPR(4), any_register(KernelDataAddr + 0x1000));
952 >        ppc_cpu = new sheepshaver_cpu();
953 >        ppc_cpu->set_register(powerpc_registers::GPR(3), any_register((uint32)ROM_BASE + 0x30d000));
954 >        ppc_cpu->set_register(powerpc_registers::GPR(4), any_register(KernelDataAddr + 0x1000));
955          WriteMacInt32(XLM_RUN_MODE, MODE_68K);
956  
976 #if MULTICORE_CPU
977        // Initialize alternate CPU emulator to handle interrupts
978        interrupt_cpu = new sheepshaver_cpu();
979 #endif
980
957          // Install the handler for SIGSEGV
958          sigsegv_install_handler(sigsegv_handler);
959  
# Line 1006 | Line 982 | void exit_emul_ppc(void)
982          printf("Total emulation time : %.1f sec\n", double(emul_time) / double(CLOCKS_PER_SEC));
983          printf("Total interrupt count: %d (%2.1f Hz)\n", interrupt_count,
984                     (double(interrupt_count) * CLOCKS_PER_SEC) / double(emul_time));
985 +        printf("Total ppc interrupt count: %d (%2.1f %%)\n", ppc_interrupt_count,
986 +                   (double(ppc_interrupt_count) * 100.0) / double(interrupt_count));
987  
988   #define PRINT_STATS(LABEL, VAR_PREFIX) do {                                                             \
989                  printf("Total " LABEL " count : %d\n", VAR_PREFIX##_count);             \
# Line 1022 | Line 1000 | void exit_emul_ppc(void)
1000          printf("\n");
1001   #endif
1002  
1003 <        delete main_cpu;
1026 < #if MULTICORE_CPU
1027 <        delete interrupt_cpu;
1028 < #endif
1003 >        delete ppc_cpu;
1004   }
1005  
1006   #if PPC_ENABLE_JIT && PPC_REENTRANT_JIT
# Line 1060 | Line 1035 | void init_emul_op_trampolines(basic_dyng
1035  
1036   void emul_ppc(uint32 entry)
1037   {
1063        current_cpu = main_cpu;
1038   #if 0
1039 <        current_cpu->start_log();
1039 >        ppc_cpu->start_log();
1040   #endif
1041          // start emulation loop and enable code translation or caching
1042 <        current_cpu->execute(entry);
1042 >        ppc_cpu->execute(entry);
1043   }
1044  
1045   /*
1046   *  Handle PowerPC interrupt
1047   */
1048  
1075 #if ASYNC_IRQ
1076 void HandleInterrupt(void)
1077 {
1078        main_cpu->handle_interrupt();
1079 }
1080 #else
1049   void TriggerInterrupt(void)
1050   {
1051   #if 0
1052    WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
1053   #else
1054    // Trigger interrupt to main cpu only
1055 <  if (main_cpu)
1056 <          main_cpu->trigger_interrupt();
1055 >  if (ppc_cpu)
1056 >          ppc_cpu->trigger_interrupt();
1057   #endif
1058   }
1091 #endif
1059  
1060   void sheepshaver_cpu::handle_interrupt(void)
1061   {
1062          // Do nothing if interrupts are disabled
1063 <        if (*(int32 *)XLM_IRQ_NEST > 0)
1063 >        if (int32(ReadMacInt32(XLM_IRQ_NEST)) > 0)
1064                  return;
1065  
1066 <        // Do nothing if there is no interrupt pending
1067 <        if (InterruptFlags == 0)
1068 <                return;
1066 >        // Current interrupt nest level
1067 >        static int interrupt_depth = 0;
1068 >        ++interrupt_depth;
1069 > #if EMUL_TIME_STATS
1070 >        interrupt_count++;
1071 > #endif
1072  
1073          // Disable MacOS stack sniffer
1074          WriteMacInt32(0x110, 0);
# Line 1107 | Line 1077 | void sheepshaver_cpu::handle_interrupt(v
1077          switch (ReadMacInt32(XLM_RUN_MODE)) {
1078          case MODE_68K:
1079                  // 68k emulator active, trigger 68k interrupt level 1
1110                assert(current_cpu == main_cpu);
1080                  WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1);
1081                  set_cr(get_cr() | tswap32(kernel_data->v[0x674 >> 2]));
1082                  break;
# Line 1115 | Line 1084 | void sheepshaver_cpu::handle_interrupt(v
1084   #if INTERRUPTS_IN_NATIVE_MODE
1085          case MODE_NATIVE:
1086                  // 68k emulator inactive, in nanokernel?
1087 <                assert(current_cpu == main_cpu);
1119 <                if (gpr(1) != KernelDataAddr) {
1087 >                if (gpr(1) != KernelDataAddr && interrupt_depth == 1) {
1088                          interrupt_context ctx(this, "PowerPC mode");
1089  
1090                          // Prepare for 68k interrupt level 1
# Line 1127 | Line 1095 | void sheepshaver_cpu::handle_interrupt(v
1095        
1096                          // Execute nanokernel interrupt routine (this will activate the 68k emulator)
1097                          DisableInterrupt();
1130                        cpu_push(interrupt_cpu);
1098                          if (ROMType == ROMTYPE_NEWWORLD)
1099 <                                current_cpu->interrupt(ROM_BASE + 0x312b1c);
1099 >                                ppc_cpu->interrupt(ROM_BASE + 0x312b1c);
1100                          else
1101 <                                current_cpu->interrupt(ROM_BASE + 0x312a3c);
1135 <                        cpu_pop();
1101 >                                ppc_cpu->interrupt(ROM_BASE + 0x312a3c);
1102                  }
1103                  break;
1104   #endif
# Line 1142 | Line 1108 | void sheepshaver_cpu::handle_interrupt(v
1108                  // 68k emulator active, within EMUL_OP routine, execute 68k interrupt routine directly when interrupt level is 0
1109                  if ((ReadMacInt32(XLM_68K_R25) & 7) == 0) {
1110                          interrupt_context ctx(this, "68k mode");
1111 + #if EMUL_TIME_STATS
1112 +                        const clock_t interrupt_start = clock();
1113 + #endif
1114   #if 1
1115                          // Execute full 68k interrupt routine
1116                          M68kRegisters r;
# Line 1167 | Line 1136 | void sheepshaver_cpu::handle_interrupt(v
1136                                  }
1137                          }
1138   #endif
1139 + #if EMUL_TIME_STATS
1140 +                        interrupt_time += (clock() - interrupt_start);
1141 + #endif
1142                  }
1143                  break;
1144   #endif
1145          }
1146 +
1147 +        // We are done with this interrupt
1148 +        --interrupt_depth;
1149   }
1150  
1151   static void get_resource(void);
# Line 1283 | Line 1258 | void sheepshaver_cpu::execute_native_op(
1258                  get_resource_callbacks[selector - NATIVE_GET_RESOURCE]();
1259                  break;
1260          }
1286        case NATIVE_DISABLE_INTERRUPT:
1287                DisableInterrupt();
1288                break;
1289        case NATIVE_ENABLE_INTERRUPT:
1290                EnableInterrupt();
1291                break;
1261          case NATIVE_MAKE_EXECUTABLE:
1262                  MakeExecutable(0, (void *)gpr(4), gpr(5));
1263                  break;
# Line 1314 | Line 1283 | void sheepshaver_cpu::execute_native_op(
1283  
1284   void Execute68k(uint32 pc, M68kRegisters *r)
1285   {
1286 <        current_cpu->execute_68k(pc, r);
1286 >        ppc_cpu->execute_68k(pc, r);
1287   }
1288  
1289   /*
# Line 1337 | Line 1306 | void Execute68kTrap(uint16 trap, M68kReg
1306  
1307   uint32 call_macos(uint32 tvect)
1308   {
1309 <        return current_cpu->execute_macos_code(tvect, 0, NULL);
1309 >        return ppc_cpu->execute_macos_code(tvect, 0, NULL);
1310   }
1311  
1312   uint32 call_macos1(uint32 tvect, uint32 arg1)
1313   {
1314          const uint32 args[] = { arg1 };
1315 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1315 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1316   }
1317  
1318   uint32 call_macos2(uint32 tvect, uint32 arg1, uint32 arg2)
1319   {
1320          const uint32 args[] = { arg1, arg2 };
1321 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1321 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1322   }
1323  
1324   uint32 call_macos3(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3)
1325   {
1326          const uint32 args[] = { arg1, arg2, arg3 };
1327 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1327 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1328   }
1329  
1330   uint32 call_macos4(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4)
1331   {
1332          const uint32 args[] = { arg1, arg2, arg3, arg4 };
1333 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1333 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1334   }
1335  
1336   uint32 call_macos5(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5)
1337   {
1338          const uint32 args[] = { arg1, arg2, arg3, arg4, arg5 };
1339 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1339 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1340   }
1341  
1342   uint32 call_macos6(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6)
1343   {
1344          const uint32 args[] = { arg1, arg2, arg3, arg4, arg5, arg6 };
1345 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1345 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1346   }
1347  
1348   uint32 call_macos7(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6, uint32 arg7)
1349   {
1350          const uint32 args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7 };
1351 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1351 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1352   }
1353  
1354   /*
# Line 1388 | Line 1357 | uint32 call_macos7(uint32 tvect, uint32
1357  
1358   void get_resource(void)
1359   {
1360 <        current_cpu->get_resource(ReadMacInt32(XLM_GET_RESOURCE));
1360 >        ppc_cpu->get_resource(ReadMacInt32(XLM_GET_RESOURCE));
1361   }
1362  
1363   void get_1_resource(void)
1364   {
1365 <        current_cpu->get_resource(ReadMacInt32(XLM_GET_1_RESOURCE));
1365 >        ppc_cpu->get_resource(ReadMacInt32(XLM_GET_1_RESOURCE));
1366   }
1367  
1368   void get_ind_resource(void)
1369   {
1370 <        current_cpu->get_resource(ReadMacInt32(XLM_GET_IND_RESOURCE));
1370 >        ppc_cpu->get_resource(ReadMacInt32(XLM_GET_IND_RESOURCE));
1371   }
1372  
1373   void get_1_ind_resource(void)
1374   {
1375 <        current_cpu->get_resource(ReadMacInt32(XLM_GET_1_IND_RESOURCE));
1375 >        ppc_cpu->get_resource(ReadMacInt32(XLM_GET_1_IND_RESOURCE));
1376   }
1377  
1378   void r_get_resource(void)
1379   {
1380 <        current_cpu->get_resource(ReadMacInt32(XLM_R_GET_RESOURCE));
1380 >        ppc_cpu->get_resource(ReadMacInt32(XLM_R_GET_RESOURCE));
1381   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines