static void fmovem(UINT16 w2) { int i; int ea = REG_IR & 0x3f; int dir = (w2 >> 13) & 0x1; int mode = (w2 >> 11) & 0x3; int reglist = w2 & 0xff; if (dir) // From FP regs to mem { switch (mode) { case 0: // Static register list, predecrement addressing mode { for (i=0; i < 8; i++) { if (reglist & (1 << i)) { WRITE_EA_FPE(ea, REG_FP[i]); USE_CYCLES(2); } } break; } default: fatalerror("040fpu0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4); } } else // From mem to FP regs { switch (mode) { case 2: // Static register list, postincrement addressing mode { for (i=0; i < 8; i++) { if (reglist & (1 << i)) { REG_FP[7-i] = READ_EA_FPE(ea); USE_CYCLES(2); } } break; } default: fatalerror("040fpu0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4); } } }
static void fmove_fpcr(UINT16 w2) { int ea = REG_IR & 0x3f; int dir = (w2 >> 13) & 0x1; int reg = (w2 >> 10) & 0x7; if (dir) // From system control reg to <ea> { switch (reg) { case 1: WRITE_EA_32(ea, REG_FPIAR); break; case 2: WRITE_EA_32(ea, REG_FPSR); break; case 4: WRITE_EA_32(ea, REG_FPCR); break; default: fatalerror("fmove_fpcr: unknown reg %d, dir %d\n", reg, dir); } } else // From <ea> to system control reg { switch (reg) { case 1: REG_FPIAR = READ_EA_32(ea); break; case 2: REG_FPSR = READ_EA_32(ea); break; case 4: REG_FPCR = READ_EA_32(ea); break; default: fatalerror("fmove_fpcr: unknown reg %d, dir %d\n", reg, dir); } } USE_CYCLES(10); }
static void fmove_reg_mem(UINT16 w2) { int ea = REG_IR & 0x3f; int src = (w2 >> 7) & 0x7; int dst = (w2 >> 10) & 0x7; //int kfactor = w2 & 0x7f; switch (dst) { case 0: // Long-Word Integer { INT32 d = (INT32)(REG_FP[src].f); WRITE_EA_32(ea, d); break; } case 1: // Single-precision Real { float f = (float)(REG_FP[src].f); UINT32 d = *(UINT32 *)&f; WRITE_EA_32(ea, d); break; } case 2: // Extended-precision Real { fatalerror("fmove_reg_mem: extended-precision real store unimplemented at %08X\n", REG_PC-4); break; } case 3: // Packed-decimal Real with Static K-factor { fatalerror("fmove_reg_mem: packed-decimal real store unimplemented at %08X\n", REG_PC-4); break; } case 4: // Word Integer { fatalerror("fmove_reg_mem: word integer store unimplemented at %08X\n", REG_PC-4); break; } case 5: // Double-precision Real { UINT64 d = REG_FP[src].i; WRITE_EA_64(ea, d); break; } case 6: // Byte Integer { fatalerror("fmove_reg_mem: byte integer store unimplemented at %08X\n", REG_PC-4); break; } case 7: // Packed-decimal Real with Dynamic K-factor { fatalerror("fmove_reg_mem: packed-decimal real store unimplemented at %08X\n", REG_PC-4); break; } } USE_CYCLES(12); }
static void fbcc(void) { INT32 disp; // int condition = REG_IR & 0x3f; int size = (REG_IR >> 6) & 0x1; if (size) // 32-bit displacement { disp = OPER_I_32(); } else { disp = (INT16)(OPER_I_16()); } // TODO: condition and jump!!! USE_CYCLES(7); }
int m68k_execute(int num_cycles) { if (regs.stopped) { regs.remainingCycles = 0; // int32_t regs.interruptCycles = 0; // uint32_t return num_cycles; } #if 0 /* Set our pool of clock cycles available */ SET_CYCLES(num_cycles); m68ki_initial_cycles = num_cycles; /* ASG: update cycles */ USE_CYCLES(CPU_INT_CYCLES); CPU_INT_CYCLES = 0; /* Return point if we had an address error */ m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */ #else regs.remainingCycles = num_cycles; /*int32_t*/ initialCycles = num_cycles; regs.remainingCycles -= regs.interruptCycles; regs.interruptCycles = 0; #endif /* Main loop. Keep going until we run out of clock cycles */ do { // This is so our debugging code can break in on a dime. // Otherwise, this is just extra slow down :-P if (regs.spcflags & SPCFLAG_DEBUGGER) { // Not sure this is correct... :-P num_cycles = initialCycles - regs.remainingCycles; regs.remainingCycles = 0; // int32_t regs.interruptCycles = 0; // uint32_t return num_cycles; } #if 0 /* Set tracing accodring to T1. (T0 is done inside instruction) */ m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */ /* Set the address space for reads */ m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */ /* Call external hook to peek at CPU */ m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */ /* Record previous program counter */ REG_PPC = REG_PC; /* Read an instruction and call its handler */ REG_IR = m68ki_read_imm_16(); m68ki_instruction_jump_table[REG_IR](); USE_CYCLES(CYC_INSTRUCTION[REG_IR]); /* Trace m68k_exception, if necessary */ m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */ #else //Testing Hover Strike... #if 0 //Dasm(regs.pc, 1); static int hitCount = 0; static int inRoutine = 0; static int instSeen; //if (regs.pc == 0x80340A) if (regs.pc == 0x803416) { hitCount++; inRoutine = 1; instSeen = 0; printf("%i: $80340A start. A0=%08X, A1=%08X ", hitCount, regs.regs[8], regs.regs[9]); } else if (regs.pc == 0x803422) { inRoutine = 0; printf("(%i instructions)\n", instSeen); } if (inRoutine) instSeen++; #endif // AvP testing... (problem was: 32 bit addresses on 24 bit address cpu--FIXED) #if 0 static int go = 0; if (regs.pc == 0x94BA) { go = 1; printf("\n"); } if (regs.pc == 0x94C6) go = 0; // if (regs.regs[10] == 0xFFFFFFFF && go) if (go) { // printf("A2=-1, PC=%08X\n", regs.pc); // go = 0; // Dasm(regs.pc, 130); Dasm(regs.pc, 1); DumpRegisters(); } //94BA: 2468 0000 MOVEA.L (A0,$0000) == $0002328A, A2 //94BE: 200A MOVE.L A2, D0 //94C0: 6A02 BPL.B $94C4 //94C2: 2452 MOVEA.L (A2), A2 ; <--- HERE //94C4: 4283 CLR.L D3 #endif // pthread_mutex_lock(&executionLock); if (checkForIRQToHandle) { checkForIRQToHandle = 0; m68k_set_irq2(IRQLevelToHandle); } #ifdef M68K_HOOK_FUNCTION M68KInstructionHook(); #endif uint32_t opcode = get_iword(0); //if ((opcode & 0xFFF8) == 0x31C0) //{ // printf("MOVE.W D%i, EA\n", opcode & 0x07); //} int32_t cycles = (int32_t)(*cpuFunctionTable[opcode])(opcode); regs.remainingCycles -= cycles; // pthread_mutex_unlock(&executionLock); //printf("Executed opcode $%04X (%i cycles)...\n", opcode, cycles); #endif } while (regs.remainingCycles > 0); #if 0 /* set previous PC to current PC for the next entry into the loop */ REG_PPC = REG_PC; /* ASG: update cycles */ USE_CYCLES(CPU_INT_CYCLES); CPU_INT_CYCLES = 0; /* return how many clocks we used */ return m68ki_initial_cycles - GET_CYCLES(); #else regs.remainingCycles -= regs.interruptCycles; regs.interruptCycles = 0; // Return # of clock cycles used return initialCycles - regs.remainingCycles; #endif }
static void fpgen_rm_reg(UINT16 w2) { int ea = REG_IR & 0x3f; int rm = (w2 >> 14) & 0x1; int src = (w2 >> 10) & 0x7; int dst = (w2 >> 7) & 0x7; int opmode = w2 & 0x7f; double source; if (rm) { switch (src) { case 0: // Long-Word Integer { INT32 d = READ_EA_32(ea); source = (double)(d); break; } case 1: // Single-precision Real { UINT32 d = READ_EA_32(ea); source = (double)(*(float*)&d); break; } case 2: // Extended-precision Real { fatalerror("fpgen_rm_reg: extended-precision real load unimplemented at %08X\n", REG_PC-4); break; } case 3: // Packed-decimal Real { fatalerror("fpgen_rm_reg: packed-decimal real load unimplemented at %08X\n", REG_PC-4); break; } case 4: // Word Integer { INT16 d = READ_EA_16(ea); source = (double)(d); break; } case 5: // Double-precision Real { UINT64 d = READ_EA_64(ea); source = *(double*)&d; break; } case 6: // Byte Integer { INT8 d = READ_EA_8(ea); source = (double)(d); break; } default: fatalerror("fmove_rm_reg: invalid source specifier at %08X\n", REG_PC-4); } } else { source = REG_FP[src].f; } switch (opmode) { case 0x00: // FMOVE { REG_FP[dst].f = source; USE_CYCLES(4); break; } case 0x04: // FSQRT { REG_FP[dst].f = sqrt(source); // TODO: condition codes USE_CYCLES(109); break; } case 0x18: // FABS { REG_FP[dst].f = fabs(source); // TODO: condition codes USE_CYCLES(3); break; } case 0x1a: // FNEG { REG_FP[dst].f = -source; // TODO: condition codes USE_CYCLES(3); break; } case 0x20: // FDIV { REG_FP[dst].f /= source; USE_CYCLES(43); break; } case 0x22: // FADD { REG_FP[dst].f += source; // TODO: condition codes USE_CYCLES(9); break; } case 0x23: // FMUL { REG_FP[dst].f *= source; // TODO: condition codes USE_CYCLES(11); break; } case 0x28: // FSUB { REG_FP[dst].f -= source; // TODO: condition codes USE_CYCLES(9); break; } case 0x38: // FCMP { // TODO: condition codes !!! USE_CYCLES(7); break; } case 0x3a: // FTST { // TODO: condition codes !!! USE_CYCLES(7); break; } default: fatalerror("fpgen_rm_reg: unimplemented opmode %02X at %08X\n", opmode, REG_PC-4); } }