From 98100466500e2a794679f14b7817779318b7376f Mon Sep 17 00:00:00 2001 From: David Haywood Date: Sat, 28 Jul 2018 06:13:49 +0100 Subject: tlcs870 - ALU flags, passes internal RAM check (nw) (#3797) * tlcs870 - ALU flags, passes internal RAM check (nw) * interrupt wait loop depends on JF always getting set --- src/devices/cpu/tlcs870/tlcs870.cpp | 5 +- src/devices/cpu/tlcs870/tlcs870.h | 20 +- src/devices/cpu/tlcs870/tlcs870_ops.cpp | 16 +- src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp | 384 +++++++++++++++++++++++-- src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp | 10 +- src/devices/cpu/tlcs870/tlcs870_ops_src.cpp | 6 +- src/mame/drivers/hng64.cpp | 66 +++-- 7 files changed, 451 insertions(+), 56 deletions(-) diff --git a/src/devices/cpu/tlcs870/tlcs870.cpp b/src/devices/cpu/tlcs870/tlcs870.cpp index db201179719..a855697cfb7 100644 --- a/src/devices/cpu/tlcs870/tlcs870.cpp +++ b/src/devices/cpu/tlcs870/tlcs870.cpp @@ -294,8 +294,6 @@ void tlcs870_device::execute_set_input(int inputnum, int state) void tlcs870_device::execute_run() { - - while (m_icount > 0) { m_prvpc.d = m_pc.d; @@ -311,7 +309,8 @@ void tlcs870_device::execute_run() if (m_cycles) { - m_icount -= m_cycles * 4; // 1 machine cycle = 4 clock cycles? + //m_icount -= m_cycles * 4; // 1 machine cycle = 4 clock cycles? (unclear, execution seems far too slow even for the ram test this way) + m_icount -= m_cycles; } else { diff --git a/src/devices/cpu/tlcs870/tlcs870.h b/src/devices/cpu/tlcs870/tlcs870.h index 7b8c8c256be..846cf818961 100644 --- a/src/devices/cpu/tlcs870/tlcs870.h +++ b/src/devices/cpu/tlcs870/tlcs870.h @@ -308,8 +308,6 @@ private: void do_CALL_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr); void do_JP_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr); - uint16_t do_alu(int op, uint16_t param1, uint16_t param2); - // tlcs870_ops_dst.cpp void do_dstprefixtype_opcode(const uint8_t opbyte0); @@ -362,10 +360,26 @@ private: void do_CALL_gg(const uint8_t opbyte0, const uint8_t opbyte1); void do_JP_gg(const uint8_t opbyte0, const uint8_t opbyte1); + + // ALU related + uint16_t do_or(uint16_t param1, uint16_t param2); + uint16_t do_xor(uint16_t param1, uint16_t param2); + uint16_t do_and(uint16_t param1, uint16_t param2); + + uint8_t do_add_8bit(uint16_t param1, uint16_t param2); + uint8_t do_sub_8bit(uint16_t param1, uint16_t param2); + void do_cmp_8bit(uint16_t param1, uint16_t param2); + uint8_t do_alu_8bit(int op, uint16_t param1, uint16_t param2); + + uint8_t do_add_16bit(uint32_t param1, uint32_t param2); + uint8_t do_sub_16bit(uint32_t param1, uint32_t param2); + void do_cmp_16bit(uint32_t param1, uint32_t param2); + uint16_t do_alu_16bit(int op, uint32_t param1, uint32_t param2); + + // Generic opcode helpers void handle_div(const int reg); void handle_mul(const int reg); void handle_swap(const int reg); - uint8_t handle_SHLC(uint8_t val); uint8_t handle_SHRC(uint8_t val); uint8_t handle_DAS(uint8_t val); diff --git a/src/devices/cpu/tlcs870/tlcs870_ops.cpp b/src/devices/cpu/tlcs870/tlcs870_ops.cpp index 034d967bca6..2a79879c8fa 100644 --- a/src/devices/cpu/tlcs870/tlcs870_ops.cpp +++ b/src/devices/cpu/tlcs870/tlcs870_ops.cpp @@ -944,8 +944,10 @@ void tlcs870_device::do_JRS_T_a(const uint8_t opbyte0) { m_cycles += 2; m_addr = m_tmppc + 2 + val; - set_JF(); } + + // always gets set? + set_JF(); } void tlcs870_device::do_JRS_F_a(const uint8_t opbyte0) @@ -967,8 +969,10 @@ void tlcs870_device::do_JRS_F_a(const uint8_t opbyte0) { m_cycles += 2; m_addr = m_tmppc + 2 + val; - set_JF(); } + + // manual isn't clear in description, but probably always set? + set_JF(); } void tlcs870_device::do_CALLV_n(const uint8_t opbyte0) @@ -1015,8 +1019,10 @@ void tlcs870_device::do_JR_cc_a(const uint8_t opbyte0) { m_cycles += 2; m_addr = m_tmppc + 2 + val; - set_JF(); } + + // manual isn't clear in description, but probably always set? + set_JF(); } void tlcs870_device::do_LD_CF_inxbit(const uint8_t opbyte0) @@ -1149,7 +1155,7 @@ void tlcs870_device::do_ALUOP_A_n(const uint8_t opbyte0) const int aluop = (opbyte0 & 0x7); const uint8_t val = READ8(); - const uint8_t result = do_alu(aluop, get_reg8(REG_A), val); + const uint8_t result = do_alu_8bit(aluop, get_reg8(REG_A), val); if (aluop != 0x07) // CMP doesn't write back { @@ -1176,7 +1182,7 @@ void tlcs870_device::do_ALUOP_A_inx(const uint8_t opbyte0) const uint16_t addr = READ8(); const uint8_t val = RM8(addr); - const uint8_t result = do_alu(aluop, get_reg8(REG_A), val); + const uint8_t result = do_alu_8bit(aluop, get_reg8(REG_A), val); if (aluop != 0x07) // CMP doesn't write back { diff --git a/src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp b/src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp index e2a11b57661..8f494ba7475 100644 --- a/src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp +++ b/src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp @@ -216,60 +216,404 @@ const bool tlcs870_device::check_jump_condition(int param1) return takejump; } +/* + All 16-bit ALU ops that would set the 'H' flag list the behavior as undefined. + Logically the half flag would be the 8/9 bit carry (usual C flag) in a 16-bit + op, but since this isn't listed as being the case there's a chance the behavior + is something unexpected, such as still using the 3/4 carry, or, if it's + internally handled as 4 4-bit operations, maybe the 12/13 bit carry + + This needs testing on hardware. + + (8-bit) JF ZF CF HF + ADDC C Z C H + ADD C Z C H + SUBB C Z C H + SUB C Z C H + AND Z Z - - + XOR Z Z - - + OR Z Z - - + CMP Z Z C H + + (16-bit) + ADDC C Z C U + ADD C Z C U + SUBB C Z C U + SUB C Z C U + AND Z Z - - + XOR Z Z - - + OR Z Z - - + CMP Z Z C U + +*/ + +uint8_t tlcs870_device::do_add_8bit(uint16_t param1, uint16_t param2) +{ + uint16_t result = param1 + param2; + + if (result & 0x100) + { + set_CF(); + } + else + { + clear_CF(); + } + + if ((result & 0xff) == 0x00) + { + set_ZF(); + } + else + { + clear_ZF(); + } + + uint8_t temp = (param1 & 0xf) + (param2 & 0xf); + + if (temp & 0x10) + { + set_HF(); + } + else + { + clear_HF(); + } + + // JF is copied from CF + is_ZF() ? set_CF() : clear_CF(); + + return result; +} + +uint8_t tlcs870_device::do_add_16bit(uint32_t param1, uint32_t param2) +{ + uint32_t result = param1 + param2; + + if (result & 0x10000) + { + set_CF(); + } + else + { + clear_CF(); + } + + if ((result & 0xffff) == 0x00) + { + set_ZF(); + } + else + { + clear_ZF(); + } + + // unknown, manual says undefined, see note above + uint8_t temp = (param1 & 0xff) + (param2 & 0xff); + + if (temp & 0x100) + { + set_HF(); + } + else + { + clear_HF(); + } + + // JF is copied from CF + is_ZF() ? set_CF() : clear_CF(); + + return result; +} + +uint8_t tlcs870_device::do_sub_8bit(uint16_t param1, uint16_t param2) +{ + uint16_t result = param1 - param2; + + if (param1 < param2) + { + set_CF(); + } + else + { + clear_CF(); + } + + if ((param1 & 0xf) < (param2 & 0xf)) + { + set_HF(); + } + else + { + clear_HF(); + } + + if ((result & 0xff) == 0x00) + { + set_ZF(); + } + else + { + clear_ZF(); + } + + // JF is copied from CF + is_ZF() ? set_CF() : clear_CF(); + + return result; +} + + +uint8_t tlcs870_device::do_sub_16bit(uint32_t param1, uint32_t param2) +{ + uint32_t result = param1 - param2; + + if (param1 < param2) + { + set_CF(); + } + else + { + clear_CF(); + } + + // unknown, manual says undefined, see note above + if ((param1 & 0xff) < (param2 & 0xff)) + { + set_HF(); + } + else + { + clear_HF(); + } + + if ((result & 0xffff) == 0x0000) + { + set_ZF(); + } + else + { + clear_ZF(); + } + + // JF is copied from CF + is_ZF() ? set_CF() : clear_CF(); + + return result; +} + +void tlcs870_device::do_cmp_8bit(uint16_t param1, uint16_t param2) +{ + if (param1 < param2) + { + set_CF(); + } + else + { + clear_CF(); + } + + if ((param1 & 0xf) < (param2 & 0xf)) // see note above about half flag + { + set_HF(); + } + else + { + clear_HF(); + } + + if (param1 == param2) + { + set_ZF(); + } + else + { + clear_ZF(); + } + + // JF is copied from ZF + is_ZF() ? set_JF() : clear_JF(); +} + +void tlcs870_device::do_cmp_16bit(uint32_t param1, uint32_t param2) +{ + if (param1 < param2) + { + set_CF(); + } + else + { + clear_CF(); + } + + // unknown, manual says undefined, see note above + if ((param1 & 0xff) < (param2 & 0xff)) + { + set_HF(); + } + else + { + clear_HF(); + } + + if (param1 == param2) + { + set_ZF(); + } + else + { + clear_ZF(); + } + + // JF is copied from ZF + is_ZF() ? set_JF() : clear_JF(); +} + + +uint16_t tlcs870_device::do_and(uint16_t param1, uint16_t param2) +{ + uint16_t result = param1 & param2; + + if (result == 0x00) + { + set_ZF(); + } + else + { + clear_ZF(); + } + + // JF is copied from ZF + is_ZF() ? set_JF() : clear_JF(); + + return result; +} + +uint16_t tlcs870_device::do_xor(uint16_t param1, uint16_t param2) +{ + uint16_t result = param1 ^ param2; -uint16_t tlcs870_device::do_alu(int op, uint16_t param1, uint16_t param2) + if (result == 0x00) + { + set_ZF(); + } + else + { + clear_ZF(); + } + + // JF is copied from ZF + is_ZF() ? set_JF() : clear_JF(); + + return result; +} + +uint16_t tlcs870_device::do_or(uint16_t param1, uint16_t param2) +{ + uint16_t result = param1 | param2; + + if (result == 0x00) + { + set_ZF(); + } + else + { + clear_ZF(); + } + + // JF is copied from ZF + is_ZF() ? set_JF() : clear_JF(); + + return result; +} + +uint8_t tlcs870_device::do_alu_8bit(int op, uint16_t param1, uint16_t param2) { uint16_t result = 0x00; - // TODO: flags switch (op) { case 0x0: // ADDC - result = param1 + param2; - result += is_CF(); + param2 += is_CF(); + result = do_add_8bit(param1, param2); break; case 0x1: // ADD - result = param1 + param2; + result = do_add_8bit(param1, param2); break; case 0x2: // SUBB - result = param1 - param2; - result -= is_CF(); + param2 += is_CF(); + result = do_sub_8bit(param1, param2); break; case 0x3: // SUB - result = param1 - param2; + result = do_sub_8bit(param1, param2); break; case 0x4: // AND - result = param1 & param2; + result = do_and(param1, param2); break; case 0x5: // XOR - result = param1 ^ param2; + result = do_xor(param1, param2); break; case 0x6: // OR - result = param1 | param2; + result = do_or(param1, param2); break; case 0x7: // CMP - if (param1 < param2) - { - set_CF(); - } - else - { - clear_CF(); - } + do_cmp_8bit(param1, param2); break; - } return result; } +uint16_t tlcs870_device::do_alu_16bit(int op, uint32_t param1, uint32_t param2) +{ + uint32_t result = 0x0000; + + switch (op) + { + case 0x0: // ADDC + param2 += is_CF(); + result = do_add_16bit(param1, param2); + break; + + case 0x1: // ADD + result = do_add_16bit(param1, param2); + break; + + case 0x2: // SUBB + param2 += is_CF(); + result = do_sub_16bit(param1, param2); + break; + + case 0x3: // SUB + result = do_sub_16bit(param1, param2); + break; + + case 0x4: // AND + result = do_and(param1, param2); + break; + + case 0x5: // XOR + result = do_xor(param1, param2); + break; + + case 0x6: // OR + result = do_or(param1, param2); + break; + + case 0x7: // CMP + do_cmp_16bit(param1, param2); + break; + } + + return result; +} uint8_t tlcs870_device::handle_SHLC(uint8_t val) { diff --git a/src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp b/src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp index 4bcc361c51d..484ce98fbb5 100644 --- a/src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp +++ b/src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp @@ -333,7 +333,7 @@ void tlcs870_device::do_ALUOP_A_g(const uint8_t opbyte0, const uint8_t opbyte1) const int aluop = (opbyte1 & 0x7); - const uint8_t result = do_alu(aluop, get_reg8(REG_A), get_reg8(opbyte0 & 0x7)); + const uint8_t result = do_alu_8bit(aluop, get_reg8(REG_A), get_reg8(opbyte0 & 0x7)); if (aluop != 0x07) // CMP doesn't write back { @@ -357,7 +357,7 @@ void tlcs870_device::do_ALUOP_g_A(const uint8_t opbyte0, const uint8_t opbyte1) m_cycles = 3; const int aluop = (opbyte1 & 0x7); - const uint8_t result = do_alu(aluop, get_reg8(opbyte0 & 0x7), get_reg8(REG_A)); + const uint8_t result = do_alu_8bit(aluop, get_reg8(opbyte0 & 0x7), get_reg8(REG_A)); if (aluop != 0x07) // CMP doesn't write back { @@ -384,7 +384,7 @@ void tlcs870_device::do_ALUOP_g_n(const uint8_t opbyte0, const uint8_t opbyte1) const uint8_t n = READ8(); - const uint8_t result = do_alu(aluop, get_reg8(opbyte0 & 0x7), n); + const uint8_t result = do_alu_8bit(aluop, get_reg8(opbyte0 & 0x7), n); if (aluop != 0x07) // CMP doesn't write back { @@ -413,7 +413,7 @@ void tlcs870_device::do_ALUOP_WA_gg(const uint8_t opbyte0, const uint8_t opbyte1 const int aluop = (opbyte1 & 0x7); - const uint16_t result = do_alu(aluop, get_reg16(REG_WA), get_reg16(opbyte0 & 0x3)); + const uint16_t result = do_alu_16bit(aluop, get_reg16(REG_WA), get_reg16(opbyte0 & 0x3)); if (aluop != 0x07) // CMP doesn't write back { @@ -441,7 +441,7 @@ void tlcs870_device::do_ALUOP_gg_mn(const uint8_t opbyte0, const uint8_t opbyte1 const uint16_t mn = READ16(); - const uint16_t result = do_alu(aluop, get_reg16(opbyte0 & 0x3), mn); + const uint16_t result = do_alu_16bit(aluop, get_reg16(opbyte0 & 0x3), mn); if (aluop != 0x07) // CMP doesn't write back { diff --git a/src/devices/cpu/tlcs870/tlcs870_ops_src.cpp b/src/devices/cpu/tlcs870/tlcs870_ops_src.cpp index 22c718a2078..0d1a5ae6205 100644 --- a/src/devices/cpu/tlcs870/tlcs870_ops_src.cpp +++ b/src/devices/cpu/tlcs870/tlcs870_ops_src.cpp @@ -524,7 +524,7 @@ void tlcs870_device::do_ALUOP_insrc_inHL(const uint8_t opbyte0, const uint8_t op const uint16_t HL = get_reg16(REG_HL); - const uint8_t result = do_alu(aluop, val, RM8(HL)); + const uint8_t result = do_alu_8bit(aluop, val, RM8(HL)); if (aluop != 0x07) // CMP doesn't write back { @@ -618,7 +618,7 @@ void tlcs870_device::do_ALUOP_insrc_n(const uint8_t opbyte0, const uint8_t opbyt const int aluop = (opbyte1 & 0x7); const uint8_t val = RM8(srcaddr); - const uint8_t result = do_alu(aluop, val, n); + const uint8_t result = do_alu_8bit(aluop, val, n); if (aluop != 0x07) // CMP doesn't write back { @@ -710,7 +710,7 @@ void tlcs870_device::do_ALUOP_A_insrc(const uint8_t opbyte0, const uint8_t opbyt const int aluop = (opbyte1 & 0x7); const uint8_t val = RM8(srcaddr); - const uint8_t result = do_alu(aluop, get_reg8(REG_A), val); + const uint8_t result = do_alu_8bit(aluop, get_reg8(REG_A), val); if (aluop != 0x07) // CMP doesn't write back { diff --git a/src/mame/drivers/hng64.cpp b/src/mame/drivers/hng64.cpp index 0ca4a5ea2e2..19f68c69c3d 100644 --- a/src/mame/drivers/hng64.cpp +++ b/src/mame/drivers/hng64.cpp @@ -1532,24 +1532,56 @@ void hng64_state::machine_reset() reset_sound(); } -READ8_MEMBER(hng64_state::ioport0_r) { logerror("ioport0_r\n"); return 0xff; } -READ8_MEMBER(hng64_state::ioport1_r) { logerror("ioport1_r\n"); return 0xff; } -READ8_MEMBER(hng64_state::ioport2_r) { logerror("ioport2_r\n"); return 0xff; } -READ8_MEMBER(hng64_state::ioport3_r) { logerror("ioport3_r\n"); return 0xff; } -READ8_MEMBER(hng64_state::ioport4_r) { logerror("ioport4_r\n"); return 0xff; } -READ8_MEMBER(hng64_state::ioport5_r) { logerror("ioport5_r\n"); return 0xff; } -READ8_MEMBER(hng64_state::ioport6_r) { logerror("ioport6_r\n"); return 0xff; } -READ8_MEMBER(hng64_state::ioport7_r) { logerror("ioport7_r\n"); return 0xff; } - -WRITE8_MEMBER(hng64_state::ioport0_w) { logerror("ioport0_w %02x\n", data); } -WRITE8_MEMBER(hng64_state::ioport1_w) { logerror("ioport1_w %02x\n", data); } -WRITE8_MEMBER(hng64_state::ioport2_w) { logerror("ioport2_w %02x\n", data); } -WRITE8_MEMBER(hng64_state::ioport3_w) { logerror("ioport3_w %02x\n", data); } -WRITE8_MEMBER(hng64_state::ioport4_w) { logerror("ioport4_w %02x\n", data); } -WRITE8_MEMBER(hng64_state::ioport5_w) { logerror("ioport5_w %02x\n", data); } -WRITE8_MEMBER(hng64_state::ioport6_w) { logerror("ioport6_w %02x\n", data); } -WRITE8_MEMBER(hng64_state::ioport7_w) { logerror("ioport7_w %02x\n", data); } +// used +READ8_MEMBER(hng64_state::ioport0_r) +{ + logerror("%s: ioport0_r\n", machine().describe_context()); + return 0x03; // expects 0x03 after writing it to port 0 earlier +} + +// used +READ8_MEMBER(hng64_state::ioport1_r) +{ + logerror("%s: ioport1_r\n", machine().describe_context()); + return 0xff; +} + +// used +WRITE8_MEMBER(hng64_state::ioport0_w) +{ + logerror("%s: ioport0_w %02x\n", machine().describe_context(), data); +} + +// used +WRITE8_MEMBER(hng64_state::ioport1_w) +{ + logerror("%s: ioport1_w %02x\n", machine().describe_context(), data); +} + +// used +WRITE8_MEMBER(hng64_state::ioport3_w) +{ + logerror("%s: ioport3_w %02x\n", machine().describe_context(), data); +} + +// used +WRITE8_MEMBER(hng64_state::ioport7_w) +{ + logerror("%s: ioport7_w %02x\n", machine().describe_context(), data); +} +// check if these are used +READ8_MEMBER(hng64_state::ioport2_r) { logerror("%s: ioport2_r\n", machine().describe_context()); return 0xff; } +READ8_MEMBER(hng64_state::ioport3_r) { logerror("%s: ioport3_r\n", machine().describe_context()); return 0xff; } +READ8_MEMBER(hng64_state::ioport4_r) { logerror("%s: ioport4_r\n", machine().describe_context()); return 0xff; } +READ8_MEMBER(hng64_state::ioport5_r) { logerror("%s: ioport5_r\n", machine().describe_context()); return 0xff; } +READ8_MEMBER(hng64_state::ioport6_r) { logerror("%s: ioport6_r\n", machine().describe_context()); return 0xff; } +READ8_MEMBER(hng64_state::ioport7_r) { logerror("%s: ioport7_r\n", machine().describe_context()); return 0xff; } + +WRITE8_MEMBER(hng64_state::ioport2_w) { logerror("%s: ioport2_w %02x\n", machine().describe_context(), data); } +WRITE8_MEMBER(hng64_state::ioport4_w) { logerror("%s: ioport4_w %02x\n", machine().describe_context(), data); } +WRITE8_MEMBER(hng64_state::ioport5_w) { logerror("%s: ioport5_w %02x\n", machine().describe_context(), data); } +WRITE8_MEMBER(hng64_state::ioport6_w) { logerror("%s: ioport6_w %02x\n", machine().describe_context(), data); } MACHINE_CONFIG_START(hng64_state::hng64) /* basic machine hardware */ -- cgit v1.2.3