From 72eeb6f6648aa92b28c4d961532ba6dc7d5a07c1 Mon Sep 17 00:00:00 2001 From: qufb <93520295+qufb@users.noreply.github.com> Date: Sat, 1 Jun 2024 20:59:17 +0100 Subject: [PATCH] cpu/f2mc16: Add and fix several instructions (#12427) --- src/devices/cpu/f2mc16/f2mc16.cpp | 1729 ++++++++++++++++++++++++++--- src/devices/cpu/f2mc16/f2mc16.h | 179 ++- 2 files changed, 1755 insertions(+), 153 deletions(-) diff --git a/src/devices/cpu/f2mc16/f2mc16.cpp b/src/devices/cpu/f2mc16/f2mc16.cpp index 7d85bff282a..f667a4fdbaf 100644 --- a/src/devices/cpu/f2mc16/f2mc16.cpp +++ b/src/devices/cpu/f2mc16/f2mc16.cpp @@ -12,6 +12,8 @@ There are two main branches: F and L. They appear to be compatible with each other as far as their extentions to the base ISA not conflicting. + TODO: Correction values applied to instruction cycles. + ***************************************************************************/ #include "emu.h" @@ -258,8 +260,18 @@ void f2mc16_device::execute_run() m_pc++; break; + // NEG A case 0x03: - // util::stream_format(stream, "NEG A"); + m_tmp8 = doSUB_8(0, m_acc & 0xff); + m_acc &= 0xffff0000; + m_acc |= m_tmp8; + if (m_acc & 0x80) + { + m_acc |= 0xff00; + } + setNZ_8(m_tmp8); + m_pc++; + m_icount -= 2; break; // PCB prefix @@ -344,7 +356,7 @@ void f2mc16_device::execute_run() // NEGW A case 0x0b: - m_tmp16 = doSUB_16(0, m_acc&0xffff); + m_tmp16 = doSUB_16(0, m_acc & 0xffff); m_acc &= 0xffff0000; m_acc |= m_tmp16; setNZ_16(m_tmp16); @@ -428,15 +440,15 @@ void f2mc16_device::execute_run() break; case 0x10: - // stream << "CMR "; + logerror("%s: Unimplemented F2MC instruction CMR\n", machine().describe_context()); break; case 0x11: - // stream << "NCC "; + logerror("%s: Unimplemented F2MC instruction NCC\n", machine().describe_context()); break; case 0x12: - // stream << "SUBDC A"; + logerror("%s: Unimplemented F2MC instruction SUBDC A\n", machine().describe_context()); break; // EXT @@ -451,7 +463,7 @@ void f2mc16_device::execute_run() { m_acc &= 0xffff00ff; if ((m_acc & 0xff) == 0) - m_pc |= F_Z; + m_ps |= F_Z; } m_pc++; m_icount--; @@ -481,11 +493,11 @@ void f2mc16_device::execute_run() m_tmp8 = read_8((m_pcb<<16) | (m_pc+1)); if (m_ps & F_S) { - m_ssp += m_tmp8; + m_ssp += (s8)m_tmp8; } else { - m_usp += m_tmp8; + m_usp += (s8)m_tmp8; } m_pc += 2; m_icount -= 3; @@ -516,6 +528,14 @@ void f2mc16_device::execute_run() m_icount -= 2; break; + // CMPL A, #imm32 + case 0x1b: + m_tmp32 = read_32((m_pcb << 16) | (m_pc+1)); + doCMP_32(m_acc, m_tmp32); + m_pc += 5; + m_icount -= 3; + break; + // EXTW case 0x1c: m_acc &= 0xffff; @@ -550,21 +570,36 @@ void f2mc16_device::execute_run() m_icount -= 2; break; + // ADDSP #imm16 + case 0x1f: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+1)); + if (m_ps & F_S) + { + m_ssp += m_tmp16; + } + else + { + m_usp += m_tmp16; + } + m_pc += 3; + m_icount -= 3; + break; + case 0x20: - // util::stream_format(stream, "ADD A, $%02x", operand); + logerror("%s: Unimplemented F2MC instruction ADD A, dir\n", machine().describe_context()); break; case 0x21: - // util::stream_format(stream, "SUB A, $%02x", operand); + logerror("%s: Unimplemented F2MC instruction SUB A, dir\n", machine().describe_context()); break; case 0x22: - // stream << "ADDC A"; + logerror("%s: Unimplemented F2MC instruction ADDC A\n", machine().describe_context()); break; // CMP A case 0x23: - doCMP_16(m_acc>>16, m_acc&0xffff); + doCMP_16(m_acc>>16, m_acc & 0xffff); m_pc++; m_icount--; break; @@ -586,11 +621,11 @@ void f2mc16_device::execute_run() break; case 0x26: - // stream << "DIVU A"; + logerror("%s: Unimplemented F2MC instruction DIVU A\n", machine().describe_context()); break; case 0x27: - // stream << "MULU A"; + logerror("%s: Unimplemented F2MC instruction MULU A\n", machine().describe_context()); break; // ADDW A @@ -686,7 +721,7 @@ void f2mc16_device::execute_run() case 0x30: m_tmp8 = read_8((m_pcb<<16) | (m_pc+1)); m_tmp8 = doADD_8(m_acc & 0xff, m_tmp8); - m_acc &= ~0xff; + m_acc &= 0xffff0000; m_acc |= m_tmp8; m_pc += 2; m_icount -= 2; @@ -696,14 +731,14 @@ void f2mc16_device::execute_run() case 0x31: m_tmp8 = read_8((m_pcb<<16) | (m_pc+1)); m_tmp8 = doSUB_8(m_acc & 0xff, m_tmp8); - m_acc &= ~0xff; + m_acc &= 0xffff0000; m_acc |= m_tmp8; m_pc += 2; m_icount -= 2; break; case 0x32: - // stream << "SUBC A"; + logerror("%s: Unimplemented F2MC instruction SUBC A\n", machine().describe_context()); break; // CMP A, #imm8 @@ -951,7 +986,7 @@ void f2mc16_device::execute_run() m_pc += 3; break; - // MOVL A, #imm16 + // MOVL A, #imm32 case 0x4b: m_acc = read_32((m_pcb<<16) | (m_pc + 1)); setNZ_32(m_acc); @@ -1074,8 +1109,24 @@ void f2mc16_device::execute_run() m_icount -= 5; break; + // MOVX A, addr16 case 0x57: - // util::stream_format(stream, "MOVX A, $%04x", opcodes.r16(pc+1)); + m_tmp16 = read_16((m_pcb<<16) | (m_pc+1)); + m_acc <<= 16; + if (m_prefix_valid) + { + m_prefix_valid = false; + m_tmp8 = read_8((m_prefix<<16) | m_tmp16); + } + else + { + m_tmp8 = read_8((m_dtb<<16) | m_tmp16); + } + m_tmp16 = (m_tmp8 & 0x80) ? (m_tmp8 | 0xff00) : m_tmp8; + m_acc |= m_tmp16; + setNZ_16(m_acc & 0xffff); + m_pc += 3; + m_icount -= 4; break; // MOVW A, io @@ -1178,8 +1229,10 @@ void f2mc16_device::execute_run() take_branch(); break; + // JMP @A case 0x61: -// stream << "JMP @A"; + m_pc = (m_pcb<<16) | (m_acc & 0xffff); + m_icount -= 2; break; // JMP addr16 @@ -1188,8 +1241,13 @@ void f2mc16_device::execute_run() m_icount -= 3; break; + // JMPP addr24 case 0x63: - // util::stream_format(stream, "JMPP #$%06x", opcodes.r8(pc+3)<<16|opcodes.r8(pc+2)<<8|opcodes.r8(pc+1)); + m_tmp16 = read_16((m_pcb << 16) | (m_pc + 1)); + m_tmp8 = read_8((m_pcb << 16) | (m_pc + 3)); + m_pcb = m_tmp8; + m_pc = m_tmp16; + m_icount -= 4; break; // CALL addr16 @@ -1319,12 +1377,16 @@ void f2mc16_device::execute_run() opcodes_ea78(read_8((m_pcb<<16) | (m_pc+1))); break; - case 0x7a: // ea RWi-type instructions - opcodes_rwi7a(read_8((m_pcb<<16) | (m_pc+1))); + case 0x7a: // Ri,ea-type instructions + opcodes_riea7a(read_8((m_pcb<<16) | (m_pc+1))); break; - case 0x7b: // ea RWi-type instructions - opcodes_rwi7b(read_8((m_pcb<<16) | (m_pc+1))); + case 0x7b: // RWi,ea-type instructions + opcodes_rwiea7b(read_8((m_pcb<<16) | (m_pc+1))); + break; + + case 0x7c: // ea,Ri-type instructions + opcodes_eari7c(read_8((m_pcb<<16) | (m_pc+1))); break; // MOV A, Rx @@ -1340,7 +1402,7 @@ void f2mc16_device::execute_run() case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: m_acc <<= 16; m_acc |= read_rwX(opcode & 7); - setNZ_16(m_acc & 0xff); + setNZ_16(m_acc & 0xffff); m_pc++; m_icount -= 2; break; @@ -1381,7 +1443,15 @@ void f2mc16_device::execute_run() // MOVX A, Rx case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: - // util::stream_format(stream, "MOVX A, R%d", (opcode & 0x7)); + m_acc <<= 16; + m_acc |= read_rX(opcode & 7); + if (m_acc & 0x80) + { + m_acc |= 0xff00; + } + setNZ_8(m_acc & 0xff); + m_pc++; + m_icount -= 2; break; // MOVW A, @RWx + disp8 @@ -1396,7 +1466,7 @@ void f2mc16_device::execute_run() m_icount -= 10; break; - // MOVX A, @Rx + disp8 + // MOVX A, @RWx + disp8 case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: m_tmp8 = read_8((m_pcb<<16) | (m_pc+1)); m_tmp16 = read_rwX(opcode & 0x7) + (s8)m_tmp8; @@ -1405,6 +1475,7 @@ void f2mc16_device::execute_run() m_tmp16 = (m_tmp8 & 0x80) ? (m_tmp8 | 0xff00) : m_tmp8; m_acc <<= 16; m_acc |= m_tmp16; + setNZ_16(m_acc & 0xffff); m_pc += 2; m_icount -= 3; break; @@ -1436,7 +1507,7 @@ void f2mc16_device::execute_run() case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: - // util::stream_format(stream, "CALLV #$%01x", (opcode & 0xf)); + logerror("%s: Unimplemented F2MC instruction CALLV #imm4\n", machine().describe_context()); break; // BEQ @@ -1491,7 +1562,7 @@ void f2mc16_device::execute_run() } break; - // + // BN case 0xf4: if (m_ps & F_N) { @@ -1608,7 +1679,7 @@ void f2mc16_device::execute_run() { u8 n = (m_ps & F_N) ? 1 : 0; u8 v = (m_ps & F_V) ? 1 : 0; - if (((v ^ n) == 1) || (m_ps & F_Z)) + if (((v ^ n) || (m_ps & F_Z)) == 1) { take_branch(); } @@ -1625,7 +1696,7 @@ void f2mc16_device::execute_run() { u8 n = (m_ps & F_N) ? 1 : 0; u8 v = (m_ps & F_V) ? 1 : 0; - if (((v ^ n) == 1) || !(m_ps & F_Z)) + if (((v ^ n) || (m_ps & F_Z)) == 0) { take_branch(); } @@ -1652,7 +1723,7 @@ void f2mc16_device::execute_run() // BHI case 0xff: - if (!(m_ps & F_C) || !(m_ps & F_Z)) + if (!((m_ps & F_C) || (m_ps & F_Z))) { take_branch(); } @@ -1673,47 +1744,53 @@ void f2mc16_device::execute_run() void f2mc16_device::opcodes_str6e(u8 operand) { + const u8 spb = (m_ps & F_S) ? m_ssb : m_usb; + + // TODO: If an interrupt occurs during the transfer, the transfer is suspended to + // handle the interrupt. The transfer is resumed after the interrupt has been handled. switch (operand) { - // MOVSI ADB, DTB - case 0x09: - if (read_rwX(0) > 0) - { - u16 al = (m_acc & 0xffff); - u16 ah = (m_acc >> 16) & 0xffff; - m_tmp8 = read_8((m_dtb<<16) | al); - write_8((m_adb<<16) | ah, m_tmp8); - al++; - ah++; - m_acc = (ah<<16) | al; - write_rwX(0, read_rwX(0) - 1); - m_icount -= 8; - } - else - { - m_pc += 2; - m_icount -= 5; - } - break; + // MOVSI destination_bank, source_bank + case 0x00: movsi(m_pcb, m_pcb); break; + case 0x01: movsi(m_pcb, m_dtb); break; + case 0x02: movsi(m_pcb, m_adb); break; + case 0x03: movsi(m_pcb, spb); break; + case 0x04: movsi(m_dtb, m_pcb); break; + case 0x05: movsi(m_dtb, m_dtb); break; + case 0x06: movsi(m_dtb, m_adb); break; + case 0x07: movsi(m_dtb, spb); break; + case 0x08: movsi(m_adb, m_pcb); break; + case 0x09: movsi(m_adb, m_dtb); break; + case 0x0a: movsi(m_adb, m_adb); break; + case 0x0b: movsi(m_adb, spb); break; + case 0x0c: movsi(spb, m_pcb); break; + case 0x0d: movsi(spb, m_dtb); break; + case 0x0e: movsi(spb, m_adb); break; + case 0x0f: movsi(spb, spb); break; - // FILSI ADB - case 0xc2: - if (read_rwX(0) > 0) - { - u16 al = (m_acc & 0xffff); - u16 ah = (m_acc >> 16) & 0xffff; - write_8((m_adb<<16) | ah, al & 0xff); - ah++; - m_acc = (ah<<16) | al; - write_rwX(0, read_rwX(0) - 1); - m_icount -= 6; - } - else - { - m_pc += 2; - m_icount -= 6; - } - break; + // MOVSWI destination_bank, source_bank + case 0x20: movswi(m_pcb, m_pcb); break; + case 0x21: movswi(m_pcb, m_dtb); break; + case 0x22: movswi(m_pcb, m_adb); break; + case 0x23: movswi(m_pcb, spb); break; + case 0x24: movswi(m_dtb, m_pcb); break; + case 0x25: movswi(m_dtb, m_dtb); break; + case 0x26: movswi(m_dtb, m_adb); break; + case 0x27: movswi(m_dtb, spb); break; + case 0x28: movswi(m_adb, m_pcb); break; + case 0x29: movswi(m_adb, m_dtb); break; + case 0x2a: movswi(m_adb, m_adb); break; + case 0x2b: movswi(m_adb, spb); break; + case 0x2c: movswi(spb, m_pcb); break; + case 0x2d: movswi(spb, m_dtb); break; + case 0x2e: movswi(spb, m_adb); break; + case 0x2f: movswi(spb, spb); break; + + // FILSI destination_bank + case 0xc0: filsi(m_pcb); break; + case 0xc1: filsi(m_dtb); break; + case 0xc2: filsi(m_adb); break; + case 0xc3: filsi( spb); break; default: fatalerror("Unknown F2MC STR6E opcode %02x (PC=%x)\n", operand, (m_pcb<<16) | m_pc); @@ -2041,6 +2118,24 @@ void f2mc16_device::opcodes_2b6f(u8 operand) m_icount -= 2; break; + // MOV A, @A + case 0x05: + if (m_prefix_valid) + { + m_prefix_valid = false; + m_tmp8 = read_8((m_prefix<<16) | (m_acc & 0xffff)); + } + else + { + m_tmp8 = read_8((m_dtb<<16) | (m_acc & 0xffff)); + } + setNZ_8(m_tmp8); + m_acc &= 0xffff0000; + m_acc |= m_tmp8; + m_pc += 2; + m_icount -= 3; + break; + // MOV A, PCB case 0x06: m_acc <<= 16; @@ -2049,6 +2144,24 @@ void f2mc16_device::opcodes_2b6f(u8 operand) m_icount -= 1; break; + // ROLC A + case 0x07: + m_shifted_carry = (m_ps & F_C) ? 1 : 0; + m_tmp8 = m_acc & 0xff; + m_ps &= ~F_C; + if (m_tmp8 & 0x80) + { + m_ps |= F_C; + } + m_tmp8 <<= 1; + m_tmp8 |= m_shifted_carry; + m_acc &= 0xffffff00; + m_acc |= m_tmp8; + setNZ_8(m_tmp8); + m_pc += 2; + m_icount -= 2; + break; + // LSLW A, R0 case 0x0c: m_tmp8 = read_rX(0); @@ -2073,6 +2186,24 @@ void f2mc16_device::opcodes_2b6f(u8 operand) m_pc += 2; break; + // MOVW A, @A + case 0x0d: + if (m_prefix_valid) + { + m_prefix_valid = false; + m_tmp16 = read_16((m_prefix<<16) | (m_acc & 0xffff)); + } + else + { + m_tmp16 = read_16((m_dtb<<16) | (m_acc & 0xffff)); + } + setNZ_16(m_tmp16); + m_acc &= 0xffff0000; + m_acc |= m_tmp16; + m_pc += 2; + m_icount -= 3; + break; + // ASRW A, R0 case 0x0e: m_tmp8 = read_rX(0); @@ -2086,6 +2217,7 @@ void f2mc16_device::opcodes_2b6f(u8 operand) } else { + m_icount -= 5; m_tmp16 = m_acc & 0xffff; for (u8 count = 0; count < m_tmp8; count++) { @@ -2112,7 +2244,7 @@ void f2mc16_device::opcodes_2b6f(u8 operand) m_tmp16 &= ~0x8000; } setNZ_16(m_tmp16); - m_icount -= 5; + m_icount --; // 1 additional cycle per iteration } m_acc &= 0xffff0000; @@ -2122,7 +2254,7 @@ void f2mc16_device::opcodes_2b6f(u8 operand) break; // LSRW A, R0 - case 0xf: + case 0x0f: m_tmp8 = read_rX(0); if (m_tmp8 == 0) { @@ -2134,6 +2266,7 @@ void f2mc16_device::opcodes_2b6f(u8 operand) } else { + m_icount -= 5; m_tmp16 = m_acc & 0xffff; for (u8 count = 0; count < m_tmp8; count++) { @@ -2151,7 +2284,7 @@ void f2mc16_device::opcodes_2b6f(u8 operand) m_tmp16 >>= 1; setNZ_16(m_tmp16); - m_icount -= 5; + m_icount --; // 1 additional cycle per iteration } m_acc &= 0xffff0000; @@ -2210,6 +2343,28 @@ void f2mc16_device::opcodes_2b6f(u8 operand) m_icount -= 3; break; + // MOVX A, @A + case 0x16: + if (m_prefix_valid) + { + m_prefix_valid = false; + m_tmp8 = read_8((m_prefix<<16) | (m_acc & 0xffff)); + } + else + { + m_tmp8 = read_8((m_dtb<<16) | (m_acc & 0xffff)); + } + setNZ_8(m_tmp8); + m_acc &= 0xffff0000; + m_acc |= m_tmp8; + if (m_acc & 0x80) + { + m_acc |= 0xff00; + } + m_pc += 2; + m_icount -= 3; + break; + // LSLL A, R0 case 0x1c: m_tmp8 = read_rX(0); @@ -2220,7 +2375,6 @@ void f2mc16_device::opcodes_2b6f(u8 operand) } else { - m_icount -= 6; for (u8 count = 0; count < m_tmp8; count++) { m_ps &= ~F_C; @@ -2233,6 +2387,113 @@ void f2mc16_device::opcodes_2b6f(u8 operand) m_pc += 2; break; + // ASRL A, R0 + case 0x1e: + m_tmp8 = read_rX(0); + m_icount -= 6; // 6 cycles base + if (m_tmp8 == 0) + { + m_ps &= ~(F_C|F_T); + m_ps |= F_Z; + } + else + { + for (u8 count = 0; count < m_tmp8; count++) + { + // T is set if either carry or T are set beforehand + if ((m_ps & F_C) || (m_ps & F_T)) + { + m_ps |= F_T; + } + // C becomes the previous LSB + m_ps &= ~F_C; + m_ps |= (m_acc & 1) ? F_C : 0; + + if (m_acc & 0x80000000) + { + m_acc >>= 1; + m_acc |= 0x80000000; + } + else + { + m_acc >>= 1; + m_acc &= ~0x80000000; + } + setNZ_32(m_acc); + m_icount --; // 1 additional cycle per iteration + } + } + m_pc += 2; + break; + + // LSRL A, R0 + case 0x1f: + m_tmp8 = read_rX(0); + m_icount -= 6; // 6 cycles base + if (m_tmp8 == 0) + { + m_ps &= ~(F_C|F_T); + m_ps |= F_Z; + } + else + { + for (u8 count = 0; count < m_tmp8; count++) + { + // T is set if either carry or T are set beforehand + if ((m_ps & F_C) || (m_ps & F_T)) + { + m_ps |= F_T; + } + // C becomes the previous LSB + m_ps &= ~F_C; + m_ps |= (m_acc & 1) ? F_C : 0; + + m_acc >>= 1; + setNZ_32(m_acc); + m_icount --; // 1 additional cycle per iteration + } + } + m_pc += 2; + break; + + // MOVX A, @RLx + disp8 + case 0x20: case 0x22: case 0x24: case 0x26: + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); + m_tmpea = read_rlX((operand>>1) & 0x3) + (s8)m_tmp8; + m_acc <<= 16; + m_acc |= read_8(m_tmpea); + if (m_acc & 0x80) + { + m_acc |= 0xff00; + } + setNZ_8(m_acc & 0xff); + m_pc += 3; + m_icount -= 10; + break; + + // NRML A, R0 + case 0x2d: + m_tmp8 = 0; + if (m_acc != 0) + { + while (!(m_acc & 0x80000000)) + { + m_acc <<= 1; + m_tmp8++; + m_icount --; // 1 additional cycle per iteration + } + m_ps &= ~(F_Z); + m_icount -= 6; + } + else + { + m_ps |= F_Z; + m_icount -= 4; + } + write_rX(0, m_tmp8); + m_pc += 2; + break; + // LSR A, R0 case 0x2f: m_tmp8 = read_rX(0); @@ -2246,7 +2507,8 @@ void f2mc16_device::opcodes_2b6f(u8 operand) } else { - m_tmp16 = m_acc & 0xff; + m_icount -= 5; + m_tmp8aux = m_acc & 0xff; for (u8 count = 0; count < m_tmp8; count++) { // T is set if either carry or T are set beforehand @@ -2256,18 +2518,18 @@ void f2mc16_device::opcodes_2b6f(u8 operand) } // C becomes the previous LSB m_ps &= ~F_C; - if (m_tmp16 & 1) + if (m_tmp8aux & 1) { m_ps |= F_C; } - m_tmp16 >>= 1; - setNZ_8(m_tmp16); - m_icount -= 5; + m_tmp8aux >>= 1; + setNZ_8(m_tmp8aux); + m_icount --; // 1 additional cycle per iteration } m_acc &= 0xffffff00; - m_acc |= m_tmp16; + m_acc |= m_tmp8aux; m_pc += 2; } break; @@ -2328,54 +2590,155 @@ void f2mc16_device::opcodes_ea70(u8 operand) case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: m_acc = doADD_32(m_acc, read_rlX((operand>>1) & 3)); m_pc += 2; - m_icount -= 7; + m_icount -= 6; break; // ADDL A, @RWx + disp8 case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: - m_tmp8 = read_32((m_pcb<<16) | (m_pc+2)); + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); m_tmp16 = read_rwX(operand & 7) + (s8)m_tmp8; m_tmpea = getRWbank(operand & 7, m_tmp16); m_tmp32 = read_32(m_tmpea); m_acc = doADD_32(m_acc, m_tmp32); m_pc += 3; - m_icount -= 7; + m_icount -= 9; + break; + + // ADDL A, @RWx + disp16 + case 0x18: case 0x19: case 0x1a: case 0x1b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp32 = read_32(m_tmpea); + m_acc = doADD_32(m_acc, m_tmp32); + m_pc += 4; + m_icount -= 9; + break; + + // ADDL A, addr16 + case 0x1f: + m_tmpea = read_16((m_pcb<<16) | (m_pc+2)); + if (m_prefix_valid) + { + m_prefix_valid = false; + m_tmpea |= (m_prefix << 16); + } + else + { + m_tmpea |= (m_dtb << 16); + } + m_acc = doADD_32(m_acc, read_32(m_tmpea)); + m_pc += 4; + m_icount -= 8; break; // SUBL A, RLx case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: m_acc = doSUB_32(m_acc, read_rlX((operand>>1) & 3)); m_pc += 2; - m_icount -= 7; + m_icount -= 6; break; // SUBL A, @RWx + disp8 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: - m_tmp8 = read_32((m_pcb<<16) | (m_pc+2)); + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); m_tmp16 = read_rwX(operand & 7) + (s8)m_tmp8; m_tmpea = getRWbank(operand & 7, m_tmp16); m_tmp32 = read_32(m_tmpea); m_acc = doSUB_32(m_acc, m_tmp32); m_pc += 3; - m_icount -= 7; + m_icount -= 9; + break; + + // SUBL A, @RWx + disp16 + case 0x38: case 0x39: case 0x3a: case 0x3b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp32 = read_32(m_tmpea); + m_acc = doSUB_32(m_acc, m_tmp32); + m_pc += 4; + m_icount -= 9; + break; + + // SUBL A, addr16 + case 0x3f: + m_tmpea = read_16((m_pcb<<16) | (m_pc+2)); + if (m_prefix_valid) + { + m_prefix_valid = false; + m_tmpea |= (m_prefix << 16); + } + else + { + m_tmpea |= (m_dtb << 16); + } + m_acc = doSUB_32(m_acc, read_32(m_tmpea)); + m_pc += 4; + m_icount -= 8; + break; + + // CWBNE RWx, #imm16, disp8 + case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp8 = read_8((m_pcb<<16) | (m_pc+4)); + doCMP_16(read_rwX(operand & 7), m_tmp16); + if (m_ps & F_Z) + { + m_pc += 5; + m_icount -= 7; + } + else + { + m_pc = m_pc + 5 + (s8)m_tmp8; + m_icount -= 8; + } break; // CMPL A, RLx case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: doCMP_32(m_acc, read_rlX((operand>>1) & 3)); m_pc += 2; - m_icount -= 7; + m_icount -= 6; break; // CMPL A, @RWx + disp8 case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: - m_tmp8 = read_32((m_pcb<<16) | (m_pc+2)); + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); m_tmp16 = read_rwX(operand & 7) + (s8)m_tmp8; m_tmpea = getRWbank(operand & 7, m_tmp16); m_tmp32 = read_32(m_tmpea); doCMP_32(m_acc, m_tmp32); m_pc += 3; - m_icount -= 7; + m_icount -= 9; + break; + + // CMPL A, @RWx + disp16 + case 0x78: case 0x79: case 0x7a: case 0x7b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp32 = read_32(m_tmpea); + doCMP_32(m_acc, m_tmp32); + m_pc += 4; + m_icount -= 9; + break; + + // CMPL A, addr16 + case 0x7f: + m_tmpea = read_16((m_pcb<<16) | (m_pc+2)); + if (m_prefix_valid) + { + m_prefix_valid = false; + m_tmpea |= (m_prefix << 16); + } + else + { + m_tmpea |= (m_dtb << 16); + } + doCMP_32(m_acc, read_32(m_tmpea)); + m_pc += 4; + m_icount -= 8; break; // ANDL A, RLx @@ -2385,12 +2748,12 @@ void f2mc16_device::opcodes_ea70(u8 operand) setNZ_32(m_acc); m_ps &= ~F_V; m_pc += 2; - m_icount -= 7; + m_icount -= 6; break; // ANDL A, @RWx + disp8 case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: - m_tmp8 = read_32((m_pcb<<16) | (m_pc+2)); + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); m_tmp16 = read_rwX(operand & 7) + (s8)m_tmp8; m_tmpea = getRWbank(operand & 7, m_tmp16); m_tmp32 = read_32(m_tmpea); @@ -2398,7 +2761,70 @@ void f2mc16_device::opcodes_ea70(u8 operand) setNZ_32(m_acc); m_ps &= ~F_V; m_pc += 3; - m_icount -= 7; + m_icount -= 9; + break; + + // ORL A, RLx + case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: + m_tmp32 = read_rlX((operand>>1) & 3); + m_acc |= m_tmp32; + setNZ_32(m_acc); + m_ps &= ~F_V; + m_pc += 2; + m_icount -= 6; + break; + + // ORL A, @RWx + disp8 + case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 7) + (s8)m_tmp8; + m_tmpea = getRWbank(operand & 7, m_tmp16); + m_tmp32 = read_32(m_tmpea); + m_acc |= m_tmp32; + setNZ_32(m_acc); + m_ps &= ~F_V; + m_pc += 3; + m_icount -= 9; + break; + + // XORL A, RLx + case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: + m_tmp32 = read_rlX((operand>>1) & 3); + m_acc ^= m_tmp32; + setNZ_32(m_acc); + m_ps &= ~F_V; + m_pc += 2; + m_icount -= 6; + break; + + // XORL A, @RWx + disp8 + case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 7) + (s8)m_tmp8; + m_tmpea = getRWbank(operand & 7, m_tmp16); + m_tmp32 = read_32(m_tmpea); + m_acc ^= m_tmp32; + setNZ_32(m_acc); + m_ps &= ~F_V; + m_pc += 3; + m_icount -= 9; + break; + + // CBNE Rx, #imm8, disp8 + case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: + m_tmp8aux = read_8((m_pcb<<16) | (m_pc+2)); + m_tmp8 = read_8((m_pcb<<16) | (m_pc+3)); + doCMP_8(read_rX(operand & 7), m_tmp8aux); + if (m_ps & F_Z) + { + m_pc += 4; + m_icount -= 12; + } + else + { + m_pc = m_pc + 4 + (s8)m_tmp8; + m_icount -= 13; + } break; default: @@ -2440,7 +2866,28 @@ void f2mc16_device::opcodes_ea71(u8 operand) m_tmp32 = doINC_32(read_32(m_tmpea)); write_32(m_tmpea, m_tmp32); m_pc += 3; - m_icount -= 7; + m_icount -= 11; + break; + + // INCL @RWx + disp16 + case 0x58: case 0x59: case 0x5a: case 0x5b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp32 = doINC_32(read_32(m_tmpea)); + write_32(m_tmpea, m_tmp32); + m_pc += 4; + m_icount -= 11; + break; + + // INCL @RWx + RW7 + case 0x5c: case 0x5d: + m_tmp16 = read_rwX(operand & 1) + read_rwX(7); + m_tmpea = getRWbank(operand & 1, m_tmp16); + m_tmp32 = doINC_32(read_32(m_tmpea)); + write_32(m_tmpea, m_tmp32); + m_pc += 2; + m_icount -= 13; break; // INCL addr16 @@ -2456,9 +2903,65 @@ void f2mc16_device::opcodes_ea71(u8 operand) m_tmp32 = doINC_32(read_32(m_tmpea)); write_32(m_tmpea, m_tmp32); m_pc += 4; + m_icount -= 10; + break; + + // DECL RLx + case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: + m_tmp32 = doDEC_32(read_rlX((operand>>1) & 3)); + write_rlX((operand>>1) & 3, m_tmp32); + m_pc += 2; m_icount -= 7; break; + // DECL @RWx + disp8 + case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 7) + (s8)m_tmp8; + m_tmpea = getRWbank(operand & 7, m_tmp16); + m_tmp32 = doDEC_32(read_32(m_tmpea)); + write_32(m_tmpea, m_tmp32); + m_pc += 3; + m_icount -= 11; + break; + + // DECL @RWx + disp16 + case 0x78: case 0x79: case 0x7a: case 0x7b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp32 = doDEC_32(read_32(m_tmpea)); + write_32(m_tmpea, m_tmp32); + m_pc += 4; + m_icount -= 11; + break; + + // DECL @RWx + RW7 + case 0x7c: case 0x7d: + m_tmp16 = read_rwX(operand & 1) + read_rwX(7); + m_tmpea = getRWbank(operand & 1, m_tmp16); + m_tmp32 = doDEC_32(read_32(m_tmpea)); + write_32(m_tmpea, m_tmp32); + m_pc += 2; + m_icount -= 13; + break; + + // DECL addr16 + case 0x7f: + m_tmpea = read_16((m_pcb<<16) | (m_pc+2)); + if (m_prefix_valid) + { + m_prefix_valid = false; + m_tmpea |= (m_prefix<<16); + } + else + m_tmpea |= (m_dtb<<16); + m_tmp32 = doDEC_32(read_32(m_tmpea)); + write_32(m_tmpea, m_tmp32); + m_pc += 4; + m_icount -= 10; + break; + // MOVL A, RLx case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: m_acc = read_rlX((operand>>1) & 3); @@ -2475,7 +2978,7 @@ void f2mc16_device::opcodes_ea71(u8 operand) m_acc = read_32(m_tmpea); setNZ_32(m_acc); m_pc += 3; - m_icount -= 4; + m_icount -= 7; break; // MOVL A, @RWx + disp16 @@ -2486,7 +2989,17 @@ void f2mc16_device::opcodes_ea71(u8 operand) m_acc = read_32(m_tmpea); setNZ_32(m_acc); m_pc += 4; - m_icount -= 4; + m_icount -= 7; + break; + + // MOVL A, @RWx + RW7 + case 0x9c: case 0x9d: + m_tmp16 = read_rwX(operand & 1) + read_rwX(7); + m_tmpea = getRWbank(operand & 1, m_tmp16); + m_acc = read_32(m_tmpea); + setNZ_32(m_acc); + m_pc += 2; + m_icount -= 9; break; // MOVL A, addr16 @@ -2523,7 +3036,28 @@ void f2mc16_device::opcodes_ea71(u8 operand) write_32(m_tmpea, m_acc); setNZ_32(m_acc); m_pc += 3; - m_icount -= 4; + m_icount -= 7; + break; + + // MOVL @RWx + disp16, A + case 0xb8: case 0xb9: case 0xba: case 0xbb: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + write_32(m_tmpea, m_acc); + setNZ_32(m_acc); + m_pc += 4; + m_icount -= 7; + break; + + // MOVL @RWx + RW7, A + case 0xbc: case 0xbd: + m_tmp16 = read_rwX(operand & 1) + read_rwX(7); + m_tmpea = getRWbank(operand & 1, m_tmp16); + write_32(m_tmpea, m_acc); + setNZ_32(m_acc); + m_pc += 2; + m_icount -= 9; break; // MOVL addr16, A @@ -2551,7 +3085,7 @@ void f2mc16_device::opcodes_ea71(u8 operand) write_8(m_tmpea, m_tmp8); setNZ_8(m_tmp8); m_pc += 3; - m_icount -= 2; + m_icount -= 6; break; // MOV @RWx+, #imm8 @@ -2563,7 +3097,7 @@ void f2mc16_device::opcodes_ea71(u8 operand) write_8(m_tmpea, m_tmp8); setNZ_8(m_tmp8); m_pc += 3; - m_icount -= 4; + m_icount -= 8; break; // MOV @RWx + disp8, #imm8 @@ -2575,28 +3109,77 @@ void f2mc16_device::opcodes_ea71(u8 operand) write_8(m_tmpea, m_tmp16 & 0xff); setNZ_8(m_tmp16 & 0xff); m_pc += 4; - m_icount -= 2; + m_icount -= 6; + break; + + // MOV @RWx + disp16, #imm8 + case 0xd8: case 0xd9: case 0xda: case 0xdb: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp8 = read_8((m_pcb<<16) | (m_pc+4)); + write_8(m_tmpea, m_tmp8); + setNZ_8(m_tmp8); + m_pc += 5; + m_icount -= 6; break; // MOV @RWx + RW7, #imm8 case 0xdc: case 0xdd: m_tmp16 = read_rwX(operand & 1) + read_rwX(7); - m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmpea = getRWbank(operand & 1, m_tmp16); + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); write_8(m_tmpea, m_tmp8); setNZ_8(m_tmp8); m_pc += 3; - m_icount -= 2; + m_icount -= 8; + break; + + // MOV addr16, #imm8 + case 0xdf: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp8 = read_8((m_pcb<<16) | (m_pc+4)); + if (m_prefix_valid) + { + m_prefix_valid = false; + write_8((m_prefix<<16) | m_tmp16, m_tmp8); + } + else + { + write_8((m_dtb<<16) | m_tmp16, m_tmp8); + } + setNZ_8(m_tmp8); + m_pc += 5; + m_icount -= 5; break; // MOVEA A, @RWx + disp8 case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: - m_acc <<= 16; m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); - m_tmp16 = read_rwX(operand & 7); - m_tmp16 += (s8)m_tmp8; + m_tmp16 = read_rwX(operand & 7) + (s8)m_tmp8; + m_acc <<= 16; m_acc |= m_tmp16; m_pc += 3; - m_icount -= 1; + m_icount -= 3; + break; + + // MOVEA A, @RWx + disp16 + case 0xf8: case 0xf9: case 0xfa: case 0xfb: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_acc <<= 16; + m_acc |= m_tmp16; + m_pc += 4; + m_icount -= 3; + break; + + // MOVEA A, @RWx + RW7 + case 0xfc: case 0xfd: + m_tmp16 = read_rwX(operand & 1) + read_rwX(7); + m_acc <<= 16; + m_acc |= m_tmp16; + m_pc += 2; + m_icount -= 5; break; default: @@ -2609,6 +3192,23 @@ void f2mc16_device::opcodes_ea72(u8 operand) { switch (operand) { + // ROLC Rx + case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: + m_shifted_carry = (m_ps & F_C) ? 1 : 0; + m_tmp8 = read_rX(operand & 7); + m_ps &= ~F_C; + if (m_tmp8 & 0x80) + { + m_ps |= F_C; + } + m_tmp8 <<= 1; + m_tmp8 |= m_shifted_carry; + write_rX(operand & 7, m_tmp8); + setNZ_8(m_tmp8); + m_pc += 2; + m_icount -= 3; + break; + // INC Rx case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: m_tmp8 = doINC_8(read_rX(operand & 7)); @@ -2624,7 +3224,7 @@ void f2mc16_device::opcodes_ea72(u8 operand) m_tmp8 = doINC_8(read_8(m_tmpea)); write_8(m_tmpea, m_tmp8); m_pc += 2; - m_icount -= 5; + m_icount -= 7; break; // INC @RWx + disp8 @@ -2635,7 +3235,28 @@ void f2mc16_device::opcodes_ea72(u8 operand) m_tmp8 = doINC_8(read_8(m_tmpea)); write_8(m_tmpea, m_tmp8); m_pc += 3; - m_icount -= 5; + m_icount -= 7; + break; + + // INC @RWx + disp16 + case 0x58: case 0x59: case 0x5a: case 0x5b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp8 = doINC_8(read_8(m_tmpea)); + write_8(m_tmpea, m_tmp8); + m_pc += 4; + m_icount -= 7; + break; + + // INC @RWx + RW7 + case 0x5c: case 0x5d: + m_tmp16 = read_rwX(operand & 1) + read_rwX(7); + m_tmpea = getRWbank(operand & 1, m_tmp16); + m_tmp8 = doINC_8(read_8(m_tmpea)); + write_8(m_tmpea, m_tmp8); + m_pc += 2; + m_icount -= 9; break; // INC addr16 @@ -2671,7 +3292,57 @@ void f2mc16_device::opcodes_ea72(u8 operand) m_tmp8 = doDEC_8(read_8(m_tmpea)); write_8(m_tmpea, m_tmp8); m_pc += 2; - m_icount -= 5; + m_icount -= 7; + break; + + // DEC @RWx + disp8 + case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 7) + (s8)m_tmp8; + m_tmpea = getRWbank(operand & 7, m_tmp16); + m_tmp8 = doDEC_8(read_8(m_tmpea)); + write_8(m_tmpea, m_tmp8); + m_pc += 3; + m_icount -= 7; + break; + + // DEC @RWx + disp16 + case 0x78: case 0x79: case 0x7a: case 0x7b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp8 = doDEC_8(read_8(m_tmpea)); + write_8(m_tmpea, m_tmp8); + m_pc += 4; + m_icount -= 7; + break; + + // DEC @RWx + RW7 + case 0x7c: case 0x7d: + m_tmp16 = read_rwX(operand & 1) + read_rwX(7); + m_tmpea = getRWbank(operand & 1, m_tmp16); + m_tmp8 = doDEC_8(read_8(m_tmpea)); + write_8(m_tmpea, m_tmp8); + m_pc += 2; + m_icount -= 9; + break; + + // DEC addr16 + case 0x7f: + m_tmpea = read_16((m_pcb<<16) | (m_pc+2)); + if (m_prefix_valid) + { + m_prefix_valid = false; + m_tmpea |= (m_prefix << 16); + } + else + { + m_tmpea |= (m_dtb << 16); + } + m_tmp8 = doDEC_8(read_8(m_tmpea)); + write_8(m_tmpea, m_tmp8); + m_pc += 4; + m_icount -= 6; break; // MOV A, @RWx @@ -2718,7 +3389,7 @@ void f2mc16_device::opcodes_ea72(u8 operand) m_icount -= 7; break; - // MOV A, @RWx + disp8 + // MOV A, @RWx + disp8 case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); m_tmp16 = read_rwX(operand & 7) + (s8)m_tmp8; @@ -2730,6 +3401,18 @@ void f2mc16_device::opcodes_ea72(u8 operand) m_icount -= 5; break; + // MOV A, @RWx + disp16 + case 0x98: case 0x99: case 0x9a: case 0x9b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_acc <<= 16; + m_acc |= read_8(m_tmpea); + setNZ_8(m_acc & 0xff); + m_pc += 4; + m_icount -= 5; + break; + // MOV A, @RWx + RW7 case 0x9c: case 0x9d: m_tmp16 = read_rwX(operand & 1) + read_rwX(7); @@ -2737,7 +3420,7 @@ void f2mc16_device::opcodes_ea72(u8 operand) m_acc <<= 16; m_acc |= read_8(m_tmpea); setNZ_8(m_acc & 0xff); - m_pc += 3; + m_pc += 2; m_icount -= 7; break; @@ -2752,13 +3435,71 @@ void f2mc16_device::opcodes_ea72(u8 operand) m_icount -= 5; break; + // MOV @RWx + disp16, A + case 0xb8: case 0xb9: case 0xba: case 0xbb: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + write_8(m_tmpea, m_acc & 0xff); + setNZ_8(m_acc & 0xff); + m_pc += 4; + m_icount -= 5; + break; + // MOV @RWx + RW7, A case 0xbc: case 0xbd: m_tmp16 = read_rwX(operand & 1) + read_rwX(7); m_tmpea = getRWbank(operand & 1, m_tmp16); write_8(m_tmpea, m_acc & 0xff); setNZ_8(m_acc & 0xff); + m_pc += 2; + m_icount -= 7; + break; + + // MOVX A, @RWx + disp8 + case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 7) + (s8)m_tmp8; + m_tmpea = getRWbank(operand & 7, m_tmp16); + m_acc <<= 16; + m_acc |= read_8(m_tmpea); + if (m_acc & 0x80) + { + m_acc |= 0xff00; + } + setNZ_8(m_acc & 0xff); m_pc += 3; + m_icount -= 5; + break; + + // MOVX A, @RWx + disp16 + case 0xd8: case 0xd9: case 0xda: case 0xdb: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_acc <<= 16; + m_acc |= read_8(m_tmpea); + if (m_acc & 0x80) + { + m_acc |= 0xff00; + } + setNZ_8(m_acc & 0xff); + m_pc += 4; + m_icount -= 5; + break; + + // MOVX A, @RWx + RW7 + case 0xdc: case 0xdd: + m_tmp16 = read_rwX(operand & 1) + read_rwX(7); + m_tmpea = getRWbank(operand & 1, m_tmp16); + m_acc <<= 16; + m_acc |= read_8(m_tmpea); + if (m_acc & 0x80) + { + m_acc |= 0xff00; + } + setNZ_8(m_acc & 0xff); + m_pc += 2; m_icount -= 7; break; @@ -2801,6 +3542,17 @@ void f2mc16_device::opcodes_ea73(u8 operand) m_icount -= 5; break; + // INCW @RWx + disp16 + case 0x58: case 0x59: case 0x5a: case 0x5b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp16 = doINC_16(read_16(m_tmpea)); + write_16(m_tmpea, m_tmp16); + m_pc += 4; + m_icount -= 5; + break; + // INCW addr16 case 0x5f: m_tmpea = read_16((m_pcb<<16) | (m_pc+2)); @@ -2848,6 +3600,17 @@ void f2mc16_device::opcodes_ea73(u8 operand) m_icount -= 5; break; + // DECW @RWx + disp16 + case 0x78: case 0x79: case 0x7a: case 0x7b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp16 = doDEC_16(read_16(m_tmpea)); + write_16(m_tmpea, m_tmp16); + m_pc += 4; + m_icount -= 5; + break; + // DECW addr16 case 0x7f: m_tmpea = read_16((m_pcb<<16) | (m_pc+2)); @@ -2889,6 +3652,30 @@ void f2mc16_device::opcodes_ea73(u8 operand) m_icount -= 7; break; + // MOVW A, @RWx + disp8 + case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 0x7) + (s8)m_tmp8; + m_tmpea = getRWbank(operand & 0x7, m_tmp16); + m_acc <<= 16; + m_acc |= read_16(m_tmpea); + setNZ_16(m_acc & 0xffff); + m_pc += 3; + m_icount -= 5; + break; + + // MOVW A, @RWx + disp16 + case 0x98: case 0x99: case 0x9a: case 0x9b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_acc <<= 16; + m_acc |= read_16(m_tmpea); + setNZ_16(m_acc & 0xffff); + m_pc += 4; + m_icount -= 5; + break; + // MOVW @RWx, A case 0xa8: case 0xa9: case 0xaa: case 0xab: m_tmp16 = read_rwX(operand & 3); @@ -2910,6 +3697,28 @@ void f2mc16_device::opcodes_ea73(u8 operand) m_icount -= 7; break; + // MOVW @RWx + disp8, A + case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 7) + (s8)m_tmp8; + m_tmpea = getRWbank(operand & 7, m_tmp16); + write_16(m_tmpea, m_acc & 0xffff); + setNZ_16(m_acc & 0xffff); + m_pc += 3; + m_icount -= 5; + break; + + // MOVW @RWx + disp16, A + case 0xb8: case 0xb9: case 0xba: case 0xbb: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + write_16(m_tmpea, m_acc & 0xffff); + setNZ_16(m_acc & 0xffff); + m_pc += 4; + m_icount -= 5; + break; + // MOVW @RWx + RW7, A case 0xbc: case 0xbd: m_tmp16 = read_rwX(operand & 1) + read_rwX(7); @@ -2927,7 +3736,7 @@ void f2mc16_device::opcodes_ea73(u8 operand) m_tmpea = getRWbank(operand & 3, m_tmpea); write_16(m_tmpea, m_tmp16); m_pc += 4; - m_icount -= 4; + m_icount -= 6; break; // MOVW @RWx+, #imm16 @@ -2938,29 +3747,29 @@ void f2mc16_device::opcodes_ea73(u8 operand) m_tmpea = getRWbank(operand & 3, m_tmpea); write_16(m_tmpea, m_tmp16); m_pc += 4; - m_icount -= 6; + m_icount -= 8; break; // MOVW @RWx + disp8, #imm16 case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: - m_tmp8 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); m_tmp16 = read_16((m_pcb<<16) | (m_pc+3)); m_tmpea = read_rwX(operand & 7) + (s8)m_tmp8; m_tmpea = getRWbank(operand & 7, m_tmpea); write_16(m_tmpea, m_tmp16); m_pc += 5; - m_icount -= 4; + m_icount -= 6; break; // MOVW @RWx + disp16, #imm16 case 0xd8: case 0xd9: case 0xda: case 0xdb: - m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); - m_tmp32 = read_16((m_pcb<<16) | (m_pc+4)); - m_tmpea = read_rwX(operand & 7) + (s16)m_tmp16; - m_tmpea = getRWbank(operand & 7, m_tmpea); - write_16(m_tmpea, m_tmp32 & 0xffff); + m_tmp16aux = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_16((m_pcb<<16) | (m_pc+4)); + m_tmpea = read_rwX(operand & 3) + (s16)m_tmp16aux; + m_tmpea = getRWbank(operand & 3, m_tmpea); + write_16(m_tmpea, m_tmp16); m_pc += 6; - m_icount -= 4; + m_icount -= 6; break; // MOVW addr16, #imm16 @@ -2977,9 +3786,44 @@ void f2mc16_device::opcodes_ea73(u8 operand) write_16((m_dtb<<16) | m_tmpea, m_tmp16); } m_pc += 6; + m_icount -= 5; + break; + + // XCHW A, RWx + case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: + m_tmp16 = read_rwX(operand & 7); + write_rwX(operand & 7, m_acc & 0xffff); + m_acc &= 0xffff0000; + m_acc |= m_tmp16; + m_pc += 2; m_icount -= 4; break; + // XCHW A, @RWx + case 0xe8: case 0xe9: case 0xea: case 0xeb: + m_tmp16 = read_rwX(operand & 3); + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp16 = read_16(m_tmpea); + write_rwX(operand & 3, m_acc & 0xffff); + m_acc &= 0xffff0000; + m_acc |= m_tmp16; + m_pc += 2; + m_icount -= 7; + break; + + // XCHW A, @RWx+ + case 0xec: case 0xed: case 0xee: case 0xef: + m_tmp16 = read_rwX(operand & 3); + write_rwX(operand & 3, (m_tmpea + 2) & 0xffff); + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp16 = read_16(m_tmpea); + write_rwX(operand & 3, m_acc & 0xffff); + m_acc &= 0xffff0000; + m_acc |= m_tmp16; + m_pc += 2; + m_icount -= 9; + break; + default: fatalerror("Unknown F2MC EA73 opcode %02x (PC=%x)\n", operand, (m_pcb<<16) | m_pc); break; @@ -2990,6 +3834,26 @@ void f2mc16_device::opcodes_ea74(u8 operand) { switch (operand) { + // SUB A, Rx + case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: + m_tmp8 = read_rX(operand & 7); + m_tmp8 = doSUB_8(m_acc & 0xff, m_tmp8); + m_acc &= 0xffff0000; + m_acc |= m_tmp8; + m_pc += 2; + m_icount -= 3; + break; + + // ADDC A, Rx + case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: + m_tmp8 = read_rX(operand & 7); + m_tmp8 = doADDC_8(m_acc & 0xff, m_tmp8); + m_acc &= 0xffff0000; + m_acc |= m_tmp8; + m_pc += 2; + m_icount -= 3; + break; + // CMP A, Rx case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: doCMP_8(m_acc & 0xff, read_rX(operand & 7)); @@ -2997,6 +3861,25 @@ void f2mc16_device::opcodes_ea74(u8 operand) m_icount -= 2; break; + // CMP A, @RWx + case 0x68: case 0x69: case 0x6a: case 0x6b: + m_tmp16 = read_rwX(operand & 3); + m_tmpea = getRWbank(operand & 3, m_tmp16); + doCMP_8(m_acc & 0xff, read_8(m_tmpea)); + m_pc += 2; + m_icount -= 5; + break; + + // CMP A, @RWx+ + case 0x6c: case 0x6d: case 0x6e: case 0x6f: + m_tmp16 = read_rwX(operand & 3); + write_rwX(operand & 3, m_tmp16 + 1); + m_tmpea = getRWbank(operand & 3, m_tmp16); + doCMP_8(m_acc & 0xff, read_8(m_tmpea)); + m_pc += 2; + m_icount -= 7; + break; + // CMP A, @RWx + disp8 case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); @@ -3005,7 +3888,45 @@ void f2mc16_device::opcodes_ea74(u8 operand) m_tmp8 = read_8(m_tmpea); doCMP_8(m_acc & 0xff, m_tmp8); m_pc += 3; - m_icount -= 10; + m_icount -= 5; + break; + + // CMP A, @RWx + disp16 + case 0x78: case 0x79: case 0x7a: case 0x7b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp8 = read_8(m_tmpea); + doCMP_8(m_acc & 0xff, m_tmp8); + m_pc += 4; + m_icount -= 5; + break; + + // CMP A, @RWx + RW7 + case 0x7c: case 0x7d: + m_tmp16 = read_rwX(operand & 1) + read_rwX(7); + m_tmpea = getRWbank(operand & 1, m_tmp16); + m_tmp8 = read_8(m_tmpea); + doCMP_8(m_acc & 0xff, m_tmp8); + m_pc += 2; + m_icount -= 7; + break; + + // CMP A, addr16 + case 0x7f: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + if (m_prefix_valid) + { + m_prefix_valid = false; + m_tmp8 = read_8((m_prefix<<16) | m_tmp16); + } + else + { + m_tmp8 = read_8((m_dtb<<16) | m_tmp16); + } + doCMP_8(m_acc & 0xff, m_tmp8); + m_pc += 4; + m_icount -= 4; break; // OR A, Rx @@ -3025,7 +3946,25 @@ void f2mc16_device::opcodes_ea74(u8 operand) setNZ_8(m_acc & 0xff); m_ps &= ~F_V; m_pc += 2; - m_icount -= 7; + m_icount -= 6; + break; + + // OR A, addr16 + case 0xbf: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + if (m_prefix_valid) + { + m_prefix_valid = false; + m_tmp8 = read_8((m_prefix<<16) | m_tmp16); + } + else + { + m_tmp8 = read_8((m_dtb<<16) | m_tmp16); + } + m_acc |= m_tmp8; + setNZ_8(m_acc & 0xff); + m_pc += 4; + m_icount -= 5; break; // DBNZ Rx, disp8 @@ -3065,14 +4004,63 @@ void f2mc16_device::opcodes_ea75(u8 operand) // ADD @RWx, A case 0x08: case 0x09: case 0x0a: case 0x0b: - m_tmp16 = read_rwX(operand & 7); - m_tmpea = getRWbank(operand & 7, m_tmp16); + m_tmp16 = read_rwX(operand & 3); + m_tmpea = getRWbank(operand & 3, m_tmp16); m_tmp8 = doADD_8(read_8(m_tmpea), m_acc & 0xff); write_8(m_tmpea, m_tmp8); m_pc += 2; m_icount -= 7; break; + // SUB Rx, A + case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: + m_tmp8 = doSUB_8(read_rX(operand & 7), m_acc & 0xff); + write_rX(operand & 7, m_tmp8); + m_pc += 2; + m_icount -= 3; + break; + + // SUBC Rx, A + case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: + m_tmp8 = doSUBC_8(read_rX(operand & 7), m_acc & 0xff); + write_rX(operand & 7, m_tmp8); + m_pc += 2; + m_icount -= 3; + break; + + // AND Rx, A + case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: + m_tmp8 = read_rX(operand & 7); + m_tmp8 &= m_acc & 0xff; + write_rX(operand & 7, m_tmp8); + setNZ_8(m_acc & 0xff); + m_ps &= ~F_V; + m_pc += 2; + m_icount -= 3; + break; + + // OR Rx, A + case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: + m_tmp8 = read_rX(operand & 7); + m_tmp8 |= m_acc & 0xff; + write_rX(operand & 7, m_tmp8); + setNZ_8(m_acc & 0xff); + m_ps &= ~F_V; + m_pc += 2; + m_icount -= 3; + break; + + // XOR Rx, A + case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: + m_tmp8 = read_rX(operand & 7); + m_tmp8 ^= m_acc & 0xff; + write_rX(operand & 7, m_tmp8); + setNZ_8(m_acc & 0xff); + m_ps &= ~F_V; + m_pc += 2; + m_icount -= 3; + break; + default: fatalerror("Unknown F2MC EA75 opcode %02x (PC=%x)\n", operand, (m_pcb<<16) | m_pc); break; @@ -3114,6 +4102,50 @@ void f2mc16_device::opcodes_ea76(u8 operand) m_acc &= 0xffff0000; m_acc |= m_tmp16aux; m_pc += 3; + m_icount -= 6; + break; + + // ADDW A, @RWx + disp16 + case 0x18: case 0x19: case 0x1a: case 0x1b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp16 = read_16(m_tmpea); + m_tmp16aux = doADD_16(m_acc & 0xffff, m_tmp16); + m_acc &= 0xffff0000; + m_acc |= m_tmp16aux; + m_pc += 4; + m_icount -= 6; + break; + + // ADDW A, @RWx + RW7 + case 0x1c: case 0x1d: + m_tmp16 = read_rwX(operand & 1) + read_rwX(7); + m_tmpea = getRWbank(operand & 1, m_tmp16); + m_tmp16 = read_16(m_tmpea); + m_tmp16aux = doADD_16(m_acc & 0xffff, m_tmp16); + m_acc &= 0xffff0000; + m_acc |= m_tmp16aux; + m_pc += 2; + m_icount -= 8; + break; + + // ADDW A, addr16 + case 0x1f: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + if (m_prefix_valid) + { + m_prefix_valid = false; + m_tmp16aux = read_16((m_prefix<<16) | m_tmp16); + } + else + { + m_tmp16aux = read_16((m_dtb<<16) | m_tmp16); + } + m_tmp16aux = doADD_16(m_acc & 0xffff, m_tmp16aux); + m_acc &= 0xffff0000; + m_acc |= m_tmp16aux; + m_pc += 4; m_icount -= 5; break; @@ -3135,7 +4167,7 @@ void f2mc16_device::opcodes_ea76(u8 operand) m_acc &= 0xffff0000; m_acc |= m_tmp16aux; m_pc += 2; - m_icount -= 5; + m_icount -= 6; break; // SUBW A, @RWx + disp8 @@ -3148,7 +4180,32 @@ void f2mc16_device::opcodes_ea76(u8 operand) m_acc &= 0xffff0000; m_acc |= m_tmp16aux; m_pc += 3; - m_icount -= 5; + m_icount -= 6; + break; + + // SUBW A, @RWx + disp16 + case 0x38: case 0x39: case 0x3a: case 0x3b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp16 = read_16(m_tmpea); + m_tmp16aux = doSUB_16(m_acc & 0xffff, m_tmp16); + m_acc &= 0xffff0000; + m_acc |= m_tmp16aux; + m_pc += 4; + m_icount -= 6; + break; + + // SUBW A, @RWx + RW7 + case 0x3c: case 0x3d: + m_tmp16 = read_rwX(operand & 1) + read_rwX(7); + m_tmpea = getRWbank(operand & 1, m_tmp16); + m_tmp16 = read_16(m_tmpea); + m_tmp16aux = doSUB_16(m_acc & 0xffff, m_tmp16); + m_acc &= 0xffff0000; + m_acc |= m_tmp16aux; + m_pc += 2; + m_icount -= 8; break; // SUBW A, addr16 @@ -3167,6 +4224,15 @@ void f2mc16_device::opcodes_ea76(u8 operand) m_acc &= 0xffff0000; m_acc |= m_tmp16aux; m_pc += 4; + m_icount -= 5; + break; + + // ADDCW A, RWx + case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: + m_tmp16 = doADDC_16(m_acc & 0xffff, read_rwX(operand & 7)); + m_acc &= 0xffff0000; + m_acc |= m_tmp16; + m_pc += 2; m_icount -= 3; break; @@ -3185,7 +4251,28 @@ void f2mc16_device::opcodes_ea76(u8 operand) m_tmp16 = read_16(m_tmpea); doCMP_16(m_acc & 0xffff, m_tmp16); m_pc += 3; - m_icount -= 10; + m_icount -= 5; + break; + + // CMPW A, @RWx + disp16 + case 0x78: case 0x79: case 0x7a: case 0x7b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp16 = read_16(m_tmpea); + doCMP_16(m_acc & 0xffff, m_tmp16); + m_pc += 4; + m_icount -= 5; + break; + + // CMPW A, @RWx + RW7 + case 0x7c: case 0x7d: + m_tmp16 = read_rwX(operand & 1) + read_rwX(7); + m_tmpea = getRWbank(operand & 1, m_tmp16); + m_tmp16 = read_16(m_tmpea); + doCMP_16(m_acc & 0xffff, m_tmp16); + m_pc += 2; + m_icount -= 7; break; // CMPW A, addr16 @@ -3202,7 +4289,18 @@ void f2mc16_device::opcodes_ea76(u8 operand) } doCMP_16(m_acc & 0xffff, m_tmp16aux); m_pc += 4; - m_icount -= 10; + m_icount -= 4; + break; + + // ANDW A, RWx + case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: + m_tmp32 = read_rwX(operand & 7); + m_tmp32 |= 0xffff0000; + m_acc &= m_tmp32; + setNZ_16(m_acc & 0xffff); + m_ps &= ~F_V; + m_pc += 2; + m_icount -= 3; break; // ORW A, RWx @@ -3212,13 +4310,13 @@ void f2mc16_device::opcodes_ea76(u8 operand) setNZ_16(m_acc & 0xffff); m_ps &= ~F_V; m_pc += 2; - m_icount -= 4; + m_icount -= 3; break; // ORW A, @RWx case 0xa8: case 0xa9: case 0xaa: case 0xab: - m_tmp16 = read_rwX(operand & 7); - m_tmpea = getRWbank(operand & 7, m_tmp16); + m_tmp16 = read_rwX(operand & 3); + m_tmpea = getRWbank(operand & 3, m_tmp16); m_tmp16 = read_16(m_tmpea); m_acc |= m_tmp16; setNZ_16(m_acc & 0xffff); @@ -3227,6 +4325,19 @@ void f2mc16_device::opcodes_ea76(u8 operand) m_icount -= 6; break; + // ORW A, @RWx+ + case 0xac: case 0xad: case 0xae: case 0xaf: + m_tmp16 = read_rwX(operand & 3); + write_rwX(operand & 3, m_tmp16 + 2); + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp16 = read_16(m_tmpea); + m_acc |= m_tmp16; + setNZ_16(m_acc & 0xffff); + m_ps &= ~F_V; + m_pc += 2; + m_icount -= 8; + break; + // ORW A, @RWx + disp8 case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); @@ -3240,6 +4351,121 @@ void f2mc16_device::opcodes_ea76(u8 operand) m_icount -= 6; break; + // ORW A, @RWx + disp16 + case 0xb8: case 0xb9: case 0xba: case 0xbb: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp16 = read_16(m_tmpea); + m_acc |= m_tmp16; + setNZ_16(m_acc & 0xffff); + m_ps &= ~F_V; + m_pc += 4; + m_icount -= 6; + break; + + // ORW A, @RWx + RW7 + case 0xbc: case 0xbd: + m_tmp16 = read_rwX(operand & 1) + read_rwX(7); + m_tmpea = getRWbank(operand & 1, m_tmp16); + m_tmp16 = read_16(m_tmpea); + m_acc |= m_tmp16; + setNZ_16(m_acc & 0xffff); + m_ps &= ~F_V; + m_pc += 2; + m_icount -= 8; + break; + + // XORW A, RWx + case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: + m_tmp16 = read_rwX(operand & 7); + m_acc ^= m_tmp16; + setNZ_16(m_acc & 0xffff); + m_ps &= ~F_V; + m_pc += 2; + m_icount -= 3; + break; + + // XORW A, @RWx + case 0xc8: case 0xc9: case 0xca: case 0xcb: + m_tmp16 = read_rwX(operand & 3); + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp16 = read_16(m_tmpea); + m_acc ^= m_tmp16; + setNZ_16(m_acc & 0xffff); + m_ps &= ~F_V; + m_pc += 2; + m_icount -= 6; + break; + + // XORW A, @RWx+ + case 0xcc: case 0xcd: case 0xce: case 0xcf: + m_tmp16 = read_rwX(operand & 3); + write_rwX(operand & 3, m_tmp16 + 2); + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp16 = read_16(m_tmpea); + m_acc ^= m_tmp16; + setNZ_16(m_acc & 0xffff); + m_ps &= ~F_V; + m_pc += 2; + m_icount -= 8; + break; + + // XORW A, @RWx + disp8 + case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 7) + (s8)m_tmp8; + m_tmpea = getRWbank(operand & 7, m_tmp16); + m_tmp16 = read_16(m_tmpea); + m_acc ^= m_tmp16; + setNZ_16(m_acc & 0xffff); + m_ps &= ~F_V; + m_pc += 3; + m_icount -= 6; + break; + + // XORW A, @RWx + disp16 + case 0xd8: case 0xd9: case 0xda: case 0xdb: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp16 = read_16(m_tmpea); + m_acc ^= m_tmp16; + setNZ_16(m_acc & 0xffff); + m_ps &= ~F_V; + m_pc += 4; + m_icount -= 6; + break; + + // XORW A, @RWx + RW7 + case 0xdc: case 0xdd: + m_tmp16 = read_rwX(operand & 1) + read_rwX(7); + m_tmpea = getRWbank(operand & 1, m_tmp16); + m_tmp16 = read_16(m_tmpea); + m_acc ^= m_tmp16; + setNZ_16(m_acc & 0xffff); + m_ps &= ~F_V; + m_pc += 2; + m_icount -= 8; + break; + + // DWBNZ RWx, disp8 + case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: + m_tmp16 = doDEC_16(read_rwX(operand & 7)); + write_rwX(operand & 7, m_tmp16); + if (m_tmp16 != 0) + { + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); + m_pc = (m_pc + 3) + (s8)m_tmp8; + m_icount -= 7; + } + else + { + m_pc += 3; + m_icount -= 6; + } + break; + default: fatalerror("Unknown F2MC EA76 opcode %02x (PC=%x)\n", operand, (m_pcb<<16) | m_pc); break; @@ -3250,6 +4476,64 @@ void f2mc16_device::opcodes_ea77(u8 operand) { switch (operand) { + // ADDW RWx, A + case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: + m_tmp16 = doADD_16(read_rwX(operand & 7), m_acc & 0xffff); + write_rwX(operand & 0x7, m_tmp16); + m_pc += 2; + m_icount -= 3; + break; + + // SUBW RWx, A + case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: + m_tmp16 = doSUB_16(read_rwX(operand & 7), m_acc & 0xffff); + write_rwX(operand & 0x7, m_tmp16); + m_pc += 2; + m_icount -= 3; + break; + + // SUBCW A, RWx + case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: + m_tmp16 = doSUBC_16(m_acc & 0xffff, read_rwX(operand & 7)); + m_acc &= 0xffff0000; + m_acc |= m_tmp16; + m_pc += 2; + m_icount -= 3; + break; + + // ANDW RWx, A + case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: + m_tmp16 = read_rwX(operand & 7); + m_tmp16 &= (m_acc & 0xffff); + write_rwX(operand & 0x7, m_tmp16); + setNZ_16(m_tmp16); + m_ps &= ~F_V; + m_pc += 2; + m_icount -= 3; + break; + + // ORW RWx, A + case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: + m_tmp16 = read_rwX(operand & 7); + m_tmp16 |= (m_acc & 0xffff); + write_rwX(operand & 0x7, m_tmp16); + setNZ_16(m_tmp16); + m_ps &= ~F_V; + m_pc += 2; + m_icount -= 3; + break; + + // XORW RWx, A + case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: + m_tmp16 = read_rwX(operand & 7); + m_tmp16 ^= (m_acc & 0xffff); + write_rwX(operand & 0x7, m_tmp16); + setNZ_16(m_tmp16); + m_ps &= ~F_V; + m_pc += 2; + m_icount -= 3; + break; + default: fatalerror("Unknown F2MC EA77 opcode %02x (PC=%x)\n", operand, (m_pcb<<16) | m_pc); break; @@ -3260,6 +4544,45 @@ void f2mc16_device::opcodes_ea78(u8 operand) { switch (operand) { + // MULU A, Rx + case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: + m_tmp16 = read_rX(operand & 7); + if (m_tmp16 == 0) + { + m_icount -= 4; + m_acc &= 0xffff0000; + } + else + { + m_icount -= 8; + m_tmp8aux = m_acc & 0xff; + m_acc &= 0xffff0000; + m_acc |= (m_tmp16 * m_tmp8aux) & 0xffff; + } + m_pc += 2; + break; + + // MULU A, @RWx + disp8 + case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: + m_tmp8 = read_8((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 7) + (s8)m_tmp8; + m_tmpea = getRWbank(operand & 7, m_tmp16); + m_tmp16 = read_8(m_tmpea); + if (m_tmp16 == 0) + { + m_icount -= 7; + m_acc &= 0xffff0000; + } + else + { + m_icount -= 11; + m_tmp8aux = m_acc & 0xff; + m_acc &= 0xffff0000; + m_acc |= (m_tmp16 * m_tmp8aux) & 0xffff; + } + m_pc += 3; + break; + // MULUW A, RWx case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: m_tmp16 = read_rwX(operand & 7); @@ -3284,17 +4607,54 @@ void f2mc16_device::opcodes_ea78(u8 operand) m_tmp16 = read_16(m_tmpea); if (m_tmp16 == 0) { - m_icount -= 4; + m_icount -= 7; m_acc = 0; } else { - m_icount -= 12; + m_icount -= 15; m_acc = m_tmp16 * (m_acc & 0xffff); } m_pc += 3; break; + // MULUW A, @RWx + disp16 + case 0x38: case 0x39: case 0x3a: case 0x3b: + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + m_tmp16 = read_rwX(operand & 3) + (s16)m_tmp16; + m_tmpea = getRWbank(operand & 3, m_tmp16); + m_tmp16 = read_16(m_tmpea); + if (m_tmp16 == 0) + { + m_icount -= 7; + m_acc = 0; + } + else + { + m_icount -= 15; + m_acc = m_tmp16 * (m_acc & 0xffff); + } + m_pc += 4; + break; + + // MULUW A, @RWx + RW7 + case 0x3c: case 0x3d: + m_tmp16 = read_rwX(operand & 1) + read_rwX(7); + m_tmpea = getRWbank(operand & 1, m_tmp16); + m_tmp16 = read_16(m_tmpea); + if (m_tmp16 == 0) + { + m_icount -= 9; + m_acc = 0; + } + else + { + m_icount -= 17; + m_acc = m_tmp16 * (m_acc & 0xffff); + } + m_pc += 2; + break; + // DIVUW A, RWx case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: m_ps &= ~(F_V|F_C); @@ -3309,7 +4669,6 @@ void f2mc16_device::opcodes_ea78(u8 operand) { m_ps |= F_V; m_icount -= 7; - m_ps |= F_V; } else // normal operation { @@ -3321,8 +4680,8 @@ void f2mc16_device::opcodes_ea78(u8 operand) } else // divide by zero { + m_ps |= (F_V|F_C); m_icount -= 4; - m_ps |= F_V; } m_pc += 2; break; @@ -3333,42 +4692,72 @@ void f2mc16_device::opcodes_ea78(u8 operand) } } -void f2mc16_device::opcodes_rwi7a(u8 operand) +void f2mc16_device::opcodes_riea7a(u8 operand) { - if (operand & 0x10) - { // MOV Rx, @RWy + disp8 + if ((operand & 0x1f) == 0x1f) + { + // MOV Rx, addr16 + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + if (m_prefix_valid) + { + m_prefix_valid = false; + m_tmp8 = read_8((m_prefix<<16) | m_tmp16); + } + else + { + m_tmp8 = read_8((m_dtb<<16) | m_tmp16); + } + write_rX((operand>>5) & 0x7, m_tmp8); + setNZ_8(m_tmp8); + m_pc += 4; + m_icount -= 5; + } + else if (operand & 0x08) + { + fatalerror("Unknown F2MC EA7A operand %02x, PC=%02x%04x\n", operand, m_pcb, m_pc); + } + else if (operand & 0x10) + { + // MOV Rx, @RWy + disp8 m_tmp16 = read_rwX(operand & 7) + (s8)read_8((m_pcb<<16) | (m_pc+2)); m_tmpea = getRWbank(operand & 0x7, m_tmp16); m_tmp8 = read_8(m_tmpea); write_rX((operand>>5) & 0x7, m_tmp8); setNZ_8(m_tmp8); m_pc += 3; - m_icount -= 5; + m_icount -= 6; } else - { // MOV Rx, Ry + { + // MOV Rx, Ry m_tmp8 = read_rX(operand & 0x7); write_rX((operand>>5) & 0x7, m_tmp8); setNZ_8(m_tmp8); m_pc += 2; - m_icount -= 4; + m_icount -= 3; } } -void f2mc16_device::opcodes_rwi7b(u8 operand) +void f2mc16_device::opcodes_rwiea7b(u8 operand) { - if (operand & 0x10) - { // MOVW RWx, @RWy + disp8 + if (operand & 0x08) + { + fatalerror("Unknown F2MC EA7B operand %02x, PC=%02x%04x\n", operand, m_pcb, m_pc); + } + else if (operand & 0x10) + { + // MOVW RWx, @RWy + disp8 m_tmp16 = read_rwX(operand & 7) + (s8)read_8((m_pcb<<16) | (m_pc+2)); m_tmpea = getRWbank(operand & 0x7, m_tmp16); m_tmp16 = read_16(m_tmpea); write_rwX((operand>>5) & 0x7, m_tmp16); setNZ_16(m_tmp16); m_pc += 3; - m_icount -= 5; + m_icount -= 7; } else - { // MOVW RWx, RWy + { + // MOVW RWx, RWy m_tmp16 = read_rwX(operand & 0x7); write_rwX((operand>>5) & 0x7, m_tmp16); setNZ_16(m_tmp16); @@ -3377,6 +4766,52 @@ void f2mc16_device::opcodes_rwi7b(u8 operand) } } +void f2mc16_device::opcodes_eari7c(u8 operand) +{ + if ((operand & 0x1f) == 0x1f) + { + // MOV addr16, Rx + m_tmp8 = read_rX((operand>>5) & 0x7); + m_tmp16 = read_16((m_pcb<<16) | (m_pc+2)); + if (m_prefix_valid) + { + m_prefix_valid = false; + write_8((m_prefix<<16) | m_tmp16, m_tmp8); + } + else + { + write_8((m_dtb<<16) | m_tmp16, m_tmp8); + } + setNZ_8(m_tmp8); + m_pc += 4; + m_icount -= 5; + } + else if (operand & 0x08) + { + fatalerror("Unknown F2MC EA7C operand %02x, PC=%02x%04x\n", operand, m_pcb, m_pc); + } + else if (operand & 0x10) + { + // MOV @RWx + disp8, Ry + m_tmp8 = read_rX((operand>>5) & 0x7); + m_tmp16 = read_rwX(operand & 0x7) + (s8)read_8((m_pcb<<16) | (m_pc+2)); + m_tmpea = getRWbank(operand & 0x7, m_tmp16); + write_8(m_tmpea, m_tmp8); + setNZ_8(m_tmp8); + m_pc += 3; + m_icount -= 6; + } + else + { + // MOV Rx, Ry + m_tmp8 = read_rX((operand>>5) & 0x7); + write_rX(operand & 0x7, m_tmp8); + setNZ_8(m_tmp8); + m_pc += 2; + m_icount -= 3; + } +} + void f2mc16_device::execute_set_input(int inputnum, int state) { } diff --git a/src/devices/cpu/f2mc16/f2mc16.h b/src/devices/cpu/f2mc16/f2mc16.h index fc1ffc3aa55..e8757734473 100644 --- a/src/devices/cpu/f2mc16/f2mc16.h +++ b/src/devices/cpu/f2mc16/f2mc16.h @@ -66,7 +66,7 @@ private: address_space *m_program; u16 m_pc, m_usp, m_ssp, m_ps, m_tmp16, m_tmp16aux; - u8 m_pcb, m_dtb, m_usb, m_ssb, m_adb, m_dpr, m_tmp8, m_prefix; + u8 m_pcb, m_dtb, m_usb, m_ssb, m_adb, m_dpr, m_tmp8, m_tmp8aux, m_shifted_carry, m_prefix; u32 m_acc, m_temp, m_tmp32, m_tmpea; s32 m_icount; bool m_prefix_valid; @@ -348,7 +348,7 @@ private: inline u8 doSUB_8(u8 lhs, u8 rhs) { - u16 tmp16 = lhs - rhs; + u16 tmp16 = u16(lhs) - u16(rhs); setNZ_8(tmp16 & 0xff); m_ps &= ~(F_C|F_V); if (tmp16 & 0x100) @@ -364,7 +364,7 @@ private: } inline u16 doSUB_16(u16 lhs, u16 rhs) { - u32 tmp32 = lhs - rhs; + u32 tmp32 = u32(lhs) - u32(rhs); setNZ_16(tmp32 & 0xffff); m_ps &= ~(F_C|F_V); if (tmp32 & 0x10000) @@ -380,7 +380,7 @@ private: } inline u32 doSUB_32(u32 lhs, u32 rhs) { - u64 tmp64 = lhs - rhs; + u64 tmp64 = u64(lhs) - u64(rhs); setNZ_32(tmp64 & 0xffffffff); m_ps &= ~(F_C|F_V); if (tmp64 & 0x100000000) @@ -394,6 +394,56 @@ private: return tmp64 & 0xffffffff; } + + inline u8 doSUBC_8(u8 lhs, u8 rhs) + { + u16 tmp16 = u16(lhs) - u16(rhs) - u16((m_ps & F_C) ? 1 : 0); + setNZ_8(tmp16 & 0xff); + m_ps &= ~(F_C|F_V); + if (tmp16 & 0x100) + { + m_ps |= F_C; + } + if ((lhs ^ rhs) & (lhs ^ (tmp16 & 0xff)) & 0x80) + { + m_ps |= F_V; + } + + return tmp16 & 0xff; + } + inline u16 doSUBC_16(u16 lhs, u16 rhs) + { + u32 tmp32 = u32(lhs) - u32(rhs) - u32((m_ps & F_C) ? 1 : 0); + setNZ_16(tmp32 & 0xffff); + m_ps &= ~(F_C|F_V); + if (tmp32 & 0x10000) + { + m_ps |= F_C; + } + if ((lhs ^ rhs) & (lhs ^ (tmp32 & 0xffff)) & 0x8000) + { + m_ps |= F_V; + } + + return tmp32 & 0xffff; + } + inline u32 doSUBC_32(u32 lhs, u32 rhs) + { + u64 tmp64 = u64(lhs) - u64(rhs) - u64((m_ps & F_C) ? 1 : 0); + setNZ_32(tmp64 & 0xffffffff); + m_ps &= ~(F_C|F_V); + if (tmp64 & 0x100000000) + { + m_ps |= F_C; + } + if ((lhs ^ rhs) & (lhs ^ (tmp64 & 0xffffffff)) & 0x80000000) + { + m_ps |= F_V; + } + + return tmp64 & 0xffffffff; + } + inline u8 doADD_8(u8 lhs, u8 rhs) { u16 tmp16 = lhs + rhs; @@ -443,6 +493,55 @@ private: return tmp64 & 0xffffffff; } + inline u8 doADDC_8(u8 lhs, u8 rhs) + { + u16 tmp16 = lhs + rhs + ((m_ps & F_C) ? 1 : 0); + m_ps &= ~(F_C|F_V); + if ((tmp16 ^ lhs) & (tmp16 ^ rhs) & 0x80) + { + m_ps |= F_V; + } + if (tmp16 > 0xff) + { + m_ps |= F_C; + } + setNZ_8(tmp16 & 0xff); + + return tmp16 & 0xff; + } + inline u16 doADDC_16(u16 lhs, u16 rhs) + { + u32 tmp32 = lhs + rhs + ((m_ps & F_C) ? 1 : 0); + m_ps &= ~(F_C|F_V); + if ((tmp32 ^ lhs) & (tmp32 ^ rhs) & 0x8000) + { + m_ps |= F_V; + } + if (tmp32 > 0xffff) + { + m_ps |= F_C; + } + setNZ_16(tmp32 & 0xffff); + + return tmp32 & 0xffff; + } + inline u32 doADDC_32(u32 lhs, u32 rhs) + { + u64 tmp64 = lhs + rhs + ((m_ps & F_C) ? 1 : 0); + m_ps &= ~(F_C|F_V); + if ((tmp64 ^ lhs) & (tmp64 ^ rhs) & 0x80000000) + { + m_ps |= F_V; + } + if (tmp64 > 0xffffffff) + { + m_ps |= F_C; + } + setNZ_32(tmp64 & 0xffffffff); + + return tmp64 & 0xffffffff; + } + inline u8 doINC_8(u8 val) { val++; @@ -518,6 +617,73 @@ private: m_icount -= 4; } + inline void movsi(u8 dst, u8 src) + { + if (read_rwX(0) > 0) + { + m_icount -= 4; + while (read_rwX(0) > 0) + { + u16 al = (m_acc & 0xffff); + u16 ah = (m_acc >> 16) & 0xffff; + m_tmp8 = read_8((src<<16) | al); + write_8((dst<<16) | ah, m_tmp8); + al++; + ah++; + m_acc = (ah<<16) | al; + write_rwX(0, read_rwX(0) - 1); + m_icount -= 8; + } + } + else + { + m_icount -= 5; + } + m_pc += 2; + } + + inline void movswi(u8 dst, u8 src) + { + if (read_rwX(0) > 0) + { + m_icount -= 4; + while (read_rwX(0) > 0) + { + u16 al = (m_acc & 0xffff); + u16 ah = (m_acc >> 16) & 0xffff; + m_tmp16 = read_16((src<<16) | al); + write_16((dst<<16) | ah, m_tmp16); + al += 2; + ah += 2; + m_acc = (ah<<16) | al; + write_rwX(0, read_rwX(0) - 1); + m_icount -= 8; + } + } + else + { + m_icount -= 5; + } + m_pc += 2; + } + + inline void filsi(u8 dst) + { + m_icount -= 6; + while (read_rwX(0) > 0) + { + u16 al = (m_acc & 0xffff); + u16 ah = (m_acc >> 16) & 0xffff; + write_8((dst<<16) | ah, al & 0xff); + ah++; + m_acc = (ah<<16) | al; + write_rwX(0, read_rwX(0) - 1); + setNZ_8(m_acc & 0xff); + m_icount -= 6; + } + m_pc += 2; + } + void opcodes_bo6c(u8 operand); void opcodes_str6e(u8 operand); void opcodes_2b6f(u8 operand); @@ -530,8 +696,9 @@ private: void opcodes_ea76(u8 operand); void opcodes_ea77(u8 operand); void opcodes_ea78(u8 operand); - void opcodes_rwi7a(u8 operand); - void opcodes_rwi7b(u8 operand); + void opcodes_riea7a(u8 operand); + void opcodes_rwiea7b(u8 operand); + void opcodes_eari7c(u8 operand); void set_irq(int vector, int level); void clear_irq(int vector);