static floatx80 READ_EA_PACK(m68000_base_device *m68k, int ea) { floatx80 fpr; int mode = (ea >> 3) & 0x7; int reg = (ea & 0x7); switch (mode) { case 2: // (An) { UINT32 ea = REG_A(m68k)[reg]; fpr = load_pack_float80(m68k, ea); break; } case 3: // (An)+ { UINT32 ea = REG_A(m68k)[reg]; REG_A(m68k)[reg] += 12; fpr = load_pack_float80(m68k, ea); break; } case 7: // extended modes { switch (reg) { case 3: // (d16,PC,Dx.w) { UINT32 ea = EA_PCIX_32(m68k); fpr = load_pack_float80(m68k, ea); } break; default: fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); break; } } break; default: fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); break; } return fpr; }
ULONG ParseIntOp(PUCHAR inString, PUCHAR *outString, POPTBLENTRY pEntry, PULONG poffset) { ULONG instruction; ULONG Ra, Rb, Rc; ULONG lit; ULONG Format; // Whether there is a literal or 3rd reg instruction = OPCODE(pEntry->opCode) + OP_FNC(pEntry->funcCode); Ra = GetIntReg(inString, &inString); if (!TestCharacter(inString, &inString, ',')) error(OPERAND); if (TestCharacter(inString, &inString, '#')) { // // User is giving us a literal value lit = GetValue(inString, &inString, TRUE, WIDTH_LIT); Format = RBV_LITERAL_FORMAT; } else { // // using a third register value Rb = GetIntReg(inString, &inString); Format = RBV_REGISTER_FORMAT; } if (!TestCharacter(inString, &inString, ',')) error(OPERAND); Rc = GetIntReg(inString, &inString); if (!TestCharacter(inString, &inString, '\0')) error(EXTRACHARS); instruction = instruction + REG_A(Ra) + RBV_TYPE(Format) + REG_C(Rc); if (Format == RBV_REGISTER_FORMAT) { instruction = instruction + REG_B(Rb); } else { instruction = instruction + LIT(lit); } return(instruction); }
static void WRITE_EA_PACK(m68000_base_device *m68k, int ea, int k, floatx80 fpr) { int mode = (ea >> 3) & 0x7; int reg = (ea & 0x7); switch (mode) { case 2: // (An) { UINT32 ea; ea = REG_A(m68k)[reg]; store_pack_float80(m68k, ea, k, fpr); break; } case 3: // (An)+ { UINT32 ea; ea = REG_A(m68k)[reg]; store_pack_float80(m68k, ea, k, fpr); REG_A(m68k)[reg] += 12; break; } case 4: // -(An) { UINT32 ea; REG_A(m68k)[reg] -= 12; ea = REG_A(m68k)[reg]; store_pack_float80(m68k, ea, k, fpr); break; } case 7: { switch (reg) { default: fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); } } default: fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); } }
static void WRITE_EA_FPE(m68ki_cpu_core *m68k, int ea, floatx80 fpr) { int mode = (ea >> 3) & 0x7; int reg = (ea & 0x7); switch (mode) { case 2: // (An) { UINT32 ea; ea = REG_A(m68k)[reg]; store_extended_float80(m68k, ea, fpr); break; } case 3: // (An)+ { UINT32 ea; ea = REG_A(m68k)[reg]; store_extended_float80(m68k, ea, fpr); REG_A(m68k)[reg] += 12; break; } case 4: // -(An) { UINT32 ea; REG_A(m68k)[reg] -= 12; ea = REG_A(m68k)[reg]; store_extended_float80(m68k, ea, fpr); break; } case 7: { switch (reg) { default: fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); } } default: fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); } }
ULONG ParseJump(PUCHAR inString, PUCHAR *outString, POPTBLENTRY pEntry, PULONG poffset) { ULONG instruction; ULONG Ra; ULONG Rb; ULONG hint; Ra = GetIntReg(inString, &inString); if (!TestCharacter(inString, &inString, ',')) error(OPERAND); if (!TestCharacter(inString, &inString, '(')) error(OPERAND); Rb = GetIntReg(inString, &inString); if (!TestCharacter(inString, &inString, ')')) error(OPERAND); if (TestCharacter(inString, &inString, ',')) { // // User is giving us a hint // hint = GetValue(inString, &inString, TRUE, WIDTH_HINT); } else { hint = 0; } if (!TestCharacter(inString, &inString, '\0')) error(EXTRACHARS); instruction = OPCODE(pEntry->opCode) + JMP_FNC(pEntry->funcCode) + REG_A(Ra) + REG_B(Rb) + HINT(hint); return(instruction); }
/*** ParseFltBranch - parse floating point branch instruction * * Purpose: * Given the users input, create the memory instruction. * * Input: * *inString - present input position * pEntry - pointer into the asmTable for this instr type * * Output: * *outstring - update input position * * Returns: * the instruction. * * Format: * op Fa,disp * *************************************************************************/ ULONG ParseFltBranch(PUCHAR inString, PUCHAR *outString, POPTBLENTRY pEntry, PULONG poffset) { ULONG instruction; ULONG Ra; LONG disp; Ra = GetFltReg(inString, &inString); if (!TestCharacter(inString, &inString, ',')) error(OPERAND); // // the user gives an absolute address; we convert // that to a displacement, which is computed as a // difference off of (pc+1) // GetValue handles both numerics and symbolics // disp = GetValue(inString, &inString, TRUE, 32); // get the relative displacement from the updated pc disp = disp - (LONG)((*poffset)+4); // divide by four disp = disp >> 2; if (!TestCharacter(inString, &inString, '\0')) error(EXTRACHARS); instruction = OPCODE(pEntry->opCode) + REG_A(Ra) + BR_DISP(disp); return(instruction); }
ULONG ParseFltMemory(PUCHAR inString, PUCHAR *outString, POPTBLENTRY pEntry, PULONG poffset) { ULONG instruction; ULONG Fa; ULONG Rb; ULONG disp; Fa = GetFltReg(inString, &inString); if (!TestCharacter(inString, &inString, ',')) error(OPERAND); disp = GetValue(inString, &inString, TRUE, WIDTH_MEM_DISP); if (!TestCharacter(inString, &inString, '(')) error(OPERAND); Rb = GetIntReg(inString, &inString); if (!TestCharacter(inString, &inString, ')')) error(OPERAND); if (!TestCharacter(inString, &inString, '\0')) error(EXTRACHARS); instruction = OPCODE(pEntry->opCode) + REG_A(Fa) + REG_B(Rb) + MEM_DISP(disp); return(instruction); }
static void WRITE_EA_32(m68000_base_device *m68k, int ea, UINT32 data) { int mode = (ea >> 3) & 0x7; int reg = (ea & 0x7); switch (mode) { case 0: // Dn { REG_D(m68k)[reg] = data; break; } case 1: // An { REG_A(m68k)[reg] = data; break; } case 2: // (An) { UINT32 ea = REG_A(m68k)[reg]; m68ki_write_32(m68k, ea, data); break; } case 3: // (An)+ { UINT32 ea = EA_AY_PI_32(m68k); m68ki_write_32(m68k, ea, data); break; } case 4: // -(An) { UINT32 ea = EA_AY_PD_32(m68k); m68ki_write_32(m68k, ea, data); break; } case 5: // (d16, An) { UINT32 ea = EA_AY_DI_32(m68k); m68ki_write_32(m68k, ea, data); break; } case 6: // (An) + (Xn) + d8 { UINT32 ea = EA_AY_IX_32(m68k); m68ki_write_32(m68k, ea, data); break; } case 7: { switch (reg) { case 1: // (xxx).L { UINT32 d1 = OPER_I_16(m68k); UINT32 d2 = OPER_I_16(m68k); UINT32 ea = (d1 << 16) | d2; m68ki_write_32(m68k, ea, data); break; } case 2: // (d16, PC) { UINT32 ea = EA_PCDI_32(m68k); m68ki_write_32(m68k, ea, data); break; } default: fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); } break; } default: fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC(m68k)); } }
static floatx80 READ_EA_FPE(m68000_base_device *m68k, int ea) { floatx80 fpr; int mode = (ea >> 3) & 0x7; int reg = (ea & 0x7); switch (mode) { case 2: // (An) { UINT32 ea = REG_A(m68k)[reg]; fpr = load_extended_float80(m68k, ea); break; } case 3: // (An)+ { UINT32 ea = REG_A(m68k)[reg]; REG_A(m68k)[reg] += 12; fpr = load_extended_float80(m68k, ea); break; } case 4: // -(An) { UINT32 ea = REG_A(m68k)[reg]-12; REG_A(m68k)[reg] -= 12; fpr = load_extended_float80(m68k, ea); break; } case 5: // (d16, An) { // FIXME: will fail for fmovem UINT32 ea = EA_AY_DI_32(m68k); fpr = load_extended_float80(m68k, ea); break; } case 6: // (An) + (Xn) + d8 { // FIXME: will fail for fmovem UINT32 ea = EA_AY_IX_32(m68k); fpr = load_extended_float80(m68k, ea); break; } case 7: // extended modes { switch (reg) { case 2: // (d16, PC) { UINT32 ea = EA_PCDI_32(m68k); fpr = load_extended_float80(m68k, ea); } break; case 3: // (d16,PC,Dx.w) { UINT32 ea = EA_PCIX_32(m68k); fpr = load_extended_float80(m68k, ea); } break; default: fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); break; } } break; default: fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); break; } return fpr; }
static UINT64 READ_EA_64(m68000_base_device *m68k, int ea) { int mode = (ea >> 3) & 0x7; int reg = (ea & 0x7); UINT32 h1, h2; switch (mode) { case 2: // (An) { UINT32 ea = REG_A(m68k)[reg]; h1 = m68ki_read_32(m68k, ea+0); h2 = m68ki_read_32(m68k, ea+4); return (UINT64)(h1) << 32 | (UINT64)(h2); } case 3: // (An)+ { UINT32 ea = REG_A(m68k)[reg]; REG_A(m68k)[reg] += 8; h1 = m68ki_read_32(m68k, ea+0); h2 = m68ki_read_32(m68k, ea+4); return (UINT64)(h1) << 32 | (UINT64)(h2); } case 4: // -(An) { UINT32 ea = REG_A(m68k)[reg]-8; REG_A(m68k)[reg] -= 8; h1 = m68ki_read_32(m68k, ea+0); h2 = m68ki_read_32(m68k, ea+4); return (UINT64)(h1) << 32 | (UINT64)(h2); } case 5: // (d16, An) { UINT32 ea = EA_AY_DI_32(m68k); h1 = m68ki_read_32(m68k, ea+0); h2 = m68ki_read_32(m68k, ea+4); return (UINT64)(h1) << 32 | (UINT64)(h2); } case 6: // (An) + (Xn) + d8 { UINT32 ea = EA_AY_IX_32(m68k); h1 = m68ki_read_32(m68k, ea+0); h2 = m68ki_read_32(m68k, ea+4); return (UINT64)(h1) << 32 | (UINT64)(h2); } case 7: { switch (reg) { case 1: // (xxx).L { UINT32 d1 = OPER_I_16(m68k); UINT32 d2 = OPER_I_16(m68k); UINT32 ea = (d1 << 16) | d2; return (UINT64)(m68ki_read_32(m68k, ea)) << 32 | (UINT64)(m68ki_read_32(m68k, ea+4)); } case 3: // (PC) + (Xn) + d8 { UINT32 ea = EA_PCIX_32(m68k); h1 = m68ki_read_32(m68k, ea+0); h2 = m68ki_read_32(m68k, ea+4); return (UINT64)(h1) << 32 | (UINT64)(h2); } case 4: // #<data> { h1 = OPER_I_32(m68k); h2 = OPER_I_32(m68k); return (UINT64)(h1) << 32 | (UINT64)(h2); } case 2: // (d16, PC) { UINT32 ea = EA_PCDI_32(m68k); h1 = m68ki_read_32(m68k, ea+0); h2 = m68ki_read_32(m68k, ea+4); return (UINT64)(h1) << 32 | (UINT64)(h2); } default: fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); } break; } default: fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); } return 0; }
static UINT32 READ_EA_32(m68000_base_device *m68k, int ea) { int mode = (ea >> 3) & 0x7; int reg = (ea & 0x7); switch (mode) { case 0: // Dn { return REG_D(m68k)[reg]; } case 2: // (An) { UINT32 ea = REG_A(m68k)[reg]; return m68ki_read_32(m68k, ea); } case 3: // (An)+ { UINT32 ea = EA_AY_PI_32(m68k); return m68ki_read_32(m68k, ea); } case 4: // -(An) { UINT32 ea = EA_AY_PD_32(m68k); return m68ki_read_32(m68k, ea); } case 5: // (d16, An) { UINT32 ea = EA_AY_DI_32(m68k); return m68ki_read_32(m68k, ea); } case 6: // (An) + (Xn) + d8 { UINT32 ea = EA_AY_IX_32(m68k); return m68ki_read_32(m68k, ea); } case 7: { switch (reg) { case 0: // (xxx).W { UINT32 ea = (UINT32)OPER_I_16(m68k); return m68ki_read_32(m68k, ea); } case 1: // (xxx).L { UINT32 d1 = OPER_I_16(m68k); UINT32 d2 = OPER_I_16(m68k); UINT32 ea = (d1 << 16) | d2; return m68ki_read_32(m68k, ea); } case 2: // (d16, PC) { UINT32 ea = EA_PCDI_32(m68k); return m68ki_read_32(m68k, ea); } case 3: // (PC) + (Xn) + d8 { UINT32 ea = EA_PCIX_32(m68k); return m68ki_read_32(m68k, ea); } case 4: // #<data> { return OPER_I_32(m68k); } default: fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); } break; } default: fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); } return 0; }
static void WRITE_EA_64(m68ki_cpu_core *m68k, int ea, UINT64 data) { int mode = (ea >> 3) & 0x7; int reg = (ea & 0x7); switch (mode) { case 2: // (An) { UINT32 ea = REG_A(m68k)[reg]; m68ki_write_32(m68k, ea, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } case 3: // (An)+ { UINT32 ea = REG_A(m68k)[reg]; REG_A(m68k)[reg] += 8; m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } case 4: // -(An) { UINT32 ea; REG_A(m68k)[reg] -= 8; ea = REG_A(m68k)[reg]; m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } case 5: // (d16, An) { UINT32 ea = EA_AY_DI_32(m68k); m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } case 6: // (An) + (Xn) + d8 { UINT32 ea = EA_AY_IX_32(m68k); m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } case 7: { switch (reg) { case 1: // (xxx).L { UINT32 d1 = OPER_I_16(m68k); UINT32 d2 = OPER_I_16(m68k); UINT32 ea = (d1 << 16) | d2; m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } case 2: // (d16, PC) { UINT32 ea = EA_PCDI_32(m68k); m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } default: fatalerror("M68kFPU: WRITE_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); } break; } default: fatalerror("M68kFPU: WRITE_EA_64: unhandled mode %d, reg %d, data %08X%08X at %08X\n", mode, reg, (UINT32)(data >> 32), (UINT32)(data), REG_PC(m68k)); } }
static const char* get_svc_call(m68000_base_device *m68k, int trap_no, int trap_code, char *sb) { UINT32 sp = REG_A(m68k)[7]; UINT32 pa; const char * name = NULL; const char * param = NULL; switch (trap_no) { case 0: if (trap_no < sizeof(trap0) / 8) { name = trap0[trap_code * 2]; param = trap0[trap_code * 2 + 1]; } break; case 1: if (trap_no < sizeof(trap1) / 8) { name = trap1[trap_code * 2]; param = trap1[trap_code * 2 + 1]; } break; case 2: if (trap_no < sizeof(trap2) / 8) { name = trap2[trap_code * 2]; param = trap2[trap_code * 2 + 1]; } break; case 3: if (trap_no < sizeof(trap3) / 8) { name = trap3[trap_code * 2]; param = trap3[trap_code * 2 + 1]; } break; case 4: if (trap_no < sizeof(trap4) / 8) { name = trap4[trap_code * 2]; param = trap4[trap_code * 2 + 1]; } break; case 5: if (trap_no < sizeof(trap5) / 8) { name = trap5[trap_code * 2]; param = trap5[trap_code * 2 + 1]; } break; case 7: if (trap_no < sizeof(trap7) / 8) { name = trap7[trap_code * 2]; param = trap7[trap_code * 2 + 1]; } break; case 8: if (trap_no < sizeof(trap8) / 8) { name = trap8[trap_code * 2]; param = trap8[trap_code * 2 + 1]; } break; } sb[0] = '\0'; if (name == NULL) { strcat(sb, "???"); } else { strcat(sb, name); if (param != NULL) { int i; strcat(sb, "("); for (i = 0, pa = sp + 4; param[i] != '\0'; i++) { switch (param[i]) { case ',': strcat(sb, ", "); pa += 4; break; default: strcat(sb, get_param(m68k, pa, param[i])); break; } } strcat(sb, ")"); } } return sb; }
int apollo_debug_instruction_hook(m68000_base_device *device, offs_t curpc) { // trap data remembered for next rte static struct { UINT32 pc; UINT32 sp; UINT16 trap_no; UINT16 trap_code; } trap = { 0, 0, 0, 0 }; if (apollo_config( APOLLO_CONF_TRAP_TRACE | APOLLO_CONF_FPU_TRACE)) { UINT32 ppc_save; UINT16 ir; m68000_base_device *m68k = device; m68k->mmu_tmp_buserror_occurred = 0; /* Read next instruction */ ir = (m68k->pref_addr == REG_PC(m68k)) ? m68k->pref_data : m68k->readimm16(REG_PC(m68k)); // apollo_cpu_context expects the PC of current opcode in REG_PPC (not the previous PC) ppc_save = REG_PPC(m68k); REG_PPC(m68k) = REG_PC(m68k); if (m68k->mmu_tmp_buserror_occurred) { m68k->mmu_tmp_buserror_occurred = 0; // give up } else if ((ir & 0xff00) == 0xf200 && (apollo_config( APOLLO_CONF_FPU_TRACE))) { char sb[256]; LOG(("%s sp=%08x FPU: %x %s", apollo_cpu_context(device->machine().firstcpu), REG_A(m68k)[7], ir, disassemble(m68k, REG_PC(m68k), sb))); } else if (!m68k->pmmu_enabled) { // skip } else if (ir == 0x4e73) // RTE { const UINT16 *data = get_data(m68k, REG_A(m68k)[7]); if ( REG_USP(m68k) == 0 && (data[0] & 0x2000) == 0) { LOG(("%s sp=%08x RTE: sr=%04x pc=%04x%04x v=%04x usp=%08x", apollo_cpu_context(device->machine().firstcpu), REG_A(m68k)[7], data[0], data[1], data[2], data[3], REG_USP(m68k))); } } else if ((ir & 0xfff0) == 0x4e40 && (ir & 0x0f) <= 8 && apollo_config(APOLLO_CONF_TRAP_TRACE)) { // trap n trap.pc = REG_PC(m68k); trap.sp = REG_A(m68k)[7]; trap.trap_no = ir & 0x0f; trap.trap_code = REG_D(m68k)[0] & 0xffff; char sb[1000]; LOG(("%s sp=%08x Domain/OS SVC: trap %x 0x%02x: %s", apollo_cpu_context(device->machine().firstcpu), trap.sp, trap.trap_no, trap.trap_code, get_svc_call(m68k, trap.trap_no, trap.trap_code, sb))); } else if (trap.pc == REG_PC(m68k) - 2 && trap.sp == REG_A(m68k)[7]) { // rte char sb[1000]; LOG(("%s sp=%08x Domain/OS SVC: %s D0=0x%x", apollo_cpu_context(device->machine().firstcpu), trap.sp, get_svc_call(m68k, trap.trap_no, trap.trap_code, sb), REG_D(m68k)[0])); trap.pc = 0; trap.sp = 0; trap.trap_no = 0; trap.trap_code = 0; } // restore previous PC REG_PPC(m68k) = ppc_save; } return 0; }