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.45 by gbeauche, 2004-06-22T14:18:35Z

# 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 1096 | Line 1071 | void sheepshaver_cpu::handle_interrupt(v
1071          if (*(int32 *)XLM_IRQ_NEST > 0)
1072                  return;
1073  
1074 <        // Do nothing if there is no interrupt pending
1075 <        if (InterruptFlags == 0)
1076 <                return;
1074 >        // Current interrupt nest level
1075 >        static int interrupt_depth = 0;
1076 >        ++interrupt_depth;
1077 > #if EMUL_TIME_STATS
1078 >        interrupt_count++;
1079 > #endif
1080  
1081          // Disable MacOS stack sniffer
1082          WriteMacInt32(0x110, 0);
# Line 1107 | Line 1085 | void sheepshaver_cpu::handle_interrupt(v
1085          switch (ReadMacInt32(XLM_RUN_MODE)) {
1086          case MODE_68K:
1087                  // 68k emulator active, trigger 68k interrupt level 1
1110                assert(current_cpu == main_cpu);
1088                  WriteMacInt16(tswap32(kernel_data->v[0x67c >> 2]), 1);
1089                  set_cr(get_cr() | tswap32(kernel_data->v[0x674 >> 2]));
1090                  break;
# Line 1115 | Line 1092 | void sheepshaver_cpu::handle_interrupt(v
1092   #if INTERRUPTS_IN_NATIVE_MODE
1093          case MODE_NATIVE:
1094                  // 68k emulator inactive, in nanokernel?
1095 <                assert(current_cpu == main_cpu);
1119 <                if (gpr(1) != KernelDataAddr) {
1095 >                if (gpr(1) != KernelDataAddr && interrupt_depth == 1) {
1096                          interrupt_context ctx(this, "PowerPC mode");
1097  
1098                          // Prepare for 68k interrupt level 1
# Line 1127 | Line 1103 | void sheepshaver_cpu::handle_interrupt(v
1103        
1104                          // Execute nanokernel interrupt routine (this will activate the 68k emulator)
1105                          DisableInterrupt();
1130                        cpu_push(interrupt_cpu);
1106                          if (ROMType == ROMTYPE_NEWWORLD)
1107 <                                current_cpu->interrupt(ROM_BASE + 0x312b1c);
1107 >                                ppc_cpu->interrupt(ROM_BASE + 0x312b1c);
1108                          else
1109 <                                current_cpu->interrupt(ROM_BASE + 0x312a3c);
1135 <                        cpu_pop();
1109 >                                ppc_cpu->interrupt(ROM_BASE + 0x312a3c);
1110                  }
1111                  break;
1112   #endif
# Line 1142 | Line 1116 | void sheepshaver_cpu::handle_interrupt(v
1116                  // 68k emulator active, within EMUL_OP routine, execute 68k interrupt routine directly when interrupt level is 0
1117                  if ((ReadMacInt32(XLM_68K_R25) & 7) == 0) {
1118                          interrupt_context ctx(this, "68k mode");
1119 + #if EMUL_TIME_STATS
1120 +                        const clock_t interrupt_start = clock();
1121 + #endif
1122   #if 1
1123                          // Execute full 68k interrupt routine
1124                          M68kRegisters r;
# Line 1167 | Line 1144 | void sheepshaver_cpu::handle_interrupt(v
1144                                  }
1145                          }
1146   #endif
1147 + #if EMUL_TIME_STATS
1148 +                        interrupt_time += (clock() - interrupt_start);
1149 + #endif
1150                  }
1151                  break;
1152   #endif
1153          }
1154 +
1155 +        // We are done with this interrupt
1156 +        --interrupt_depth;
1157   }
1158  
1159   static void get_resource(void);
# Line 1314 | Line 1297 | void sheepshaver_cpu::execute_native_op(
1297  
1298   void Execute68k(uint32 pc, M68kRegisters *r)
1299   {
1300 <        current_cpu->execute_68k(pc, r);
1300 >        ppc_cpu->execute_68k(pc, r);
1301   }
1302  
1303   /*
# Line 1337 | Line 1320 | void Execute68kTrap(uint16 trap, M68kReg
1320  
1321   uint32 call_macos(uint32 tvect)
1322   {
1323 <        return current_cpu->execute_macos_code(tvect, 0, NULL);
1323 >        return ppc_cpu->execute_macos_code(tvect, 0, NULL);
1324   }
1325  
1326   uint32 call_macos1(uint32 tvect, uint32 arg1)
1327   {
1328          const uint32 args[] = { arg1 };
1329 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1329 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1330   }
1331  
1332   uint32 call_macos2(uint32 tvect, uint32 arg1, uint32 arg2)
1333   {
1334          const uint32 args[] = { arg1, arg2 };
1335 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1335 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1336   }
1337  
1338   uint32 call_macos3(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3)
1339   {
1340          const uint32 args[] = { arg1, arg2, arg3 };
1341 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1341 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1342   }
1343  
1344   uint32 call_macos4(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4)
1345   {
1346          const uint32 args[] = { arg1, arg2, arg3, arg4 };
1347 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1347 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1348   }
1349  
1350   uint32 call_macos5(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5)
1351   {
1352          const uint32 args[] = { arg1, arg2, arg3, arg4, arg5 };
1353 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1353 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1354   }
1355  
1356   uint32 call_macos6(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6)
1357   {
1358          const uint32 args[] = { arg1, arg2, arg3, arg4, arg5, arg6 };
1359 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1359 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1360   }
1361  
1362   uint32 call_macos7(uint32 tvect, uint32 arg1, uint32 arg2, uint32 arg3, uint32 arg4, uint32 arg5, uint32 arg6, uint32 arg7)
1363   {
1364          const uint32 args[] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7 };
1365 <        return current_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1365 >        return ppc_cpu->execute_macos_code(tvect, sizeof(args)/sizeof(args[0]), args);
1366   }
1367  
1368   /*
# Line 1388 | Line 1371 | uint32 call_macos7(uint32 tvect, uint32
1371  
1372   void get_resource(void)
1373   {
1374 <        current_cpu->get_resource(ReadMacInt32(XLM_GET_RESOURCE));
1374 >        ppc_cpu->get_resource(ReadMacInt32(XLM_GET_RESOURCE));
1375   }
1376  
1377   void get_1_resource(void)
1378   {
1379 <        current_cpu->get_resource(ReadMacInt32(XLM_GET_1_RESOURCE));
1379 >        ppc_cpu->get_resource(ReadMacInt32(XLM_GET_1_RESOURCE));
1380   }
1381  
1382   void get_ind_resource(void)
1383   {
1384 <        current_cpu->get_resource(ReadMacInt32(XLM_GET_IND_RESOURCE));
1384 >        ppc_cpu->get_resource(ReadMacInt32(XLM_GET_IND_RESOURCE));
1385   }
1386  
1387   void get_1_ind_resource(void)
1388   {
1389 <        current_cpu->get_resource(ReadMacInt32(XLM_GET_1_IND_RESOURCE));
1389 >        ppc_cpu->get_resource(ReadMacInt32(XLM_GET_1_IND_RESOURCE));
1390   }
1391  
1392   void r_get_resource(void)
1393   {
1394 <        current_cpu->get_resource(ReadMacInt32(XLM_R_GET_RESOURCE));
1394 >        ppc_cpu->get_resource(ReadMacInt32(XLM_R_GET_RESOURCE));
1395   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines