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.44 by gbeauche, 2004-06-05T07:09:38Z

# 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 472 | Line 471 | int sheepshaver_cpu::compile1(codegen_co
471                          break;
472                  }
473                  // Could we fully translate this NativeOp?
474 <                if (FN_field::test(opcode)) {
475 <                        if (status != COMPILE_FAILURE) {
474 >                if (status == COMPILE_CODE_OK) {
475 >                        if (!FN_field::test(opcode))
476 >                                cg_context.done_compile = false;
477 >                        else {
478                                  dg.gen_load_A0_LR();
479                                  dg.gen_set_PC_A0();
480 +                                cg_context.done_compile = true;
481                          }
480                        cg_context.done_compile = true;
481                        break;
482                }
483                else if (status != COMPILE_FAILURE) {
484                        cg_context.done_compile = false;
482                          break;
483                  }
484   #if PPC_REENTRANT_JIT
485                  // Try to execute NativeOp trampoline
486 <                dg.gen_set_PC_im(cg_context.pc + 4);
486 >                if (!FN_field::test(opcode))
487 >                        dg.gen_set_PC_im(cg_context.pc + 4);
488 >                else {
489 >                        dg.gen_load_A0_LR();
490 >                        dg.gen_set_PC_A0();
491 >                }
492                  dg.gen_mov_32_T0_im(selector);
493                  dg.gen_jmp(native_op_trampoline);
494                  cg_context.done_compile = true;
# Line 494 | Line 496 | int sheepshaver_cpu::compile1(codegen_co
496                  break;
497   #endif
498                  // Invoke NativeOp handler
499 <                typedef void (*func_t)(dyngen_cpu_base, uint32);
500 <                func_t func = (func_t)nv_mem_fun(&sheepshaver_cpu::execute_native_op).ptr();
501 <                dg.gen_invoke_CPU_im(func, selector);
502 <                cg_context.done_compile = false;
503 <                status = COMPILE_CODE_OK;
499 >                if (!FN_field::test(opcode)) {
500 >                        typedef void (*func_t)(dyngen_cpu_base, uint32);
501 >                        func_t func = (func_t)nv_mem_fun(&sheepshaver_cpu::execute_native_op).ptr();
502 >                        dg.gen_invoke_CPU_im(func, selector);
503 >                        cg_context.done_compile = false;
504 >                        status = COMPILE_CODE_OK;
505 >                }
506 >                // Otherwise, let it generate a call to execute_sheep() which
507 >                // will cause necessary updates to the program counter
508                  break;
509          }
510  
# Line 592 | Line 598 | sheepshaver_cpu::interrupt_context::~int
598   void sheepshaver_cpu::interrupt(uint32 entry)
599   {
600   #if EMUL_TIME_STATS
601 <        interrupt_count++;
601 >        ppc_interrupt_count++;
602          const clock_t interrupt_start = clock();
603   #endif
604  
# Line 603 | Line 609 | void sheepshaver_cpu::interrupt(uint32 e
609          depth++;
610   #endif
611  
606 #if !MULTICORE_CPU
612          // Save program counters and branch registers
613          uint32 saved_pc = pc();
614          uint32 saved_lr = lr();
615          uint32 saved_ctr= ctr();
616          uint32 saved_sp = gpr(1);
612 #endif
617  
618          // Initialize stack pointer to SheepShaver alternate stack base
619          gpr(1) = SignalStackBase() - 64;
# Line 649 | Line 653 | void sheepshaver_cpu::interrupt(uint32 e
653          // Enter nanokernel
654          execute(entry);
655  
652 #if !MULTICORE_CPU
656          // Restore program counters and branch registers
657          pc() = saved_pc;
658          lr() = saved_lr;
659          ctr()= saved_ctr;
660          gpr(1) = saved_sp;
658 #endif
661  
662   #if EMUL_TIME_STATS
663          interrupt_time += (clock() - interrupt_start);
# Line 857 | Line 859 | inline void sheepshaver_cpu::get_resourc
859   *              SheepShaver CPU engine interface
860   **/
861  
862 < static sheepshaver_cpu *main_cpu = NULL;                // CPU emulator to handle usual control flow
863 < static sheepshaver_cpu *interrupt_cpu = NULL;   // CPU emulator to handle interrupts
862 < static sheepshaver_cpu *current_cpu = NULL;             // Current CPU emulator context
862 > // PowerPC CPU emulator
863 > static sheepshaver_cpu *ppc_cpu = NULL;
864  
865   void FlushCodeCache(uintptr start, uintptr end)
866   {
867          D(bug("FlushCodeCache(%08x, %08x)\n", start, end));
868 <        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
868 >        ppc_cpu->invalidate_cache_range(start, end);
869   }
870  
871   // Dump PPC registers
872   static void dump_registers(void)
873   {
874 <        current_cpu->dump_registers();
874 >        ppc_cpu->dump_registers();
875   }
876  
877   // Dump log
878   static void dump_log(void)
879   {
880 <        current_cpu->dump_log();
880 >        ppc_cpu->dump_log();
881   }
882  
883   /*
# Line 916 | Line 900 | static sigsegv_return_t sigsegv_handler(
900                  return SIGSEGV_RETURN_SKIP_INSTRUCTION;
901  
902          // Get program counter of target CPU
903 <        sheepshaver_cpu * const cpu = current_cpu;
903 >        sheepshaver_cpu * const cpu = ppc_cpu;
904          const uint32 pc = cpu->pc();
905          
906          // Fault in Mac ROM or RAM?
907 <        bool mac_fault = (pc >= ROM_BASE) && (pc < (ROM_BASE + ROM_AREA_SIZE)) || (pc >= RAMBase) && (pc < (RAMBase + RAMSize));
907 >        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));
908          if (mac_fault) {
909  
910                  // "VM settings" during MacOS 8 installation
# Line 940 | Line 924 | static sigsegv_return_t sigsegv_handler(
924                          return SIGSEGV_RETURN_SKIP_INSTRUCTION;
925                  else if (pc == ROM_BASE + 0x4a10a0 && (cpu->gpr(20) == 0xf3012002 || cpu->gpr(20) == 0xf3012000))
926                          return SIGSEGV_RETURN_SKIP_INSTRUCTION;
927 +        
928 +                // MacOS 8.6 serial drivers on startup (with DR Cache and OldWorld ROM)
929 +                else if ((pc - DR_CACHE_BASE) < DR_CACHE_SIZE && (cpu->gpr(16) == 0xf3012002 || cpu->gpr(16) == 0xf3012000))
930 +                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
931 +                else if ((pc - DR_CACHE_BASE) < DR_CACHE_SIZE && (cpu->gpr(20) == 0xf3012002 || cpu->gpr(20) == 0xf3012000))
932 +                        return SIGSEGV_RETURN_SKIP_INSTRUCTION;
933  
934                  // Ignore writes to the zero page
935                  else if ((uint32)(addr - SheepMem::ZeroPage()) < (uint32)SheepMem::PageSize())
# Line 956 | Line 946 | static sigsegv_return_t sigsegv_handler(
946          printf("SIGSEGV\n");
947          printf("  pc %p\n", fault_instruction);
948          printf("  ea %p\n", fault_address);
959        printf(" cpu %s\n", current_cpu == main_cpu ? "main" : "interrupts");
949          dump_registers();
950 <        current_cpu->dump_log();
950 >        ppc_cpu->dump_log();
951          enter_mon();
952          QuitEmulator();
953  
# Line 968 | Line 957 | static sigsegv_return_t sigsegv_handler(
957   void init_emul_ppc(void)
958   {
959          // Initialize main CPU emulator
960 <        main_cpu = new sheepshaver_cpu();
961 <        main_cpu->set_register(powerpc_registers::GPR(3), any_register((uint32)ROM_BASE + 0x30d000));
962 <        main_cpu->set_register(powerpc_registers::GPR(4), any_register(KernelDataAddr + 0x1000));
960 >        ppc_cpu = new sheepshaver_cpu();
961 >        ppc_cpu->set_register(powerpc_registers::GPR(3), any_register((uint32)ROM_BASE + 0x30d000));
962 >        ppc_cpu->set_register(powerpc_registers::GPR(4), any_register(KernelDataAddr + 0x1000));
963          WriteMacInt32(XLM_RUN_MODE, MODE_68K);
964  
976 #if MULTICORE_CPU
977        // Initialize alternate CPU emulator to handle interrupts
978        interrupt_cpu = new sheepshaver_cpu();
979 #endif
980
965          // Install the handler for SIGSEGV
966          sigsegv_install_handler(sigsegv_handler);
967  
# Line 1006 | Line 990 | void exit_emul_ppc(void)
990          printf("Total emulation time : %.1f sec\n", double(emul_time) / double(CLOCKS_PER_SEC));
991          printf("Total interrupt count: %d (%2.1f Hz)\n", interrupt_count,
992                     (double(interrupt_count) * CLOCKS_PER_SEC) / double(emul_time));
993 +        printf("Total ppc interrupt count: %d (%2.1f %%)\n", ppc_interrupt_count,
994 +                   (double(ppc_interrupt_count) * 100.0) / double(interrupt_count));
995  
996   #define PRINT_STATS(LABEL, VAR_PREFIX) do {                                                             \
997                  printf("Total " LABEL " count : %d\n", VAR_PREFIX##_count);             \
# Line 1022 | Line 1008 | void exit_emul_ppc(void)
1008          printf("\n");
1009   #endif
1010  
1011 <        delete main_cpu;
1026 < #if MULTICORE_CPU
1027 <        delete interrupt_cpu;
1028 < #endif
1011 >        delete ppc_cpu;
1012   }
1013  
1014   #if PPC_ENABLE_JIT && PPC_REENTRANT_JIT
# Line 1060 | Line 1043 | void init_emul_op_trampolines(basic_dyng
1043  
1044   void emul_ppc(uint32 entry)
1045   {
1063        current_cpu = main_cpu;
1046   #if 0
1047 <        current_cpu->start_log();
1047 >        ppc_cpu->start_log();
1048   #endif
1049          // start emulation loop and enable code translation or caching
1050 <        current_cpu->execute(entry);
1050 >        ppc_cpu->execute(entry);
1051   }
1052  
1053   /*
1054   *  Handle PowerPC interrupt
1055   */
1056  
1075 #if ASYNC_IRQ
1076 void HandleInterrupt(void)
1077 {
1078        main_cpu->handle_interrupt();
1079 }
1080 #else
1057   void TriggerInterrupt(void)
1058   {
1059   #if 0
1060    WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
1061   #else
1062    // Trigger interrupt to main cpu only
1063 <  if (main_cpu)
1064 <          main_cpu->trigger_interrupt();
1063 >  if (ppc_cpu)
1064 >          ppc_cpu->trigger_interrupt();
1065   #endif
1066   }
1091 #endif
1067  
1068   void sheepshaver_cpu::handle_interrupt(void)
1069   {
# Line 1100 | Line 1075 | void sheepshaver_cpu::handle_interrupt(v
1075          if (InterruptFlags == 0)
1076                  return;
1077  
1078 +        // Current interrupt nest level
1079 +        static int interrupt_depth = 0;
1080 +        ++interrupt_depth;
1081 + #if EMUL_TIME_STATS
1082 +        interrupt_count++;
1083 + #endif
1084 +
1085          // Disable MacOS stack sniffer
1086          WriteMacInt32(0x110, 0);
1087  
# Line 1107 | Line 1089 | void sheepshaver_cpu::handle_interrupt(v
1089          switch (ReadMacInt32(XLM_RUN_MODE)) {
1090          case MODE_68K:
1091                  // 68k emulator active, trigger 68k interrupt level 1
1110                assert(current_cpu == main_cpu);
1092                  WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1);
1093                  set_cr(get_cr() | tswap32(kernel_data->v[0x674 >> 2]));
1094                  break;
# Line 1115 | Line 1096 | void sheepshaver_cpu::handle_interrupt(v
1096   #if INTERRUPTS_IN_NATIVE_MODE
1097          case MODE_NATIVE:
1098                  // 68k emulator inactive, in nanokernel?
1099 <                assert(current_cpu == main_cpu);
1119 <                if (gpr(1) != KernelDataAddr) {
1099 >                if (gpr(1) != KernelDataAddr && interrupt_depth == 1) {
1100                          interrupt_context ctx(this, "PowerPC mode");
1101  
1102                          // Prepare for 68k interrupt level 1
# Line 1127 | Line 1107 | void sheepshaver_cpu::handle_interrupt(v
1107        
1108                          // Execute nanokernel interrupt routine (this will activate the 68k emulator)
1109                          DisableInterrupt();
1130                        cpu_push(interrupt_cpu);
1110                          if (ROMType == ROMTYPE_NEWWORLD)
1111 <                                current_cpu->interrupt(ROM_BASE + 0x312b1c);
1111 >                                ppc_cpu->interrupt(ROM_BASE + 0x312b1c);
1112                          else
1113 <                                current_cpu->interrupt(ROM_BASE + 0x312a3c);
1135 <                        cpu_pop();
1113 >                                ppc_cpu->interrupt(ROM_BASE + 0x312a3c);
1114                  }
1115                  break;
1116   #endif
# Line 1142 | Line 1120 | void sheepshaver_cpu::handle_interrupt(v
1120                  // 68k emulator active, within EMUL_OP routine, execute 68k interrupt routine directly when interrupt level is 0
1121                  if ((ReadMacInt32(XLM_68K_R25) & 7) == 0) {
1122                          interrupt_context ctx(this, "68k mode");
1123 + #if EMUL_TIME_STATS
1124 +                        const clock_t interrupt_start = clock();
1125 + #endif
1126   #if 1
1127                          // Execute full 68k interrupt routine
1128                          M68kRegisters r;
# Line 1167 | Line 1148 | void sheepshaver_cpu::handle_interrupt(v
1148                                  }
1149                          }
1150   #endif
1151 + #if EMUL_TIME_STATS
1152 +                        interrupt_time += (clock() - interrupt_start);
1153 + #endif
1154                  }
1155                  break;
1156   #endif
1157          }
1158 +
1159 +        // We are done with this interrupt
1160 +        --interrupt_depth;
1161   }
1162  
1163   static void get_resource(void);
# Line 1314 | Line 1301 | void sheepshaver_cpu::execute_native_op(
1301  
1302   void Execute68k(uint32 pc, M68kRegisters *r)
1303   {
1304 <        current_cpu->execute_68k(pc, r);
1304 >        ppc_cpu->execute_68k(pc, r);
1305   }
1306  
1307   /*
# Line 1337 | Line 1324 | void Execute68kTrap(uint16 trap, M68kReg
1324  
1325   uint32 call_macos(uint32 tvect)
1326   {
1327 <        return current_cpu->execute_macos_code(tvect, 0, NULL);
1327 >        return ppc_cpu->execute_macos_code(tvect, 0, NULL);
1328   }
1329  
1330   uint32 call_macos1(uint32 tvect, uint32 arg1)
1331   {
1332          const uint32 args[] = { arg1 };
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_macos2(uint32 tvect, uint32 arg1, uint32 arg2)
1337   {
1338          const uint32 args[] = { arg1, arg2 };
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_macos3(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3)
1343   {
1344          const uint32 args[] = { arg1, arg2, arg3 };
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_macos4(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4)
1349   {
1350          const uint32 args[] = { arg1, arg2, arg3, arg4 };
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   uint32 call_macos5(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5)
1355   {
1356          const uint32 args[] = { arg1, arg2, arg3, arg4, arg5 };
1357 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1357 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1358   }
1359  
1360   uint32 call_macos6(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6)
1361   {
1362          const uint32 args[] = { arg1, arg2, arg3, arg4, arg5, arg6 };
1363 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1363 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1364   }
1365  
1366   uint32 call_macos7(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6, uint32 arg7)
1367   {
1368          const uint32 args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7 };
1369 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1369 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1370   }
1371  
1372   /*
# Line 1388 | Line 1375 | uint32 call_macos7(uint32 tvect, uint32
1375  
1376   void get_resource(void)
1377   {
1378 <        current_cpu->get_resource(ReadMacInt32(XLM_GET_RESOURCE));
1378 >        ppc_cpu->get_resource(ReadMacInt32(XLM_GET_RESOURCE));
1379   }
1380  
1381   void get_1_resource(void)
1382   {
1383 <        current_cpu->get_resource(ReadMacInt32(XLM_GET_1_RESOURCE));
1383 >        ppc_cpu->get_resource(ReadMacInt32(XLM_GET_1_RESOURCE));
1384   }
1385  
1386   void get_ind_resource(void)
1387   {
1388 <        current_cpu->get_resource(ReadMacInt32(XLM_GET_IND_RESOURCE));
1388 >        ppc_cpu->get_resource(ReadMacInt32(XLM_GET_IND_RESOURCE));
1389   }
1390  
1391   void get_1_ind_resource(void)
1392   {
1393 <        current_cpu->get_resource(ReadMacInt32(XLM_GET_1_IND_RESOURCE));
1393 >        ppc_cpu->get_resource(ReadMacInt32(XLM_GET_1_IND_RESOURCE));
1394   }
1395  
1396   void r_get_resource(void)
1397   {
1398 <        current_cpu->get_resource(ReadMacInt32(XLM_R_GET_RESOURCE));
1398 >        ppc_cpu->get_resource(ReadMacInt32(XLM_R_GET_RESOURCE));
1399   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines