summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author David Haywood <hazemamewip@hotmail.com>2018-07-23 01:24:10 +0100
committer Vas Crabb <cuavas@users.noreply.github.com>2018-07-23 10:24:10 +1000
commit88b1546f30a6384cdbc3dcd8e26389a9208e3aba (patch)
tree79ced1df7efab420e45c9e37dd99599cfbeeb38d
parentfedf58aa42846315d2acb4499743835676dc6135 (diff)
Flesh out TLCS870 core (#3763)
* rewrote most of the execution for my tlcs870 core * no longer the case (nw) * note updates (nw) * address concerns, const qualify more things where possible (nw) * more const (nw) * oops (nw) * consistency (nw)
-rw-r--r--scripts/src/cpu.lua5
-rw-r--r--src/devices/cpu/tlcs870/tlcs870.cpp3026
-rw-r--r--src/devices/cpu/tlcs870/tlcs870.h362
-rw-r--r--src/devices/cpu/tlcs870/tlcs870_ops.cpp951
-rw-r--r--src/devices/cpu/tlcs870/tlcs870_ops_dst.cpp127
-rw-r--r--src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp500
-rw-r--r--src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp760
-rw-r--r--src/devices/cpu/tlcs870/tlcs870_ops_src.cpp548
-rw-r--r--src/devices/cpu/tlcs870/tlcs870d.cpp27
-rw-r--r--src/mame/drivers/hng64.cpp20
10 files changed, 3294 insertions, 3032 deletions
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua
index 456a7412131..a94c4c709a9 100644
--- a/scripts/src/cpu.lua
+++ b/scripts/src/cpu.lua
@@ -2383,6 +2383,11 @@ end
if (CPUS["TLCS870"]~=null) then
files {
MAME_DIR .. "src/devices/cpu/tlcs870/tlcs870.cpp",
+ MAME_DIR .. "src/devices/cpu/tlcs870/tlcs870_ops.cpp",
+ MAME_DIR .. "src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp",
+ MAME_DIR .. "src/devices/cpu/tlcs870/tlcs870_ops_src.cpp",
+ MAME_DIR .. "src/devices/cpu/tlcs870/tlcs870_ops_dst.cpp",
+ MAME_DIR .. "src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp",
MAME_DIR .. "src/devices/cpu/tlcs870/tlcs870.h",
}
end
diff --git a/src/devices/cpu/tlcs870/tlcs870.cpp b/src/devices/cpu/tlcs870/tlcs870.cpp
index 1d775a29951..e893cf69e0b 100644
--- a/src/devices/cpu/tlcs870/tlcs870.cpp
+++ b/src/devices/cpu/tlcs870/tlcs870.cpp
@@ -8,8 +8,6 @@
The TLCS-870/C appears to have a completely different encoding.
- loosely baesd on the tlcs90 core by Luca Elia
-
*************************************************************************************************************/
@@ -19,59 +17,6 @@
#include "tlcs870d.h"
#include "debugger.h"
-#define IS16BIT 0x80
-#define BITPOS 0x40
-#define BITPOS_INDIRECT 0x20
-
-#define ABSOLUTE_VAL_8 0x01
-#define REG_8BIT 0x02
-
-// special
-#define CONDITIONAL 0x03
-#define STACKPOINTER (0x04 | IS16BIT) // this is a 16-bit reg
-#define CARRYFLAG (0x5 | BITPOS) // also flag as BITPOS since it's a bit operation?
-#define MEMVECTOR_16BIT 0x6
-#define REGISTERBANK 0x7
-#define PROGRAMSTATUSWORD 0x8
-
-#define ABSOLUTE_VAL_16 (ABSOLUTE_VAL_8|IS16BIT)
-#define REG_16BIT (REG_8BIT|IS16BIT)
-
-#define ADDR_IN_BASE 0x10
-#define ADDR_IN_IMM_X (ADDR_IN_BASE+0x0)
-#define ADDR_IN_PC_PLUS_REG_A (ADDR_IN_BASE+0x1)
-#define ADDR_IN_DE (ADDR_IN_BASE+0x2)
-#define ADDR_IN_HL (ADDR_IN_BASE+0x3)
-#define ADDR_IN_HL_PLUS_IMM_D (ADDR_IN_BASE+0x4)
-#define ADDR_IN_HL_PLUS_REG_C (ADDR_IN_BASE+0x5)
-#define ADDR_IN_HLINC (ADDR_IN_BASE+0x6)
-#define ADDR_IN_DECHL (ADDR_IN_BASE+0x7)
-
-#define MODE_MASK 0x1f
-
-
-#define FLAG_J (0x80)
-#define FLAG_Z (0x40)
-#define FLAG_C (0x20)
-#define FLAG_H (0x10)
-
-
-#define IS_JF ((m_F & FLAG_J) ? 1 : 0)
-#define IS_ZF ((m_F & FLAG_Z) ? 1 : 0)
-#define IS_CF ((m_F & FLAG_C) ? 1 : 0)
-#define IS_HF ((m_F & FLAG_H) ? 1 : 0)
-
-#define SET_JF (m_F |= FLAG_J)
-#define SET_ZF (m_F |= FLAG_Z)
-#define SET_CF (m_F |= FLAG_C)
-#define SET_HF (m_F |= FLAG_H)
-
-#define CLEAR_JF (m_F &= ~FLAG_J)
-#define CLEAR_ZF (m_F &= ~FLAG_Z)
-#define CLEAR_CF (m_F &= ~FLAG_C)
-#define CLEAR_HF (m_F &= ~FLAG_H)
-
-
DEFINE_DEVICE_TYPE(TMP87PH40AN, tmp87ph40an_device, "tmp87ph40an", "Toshiba TMP87PH40AN")
@@ -157,8 +102,8 @@ void tlcs870_device::tmp87ph40an_mem(address_map &map)
}
-tlcs870_device::tlcs870_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor program_map)
- : cpu_device(mconfig, type, tag, owner, clock)
+tlcs870_device::tlcs870_device(const machine_config &mconfig, device_type optype, const char *tag, device_t *owner, uint32_t clock, address_map_constructor program_map)
+ : cpu_device(mconfig, optype, tag, owner, clock)
, m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0, program_map)
, m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0)
, m_intram(*this, "intram")
@@ -173,2949 +118,176 @@ tmp87ph40an_device::tmp87ph40an_device(const machine_config &mconfig, const char
device_memory_interface::space_config_vector tlcs870_device::memory_space_config() const
{
- return space_config_vector {
+ return space_config_vector{
std::make_pair(AS_PROGRAM, &m_program_config),
std::make_pair(AS_IO, &m_io_config)
};
}
-uint8_t tlcs870_device::RM8 (uint32_t a) { return m_program->read_byte( a ); }
-uint16_t tlcs870_device::RM16(uint32_t a) { return RM8(a) | (RM8( (a+1) & 0xffff ) << 8); }
-
-void tlcs870_device::WM8 (uint32_t a, uint8_t v) { m_program->write_byte( a, v ); }
-void tlcs870_device::WM16(uint32_t a, uint16_t v) { WM8(a,v); WM8( (a+1) & 0xffff, v >> 8); }
-
-uint8_t tlcs870_device::RX8 (uint32_t a, uint32_t base) { return m_program->read_byte( base | a ); }
-uint16_t tlcs870_device::RX16(uint32_t a, uint32_t base) { return RX8(a,base) | (RX8( (a+1) & 0xffff, base ) << 8); }
-
-void tlcs870_device::WX8 (uint32_t a, uint8_t v, uint32_t base) { m_program->write_byte( base | a, v ); }
-void tlcs870_device::WX16(uint32_t a, uint16_t v, uint32_t base) { WX8(a,v,base); WX8( (a+1) & 0xffff, v >> 8, base); }
-
-uint8_t tlcs870_device::READ8() { uint8_t b0 = RM8( m_addr++ ); m_addr &= 0xffff; return b0; }
-uint16_t tlcs870_device::READ16() { uint8_t b0 = READ8(); return b0 | (READ8() << 8); }
-
-void tlcs870_device::decode()
+bool tlcs870_device::stream_arg(std::ostream &stream, uint32_t pc, const char *pre, const uint16_t mode, const uint16_t r, const uint16_t rb)
{
- m_op = 0;
- m_param1_type = 0;
- m_param1 = 0;
- m_param2_type = 0;
- m_param2 = 0;
- m_bitpos = 0;
- m_cycles = 1;
- m_flagsaffected = 0; // needed to signal which flags to change and which to leave alone in some cases (LD operations at least)
-
- uint8_t b0;
- uint8_t b1;
-
- int tmppc = m_addr;
-
- b0 = READ8();
-
-
- switch (b0)
- {
- case 0x00:
- m_op = NOP;
- // NOP;
- break;
-
- case 0x01:
- // SWAP A
- m_op = SWAP;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
- break;
-
- case 0x02:
- // MUL W,A
- m_op = MUL;
-
- m_param1_type = REG_8BIT;
- m_param1 = 1; // W
-
- m_param2_type = REG_8BIT;
- m_param2 = 0; // A
- break;
-
- case 0x03:
- // DIV WA,C
- m_op = DIV;
-
- m_param1_type = REG_16BIT;
- m_param1 = 0; // WA
-
- m_param2_type = REG_8BIT;
- m_param2 = 2; // C
- break;
-
- case 0x04:
- // RETI
- m_op = RETI;
- break;
-
- case 0x05:
- // RET
- m_op = RET;
- break;
-
- case 0x06:
- // POP PSW
- m_op = POP;
- m_param1_type = PROGRAMSTATUSWORD;
- break;
-
- case 0x07:
- // PUSH PSW:
- m_op = PUSH;
- m_param1_type = PROGRAMSTATUSWORD;
- break;
-
- case 0x08:
- case 0x09:
- // unused?
- break;
-
- case 0x0a:
- // DAA A
- m_op = DAA;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
- break;
-
- case 0x0b:
- // DAS A
- m_op = DAS;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
- break;
-
- case 0x0c:
- // CLR CF
- m_op = CLR;
-
- m_param1_type = CARRYFLAG; // 16-bit register
- //m_param1 = 0;
- break;
-
- case 0x0d:
- // SET CF
- m_op = SET;
-
- m_param1_type = CARRYFLAG; // 16-bit register
- //m_param1 = 0;
- break;
-
- case 0x0e:
- // CPL CF
- m_op = CPL;
-
- m_param1_type = CARRYFLAG; // 16-bit register
- //m_param1 = 0;
- break;
-
- case 0x0f:
- // LD RBS,n
- m_op = LD; // Flags / Cycles 1--- / 2
- m_flagsaffected |= FLAG_J;
-
- m_param1_type = REGISTERBANK; // 4-bit register
- //m_param1 = 0;
-
- m_param2_type = ABSOLUTE_VAL_8;
- m_param2 = READ8();
-
- break;
-
- case 0x10:
- case 0x11:
- case 0x12:
- case 0x13:
- // INC rr
- m_op = INC;
-
- m_param1_type = REG_16BIT; // 16-bit register
- m_param1 = b0&3;
-
- break;
-
- case 0x14:
- case 0x15:
- case 0x16:
- case 0x17:
- // LD rr,mn
- m_op = LD; // Flags / Cycles 1--- / 3
- m_flagsaffected |= FLAG_J;
-
- m_param1_type = REG_16BIT; // 16-bit register
- m_param1 = b0&3;
-
- m_param2_type = ABSOLUTE_VAL_16; // absolute value
- m_param2 = READ16(); // 16-bit
-
- break;
-
- case 0x18:
- case 0x19:
- case 0x1a:
- case 0x1b:
- // DEC rr
- m_op = DEC;
-
- m_param1_type = REG_16BIT; // 16-bit register
- m_param1 = b0&3;
-
- break;
-
- case 0x1c:
- // SHLC A
- m_op = SHLC;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
- break;
-
- case 0x1d:
- // SHRC A
- m_op = SHRC;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
- break;
-
- case 0x1e:
- // ROLC A
- m_op = ROLC;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
- break;
-
- case 0x1f:
- // RORC A
- m_op = RORC;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
- break;
-
- case 0x20:
- // INC (x)
- m_op = INC;
- m_param1_type = ADDR_IN_IMM_X;
- m_param1 = READ8();
- break;
-
- case 0x21:
- // INC (HL)
- m_op = INC;
- m_param1_type = ADDR_IN_HL;
- //m_param1 = 0;
- break;
-
- case 0x22:
- // LD A,(x)
- m_op = LD; // Flags / Cycles 1Z-- / 3
- m_flagsaffected |= FLAG_J | FLAG_Z;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
-
- m_param2_type = ADDR_IN_IMM_X;
- m_param2 = READ8();
- break;
-
- case 0x23:
- // LD A,(HL)
- m_op = LD; // Flags / Cycles 1Z-- / 2
- m_flagsaffected |= FLAG_J | FLAG_Z;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
-
- m_param2_type = ADDR_IN_HL;
- //m_param2 = 0;
- break;
-
- case 0x24:
- // LDW (x),mn
- m_op = LDW;
- m_param1_type = ADDR_IN_IMM_X; // 8-bit memory address
- m_param1 = READ8();
-
- m_param2_type = ABSOLUTE_VAL_16; // absolute value
- m_param2 = READ16();
- break;
-
- case 0x25:
- // LDW (HL),mn
- m_op = LDW;
- m_param1_type = ADDR_IN_HL;
- //m_param1 = 0;
-
- m_param2_type = ABSOLUTE_VAL_16;
- m_param2 = READ16();
- break;
-
-
- case 0x26:
- // LD (x),(y) // Flags / Cycles 1Z-- / 5
- m_op = LD;
- m_flagsaffected |= FLAG_J | FLAG_Z;
-
- m_param2_type = ADDR_IN_IMM_X;
- m_param2 = READ8();
-
- m_param1_type = ADDR_IN_IMM_X;
- m_param1 = READ8();
- break;
-
- case 0x27:
- // unused
- break;
-
- case 0x28:
- // DEC (x)
- m_op = DEC;
- m_param1_type = ADDR_IN_IMM_X;
- m_param1 = READ8();
- break;
-
- case 0x29:
- // DEC (HL)
- m_op = DEC;
- m_param1_type = ADDR_IN_HL;
- //m_param1 = 0;
- break;
-
- case 0x2a:
- // LD (x),A // Flags / Cycles 1Z-- / 3
- m_op = LD;
- m_flagsaffected |= FLAG_J | FLAG_Z;
-
- m_param1_type = ADDR_IN_IMM_X;
- m_param1 = READ8();
-
- m_param2_type = REG_8BIT;
- m_param2 = 0; // A
-
- break;
-
- case 0x2b:
- // LD (HL),A // Flags / Cycles 1--- / 2
- m_op = LD;
- m_flagsaffected |= FLAG_J;
-
- m_param1_type = ADDR_IN_HL;
- //m_param1 = 0;
-
- m_param2_type = REG_8BIT;
- m_param2 = 0; // A
- break;
-
- case 0x2c:
- // LD (x),n
- m_op = LD; // Flags / Cycles 1--- / 4
- m_flagsaffected |= FLAG_J;
-
- m_param1_type = ADDR_IN_IMM_X; // 8-bit memory address
- m_param1 = READ8();
-
- m_param2_type = ABSOLUTE_VAL_8; // absolute value
- m_param2 = READ8();
-
- break;
-
- case 0x2d:
- // LD (HL),n
- m_op = LD; // Flags / Cycles 1--- / 3
- m_flagsaffected |= FLAG_J;
-
- m_param1_type = ADDR_IN_HL; // memory address in 16-bit register
- //m_param1 = 3; // (HL)
-
- m_param2_type = ABSOLUTE_VAL_8; // absolute value
- m_param2 = READ8();
-
- break;
-
- case 0x2e:
- // CLR (x)
- m_op = CLR;
- m_param1_type = ADDR_IN_IMM_X; // 8-bit memory address
- m_param1 = READ8();
-
- break;
-
- case 0x2f:
- // CLR (HL)
- m_op = CLR;
- m_param1_type = ADDR_IN_HL; // memory address in 16-bit register
- //m_param1 = 3; // (HL)
-
- break;
-
- case 0x30:
- case 0x31:
- case 0x32:
- case 0x33:
- case 0x34:
- case 0x35:
- case 0x36:
- case 0x37:
- // LD r,n
-
- m_op = LD; // Flags / Cycles 1--- / 2
- m_flagsaffected |= FLAG_J;
-
- m_param1_type = REG_8BIT; // 8-bit register register
- m_param1 = b0&7;
-
- m_param2_type = ABSOLUTE_VAL_8; // absolute value
- m_param2 = READ8();
-
-
- break;
-
- case 0x38:
- case 0x39:
- case 0x3a:
- case 0x3b:
- case 0x3c:
- case 0x3d:
- case 0x3e:
- case 0x3f:
- break;
-
- case 0x40:
- case 0x41:
- case 0x42:
- case 0x43:
- case 0x44:
- case 0x45:
- case 0x46:
- case 0x47:
- // SET (x).b
- b1 = READ8();
-#if 0
- // this is just an alias
- if ((b0 == 0x40) && (b1 == 0x3a))
- {
- // EI 'Assembler expansion machine instruction'
- break;
- }
-#endif
- m_op = SET;
-
- m_param1_type = ADDR_IN_IMM_X | BITPOS;
- m_param1 = b1;
- m_bitpos = b0 & 7;
-
- break;
+ return false;
+}
- case 0x48:
- case 0x49:
- case 0x4a:
- case 0x4b:
- case 0x4c:
- case 0x4d:
- case 0x4e:
- case 0x4f:
- // CLR (x).b
- b1 = READ8();
+void tlcs870_device::execute_set_input(int inputnum, int state)
+{
#if 0
- // this is just an alias
- if ((b0 == 0x48) && (b1 == 0x3a))
- {
- // DI 'Assembler expansion machine instruction'
- break;
- }
-#endif
- m_op = CLR;
-
- m_param1_type = ADDR_IN_IMM_X | BITPOS;
- m_param1 = b1;
- m_bitpos = b0 & 7;
-
- break;
-
- case 0x50:
- case 0x51:
- case 0x52:
- case 0x53:
- case 0x54:
- case 0x55:
- case 0x56:
- case 0x57:
- // LD A,r 0101 0rrr
- m_op = LD; // Flags / Cycles 1Z-- / 1
- m_flagsaffected |= FLAG_J | FLAG_Z;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
-
- m_param2_type = REG_8BIT;
- m_param2 = b0 & 0x7;
-
- break;
-
- case 0x58:
- case 0x59:
- case 0x5a:
- case 0x5b:
- case 0x5c:
- case 0x5d:
- case 0x5e:
- case 0x5f:
- // LD r,A 0101 1rrr
- m_op = LD; // Flags / Cycles 1Z-- / 1
- m_flagsaffected |= FLAG_J | FLAG_Z;
-
- m_param2_type = REG_8BIT;
- m_param2 = 0; // A
-
- m_param1_type = REG_8BIT;
- m_param1 = b0 & 0x7;
+ switch (inputnum) {
+ case INPUT_LINE_NMI:
+ set_irq_line(INTNMI, state);
break;
-
- case 0x60:
- case 0x61:
- case 0x62:
- case 0x63:
- case 0x64:
- case 0x65:
- case 0x66:
- case 0x67:
- // INC r
- m_op = INC;
- m_param1_type = REG_8BIT;
- m_param1 = b0 & 0x7;
- break;
-
- case 0x68:
- case 0x69:
- case 0x6a:
- case 0x6b:
- case 0x6c:
- case 0x6d:
- case 0x6e:
- case 0x6f:
- // DEC r
- m_op = DEC;
- m_param1_type = REG_8BIT;
- m_param1 = b0 & 0x7;
- break;
-
- case 0x70:
- case 0x71:
- case 0x72:
- case 0x73:
- case 0x74:
- case 0x75:
- case 0x76:
- case 0x77:
- // (ALU OP) A,n
- m_op = (b0 & 0x7)+ALU_ADDC;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
-
- m_param2_type = ABSOLUTE_VAL_8;
- m_param2 = READ8();
-
- break;
-
- case 0x78:
- case 0x79:
- case 0x7a:
- case 0x7b:
- case 0x7c:
- case 0x7d:
- case 0x7e:
- case 0x7f:
- // (ALU OP) A,(x)
- m_op = (b0 & 0x7)+ALU_ADDC;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
-
- m_param2_type = ADDR_IN_IMM_X;
- m_param2 = READ8();
-
+ case INPUT_LINE_IRQ0:
+ set_irq_line(INT0, state);
break;
-
- case 0x80:
- case 0x81:
- case 0x82:
- case 0x83:
- case 0x84:
- case 0x85:
- case 0x86:
- case 0x87:
- case 0x88:
- case 0x89:
- case 0x8a:
- case 0x8b:
- case 0x8c:
- case 0x8d:
- case 0x8e:
- case 0x8f:
- case 0x90:
- case 0x91:
- case 0x92:
- case 0x93:
- case 0x94:
- case 0x95:
- case 0x96:
- case 0x97:
- case 0x98:
- case 0x99:
- case 0x9a:
- case 0x9b:
- case 0x9c:
- case 0x9d:
- case 0x9e:
- case 0x9f:
- {
- // JRS T,a
- m_op = JRS;
-
- m_param1_type = CONDITIONAL;
- m_param1 = 6;
-
- m_param2_type = ABSOLUTE_VAL_16;
-
- int val = b0 & 0x1f;
- if (val & 0x10) val -= 0x20;
-
- m_param2 = tmppc + 2 + val;
-
+ case INPUT_LINE_IRQ1:
+ set_irq_line(INT1, state);
break;
- }
- case 0xa0:
- case 0xa1:
- case 0xa2:
- case 0xa3:
- case 0xa4:
- case 0xa5:
- case 0xa6:
- case 0xa7:
- case 0xa8:
- case 0xa9:
- case 0xaa:
- case 0xab:
- case 0xac:
- case 0xad:
- case 0xae:
- case 0xaf:
- case 0xb0:
- case 0xb1:
- case 0xb2:
- case 0xb3:
- case 0xb4:
- case 0xb5:
- case 0xb6:
- case 0xb7:
- case 0xb8:
- case 0xb9:
- case 0xba:
- case 0xbb:
- case 0xbc:
- case 0xbd:
- case 0xbe:
- case 0xbf:
- {
- // JRS F,a
- m_op = JRS;
-
- m_param1_type = CONDITIONAL;
- m_param1 = 7;
-
- m_param2_type = ABSOLUTE_VAL_16;
-
- int val = b0 & 0x1f;
- if (val & 0x10) val -= 0x20;
-
- m_param2 = tmppc + 2 + val;
-
+ case INPUT_LINE_IRQ2:
+ set_irq_line(INT2, state);
break;
}
+#endif
+}
- case 0xc0:
- case 0xc1:
- case 0xc2:
- case 0xc3:
- case 0xc4:
- case 0xc5:
- case 0xc6:
- case 0xc7:
- case 0xc8:
- case 0xc9:
- case 0xca:
- case 0xcb:
- case 0xcc:
- case 0xcd:
- case 0xce:
- case 0xcf:
- // CALLV n
- m_op = CALLV;
-
- m_param1_type = MEMVECTOR_16BIT;
-
- m_param1 = 0xffc0 + ((b0 & 0xf) * 2);
-
- break;
-
- case 0xd0:
- case 0xd1:
- case 0xd2:
- case 0xd3:
- case 0xd4:
- case 0xd5:
- case 0xd6:
- case 0xd7:
- {
- // JR cc,a
-
- m_op = JR;
-
- m_param1_type = CONDITIONAL;
- m_param1 = b0 & 0x7;
-
- m_param2_type = ABSOLUTE_VAL_16;
-
- int val = READ8();
- if (val & 0x80) val -= 0x100;
-
- m_param2 = tmppc+ 2 + val;
-
- break;
- }
- case 0xd8:
- case 0xd9:
- case 0xda:
- case 0xdb:
- case 0xdc:
- case 0xdd:
- case 0xde:
- case 0xdf:
- // LD CF, (x).b aka TEST (x).b
- m_op = LD; // Flags / Cycles %-*- / 4
- m_flagsaffected |= FLAG_J | FLAG_C;
-
- m_param1_type = CARRYFLAG;
- //m_param1 = 0;
-
- m_param2_type = ADDR_IN_IMM_X | BITPOS;
- m_param2 = READ8();
- m_bitpos = b0 & 0x7;
- break;
-
- case 0xe0:
- // src prefix
- decode_source(ADDR_IN_BASE+(b0&0x7), READ8());
- break;
-
- case 0xe1:
- case 0xe2:
- case 0xe3:
- decode_source(ADDR_IN_BASE+(b0&0x7), 0);
- break;
-
- case 0xe4:
- decode_source(ADDR_IN_BASE+(b0&0x7), READ8());
- break;
-
- case 0xe5:
- case 0xe6:
- case 0xe7:
- decode_source(ADDR_IN_BASE+(b0&0x7), 0);
- break;
-
- case 0xe8:
- case 0xe9:
- case 0xea:
- case 0xeb:
- case 0xec:
- case 0xed:
- case 0xee:
- case 0xef:
- // register prefix: g/gg
- decode_register_prefix(b0);
- break;
-
- case 0xf0: // 1111 0000 xxxx xxxx 0101 0rrr
- // destination memory prefix (dst)
- m_param1_type = ADDR_IN_BASE+(b0&0x7);
- m_param1 = READ8();
- decode_dest(b0);
- break;
-
- case 0xf2: // 1111 001p 0101 0rrr
- case 0xf3: // 1111 001p 0101 0rrr
- // destination memory prefix (dst)
- m_param1_type = ADDR_IN_BASE+(b0&0x7);
- decode_dest(b0);
- break;
-
-
- case 0xf4: // 1111 0100 dddd dddd 0101 0rrr
- // destination memory prefix (dst)
- m_param1_type = ADDR_IN_BASE+(b0&0x7);
- m_param1 = READ8();
- decode_dest(b0);
- break;
-
- case 0xf6: // 1110 0110 0101 0rrr
- case 0xf7: // 1111 0111 0101 0rrr
- // destination memory prefix (dst)
- m_param1_type = ADDR_IN_BASE+(b0&0x7);
- decode_dest(b0);
- break;
-
- case 0xf1:
- case 0xf5:
- // invalid dst memory prefix
- break;
-
-
- case 0xf8:
- case 0xf9:
- // unused
- break;
-
- case 0xfa:
- // LD SP,mn
- m_op = LD; // Flags / Cycles 1--- / 3
- m_flagsaffected |= FLAG_J;
-
- m_param1_type = STACKPOINTER;
- //m_param1 = 0;
-
- m_param2_type = ABSOLUTE_VAL_16;
- m_param2 = READ16();
-
- break;
+void tlcs870_device::execute_run()
+{
+ m_cycles = 1;
- case 0xfb:
+ while (m_icount > 0)
{
- // JR a
- m_op = JR;
-
- m_param2_type = ABSOLUTE_VAL_16;
-
- int val = READ8();
- if (val & 0x80) val -= 0x100;
-
- m_param2 = tmppc + 2 + val;
-
- break;
- }
-
- break;
-
- case 0xfc:
- // CALL mn
- m_op = CALL;
-
- m_param1_type = ABSOLUTE_VAL_16;
- m_param1 = READ16();
- break;
-
- case 0xfd:
- // CALLP n
- m_op = CALLP;
-
- m_param1_type = ABSOLUTE_VAL_16;
- m_param1 = READ8()+0xff00;
-
- break;
-
- case 0xfe:
- // JP mn
- m_op = JP;
-
- m_param2_type = ABSOLUTE_VAL_16;
- m_param2 = READ16();
-
- break;
+ m_prvpc.d = m_pc.d;
+ debugger_instruction_hook(m_pc.d);
- case 0xff:
- // SWI
- m_op = SWI;
+ //check_interrupts();
+ m_addr = m_pc.d;
+ m_tmppc = m_addr; // used for jumps etc.
+ decode();
+ m_pc.d = m_addr;
- break;
- }
+ m_icount -= m_cycles * 4; // 1 machine cycle = 4 clock cycles?
+ };
}
-// e8 - ef use this table
-void tlcs870_device::decode_register_prefix(uint8_t b0)
+void tlcs870_device::device_reset()
{
- uint8_t bx;
-
- bx = READ8();
+ m_pc.d = RM16(0xfffe);
+ m_RBS = 0;
+}
- switch (bx)
+void tlcs870_device::state_import(const device_state_entry &entry)
+{
+ switch (entry.index())
{
- case 0x00:
- // nothing
- break;
-
- case 0x01:
- // SWAP g
- m_op = SWAP;
-
- m_param1_type = REG_8BIT;
- m_param1 = b0 & 0x7;
- break;
-
- case 0x02:
- // MUL ggG, ggL
- m_op = MUL;
-
- m_param1_type = REG_16BIT; // odd syntax
- m_param1 = b0 & 0x3;
- break;
-
- case 0x03:
- // DIV gg,C
- m_op = DIV;
- m_param1_type = REG_16BIT;
- m_param1 = b0 & 3;
-
- m_param2_type = REG_8BIT;
- m_param2 = 2; // C
-
- break;
-
- case 0x04:
- // with E8 only
- // RETN
- if (b0 == 0xe8)
- {
- m_op = RETN;
- }
-
- break;
-
- case 0x05:
- break;
-
- case 0x06:
- // POP gg
- m_op = POP;
- m_param1_type = REG_16BIT;
- m_param1 = b0 & 3;
- // b0 & 4 = invalid?
-
- break;
-
- case 0x07:
- // PUSH gg
- m_op = PUSH;
- m_param1_type = REG_16BIT;
- m_param1 = b0 & 3;
- // b0 & 4 = invalid?
-
- break;
-
- case 0x08:
- case 0x09:
- break;
-
- case 0x0a:
- // DAA g
- m_op = DAA;
-
- m_param1_type = REG_8BIT;
- m_param1 = b0 & 0x7;
-
- break;
-
- case 0x0b:
- // DAS g
- m_op = DAS;
-
- m_param1_type = REG_8BIT;
- m_param1 = b0 & 0x7;
-
- break;
-
- case 0x0c:
- case 0x0d:
- case 0x0e:
- case 0x0f:
- break;
-
- case 0x10:
- case 0x11:
- case 0x12:
- case 0x13:
- // XCH rr,gg
- m_op = XCH;
-
- m_param1_type = REG_16BIT;
- m_param1 = bx & 0x3;
-
- m_param2_type = REG_16BIT;
- m_param2 = b0 & 0x3;
- break;
-
- case 0x14:
- case 0x15:
- case 0x16:
- case 0x17:
- // LD rr,gg
- m_op = LD; // Flags / Cycles 1--- / 2
- m_flagsaffected |= FLAG_J;
-
- m_param1_type = REG_16BIT;
- m_param1 = bx & 0x3;
-
- m_param2_type = REG_16BIT;
- m_param2 = b0 & 0x3;
-
- break;
-
- case 0x18:
- case 0x19:
- case 0x1a:
- case 0x1b:
- break;
-
- case 0x1c:
- // SHLC g
- m_op = SHLC;
-
- m_param1_type = REG_8BIT;
- m_param1 = b0 & 0x7;
-
- break;
-
- case 0x1d:
- // SHRC g
- m_op = SHRC;
-
- m_param1_type = REG_8BIT;
- m_param1 = b0 & 0x7;
-
- break;
-
- case 0x1e:
- // ROLC g
- m_op = ROLC;
-
- m_param1_type = REG_8BIT;
- m_param1 = b0 & 0x7;
-
- break;
-
- case 0x1f:
- // RORC g
- m_op = RORC;
-
- m_param1_type = REG_8BIT;
- m_param1 = b0 & 0x7;
-
- break;
-
- case 0x20:
- case 0x21:
- case 0x22:
- case 0x23:
- case 0x24:
- case 0x25:
- case 0x26:
- case 0x27:
- case 0x28:
- case 0x29:
- case 0x2a:
- case 0x2b:
- case 0x2c:
- case 0x2d:
- case 0x2e:
- case 0x2f:
- break;
-
- case 0x30:
- case 0x31:
- case 0x32:
- case 0x33:
- case 0x34:
- case 0x35:
- case 0x36:
- case 0x37:
- // (ALU OP) WA,gg
- m_op = (bx & 0x7)+ALU_ADDC;
-
- m_param1_type = REG_16BIT;
- m_param1 = 0;
-
- m_param2_type = REG_16BIT;
- m_param2 = b0 & 3;
- // b0 & 4 would be invalid?
-
-
- break;
-
- case 0x38:
- case 0x39:
- case 0x3a:
- case 0x3b:
- case 0x3c:
- case 0x3d:
- case 0x3e:
- case 0x3f:
- // (ALU OP) gg,mn
- m_op = (bx & 0x7)+ALU_ADDC;
-
- m_param1_type = REG_16BIT;
- m_param1 = b0 & 0x3;
-
- m_param2_type = ABSOLUTE_VAL_16; // absolute value
- m_param2 = READ16(); // 16-bit
-
- break;
-
- case 0x40:
- case 0x41:
- case 0x42:
- case 0x43:
- case 0x44:
- case 0x45:
- case 0x46:
- case 0x47:
- // SET g.b
- m_op = SET;
-
- m_param1_type = REG_8BIT | BITPOS;
- m_param1 = b0 & 0x7;
- m_bitpos = bx & 0x7;
-
-
- break;
-
- case 0x48:
- case 0x49:
- case 0x4a:
- case 0x4b:
- case 0x4c:
- case 0x4d:
- case 0x4e:
- case 0x4f:
- // CLR g.b
- m_op = CLR;
-
- m_param1_type = REG_8BIT | BITPOS;
- m_param1 = b0 & 0x7;
- m_bitpos = bx & 0x7;
-
- break;
-
- case 0x50:
- case 0x51:
- case 0x52:
- case 0x53:
- case 0x54:
- case 0x55:
- case 0x56:
- case 0x57:
- break;
-
- case 0x58:
- case 0x59:
- case 0x5a:
- case 0x5b:
- case 0x5c:
- case 0x5d:
- case 0x5e:
- case 0x5f:
- // LD r,g
- m_op = LD; // Flags / Cycles 1Z-- / 2
- m_flagsaffected |= FLAG_J | FLAG_Z;
-
- m_param1_type = REG_8BIT;
- m_param1 = bx & 0x7;
-
- m_param2_type = REG_8BIT;
- m_param2 = b0 & 0x7;
- break;
-
- case 0x60:
- case 0x61:
- case 0x62:
- case 0x63:
- case 0x64:
- case 0x65:
- case 0x66:
- case 0x67:
- // (ALU OP) A,g
- m_op = (bx & 0x7)+ALU_ADDC;
-
- m_param2_type = REG_8BIT;
- m_param2 = b0 & 0x7;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
- break;
-
- case 0x68:
- case 0x69:
- case 0x6a:
- case 0x6b:
- case 0x6c:
- case 0x6d:
- case 0x6e:
- case 0x6f:
- // (ALU OP) g,A
- m_op = (bx & 0x7)+ALU_ADDC;
-
- m_param1_type = REG_8BIT;
- m_param1 = b0 & 0x7;
-
- m_param2_type = REG_8BIT;
- m_param2 = 0; // A
- break;
-
- case 0x70:
- case 0x71:
- case 0x72:
- case 0x73:
- case 0x74:
- case 0x75:
- case 0x76:
- case 0x77:
- // (ALU OP) g,n
- m_op = (bx & 0x7)+ALU_ADDC;
-
- m_param1_type = REG_8BIT;
- m_param1 = b0 & 0x7;
-
- m_param2_type = ABSOLUTE_VAL_8;
- m_param2 = READ8();
-
-
- break;
-
- case 0x78:
- case 0x79:
- case 0x7a:
- case 0x7b:
- case 0x7c:
- case 0x7d:
- case 0x7e:
- case 0x7f:
- break;
-
-
- case 0x80:
- case 0x81:
- break;
-
- case 0x82:
- case 0x83:
- // SET (pp).g
- m_op = SET;
- m_param1_type = (ADDR_IN_DE+(bx&1)) | BITPOS | BITPOS_INDIRECT;
- //m_param1 = 0;
- m_bitpos = b0 & 7;
- break;
-
- case 0x84:
- case 0x85:
- case 0x86:
- case 0x87:
- break;
-
- case 0x88:
- case 0x89:
- break;
-
- case 0x8a:
- case 0x8b:
- // CLR (pp).g
- m_op = CLR;
- m_param1_type = (ADDR_IN_DE+(bx&1)) | BITPOS | BITPOS_INDIRECT;
- //m_param1 = 0;
- m_bitpos = b0 & 7;
- break;
-
- case 0x8c:
- case 0x8d:
- case 0x8e:
- case 0x8f:
- break;
-
-
- case 0x90:
- case 0x91:
- break;
-
- case 0x92:
- case 0x93:
- // CPL (pp).g
- m_op = CPL;
- m_param1_type = (ADDR_IN_DE+(bx&1)) | BITPOS | BITPOS_INDIRECT;
- //m_param1 = 0;
- m_bitpos = b0 & 7;
- break;
-
- case 0x94:
- case 0x95:
- case 0x96:
- case 0x97:
- break;
-
- case 0x9a:
- case 0x9b:
- // LD (pp).g,CF
- m_op = LD; // Flags / Cycles 1--- / 5
- m_flagsaffected |= FLAG_J;
-
- m_param1_type = (ADDR_IN_DE+(bx&1)) | BITPOS | BITPOS_INDIRECT;
- //m_para1 = 0;
- m_bitpos = b0 & 7;
-
- m_param2_type = CARRYFLAG;
- //m_param2 = 0;
- break;
-
- case 0x9c:
- case 0x9d:
- break;
-
- case 0x9e:
- case 0x9f:
- // LD CF,(pp).g aka TEST (pp).g
- m_op = LD; // Flags / Cycles %-*- / 4
- m_flagsaffected |= FLAG_J | FLAG_C;
-
- m_param1_type = CARRYFLAG;
- //m_param1 = 0;
-
- m_param2_type = (ADDR_IN_DE+(bx&1)) | BITPOS | BITPOS_INDIRECT;
- //m_param2 = 0;
- m_bitpos = b0 & 7;
- break;
-
- case 0xa0:
- case 0xa1:
- case 0xa2:
- case 0xa3:
- case 0xa4:
- case 0xa5:
- case 0xa6:
- case 0xa7:
+ case DEBUGGER_REG_A:
+ set_reg8(REG_A, m_debugger_temp);
break;
- case 0xb0:
- case 0xb1:
- case 0xb2:
- case 0xb3:
- case 0xb4:
- case 0xb5:
- case 0xb6:
- case 0xb7:
- case 0xb8:
- case 0xb9:
- case 0xba:
- case 0xbb:
- case 0xbc:
- case 0xbd:
- case 0xbe:
- case 0xbf:
+ case DEBUGGER_REG_W:
+ set_reg8(REG_W, m_debugger_temp);
break;
- case 0xc0:
- case 0xc1:
- case 0xc2:
- case 0xc3:
- case 0xc4:
- case 0xc5:
- case 0xc6:
- case 0xc7:
- // CPL g.b
- m_op = CPL;
-
- m_param1_type = REG_8BIT | BITPOS;
- m_param1 = b0 & 0x7;
- m_bitpos = bx & 0x7;
+ case DEBUGGER_REG_C:
+ set_reg8(REG_C, m_debugger_temp);
break;
- case 0xc8:
- case 0xc9:
- case 0xca:
- case 0xcb:
- case 0xcc:
- case 0xcd:
- case 0xce:
- case 0xcf:
- // LD g.b,CF
- m_op = LD; // Flags / Cycles 1--- / 2
- m_flagsaffected |= FLAG_J;
-
- m_param2_type = CARRYFLAG;
- //m_param2 = 0;
-
- m_param1_type = REG_8BIT | BITPOS;
- m_param1 = b0 & 0x7;
- m_bitpos = bx & 0x7;
-
+ case DEBUGGER_REG_B:
+ set_reg8(REG_B, m_debugger_temp);
break;
- case 0xd0:
- case 0xd1:
- case 0xd2:
- case 0xd3:
- case 0xd4:
- case 0xd5:
- case 0xd6:
- case 0xd7:
- // XOR CF,g.b
- m_op = ALU_XOR;
-
- m_param1_type = CARRYFLAG;
- //m_param1 = 0;
-
- m_param2_type = REG_8BIT | BITPOS;
- m_param2 = b0 & 0x7;
- m_bitpos = bx & 0x7;
-
+ case DEBUGGER_REG_E:
+ set_reg8(REG_E, m_debugger_temp);
break;
- case 0xd8:
- case 0xd9:
- case 0xda:
- case 0xdb:
- case 0xdc:
- case 0xdd:
- case 0xde:
- case 0xdf:
- // LD CF,g.b aka TEST g.b
- m_op = LD; // Flags / Cycles %-*- / 2
- m_flagsaffected |= FLAG_J | FLAG_C;
-
- m_param1_type = CARRYFLAG;
- //m_param1 = 0;
-
- m_param2_type = REG_8BIT | BITPOS;
- m_param2 = b0 & 0x7;
- m_bitpos = bx & 0x7;
-
+ case DEBUGGER_REG_D:
+ set_reg8(REG_D, m_debugger_temp);
break;
- 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:
+ case DEBUGGER_REG_L:
+ set_reg8(REG_L, m_debugger_temp);
break;
- case 0xf0:
- case 0xf1:
- case 0xf2:
- case 0xf3:
- case 0xf4:
- case 0xf5:
- case 0xf6:
- case 0xf7:
+ case DEBUGGER_REG_H:
+ set_reg8(REG_H, m_debugger_temp);
break;
- case 0xf8:
- case 0xf9:
+ case DEBUGGER_REG_WA:
+ set_reg16(REG_WA, m_debugger_temp);
break;
- case 0xfa:
- // LD SP,gg
- m_op = LD; // Flags / Cycles 1--- / 3
- m_flagsaffected |= FLAG_J;
-
- m_param2_type = REG_16BIT;
- m_param2 = b0 & 3;
- // b0 & 4 would be invalid?
-
- m_param1_type = STACKPOINTER;
- // m_param1 = 0;
-
+ case DEBUGGER_REG_BC:
+ set_reg16(REG_BC, m_debugger_temp);
break;
- case 0xfb:
- // LD gg,SP
- m_op = LD; // Flags / Cycles 1--- / 3
- m_flagsaffected |= FLAG_J;
-
- m_param1_type = REG_16BIT;
- m_param1 = b0 & 3;
- // b0 & 4 would be invalid?
-
- m_param2_type = STACKPOINTER;
- // m_param2 = 0;
+ case DEBUGGER_REG_DE:
+ set_reg16(REG_DE, m_debugger_temp);
break;
- case 0xfc:
- // CALL gg
- m_op = CALL;
-
- m_param2_type = REG_16BIT;
- m_param2 = b0 & 3;
- // b0 & 4 would be invalid?
-
- break;
-
- case 0xfd:
- break;
-
- case 0xfe:
- // JP gg
- m_op = JP;
-
- m_param2_type = REG_16BIT;
- m_param2 = b0 & 3;
- // b0 & 4 would be invalid?
-
+ case DEBUGGER_REG_HL:
+ set_reg16(REG_HL, m_debugger_temp);
break;
-
- case 0xff:
- break;
-
}
-
}
-
-// e0 - e7 use this table
-void tlcs870_device::decode_source(int type, uint16_t val)
+void tlcs870_device::state_export(const device_state_entry &entry)
{
- uint8_t bx;
-
- bx = READ8();
-
- switch (bx)
+ switch (entry.index())
{
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x07:
+ case DEBUGGER_REG_A:
+ m_debugger_temp = get_reg8(REG_A);
break;
- case 0x08:
- // ROLD A,(src)
- m_op = ROLD;
- m_param2_type = type;
- m_param2 = val;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
+ case DEBUGGER_REG_W:
+ m_debugger_temp = get_reg8(REG_W);
break;
- case 0x09:
- // RORD A,(src)
- m_op = RORD;
- m_param2_type = type;
- m_param2 = val;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
+ case DEBUGGER_REG_C:
+ m_debugger_temp = get_reg8(REG_C);
break;
- case 0x0a:
- case 0x0b:
- case 0x0c:
- case 0x0d:
- case 0x0e:
- case 0x0f:
-
- case 0x10:
- case 0x11:
- case 0x12:
- case 0x13:
- // see dst
+ case DEBUGGER_REG_B:
+ m_debugger_temp = get_reg8(REG_B);
break;
- case 0x14:
- case 0x15:
- case 0x16:
- case 0x17:
- // LD rr, (src)
- m_op = LD; // Flags / Cycles 1--- / x
- m_flagsaffected |= FLAG_J;
-
- m_param1_type = REG_16BIT;
- m_param1 = bx & 0x3;
-
- m_param2_type = type | IS16BIT;
- m_param2 = val;
+ case DEBUGGER_REG_E:
+ m_debugger_temp = get_reg8(REG_E);
break;
- case 0x18:
- case 0x19:
- case 0x1a:
- case 0x1b:
- case 0x1c:
- case 0x1d:
- case 0x1e:
- case 0x1f:
+ case DEBUGGER_REG_D:
+ m_debugger_temp = get_reg8(REG_D);
break;
- case 0x20:
- // INC (src)
- m_op = INC;
- m_param1_type = type;
- m_param1 = val;
-
+ case DEBUGGER_REG_L:
+ m_debugger_temp = get_reg8(REG_L);
break;
- case 0x21:
- case 0x22:
- case 0x23:
- case 0x24:
- case 0x25:
+ case DEBUGGER_REG_H:
+ m_debugger_temp = get_reg8(REG_H);
break;
- case 0x26: // invalid if (src) is also (x) ? (not specified)
- // LD (x),(src)
- m_op = LD; // Flags / Cycles 1U-- / x
- m_flagsaffected |= FLAG_J /*| FLAG_Z*/; // Z is undefined!
-
- m_param1_type = ADDR_IN_IMM_X;
- m_param1 = READ8();
-
- m_param2_type = type;
- m_param2 = val;
- break;
-
- case 0x27:
- // LD (HL),(src)
- m_op = LD; // Flags / Cycles 1Z-- / x
- m_flagsaffected |= FLAG_J | FLAG_Z;
-
- m_param1_type = ADDR_IN_HL;
- //m_param1 = 0;
-
- m_param2_type = type;
- m_param2 = val;
+ case DEBUGGER_REG_WA:
+ m_debugger_temp = get_reg16(REG_WA);
break;
-
- case 0x28:
- // DEC (src)
- m_op = DEC;
- m_param1_type = type;
- m_param1 = val;
-
+ case DEBUGGER_REG_BC:
+ m_debugger_temp = get_reg16(REG_BC);
break;
- case 0x29:
- case 0x2a:
- case 0x2b:
- case 0x2c:
- case 0x2d:
- case 0x2e:
+ case DEBUGGER_REG_DE:
+ m_debugger_temp = get_reg16(REG_DE);
break;
- case 0x2f:
- // MCMP (src), n
- m_op = MCMP;
- m_param1_type = type;
- m_param1 = val;
-
- m_param2_type = ABSOLUTE_VAL_8;
- m_param2 = READ8();
+ case DEBUGGER_REG_HL:
+ m_debugger_temp = get_reg16(REG_HL);
break;
- case 0x30:
- case 0x31:
- case 0x32:
- case 0x33:
- case 0x34:
- case 0x35:
- case 0x36:
- case 0x37:
- case 0x38:
- case 0x39:
- case 0x3a:
- case 0x3b:
- case 0x3c:
- case 0x3d:
- case 0x3e:
- case 0x3f:
- break;
-
- case 0x40:
- case 0x41:
- case 0x42:
- case 0x43:
- case 0x44:
- case 0x45:
- case 0x46:
- case 0x47:
- // SET (src).b
- m_op = SET;
-
- m_param1_type = type | BITPOS;
- m_param1 = val;
- m_bitpos = bx & 0x7;
- break;
-
- case 0x48:
- case 0x49:
- case 0x4a:
- case 0x4b:
- case 0x4c:
- case 0x4d:
- case 0x4e:
- case 0x4f:
- // CLR (src).b
- m_op = CLR;
-
- m_param1_type = type | BITPOS;
- m_param1 = val;
- m_bitpos = bx & 0x7;
- break;
-
- case 0x50:
- case 0x51:
- case 0x52:
- case 0x53:
- case 0x54:
- case 0x55:
- case 0x56:
- case 0x57:
- // see dst
- break;
-
- case 0x58:
- case 0x59:
- case 0x5a:
- case 0x5b:
- case 0x5c:
- case 0x5d:
- case 0x5e:
- case 0x5f:
- // LD r, (src)
- m_op = LD; // Flags / Cycles 1Z-- / x
- m_flagsaffected |= FLAG_J | FLAG_Z;
-
- m_param1_type = REG_8BIT;
- m_param1 = bx & 0x7;
-
- m_param2_type = type;
- m_param2 = val;
- break;
-
- case 0x60:
- case 0x61:
- case 0x62:
- case 0x63:
- case 0x64:
- case 0x65:
- case 0x66:
- case 0x67:
- // (ALU OP) (src), (HL)
- m_op = (bx & 0x7)+ALU_ADDC;
- m_param1_type = type;
- m_param1 = val;
-
- m_param2_type = ADDR_IN_HL;
- //m_param2 = 0;
- break;
-
- case 0x68:
- case 0x69:
- case 0x6a:
- case 0x6b:
- case 0x6c:
- case 0x6d:
- case 0x6e:
- case 0x6f:
- break;
-
- case 0x70:
- case 0x71:
- case 0x72:
- case 0x73:
- case 0x74:
- case 0x75:
- case 0x76:
- case 0x77:
- // (ALU OP) (src), n
- m_op = (bx & 0x7)+ALU_ADDC;
- m_param1_type = type;
- m_param1 = val;
-
- m_param2_type = ABSOLUTE_VAL_8;
- m_param2 = READ8();
- break;
-
- case 0x78:
- case 0x79:
- case 0x7a:
- case 0x7b:
- case 0x7c:
- case 0x7d:
- case 0x7e:
- case 0x7f:
- // (ALU OP) A, (src)
-
- m_op = (bx & 0x7)+ALU_ADDC;
- m_param2_type = type;
- m_param2 = val;
-
- m_param1_type = REG_8BIT;
- m_param1 = 0; // A
- break;
-
- case 0x80:
- case 0x81:
- case 0x82:
- case 0x83:
- case 0x84:
- case 0x85:
- case 0x86:
- case 0x87:
- case 0x88:
- case 0x89:
- case 0x8a:
- case 0x8b:
- case 0x8c:
- case 0x8d:
- case 0x8e:
- case 0x8f:
- break;
-
- case 0x90:
- case 0x91:
- case 0x92:
- case 0x93:
- case 0x94:
- case 0x95:
- case 0x96:
- case 0x97:
- case 0x98:
- case 0x99:
- case 0x9a:
- case 0x9b:
- case 0x9c:
- case 0x9d:
- case 0x9e:
- case 0x9f:
- break;
-
- case 0xa0:
- case 0xa1:
- case 0xa2:
- case 0xa3:
- case 0xa4:
- case 0xa5:
- case 0xa6:
- case 0xa7:
- break;
-
- case 0xa8:
- case 0xa9:
- case 0xaa:
- case 0xab:
- case 0xac:
- case 0xad:
- case 0xae:
- case 0xaf:
- // XCH r,(src)
- m_op = XCH;
-
- m_param1_type = REG_8BIT;
- m_param1 = bx & 0x7;
-
- m_param2_type = type;
- m_param2 = val;
- break;
-
-
- case 0xb0:
- case 0xb1:
- case 0xb2:
- case 0xb3:
- case 0xb4:
- case 0xb5:
- case 0xb6:
- case 0xb7:
- case 0xb8:
- case 0xb9:
- case 0xba:
- case 0xbb:
- case 0xbc:
- case 0xbd:
- case 0xbe:
- case 0xbf:
- break;
-
- case 0xc0:
- case 0xc1:
- case 0xc2:
- case 0xc3:
- case 0xc4:
- case 0xc5:
- case 0xc6:
- case 0xc7:
- // CPL (src).b
- m_op = CPL;
-
- m_param1_type = type | BITPOS;
- m_param1 = val;
- m_bitpos = bx & 0x7;
- break;
-
- case 0xc8:
- case 0xc9:
- case 0xca:
- case 0xcb:
- case 0xcc:
- case 0xcd:
- case 0xce:
- case 0xcf:
- // LD (src).b,CF
- m_op = LD; // Flags / Cycles 1--- / x
- m_flagsaffected |= FLAG_J;
-
- m_param1_type = type | BITPOS;
- m_param1 = val;
- m_bitpos = bx & 0x7;
-
- m_param2_type = CARRYFLAG;
- //m_param2 = 0;
- break;
-
-
- case 0xd0:
- case 0xd1:
- case 0xd2:
- case 0xd3:
- case 0xd4:
- case 0xd5:
- case 0xd6:
- case 0xd7:
- // XOR CF,(src).b
- m_op = ALU_XOR;
- m_param1_type = CARRYFLAG;
- //m_param1 = 0;
-
- m_param2_type = type | BITPOS;
- m_param2 = val;
- m_bitpos = bx & 0x7;
- break;
-
- case 0xd8:
- case 0xd9:
- case 0xda:
- case 0xdb:
- case 0xdc:
- case 0xdd:
- case 0xde:
- case 0xdf:
- // LD CF,(src).b aka TEST (src).b
- m_op = LD; // Flags / Cycles %-*- / x
- m_flagsaffected |= FLAG_J | FLAG_C;
-
- m_param2_type = type | BITPOS;
- m_param2 = val;
- m_bitpos = bx & 0x7;
-
- m_param1_type = CARRYFLAG;
- //m_param1 = 0;
- break;
-
-
- 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:
- break;
-
- case 0xf0:
- case 0xf1:
- case 0xf2:
- case 0xf3:
- case 0xf4:
- case 0xf5:
- case 0xf6:
- case 0xf7:
- break;
-
- case 0xf8:
- case 0xf9:
- case 0xfa:
- case 0xfb:
- case 0xfc:
- // CALL (src)
- m_op = CALL;
- m_param1_type = type;
- m_param1 = val;
- break;
-
- case 0xfd:
- break;
-
- case 0xfe:
- // JP (src)
- m_op = JP;
- m_param2_type = type | IS16BIT;
- m_param2 = val;
- break;
-
- case 0xff:
- break;
-
-
- }
-
-}
-
-// f0 - f7 use this table
-// note, same table is shown as above in manual, there's no overlap between src/dest, but they're not compatible
-void tlcs870_device::decode_dest(uint8_t b0)
-{
- uint8_t bx;
-
- bx = READ8();
-
- switch (bx)
- {
- case 0x10:
- case 0x11:
- case 0x12:
- case 0x13:
- // LD (dst),rr // (dst) can only be (x) (pp) or (HL+d) ? not (HL+) or (-HL) ?
- m_op = LD; // Flags / Cycles 1--- / x
- m_flagsaffected |= FLAG_J;
-
- m_param1_type |= IS16BIT;
-
-
- m_param2_type = REG_16BIT;
- m_param2 = bx&0x3;
- break;
-
- case 0x2c:
- // LD (dst),n // (dst) can only be (DE), (HL+), (-HL), or (HL+d) because (x) and (HL) are redundant encodings?
- m_op = LD; // Flags / Cycles 1--- / x
- m_flagsaffected |= FLAG_J;
-
- m_param2_type = ABSOLUTE_VAL_8;
- m_param2 = READ8();
- break;
-
- case 0x50:
- case 0x51:
- case 0x52:
- case 0x53:
- case 0x54:
- case 0x55:
- case 0x56:
- case 0x57:
- // LD (dst),r
- m_op = LD; // Flags / Cycles 1--- / x
- m_flagsaffected |= FLAG_J;
-
- m_param2_type = REG_8BIT;
- m_param2 = bx&0x7;
- break;
-
- default:
- break;
- }
-}
-
-bool tlcs870_device::stream_arg(std::ostream &stream, uint32_t pc, const char *pre, const uint16_t mode, const uint16_t r, const uint16_t rb)
-{
- return false;
-}
-
-void tlcs870_device::execute_set_input(int inputnum, int state)
-{
-#if 0
- switch(inputnum) {
- case INPUT_LINE_NMI:
- set_irq_line(INTNMI, state);
- break;
- case INPUT_LINE_IRQ0:
- set_irq_line(INT0, state);
- break;
- case INPUT_LINE_IRQ1:
- set_irq_line(INT1, state);
- break;
- case INPUT_LINE_IRQ2:
- set_irq_line(INT2, state);
- break;
- }
-#endif
-}
-
-uint16_t tlcs870_device::get_addr(uint16_t param_type, uint16_t param_val)
-{
- uint16_t addr = 0x0000;
-
- switch (param_type&MODE_MASK)
- {
- case ADDR_IN_IMM_X:
- addr = param_val;
- break;
- case ADDR_IN_PC_PLUS_REG_A:
- addr = m_temppc + 2 + get_reg8(REG_A);
- break;
- case ADDR_IN_DE:
- addr = get_reg16(REG_DE);
- break;
- case ADDR_IN_HL:
- addr = get_reg16(REG_HL);
- break;
- case ADDR_IN_HL_PLUS_IMM_D:
- addr = get_reg16(REG_HL) + param_val;
- break;
- case ADDR_IN_HL_PLUS_REG_C:
- addr = get_reg16(REG_HL) + get_reg16(REG_C);
- break;
- case ADDR_IN_HLINC:
- {
- uint16_t tmpHL = get_reg16(REG_HL);
- addr = tmpHL;
- tmpHL++;
- set_reg16(REG_HL, tmpHL);
- break;
- }
- case ADDR_IN_DECHL:
- {
- uint16_t tmpHL = get_reg16(REG_HL);
- tmpHL--;
- set_reg16(REG_HL, tmpHL);
- addr = tmpHL;
- break;
- }
- }
-
- return addr;
-}
-
-void tlcs870_device::set_dest_val(uint16_t param_type, uint16_t param_val, uint16_t dest_val)
-{
- if (param_type & IS16BIT)
- {
- switch (param_type)
- {
- case ABSOLUTE_VAL_16:
- logerror("illegal dest ABSOLUTE_VAL_16\n");
- break;
-
- case REG_16BIT:
- set_reg16(param_val, dest_val);
- break;
-
- case (STACKPOINTER):
- m_sp.d = dest_val;
- break;
- }
- }
- else
- {
- switch (param_type & MODE_MASK)
- {
- case ABSOLUTE_VAL_8:
- logerror("illegal dest ABSOLUTE_VAL_8\n");
- break;
- case REG_8BIT:
- set_reg8(param_val, dest_val);
- break;
- }
- }
-}
-
-uint16_t tlcs870_device::get_source_val(uint16_t param_type, uint16_t param_val)
-{
- uint16_t ret_val = 0x0000;
-
- if (param_type & IS16BIT)
- {
- switch (param_type)
- {
- case ABSOLUTE_VAL_16:
- ret_val = param_val;
- break;
-
- case REG_16BIT:
- ret_val = get_reg16(param_val);
- break;
-
- case (STACKPOINTER):
- ret_val = m_sp.d;
- break;
- }
- }
- else
- {
- switch (param_type & MODE_MASK)
- {
- case ABSOLUTE_VAL_8:
- ret_val = param_val;
- break;
- case REG_8BIT:
- ret_val = get_reg8(param_val);
- break;
- }
- }
- return ret_val;
-}
-
-void tlcs870_device::setbit_param(uint16_t param_type, uint16_t param, uint8_t bit, bool do_flag)
-{
- if (param_type & BITPOS)
- {
- uint8_t bitpos = 0;
-
- // need to read param 1
- uint16_t addr = 0x0000;
- uint16_t val = 0;
-
- // READ
- if (param_type & ADDR_IN_BASE)
- {
- addr = get_addr(param_type, param); // any pre/post HL address adjustments happen here
- if (param_type & IS16BIT)
- val = RM16(addr);
- else
- val = RM8(addr);
- }
- else
- {
- val = get_source_val(param_type, param);
- }
-
- if (param_type & BITPOS_INDIRECT)
- {
- bitpos = get_reg8(m_bitpos & 7) & 0x7;
- }
- else
- {
- bitpos = m_bitpos;
- }
-
- // MODIFY
- int bitused = (1 << bitpos);
-
- // this is the flag behavior for the set/clr bit opcodes
- if (do_flag)
- {
- int existingbit = (val & bitused);
- if (existingbit)
- {
- CLEAR_ZF;
- CLEAR_JF; // 'Z' (so copy Z flag?)
- }
- else
- {
- SET_ZF;
- SET_JF; // 'Z'
- }
- }
-
-
- bit ? (val |= bitused) : (val &= ~bitused);
-
- //printf("bit to set is %d, value is %02x", bitused, val);
-
- // WRITE
- if (param_type & ADDR_IN_BASE)
- {
- //addr = get_addr(param_type,param); // already have addr, don't want to cause any further HL decrements/increments.
- if (param_type & IS16BIT)
- WM16(addr, val);
- else
- WM8(addr, val);
- }
- else
- {
- set_dest_val(param_type, param, val);
- }
- }
- else
- {
- fatalerror("not a bit op? 0\n");
- }
-}
-
-uint8_t tlcs870_device::getbit_param(uint16_t param_type, uint16_t param)
-{
- uint8_t bit = 0;
-
- if (param_type & BITPOS)
- {
- uint8_t bitpos;
-
- // need to read param 2
- uint16_t addr = 0x0000;
- uint16_t val = 0;
- if (param_type & ADDR_IN_BASE)
- {
- addr = get_addr(param_type, param);
- if (param_type & IS16BIT)
- val = RM16(addr);
- else
- val = RM8(addr);
- }
- else
- {
- val = get_source_val(param_type, param);
- }
-
- if (param_type & BITPOS_INDIRECT)
- {
- bitpos = get_reg8(m_bitpos & 7) & 0x7;
- }
- else
- {
- bitpos = m_bitpos;
- }
-
- bit = (val >> bitpos) & 1;
- }
- else
- {
- fatalerror("not a bit op? 0\n");
- }
-
- return bit;
-}
-
-void tlcs870_device::execute_run()
-{
- do
- {
- m_prvpc.d = m_pc.d;
- debugger_instruction_hook(m_pc.d);
-
- //check_interrupts();
- m_temppc = m_pc.d;
-
- m_addr = m_pc.d;
- decode();
- m_pc.d = m_addr;
-
- switch (m_op)
- {
- case UNKNOWN:
- // invalid instruction
- break;
-
- case CALL:
- break;
- case CALLP:
- break;
- case CALLV:
- break;
-
- case CLR:
- if ((m_param1_type & BITPOS))
- {
- //printf("clr on bit\n");
-
- if (m_param1_type == CARRYFLAG)
- {
- CLEAR_CF;
- SET_JF;
- }
- else
- {
- setbit_param(m_param1_type, m_param1, 0, true);
- }
- }
- else
- {
- // grouped with the LD operations in the manual but with CLR name, so probably internally just calling LD with 0 value
-
- uint16_t addr = 0x0000;
- uint16_t val = 0;
-
- if (m_param1_type & ADDR_IN_BASE)
- {
- addr = get_addr(m_param1_type,m_param1);
- if (m_param1_type & IS16BIT)
- WM16(addr, val);
- else
- WM8(addr, val);
- }
- else
- {
- set_dest_val(m_param1_type,m_param1, val);
- }
- SET_JF;
- }
- break;
-
-
- case CPL:
- break;
- case DAA:
- break;
- case DAS:
- break;
- case DEC:
- break;
- /*
- case DI:
- break;
- */
- case DIV:
- break;
- /*
- case EI:
- break;
- */
- case INC:
- {
- // READ
- uint16_t addr = 0x0000;
- uint16_t val = 0;
- if (m_param1_type & ADDR_IN_BASE)
- {
- addr = get_addr(m_param1_type, m_param1);
- if (m_param1_type & IS16BIT)
- val = RM16(addr);
- else
- val = RM8(addr);
- }
- else
- {
- val = get_source_val(m_param1_type, m_param1);
- }
-
- // MODIFY
- val++;
-
- if (!(m_param1_type & IS16BIT))
- val &= 0xff;
-
- if (val == 0)
- {
- SET_ZF;
- SET_JF;
- }
- else
- {
- CLEAR_ZF;
- CLEAR_JF;
- }
-
- // WRITE
- if (m_param1_type & ADDR_IN_BASE)
- {
- //addr = get_addr(m_param1_type,m_param1); // already have
- if (m_param1_type & IS16BIT)
- WM16(addr, val);
- else
- WM8(addr, val);
- }
- else
- {
- set_dest_val(m_param1_type,m_param1, val);
- }
-
- break;
- }
- /*
- case J:
- break;
- */
- case JP:
- case JR:
- case JRS:
- {
- bool takejump = true;
-
- if (m_param1_type == CONDITIONAL)
- {
- switch (m_param1)
- {
- case COND_EQ_Z:
- if (IS_ZF == 1) takejump = true;
- else takejump = false;
- break;
-
- case COND_NE_NZ:
- if (IS_ZF == 0) takejump = true;
- else takejump = false;
- break;
-
- case COND_LT_CS:
- if (IS_CF == 1) takejump = true;
- else takejump = false;
- break;
-
- case COND_GE_CC:
- if (IS_CF == 0) takejump = true;
- else takejump = false;
- break;
-
- case COND_LE:
- if ((IS_CF || IS_ZF) == 1) takejump = true;
- else takejump = false;
- break;
-
- case COND_GT:
- if ((IS_CF || IS_ZF) == 0) takejump = true;
- else takejump = false;
- break;
-
- case COND_T:
- if (IS_JF == 1) takejump = true;
- else takejump = false;
- break;
-
- case COND_F:
- if (IS_JF == 0) takejump = true;
- else takejump = false;
- break;
-
- }
- }
-
- if (takejump)
- {
- // would the address / register be read even if the jump isn't going to be taken?
- uint16_t addr = 0x0000;
- uint16_t val = 0;
- if (m_param2_type & ADDR_IN_BASE)
- {
- addr = get_addr(m_param2_type,m_param2);
- if (m_param2_type & IS16BIT)
- val = RM16(addr);
- else
- {
- fatalerror("8-bit jump destination?");
- // val = RM8(addr);
- }
- }
- else
- {
- val = get_source_val(m_param2_type,m_param2);
- }
-
- m_pc.d = val;
- }
-
- SET_JF;
-
- break;
- }
- case LD:
- {
- if ((m_param1_type & BITPOS) || (m_param2_type & BITPOS))
- {
- // bit operations, including the 'TEST' style bit instruction
- uint8_t bit = 0;
-
- if (m_param2_type == CARRYFLAG)
- {
- bit = IS_CF;
-
- setbit_param(m_param1_type,m_param1,bit, false);
-
- // for this type of operation ( LD *.b, CF ) the Jump Flag always ends up being 1
- SET_JF;
-
- }
- else if (m_param1_type == CARRYFLAG)
- {
- getbit_param(m_param2_type,m_param2);
-
- bit ? SET_CF : CLEAR_CF;
- // for this type of operation ( LD CF, *.b ) the Jump Flag always ends up the inverse of the Carry Flag
- bit ? CLEAR_JF : SET_JF;
- }
- else
- {
- fatalerror("not a bit op?! 2");
- }
- }
- else
- {
- uint16_t addr = 0x0000;
- uint16_t val = 0;
- if (m_param2_type & ADDR_IN_BASE)
- {
- addr = get_addr(m_param2_type,m_param2);
- if (m_param2_type & IS16BIT)
- val = RM16(addr);
- else
- val = RM8(addr);
- }
- else
- {
- val = get_source_val(m_param2_type,m_param2);
- }
-
- SET_JF; // Jump Flag always gets set
-
- // some (but not all) LD operations change the Zero Flag, some leave it undefined (for those we don't change it)
- if (m_flagsaffected & FLAG_Z)
- {
- if (val == 0x00) SET_ZF;
- else CLEAR_ZF;
- }
-
- if (m_param1_type & ADDR_IN_BASE)
- {
- addr = get_addr(m_param1_type,m_param1);
- if (m_param1_type & IS16BIT)
- WM16(addr, val);
- else
- WM8(addr, val);
- }
- else
- {
- set_dest_val(m_param1_type,m_param1, val);
- }
- }
- break;
- }
- case LDW:
- break;
- case MCMP:
- break;
- case MUL:
- break;
- case NOP:
- break;
- case POP:
- break;
- case PUSH:
- break;
- case RET:
- break;
- case RETI:
- break;
- case RETN:
- break;
- case ROLC:
- break;
- case ROLD:
- break;
- case RORC:
- break;
- case RORD:
- break;
-
-
- case SET:
- if ((m_param1_type & BITPOS))
- {
- //printf("set on bit\n");
-
- if (m_param1_type == CARRYFLAG)
- {
- SET_CF;
- CLEAR_JF;
- }
- else
- {
- //printf("set with setbit_param\n");
-
- setbit_param(m_param1_type, m_param1, 1, true);
- }
- }
- else
- {
- fatalerror("all SET opcode should be bit operations\n");
- /*
- uint16_t addr = 0x0000;
- uint16_t val = 1;
-
- if (m_param1_type & ADDR_IN_BASE)
- {
- addr = get_addr(m_param1_type,m_param1);
- if (m_param1_type & IS16BIT)
- WM16(addr, val);
- else
- WM8(addr, val);
- }
- else
- {
- set_dest_val(m_param1_type,m_param1, val);
- }
- */
-
- }
- break;
-
-
- case SHLC:
- break;
- case SHRC:
- break;
- case SWAP:
- break;
- case SWI:
- break;
- /*
- case TEST:
- break;
- */
- case XCH:
- break;
- case ALU_ADDC:
- break;
- case ALU_ADD:
- break;
- case ALU_SUBB:
- break;
- case ALU_SUB:
- break;
- case ALU_AND:
- break;
- case ALU_XOR:
- break;
- case ALU_OR:
- break;
- case ALU_CMP:
-
- uint16_t addr = 0x0000;
- uint16_t val = 0;
- if (m_param2_type & ADDR_IN_BASE)
- {
- addr = get_addr(m_param2_type,m_param2);
- if (m_param2_type & IS16BIT)
- val = RM16(addr);
- else
- val = RM8(addr);
- }
- else
- {
- val = get_source_val(m_param2_type,m_param2);
- }
-
- uint16_t val2 = val;
-
- if (m_param1_type & ADDR_IN_BASE)
- {
- addr = get_addr(m_param1_type,m_param1);
- if (m_param1_type & IS16BIT)
- val = RM16(addr);
- else
- val = RM8(addr);
- }
- else
- {
- val = get_source_val(m_param1_type,m_param1);
- }
-
- if (val < val2)
- {
- SET_CF;
- }
- else
- {
- CLEAR_CF;
- }
-
- if (val == val2)
- {
- SET_ZF;
- SET_JF;
- }
- else
- {
- CLEAR_ZF;
- CLEAR_JF;
- }
-
- // TODO: HF (how to calculate it?)
-
-
- break;
- }
-
- m_icount-=m_cycles*4; // 1 machine cycle = 4 clock cycles?
-
-
- } while( m_icount > 0 );
-}
-
-void tlcs870_device::device_reset()
-{
- // todo, read from top address
- m_pc.d = 0xc030;
-
- m_RBS = 0;
-
-}
-
-uint8_t tlcs870_device::get_reg8(int reg)
-{
- return m_intram[((m_RBS & 0xf) * 8) + (reg & 0x7)];
-}
-
-void tlcs870_device::set_reg8(int reg, uint8_t val)
-{
- m_intram[((m_RBS & 0xf) * 8) + (reg & 0x7)] = val;
-}
-
-uint16_t tlcs870_device::get_reg16(int reg)
-{
- uint16_t res = 0;
- res |= get_reg8(((reg & 0x3) * 2) + 1) << 8;
- res |= get_reg8(((reg & 0x3) * 2) + 0) << 0;
- return res;
-}
-
-void tlcs870_device::set_reg16(int reg, uint16_t val)
-{
- set_reg8(((reg & 0x3) * 2) + 1, (val & 0xff00) >> 8);
- set_reg8(((reg & 0x3) * 2) + 0, (val & 0x00ff) >> 0);
-}
-
-
-
-void tlcs870_device::state_import(const device_state_entry &entry)
-{
- switch (entry.index())
- {
- case DEBUGGER_REG_A:
- set_reg8(REG_A, m_debugger_temp);
- break;
-
- case DEBUGGER_REG_W:
- set_reg8(REG_W, m_debugger_temp);
- break;
-
- case DEBUGGER_REG_C:
- set_reg8(REG_C, m_debugger_temp);
- break;
-
- case DEBUGGER_REG_B:
- set_reg8(REG_B, m_debugger_temp);
- break;
-
- case DEBUGGER_REG_E:
- set_reg8(REG_E, m_debugger_temp);
- break;
-
- case DEBUGGER_REG_D:
- set_reg8(REG_D, m_debugger_temp);
- break;
-
- case DEBUGGER_REG_L:
- set_reg8(REG_L, m_debugger_temp);
- break;
-
- case DEBUGGER_REG_H:
- set_reg8(REG_H, m_debugger_temp);
- break;
-
- case DEBUGGER_REG_WA:
- set_reg16(REG_WA, m_debugger_temp);
- break;
-
- case DEBUGGER_REG_BC:
- set_reg16(REG_BC, m_debugger_temp);
- break;
-
- case DEBUGGER_REG_DE:
- set_reg16(REG_DE, m_debugger_temp);
- break;
-
- case DEBUGGER_REG_HL:
- set_reg16(REG_HL, m_debugger_temp);
- break;
- }
-}
-
-
-void tlcs870_device::state_export(const device_state_entry &entry)
-{
- switch (entry.index())
- {
- case DEBUGGER_REG_A:
- m_debugger_temp = get_reg8(REG_A);
- break;
-
- case DEBUGGER_REG_W:
- m_debugger_temp = get_reg8(REG_W);
- break;
-
- case DEBUGGER_REG_C:
- m_debugger_temp = get_reg8(REG_C);
- break;
-
- case DEBUGGER_REG_B:
- m_debugger_temp = get_reg8(REG_B);
- break;
-
- case DEBUGGER_REG_E:
- m_debugger_temp = get_reg8(REG_E);
- break;
-
- case DEBUGGER_REG_D:
- m_debugger_temp = get_reg8(REG_D);
- break;
-
- case DEBUGGER_REG_L:
- m_debugger_temp = get_reg8(REG_L);
- break;
-
- case DEBUGGER_REG_H:
- m_debugger_temp = get_reg8(REG_H);
- break;
-
- case DEBUGGER_REG_WA:
- m_debugger_temp = get_reg16(REG_WA);
- break;
-
- case DEBUGGER_REG_BC:
- m_debugger_temp = get_reg16(REG_BC);
- break;
-
- case DEBUGGER_REG_DE:
- m_debugger_temp = get_reg16(REG_DE);
- break;
-
- case DEBUGGER_REG_HL:
- m_debugger_temp = get_reg16(REG_HL);
- break;
-
}
}
void tlcs870_device::device_start()
{
-// int i, p;
+ // int i, p;
m_sp.d = 0x0000;
m_F = 0;
@@ -3140,7 +312,7 @@ void tlcs870_device::device_start()
state_add(STATE_GENPC, "GENPC", m_pc.w.l).formatstr("%04X");
state_add(STATE_GENPCBASE, "CURPC", m_prvpc.w.l).formatstr("%04X").noshow();
state_add(STATE_GENSP, "GENSP", m_sp.w.l).formatstr("%04X");
- state_add(STATE_GENFLAGS, "GENFLAGS", m_F ).formatstr("%8s").noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_F).formatstr("%8s").noshow();
set_icountptr(m_icount);
}
@@ -3153,14 +325,14 @@ void tlcs870_device::state_string_export(const device_state_entry &entry, std::s
switch (entry.index())
{
- case STATE_GENFLAGS:
- str = string_format("%c%c%c%c",
- F & 0x80 ? 'J':'.',
- F & 0x40 ? 'Z':'.',
- F & 0x20 ? 'C':'.',
- F & 0x10 ? 'H':'.'
- );
- break;
+ case STATE_GENFLAGS:
+ str = string_format("%c%c%c%c",
+ F & 0x80 ? 'J' : '.',
+ F & 0x40 ? 'Z' : '.',
+ F & 0x20 ? 'C' : '.',
+ F & 0x10 ? 'H' : '.'
+ );
+ break;
}
}
diff --git a/src/devices/cpu/tlcs870/tlcs870.h b/src/devices/cpu/tlcs870/tlcs870.h
index 42ca4b1c6c6..d959a677518 100644
--- a/src/devices/cpu/tlcs870/tlcs870.h
+++ b/src/devices/cpu/tlcs870/tlcs870.h
@@ -8,32 +8,40 @@
class tlcs870_device : public cpu_device
{
protected:
- enum _e_op {
- UNKNOWN = 0x00,
- CALL, CALLP, CALLV, CLR, CPL,
- DAA, DAS, DEC, /*DI,*/ DIV,
- /*EI,*/
- INC,
- /*J,*/ JP, JR, JRS,
- LD, LDW,
- MCMP, MUL,
- NOP,
- POP, PUSH,
- RET, RETI, RETN, ROLC, ROLD, RORC, RORD,
- SET, SHLC, SHRC, SWAP, SWI,
- /*TEST,*/ XCH,
-
- ALU_ADDC,
- ALU_ADD,
- ALU_SUBB,
- ALU_SUB,
- ALU_AND,
- ALU_XOR,
- ALU_OR,
- ALU_CMP
- };
+ // construction/destruction
+ tlcs870_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor program_map);
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_execute_interface overrides
+ virtual uint32_t execute_min_cycles() const override { return 2; }
+ virtual uint32_t execute_max_cycles() const override { return 26; }
+ virtual uint32_t execute_input_lines() const override { return 1; }
+ virtual bool execute_input_edge_triggered(int inputnum) const override { return inputnum == INPUT_LINE_NMI; }
+ virtual void execute_run() override;
+ virtual void execute_set_input(int inputnum, int state) override;
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+
+ // device_state_interface overrides
+ virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+ virtual void state_import(const device_state_entry &entry) override;
+ virtual void state_export(const device_state_entry &entry) override;
+
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+ void tmp87ph40an_mem(address_map &map);
+
+ uint32_t m_debugger_temp;
- enum _regs8 {
+private:
+
+ enum _regs8
+ {
REG_A,
REG_W,
REG_C,
@@ -44,19 +52,16 @@ protected:
REG_H
};
- enum _regs16 {
+ enum _regs16
+ {
REG_WA,
REG_BC,
REG_DE,
REG_HL
};
- enum _regs16p {
- pREG_DE,
- pREG_HL
- };
-
- enum _regs_debugger {
+ enum _regs_debugger
+ {
DEBUGGER_REG_A,
DEBUGGER_REG_W,
DEBUGGER_REG_C,
@@ -71,7 +76,8 @@ protected:
DEBUGGER_REG_HL
};
- enum _conditions {
+ enum _conditions
+ {
COND_EQ_Z,
COND_NE_NZ,
COND_LT_CS,
@@ -82,37 +88,18 @@ protected:
COND_F
};
- // construction/destruction
- tlcs870_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor program_map);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const override { return 2; }
- virtual uint32_t execute_max_cycles() const override { return 26; }
- virtual uint32_t execute_input_lines() const override { return 1; }
- virtual bool execute_input_edge_triggered(int inputnum) const override { return inputnum == INPUT_LINE_NMI; }
- virtual void execute_run() override;
- virtual void execute_set_input(int inputnum, int state) override;
-
- // device_memory_interface overrides
- virtual space_config_vector memory_space_config() const override;
-
- // device_state_interface overrides
- virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
- virtual void state_import(const device_state_entry &entry) override;
- virtual void state_export(const device_state_entry &entry) override;
-
- // device_disasm_interface overrides
- virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
-
- void tmp87ph40an_mem(address_map &map);
-
- uint32_t m_debugger_temp;
+ enum _srcdst_addressingmode
+ {
+ ADDR_IN_IMM_X,
+ ADDR_IN_PC_PLUS_REG_A,
+ ADDR_IN_DE,
+ ADDR_IN_HL,
+ ADDR_IN_HL_PLUS_IMM_D,
+ ADDR_IN_HL_PLUS_REG_C,
+ ADDR_IN_HLINC,
+ ADDR_IN_DECHL
+ };
-private:
address_space_config m_program_config;
address_space_config m_io_config;
required_shared_ptr<uint8_t> m_intram;
@@ -124,18 +111,8 @@ private:
int m_icount;
// Work registers
- uint16_t m_op;
- int m_param2_type;
- uint16_t m_param2;
-
- int m_param1_type;
- uint16_t m_param1;
- uint16_t m_temppc; // this is just PPC? use generic reg?
-
- uint8_t m_bitpos;
- uint8_t m_flagsaffected;
uint8_t m_cycles;
-
+ uint16_t m_tmppc;
uint32_t m_addr;
uint16_t m_F;
@@ -143,34 +120,225 @@ private:
/* CPU registers */
uint8_t m_RBS; // register base (4-bits)
- inline uint8_t RM8 (uint32_t a);
- inline uint16_t RM16(uint32_t a);
- inline void WM8 (uint32_t a, uint8_t v);
- inline void WM16(uint32_t a, uint16_t v);
- inline uint8_t RX8 (uint32_t a, uint32_t base);
- inline uint16_t RX16(uint32_t a, uint32_t base);
- inline void WX8 (uint32_t a, uint8_t v, uint32_t base);
- inline void WX16(uint32_t a, uint16_t v, uint32_t base);
- inline uint8_t READ8();
- inline uint16_t READ16();
- void decode();
- void decode_register_prefix(uint8_t b0);
- void decode_source(int type, uint16_t val);
- void decode_dest(uint8_t b0);
+ uint8_t RM8(const uint32_t a) { return m_program->read_byte(a); }
+ uint16_t RM16(const uint32_t a) { return RM8(a) | (RM8((a + 1) & 0xffff) << 8); }
+
+ void WM8(const uint32_t a, const uint8_t v) { m_program->write_byte(a, v); }
+ void WM16(const uint32_t a, const uint16_t v) { WM8(a, v); WM8((a + 1) & 0xffff, v >> 8); }
- void setbit_param(uint16_t param_type, uint16_t param, uint8_t bit, bool do_flag);
- uint8_t getbit_param(uint16_t param_type, uint16_t param);
+ uint8_t RX8(const uint32_t a, const uint32_t base) { return m_program->read_byte(base | a); }
+ uint16_t RX16(const uint32_t a, const uint32_t base) { return RX8(a, base) | (RX8((a + 1) & 0xffff, base) << 8); }
- uint16_t get_addr(uint16_t param_type, uint16_t param_val);
- uint16_t get_source_val(uint16_t param_type, uint16_t param_val);
- void set_dest_val(uint16_t param_type, uint16_t param_val, uint16_t dest_val);
+ void WX8(const uint32_t a, const uint8_t v, const uint32_t base) { m_program->write_byte(base | a, v); }
+ void WX16(const uint32_t a, const uint16_t v, const uint32_t base) { WX8(a, v, base); WX8((a + 1) & 0xffff, v >> 8, base); }
- uint8_t get_reg8(int reg);
- void set_reg8(int reg, uint8_t val);
- uint16_t get_reg16(int reg);
- void set_reg16(int reg, uint16_t val);
+ uint8_t READ8() { const uint8_t b0 = RM8(m_addr++); m_addr &= 0xffff; return b0; }
+ uint16_t READ16() { const uint8_t b0 = READ8(); return b0 | (READ8() << 8); }
+
+ uint16_t get_addr(uint16_t opbyte0, uint16_t val);
+
+ const uint8_t get_reg8(const int reg);
+ void set_reg8(const int reg, uint8_t val);
+ const uint16_t get_reg16(const int reg);
+ void set_reg16(const int reg, uint16_t val);
+
+ const int FLAG_J = 0x80;
+ const int FLAG_Z = 0x40;
+ const int FLAG_C = 0x20;
+ const int FLAG_H = 0x10;
+
+ void clear_JF() { m_F &= ~FLAG_J; };
+ void clear_ZF() { m_F &= ~FLAG_Z; };
+ void clear_CF() { m_F &= ~FLAG_C; };
+ void clear_HF() { m_F &= ~FLAG_H; };
+
+ void set_JF() { m_F |= FLAG_J; };
+ void set_ZF() { m_F |= FLAG_Z; };
+ void set_CF() { m_F |= FLAG_C; };
+ void set_HF() { m_F |= FLAG_H; };
+
+ const int is_JF() { return ((m_F & FLAG_J) ? 1 : 0); };
+ const int is_ZF() { return ((m_F & FLAG_Z) ? 1 : 0); };
+ const int is_CF() { return ((m_F & FLAG_C) ? 1 : 0); };
+ const int is_HF() { return ((m_F & FLAG_H) ? 1 : 0); };
bool stream_arg(std::ostream &stream, uint32_t pc, const char *pre, const uint16_t mode, const uint16_t r, const uint16_t rb);
+
+ // tlcs870_ops.cpp
+ void decode();
+
+ void do_illegal(const uint8_t opbyte0);
+
+ void do_NOP(const uint8_t opbyte0);
+ void do_SWAP_A(const uint8_t opbyte0);
+ void do_MUL_W_A(const uint8_t opbyte0);
+ void do_DIV_WA_C(const uint8_t opbyte0);
+ void do_RETI(const uint8_t opbyte0);
+ void do_RET(const uint8_t opbyte0);
+ void do_POP_PSW(const uint8_t opbyte0);
+ void do_PUSH_PSW(const uint8_t opbyte0);
+
+ void do_DAA_A(const uint8_t opbyte0);
+ void do_DAS_A(const uint8_t opbyte0);
+ void do_CLR_CF(const uint8_t opbyte0);
+ void do_SET_CF(const uint8_t opbyte0);
+ void do_CPL_CF(const uint8_t opbyte0);
+ void do_LD_RBS_n(const uint8_t opbyte0);
+ void do_INC_rr(const uint8_t opbyte0);
+ void do_LD_rr_mn(const uint8_t opbyte0);
+ void do_DEC_rr(const uint8_t opbyte0);
+ void do_SHLC_A(const uint8_t opbyte0);
+ void do_SHRC_A(const uint8_t opbyte0);
+ void do_ROLC_A(const uint8_t opbyte0);
+ void do_RORC_A(const uint8_t opbyte0);
+ void do_INC_inx(const uint8_t opbyte0);
+ void do_INC_inHL(const uint8_t opbyte0);
+ void do_LD_A_inx(const uint8_t opbyte0);
+ void do_LD_A_inHL(const uint8_t opbyte0);
+ void do_LDW_inx_mn(const uint8_t opbyte0);
+ void do_LDW_inHL_mn(const uint8_t opbyte0);
+ void do_LD_inx_iny(const uint8_t opbyte0);
+
+ void do_DEC_inx(const uint8_t opbyte0);
+ void do_DEC_inHL(const uint8_t opbyte0);
+ void do_LD_inx_A(const uint8_t opbyte0);
+ void do_LD_inHL_A(const uint8_t opbyte0);
+ void do_LD_inx_n(const uint8_t opbyte0);
+ void do_LD_inHL_n(const uint8_t opbyte0);
+ void do_CLR_inx(const uint8_t opbyte0);
+ void do_CLR_inHL(const uint8_t opbyte0);
+ void do_LD_r_n(const uint8_t opbyte0);
+
+ void do_SET_inxbit(const uint8_t opbyte0);
+ void do_CLR_inxbit(const uint8_t opbyte0);
+ void do_LD_A_r(const uint8_t opbyte0);
+ void do_LD_r_A(const uint8_t opbyte0);
+ void do_INC_r(const uint8_t opbyte0);
+ void do_DEC_r(const uint8_t opbyte0);
+ void do_ALUOP_A_n(const uint8_t opbyte0);
+ void do_ALUOP_A_inx(const uint8_t opbyte0);
+ void do_JRS_T_a(const uint8_t opbyte0);
+ void do_JRS_F_a(const uint8_t opbyte0);
+ void do_CALLV_n(const uint8_t opbyte0);
+ void do_JR_cc_a(const uint8_t opbyte0);
+ void do_LD_CF_inxbit(const uint8_t opbyte0);
+
+ void do_LD_SP_mn(const uint8_t opbyte0);
+ void do_JR_a(const uint8_t opbyte0);
+ void do_CALL_mn(const uint8_t opbyte0);
+ void do_CALLP_n(const uint8_t opbyte0);
+ void do_JP_mn(const uint8_t opbyte0);
+ void do_ff_opcode(const uint8_t opbyte0);
+
+ // tlcs870_ops_src.cpp
+
+ void do_e0_opcode(const uint8_t opbyte0);
+ void do_e1_to_e3_opcode(const uint8_t opbyte0);
+ void do_e4_opcode(const uint8_t opbyte0);
+ void do_e5_to_e7_opcode(const uint8_t opbyte0);
+
+ void do_e0_to_e7_opcode(uint8_t opbyte0, uint16_t srcaddr);
+
+ void do_e0_to_e7_oprand_illegal(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+
+ void do_ROLD_A_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_RORD_A_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_LD_rr_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_INC_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_LD_inx_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_LD_inHL_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_DEC_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_MCMP_insrc_n(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_SET_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_CLR_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_LD_r_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_ALUOP_insrc_inHL(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_ALUOP_insrc_n(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_ALUOP_A_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_XCH_r_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_CPL_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_LD_insrcbit_CF(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_XOR_CF_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ void do_LD_CF_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
+ 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_f0_opcode(const uint8_t opbyte0);
+ void do_f2_to_f3_opcode(const uint8_t opbyte0);
+ void do_f4_opcode(const uint8_t opbyte0);
+ void do_f6_to_f7_opcode(const uint8_t opbyte0);
+
+ void do_f0_to_f7_opcode(const uint8_t opbyte0, const uint16_t dstaddr);
+
+ void do_f0_to_f7_oprand_illegal_opcode(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr);
+
+ void do_LD_indst_rr(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr);
+ void do_LD_indst_n(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr);
+ void do_LD_indst_r(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr);
+
+ // tlcs870_ops_reg.cpp
+
+ void do_regprefixtype_opcode(const uint8_t opbyte0);
+
+ void do_regprefixtype_oprand_illegal(const uint8_t opbyte0, const uint8_t opbyte1);
+
+ void do_SWAP_g(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_MUL_gg(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_DIV_gg_C(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_RETN(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_POP_gg(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_PUSH_gg(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_DAA_g(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_DAS_g(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_XCH_rr_gg(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_LD_rr_gg(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_SHLC_g(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_SHRC_g(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_ROLC_g(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_RORC_g(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_ALUOP_WA_gg(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_ALUOP_gg_mn(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_SET_gbit(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_CLR_gbit(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_LD_r_g(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_ALUOP_A_g(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_ALUOP_g_A(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_ALUOP_g_n(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_SET_inppbit(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_CLR_inppbit(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_CPL_inppbit(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_LD_inppbit_CF(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_LD_CF_inppbit(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_XCH_r_g(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_CPL_gbit(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_LD_gbit_CF(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_XOR_CF_gbit(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_LD_CF_gbit(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_LD_SP_gg(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_LD_gg_SP(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_CALL_gg(const uint8_t opbyte0, const uint8_t opbyte1);
+ void do_JP_gg(const uint8_t opbyte0, const uint8_t opbyte1);
+
+ 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);
+ uint8_t handle_DAA(uint8_t val);
+ uint8_t handle_ROLC(uint8_t val);
+ uint8_t handle_RORC(uint8_t val);
+ void handle_take_interrupt(int level);
+
+ const bool check_jump_condition(int param1);
+
+ const uint8_t get_PSW();
+ void set_PSW(uint8_t data);
};
diff --git a/src/devices/cpu/tlcs870/tlcs870_ops.cpp b/src/devices/cpu/tlcs870/tlcs870_ops.cpp
new file mode 100644
index 00000000000..a2ab06ca962
--- /dev/null
+++ b/src/devices/cpu/tlcs870/tlcs870_ops.cpp
@@ -0,0 +1,951 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+/*************************************************************************************************************
+
+ Toshiba TLCS-870 Series MCUs
+
+ (src) prefix ops (e0 to e7 subtable)
+
+ (src) address depends on the first byte of the opcode
+
+ E0 (x)
+ E1 (PC+A)
+ E2 (DE)
+ E3 (HL)
+ E4 (HL+d)
+ E5 (HL+)
+ E6 (-HL)
+
+ note, in cases where the address is an immediate value, not a register (x) and (HL+d) the
+ immediate value is directly after the first byte of the opcode
+
+*************************************************************************************************************/
+
+#include "emu.h"
+#include "tlcs870.h"
+#include "tlcs870d.h"
+#include "debugger.h"
+
+// Main dispatch handlers for these
+
+void tlcs870_device::decode()
+{
+ const uint8_t opbyte0 = READ8();
+
+ switch (opbyte0)
+ {
+ case 0x00:
+ do_NOP(opbyte0); break;
+ case 0x01:
+ do_SWAP_A(opbyte0); break;
+ case 0x02:
+ do_MUL_W_A(opbyte0); break;
+ case 0x03:
+ do_DIV_WA_C(opbyte0); break;
+ case 0x04:
+ do_RETI(opbyte0); break;
+ case 0x05:
+ do_RET(opbyte0); break;
+ case 0x06:
+ do_POP_PSW(opbyte0); break;
+ case 0x07:
+ do_PUSH_PSW(opbyte0); break;
+ case 0x0a:
+ do_DAA_A(opbyte0); break;
+ case 0x0b:
+ do_DAS_A(opbyte0); break;
+ case 0x0c:
+ do_CLR_CF(opbyte0); break;
+ case 0x0d:
+ do_SET_CF(opbyte0); break;
+ case 0x0e:
+ do_CPL_CF(opbyte0); break;
+ case 0x0f:
+ do_LD_RBS_n(opbyte0); break;
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ do_INC_rr(opbyte0); break;
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ do_LD_rr_mn(opbyte0); break;
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ do_DEC_rr(opbyte0); break;
+ case 0x1c:
+ do_SHLC_A(opbyte0); break;
+ case 0x1d:
+ do_SHRC_A(opbyte0); break;
+ case 0x1e:
+ do_ROLC_A(opbyte0); break;
+ case 0x1f:
+ do_RORC_A(opbyte0); break;
+ case 0x20:
+ do_INC_inx(opbyte0); break;
+ case 0x21:
+ do_INC_inHL(opbyte0); break;
+ case 0x22:
+ do_LD_A_inx(opbyte0); break;
+ case 0x23:
+ do_LD_A_inHL(opbyte0); break;
+ case 0x24:
+ do_LDW_inx_mn(opbyte0); break;
+ case 0x25:
+ do_LDW_inHL_mn(opbyte0); break;
+ case 0x26:
+ do_LD_inx_iny(opbyte0); break;
+ case 0x28:
+ do_DEC_inx(opbyte0); break;
+ case 0x29:
+ do_DEC_inHL(opbyte0); break;
+ case 0x2a:
+ do_LD_inx_A(opbyte0); break;
+ case 0x2b:
+ do_LD_inHL_A(opbyte0); break;
+ case 0x2c:
+ do_LD_inx_n(opbyte0); break;
+ case 0x2d:
+ do_LD_inHL_n(opbyte0); break;
+ case 0x2e:
+ do_CLR_inx(opbyte0); break;
+ case 0x2f:
+ do_CLR_inHL(opbyte0); break;
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ do_LD_r_n(opbyte0); break;
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
+ do_SET_inxbit(opbyte0); break;
+ case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ do_CLR_inxbit(opbyte0); break;
+ case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
+ do_LD_A_r(opbyte0); break;
+ case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+ do_LD_r_A(opbyte0); break;
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
+ do_INC_r(opbyte0); break;
+ case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ do_DEC_r(opbyte0); break;
+ case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
+ do_ALUOP_A_n(opbyte0); break;
+ case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ do_ALUOP_A_inx(opbyte0); break;
+ case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ do_JRS_T_a(opbyte0); break;
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ do_JRS_F_a(opbyte0); break;
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ do_CALLV_n(opbyte0); break;
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ do_JR_cc_a(opbyte0); break;
+ case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
+ do_LD_CF_inxbit(opbyte0); break;
+ case 0xe0:
+ do_e0_opcode(opbyte0); break;
+ case 0xe1: case 0xe2: case 0xe3:
+ do_e1_to_e3_opcode(opbyte0); break;
+ case 0xe4:
+ do_e4_opcode(opbyte0); break;
+ case 0xe5: case 0xe6: case 0xe7:
+ do_e5_to_e7_opcode(opbyte0); break;
+ case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
+ do_regprefixtype_opcode(opbyte0); break;
+ case 0xf0:
+ do_f0_opcode(opbyte0); break;
+ case 0xf2: case 0xf3:
+ do_f2_to_f3_opcode(opbyte0); break;
+ case 0xf4:
+ do_f4_opcode(opbyte0); break;
+ case 0xf6: case 0xf7:
+ do_f6_to_f7_opcode(opbyte0); break;
+ case 0xfa:
+ do_LD_SP_mn(opbyte0); break;
+ case 0xfb:
+ do_JR_a(opbyte0); break;
+ case 0xfc:
+ do_CALL_mn(opbyte0); break;
+ case 0xfd:
+ do_CALLP_n(opbyte0); break;
+ case 0xfe:
+ do_JP_mn(opbyte0); break;
+ case 0xff:
+ do_ff_opcode(opbyte0); break;
+
+ default:
+ do_illegal(opbyte0); break;
+ }
+}
+
+
+void tlcs870_device::do_illegal(const uint8_t opbyte0)
+{
+ logerror("illegal opcode %02x\n", opbyte0);
+}
+
+void tlcs870_device::do_NOP(const uint8_t opbyte0)
+{
+ // NOP
+}
+
+void tlcs870_device::do_SWAP_A(const uint8_t opbyte0)
+{
+ // SWAP A
+ handle_swap(REG_A);
+}
+
+void tlcs870_device::do_MUL_W_A(const uint8_t opbyte0)
+{
+ // MUL W,A
+ handle_mul(REG_WA);
+}
+
+void tlcs870_device::do_DIV_WA_C(const uint8_t opbyte0)
+{
+ // DIV WA,C
+ handle_div(REG_WA);
+}
+
+void tlcs870_device::do_RETI(const uint8_t opbyte0)
+{
+ // RETI
+ // Return from maskable interrupt service (how does this differ from RETN?)
+ m_sp.d += 3;
+ m_addr = RM16(m_sp.d - 2);
+ set_PSW(RM8(m_sp.d - 1));
+}
+
+void tlcs870_device::do_RET(const uint8_t opbyte0)
+{
+ // RET
+ m_sp.d += 2;
+ m_addr = RM16(m_sp.d - 1);
+};
+
+void tlcs870_device::do_POP_PSW(const uint8_t opbyte0)
+{
+ // POP PSW
+ m_sp.d += 2;
+ const uint16_t val = RM16(m_sp.d - 1);
+ set_PSW(val);
+}
+
+void tlcs870_device::do_PUSH_PSW(const uint8_t opbyte0)
+{
+ // PUSH PSW:
+ const uint16_t val = get_PSW();
+ WM16(m_sp.d - 1, val);
+ m_sp.d -= 2;
+}
+
+void tlcs870_device::do_DAA_A(const uint8_t opbyte0)
+{
+ // DAA A
+ uint8_t val = get_reg8(REG_A);
+
+ val = handle_DAA(val);
+
+ set_reg8(REG_A, val);
+}
+
+void tlcs870_device::do_DAS_A(const uint8_t opbyte0)
+{
+ // DAS A
+ uint8_t val = get_reg8(REG_A);
+
+ val = handle_DAS(val);
+
+ set_reg8(REG_A, val);
+}
+
+void tlcs870_device::do_CLR_CF(const uint8_t opbyte0)
+{
+ // CLR CF
+ clear_CF();
+ set_JF();
+}
+
+void tlcs870_device::do_SET_CF(const uint8_t opbyte0)
+{
+ // SET CF
+ set_CF();
+ clear_JF();
+}
+
+void tlcs870_device::do_CPL_CF(const uint8_t opbyte0)
+{
+ // CPL CF
+ if (is_CF())
+ {
+ set_JF();
+ clear_CF();
+ }
+ else
+ {
+ clear_JF();
+ set_CF();
+ }
+}
+
+void tlcs870_device::do_LD_RBS_n(const uint8_t opbyte0) // register bank switching
+{
+ // LD RBS,n
+ const uint8_t param = READ8();
+ m_RBS = param & 0x0f;
+ set_JF();
+}
+
+
+void tlcs870_device::do_INC_rr(const uint8_t opbyte0)
+{
+ // INC rr
+ const int reg = opbyte0 & 3;
+ uint16_t temp = get_reg16(reg);
+ temp++;
+ set_reg16(reg, temp);
+
+ if (temp == 0x0000)
+ {
+ set_ZF();
+ set_JF();
+ }
+ else
+ {
+ // do we clear?
+ clear_ZF();
+ clear_JF();
+ }
+}
+
+
+void tlcs870_device::do_LD_rr_mn(const uint8_t opbyte0)
+{
+ // LD rr,mn
+ const uint16_t val = READ16(); // 16-bit
+ set_reg16(opbyte0 & 3, val);
+ set_JF();
+}
+
+
+void tlcs870_device::do_DEC_rr(const uint8_t opbyte0)
+{
+ // DEC rr
+ const int reg = opbyte0 & 3;
+ uint16_t temp = get_reg16(reg);
+ temp--;
+ set_reg16(reg, temp);
+
+ if (temp == 0xffff)
+ {
+ set_JF();
+ }
+ else
+ {
+ // do we clear?
+ clear_JF();
+ }
+
+ if (temp == 0x0000) // check
+ {
+ set_ZF();
+ }
+ else
+ {
+ set_ZF();
+ }
+}
+
+
+void tlcs870_device::do_SHLC_A(const uint8_t opbyte0)
+{
+ // SHLC A
+ uint8_t val = get_reg8(REG_A);
+
+ val = handle_SHLC(val);
+
+ set_reg8(REG_A, val);
+}
+
+void tlcs870_device::do_SHRC_A(const uint8_t opbyte0)
+{
+ // SHRC A
+ uint8_t val = get_reg8(REG_A);
+
+ val = handle_SHRC(val);
+
+ set_reg8(REG_A, val);
+}
+
+void tlcs870_device::do_ROLC_A(const uint8_t opbyte0)
+{
+ // ROLC A
+ uint8_t val = get_reg8(REG_A);
+
+ val = handle_ROLC(val);
+
+ set_reg8(REG_A, val);
+}
+
+void tlcs870_device::do_RORC_A(const uint8_t opbyte0)
+{
+ // RORC A
+ uint8_t val = get_reg8(REG_A);
+
+ val = handle_RORC(val);
+
+ set_reg8(REG_A, val);
+}
+
+void tlcs870_device::do_INC_inx(const uint8_t opbyte0)
+{
+ // INC (x)
+ const uint16_t srcaddr = READ8();
+ uint8_t val = RM8(srcaddr);
+
+ val++;
+
+ if (val == 0)
+ {
+ set_ZF();
+ set_JF();
+ }
+ else
+ {
+ clear_ZF();
+ clear_JF();
+ }
+
+ // WRITE
+ WM8(srcaddr, val);
+}
+
+void tlcs870_device::do_INC_inHL(const uint8_t opbyte0)
+{
+ // INC (HL)
+ const uint16_t addr = get_reg16(REG_HL);
+ uint8_t val = RM8(addr);
+
+ val++;
+
+ if (val == 0)
+ {
+ set_ZF();
+ set_JF();
+ }
+ else
+ {
+ clear_ZF();
+ clear_JF();
+ }
+
+ WM8(addr, val);
+}
+
+void tlcs870_device::do_LD_A_inx(const uint8_t opbyte0)
+{
+ // LD A,(x)
+ const uint16_t srcaddr = READ8();
+ const uint8_t val = RM8(srcaddr);
+
+ set_reg8(REG_A, val);
+
+ set_JF();
+
+ if (val == 0x00) set_ZF();
+ else clear_ZF();
+}
+
+void tlcs870_device::do_LD_A_inHL(const uint8_t opbyte0)
+{
+ // LD A,(HL)
+ const uint16_t srcaddr = get_reg16(REG_HL);
+ const uint8_t val = RM8(srcaddr);
+
+ set_reg8(REG_A, val);
+
+ set_JF();
+
+ if (val == 0x00) set_ZF();
+ else clear_ZF();
+}
+
+void tlcs870_device::do_LD_inx_iny(const uint8_t opbyte0)
+{
+ // LD (x),(y)
+ const uint16_t srcaddr = READ8();
+ const uint16_t dstaddr = READ8();
+
+ const uint8_t val = RM8(srcaddr);
+
+ set_JF();
+
+ if (val == 0x00) set_ZF();
+ else clear_ZF();
+
+ WM8(dstaddr, val);
+}
+
+void tlcs870_device::do_DEC_inx(const uint8_t opbyte0)
+{
+ // DEC (x)
+ const uint16_t addr = READ8();
+
+ uint8_t temp = RM8(addr);
+ temp--;
+ WM8(addr, temp);
+
+ if (temp == 0xff)
+ {
+ set_JF();
+ }
+ else
+ {
+ // do we clear?
+ clear_JF();
+ }
+
+ if (temp == 0x00)
+ {
+ set_ZF();
+ }
+ else
+ {
+ set_ZF();
+ }
+}
+
+void tlcs870_device::do_DEC_inHL(const uint8_t opbyte0)
+{
+ // DEC (HL)
+ const uint16_t addr = get_reg16(REG_HL);
+
+ uint8_t temp = RM8(addr);
+ temp--;
+ WM8(addr, temp);
+
+ if (temp == 0xff)
+ {
+ set_JF();
+ }
+ else
+ {
+ // do we clear?
+ clear_JF();
+ }
+
+ if (temp == 0x00)
+ {
+ set_ZF();
+ }
+ else
+ {
+ set_ZF();
+ }
+}
+
+void tlcs870_device::do_LD_inx_A(const uint8_t opbyte0)
+{
+ // LD (x),A
+ const uint16_t dstaddr = READ8();
+ const uint8_t val = get_reg8(REG_A);
+
+ set_JF();
+
+ if (val == 0x00) set_ZF();
+ else clear_ZF();
+
+ WM8(dstaddr, val);
+}
+
+void tlcs870_device::do_LD_inHL_A(const uint8_t opbyte0)
+{
+ // LD (HL),A
+ const uint8_t val = get_reg8(REG_A);
+
+ set_JF();
+
+ const uint16_t addr = get_reg16(REG_HL);
+ WM8(addr, val);
+}
+
+void tlcs870_device::do_LD_inx_n(const uint8_t opbyte0)
+{
+ // LD (x),n
+ const uint16_t dstaddr = READ8();
+ const uint8_t val = READ8();
+
+ set_JF();
+
+ WM8(dstaddr, val);
+}
+
+void tlcs870_device::do_LD_inHL_n(const uint8_t opbyte0)
+{
+ // LD (HL),n
+ const uint8_t val = READ8();
+ const uint16_t addr = get_reg16(REG_HL);
+
+ set_JF();
+
+ WM8(addr, val);
+}
+
+void tlcs870_device::do_CLR_inx(const uint8_t opbyte0)
+{
+ // CLR (x)
+ const uint16_t addr = READ8();
+
+ WM8(addr, 0);
+
+ set_JF();
+}
+
+void tlcs870_device::do_CLR_inHL(const uint8_t opbyte0)
+{
+ // CLR (HL)
+ const uint16_t addr = get_reg16(REG_HL);
+ WM8(addr, 0);
+
+ set_JF();
+}
+
+void tlcs870_device::do_LD_r_n(const uint8_t opbyte0)
+{
+ // LD r,n
+ const uint8_t param1 = opbyte0 & 7;
+ const uint8_t param2 = READ8();
+
+ set_reg8(param1, param2);
+
+ set_JF();
+}
+
+void tlcs870_device::do_SET_inxbit(const uint8_t opbyte0)
+{
+ // SET (x).b
+ // 0100 0bbb xxxx xxxx
+
+ // (opbyte0 == 0x40) && (opval == 0x3a) is EI
+ const uint8_t srcaddr = READ8();
+
+ uint8_t val = RM8(srcaddr);
+ const uint8_t bitpos = opbyte0 & 0x7;
+
+ const int bitused = (1 << bitpos);
+
+ if (val & bitused) // Zero flag gets set based on original value of bit?
+ {
+ clear_ZF();
+ clear_JF(); // 'Z' (so copy Z flag?)
+ }
+ else
+ {
+ set_ZF();
+ set_JF(); // 'Z'
+ }
+
+ val |= bitused;
+
+ WM8(srcaddr, val);
+}
+
+void tlcs870_device::do_CLR_inxbit(const uint8_t opbyte0)
+{
+ // CLR (x).b
+ // 0100 1bbb xxxx xxxx
+
+ // (opbyte0 == 0x48) && (opval == 0x3a) is DI
+ const uint8_t srcaddr = READ8();
+
+ uint8_t val = RM8(srcaddr);
+ const uint8_t bitpos = opbyte0 & 0x7;
+
+ const int bitused = (1 << bitpos);
+
+ if (val & bitused) // Zero flag gets set based on original value of bit?
+ {
+ clear_ZF();
+ clear_JF(); // 'Z' (so copy Z flag?)
+ }
+ else
+ {
+ set_ZF();
+ set_JF(); // 'Z'
+ }
+
+ val &= ~bitused;
+
+ WM8(srcaddr, val);
+}
+
+void tlcs870_device::do_LD_A_r(const uint8_t opbyte0)
+{
+ // LD A,r
+ // 0101 0rrr
+ const uint8_t val = get_reg8(opbyte0 & 0x7);
+ set_reg8(REG_A, val);
+
+ set_JF();
+
+ if (val == 0x00) set_ZF();
+ else clear_ZF();
+}
+
+void tlcs870_device::do_LD_r_A(const uint8_t opbyte0)
+{
+ // LD r,A
+ // 0101 1rrr
+ const uint8_t val = get_reg8(REG_A);
+ set_reg8(opbyte0 & 0x7, val);
+
+ set_JF();
+
+ if (val == 0x00) set_ZF();
+ else clear_ZF();
+}
+
+void tlcs870_device::do_INC_r(const uint8_t opbyte0)
+{
+ // INC r
+ const int reg = opbyte0 & 7;
+ uint8_t temp = get_reg8(reg);
+ temp++;
+ set_reg8(reg, temp);
+
+ if (temp == 0x00)
+ {
+ set_ZF();
+ set_JF();
+ }
+ else
+ {
+ // do we clear?
+ clear_ZF();
+ clear_JF();
+ }
+}
+
+void tlcs870_device::do_DEC_r(const uint8_t opbyte0)
+{
+ // DEC r
+ const int reg = opbyte0 & 7;
+ uint8_t temp = get_reg8(reg);
+ temp--;
+ set_reg8(reg, temp);
+
+ if (temp == 0xff)
+ {
+ set_JF();
+ }
+ else
+ {
+ // do we clear?
+ clear_JF();
+ }
+
+ if (temp == 0x00)
+ {
+ set_ZF();
+ }
+ else
+ {
+ set_ZF();
+ }
+}
+
+void tlcs870_device::do_JRS_T_a(const uint8_t opbyte0)
+{
+ // JRS T,a
+ const int param1 = 6;
+
+ int val = opbyte0 & 0x1f;
+ if (val & 0x10) val -= 0x20;
+
+ const bool takejump = check_jump_condition(param1);
+
+ if (takejump)
+ {
+ m_addr = m_tmppc + 2 + val;
+ set_JF();
+ }
+}
+
+void tlcs870_device::do_JRS_F_a(const uint8_t opbyte0)
+{
+ // JRS F,a
+ const int param1 = 7;
+
+ int val = opbyte0 & 0x1f;
+ if (val & 0x10) val -= 0x20;
+
+ const bool takejump = check_jump_condition(param1);
+
+ if (takejump)
+ {
+ m_addr = m_tmppc + 2 + val;
+ set_JF();
+ }
+}
+
+void tlcs870_device::do_CALLV_n(const uint8_t opbyte0)
+{
+ // CALLV n
+ const uint16_t addr = 0xffc0 + ((opbyte0 & 0xf) * 2);
+
+ WM16(m_sp.d - 1, m_addr);
+ m_sp.d -= 2;
+
+ m_addr = addr;
+}
+
+void tlcs870_device::do_JR_cc_a(const uint8_t opbyte0)
+{
+ // JR cc,a
+ const int param1 = opbyte0 & 0x7;
+
+ int val = READ8();
+ if (val & 0x80) val -= 0x100;
+
+ bool takejump = check_jump_condition(param1);
+
+ if (takejump)
+ {
+ m_addr = m_tmppc + 2 + val;
+ set_JF();
+ }
+}
+
+void tlcs870_device::do_LD_CF_inxbit(const uint8_t opbyte0)
+{
+ // LD CF, (x).b aka TEST (x).b
+ const uint16_t srcaddr = READ8();
+ const uint8_t val = RM8(srcaddr);
+ const uint8_t bitpos = opbyte0 & 0x7;
+
+ const int bitused = (1 << bitpos);
+
+ uint8_t bit = val & bitused;
+
+ bit ? set_CF() : clear_CF();
+ // for this optype of operation ( LD CF, *.b ) the Jump Flag always ends up the inverse of the Carry Flag
+ bit ? clear_JF() : set_JF();
+}
+
+void tlcs870_device::do_LD_SP_mn(const uint8_t opbyte0)
+{
+ // LD SP,mn
+ // Flags / Cycles 1--- / 3
+ const uint16_t param = READ16();
+ m_sp.d = param;
+ set_JF();
+}
+
+void tlcs870_device::do_JR_a(const uint8_t opbyte0)
+{
+ // JR a
+ int val = READ8();
+ if (val & 0x80) val -= 0x100;
+
+ m_addr = m_tmppc + 2 + val;;
+
+ set_JF();
+}
+
+void tlcs870_device::do_CALL_mn(const uint8_t opbyte0)
+{
+ // CALL mn
+ const uint16_t addr = READ16();
+
+ WM16(m_sp.d - 1, m_addr);
+ m_sp.d -= 2;
+
+ m_addr = addr;
+}
+
+void tlcs870_device::do_CALLP_n(const uint8_t opbyte0)
+{
+ // CALLP n
+ const uint16_t addr = READ8() + 0xff00;
+
+ WM16(m_sp.d - 1, m_addr);
+ m_sp.d -= 2;
+
+ m_addr = addr;
+}
+
+void tlcs870_device::do_JP_mn(const uint8_t opbyte0)
+{
+ // JP mn
+ const int param2 = READ16();
+ m_addr = param2;
+ set_JF();
+}
+
+void tlcs870_device::do_ff_opcode(const uint8_t opbyte0)
+{
+ // SWI
+ handle_take_interrupt(0x0e);
+}
+
+/**********************************************************************************************************************/
+// ALU Operations
+/**********************************************************************************************************************/
+
+void tlcs870_device::do_ALUOP_A_n(const uint8_t opbyte0)
+{
+ // (ALU OP) A,n
+ // 0111 0000 nnnn nnnn ADDC A,n
+ // 0111 0001 nnnn nnnn ADD A,n
+
+ const int aluop = (opbyte0 & 0x7);
+ const uint8_t val = READ8();
+
+ const uint8_t result = do_alu(aluop, get_reg8(REG_A), val);
+
+ if (aluop != 0x07) // CMP doesn't write back
+ {
+ set_reg8(REG_A, result);
+ }
+}
+
+void tlcs870_device::do_ALUOP_A_inx(const uint8_t opbyte0)
+{
+ // (ALU OP) A,(x)
+ // 0111 1000 nnnn nnnn ADDC A,(x)
+ // 0111 1001 nnnn nnnn ADD A,(x)
+
+ const int aluop = (opbyte0 & 0x7);
+ const uint16_t addr = READ8();
+ const uint8_t val = RM8(addr);
+
+ const uint8_t result = do_alu(aluop, get_reg8(REG_A), val);
+
+ if (aluop != 0x07) // CMP doesn't write back
+ {
+ set_reg8(REG_A, result);
+ }
+}
+
+/**********************************************************************************************************************/
+// 16-bit loads
+/**********************************************************************************************************************/
+
+void tlcs870_device::do_LDW_inx_mn(const uint8_t opbyte0)
+{
+ // LDW (x),mn
+ const uint16_t dstaddr = READ8();
+
+ const uint16_t val = READ16();
+
+ WM16(dstaddr, val);
+
+ set_JF(); // only JF changes
+}
+
+void tlcs870_device::do_LDW_inHL_mn(const uint8_t opbyte0)
+{
+ // LDW (HL),mn
+ // m_op = LDW;
+ const uint16_t dstaddr = get_reg16(REG_HL);
+
+ const uint16_t val = READ16();
+
+ WM16(dstaddr, val);
+
+ set_JF(); // only JF changes
+}
diff --git a/src/devices/cpu/tlcs870/tlcs870_ops_dst.cpp b/src/devices/cpu/tlcs870/tlcs870_ops_dst.cpp
new file mode 100644
index 00000000000..6eee0ff72bc
--- /dev/null
+++ b/src/devices/cpu/tlcs870/tlcs870_ops_dst.cpp
@@ -0,0 +1,127 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+/*************************************************************************************************************
+
+ Toshiba TLCS-870 Series MCUs
+
+ (dst) prefix ops (f0 to f7 subtable)
+
+ (dst) address depends on the first byte of the opcode
+
+ F0 (x)
+ F1 invalid (would be (PC+A) based on the src table, check for undefined behavior?)
+ F2 (DE)
+ F3 (HL)
+ F4 (HL+d)
+ F5 invalid (would be (HL+) based on the src table, check for undefined behavior?)
+ F6 (-HL)
+
+ note, in cases where the address is an immediate value, not a register (x) and (HL+d) the
+ immediate value is directly after the first byte of the opcode
+
+*************************************************************************************************************/
+
+#include "emu.h"
+#include "tlcs870.h"
+#include "tlcs870d.h"
+#include "debugger.h"
+
+// Main dispatch handlers for these
+
+void tlcs870_device::do_f0_opcode(const uint8_t opbyte0)
+{
+ // 1111 0000 xxxx xxxx 0101 0rrr
+ // destination memory prefix (dst)
+ const uint16_t dstaddr = get_addr((opbyte0 & 0x7), READ8());
+ do_f0_to_f7_opcode(opbyte0, dstaddr);
+}
+
+void tlcs870_device::do_f2_to_f3_opcode(const uint8_t opbyte0)
+{
+ // 0xf2: 1111 001p 0101 0rrr
+ // 0xf3: 1111 001p 0101 0rrr
+ // destination memory prefix (dst)
+ const uint16_t dstaddr = get_addr((opbyte0 & 0x7), 0);
+ do_f0_to_f7_opcode(opbyte0, dstaddr);
+}
+
+
+void tlcs870_device::do_f4_opcode(const uint8_t opbyte0)
+{
+ // 0xf4: 1111 0100 dddd dddd 0101 0rrr
+ // destination memory prefix (dst)
+ const uint16_t dstaddr = get_addr((opbyte0 & 0x7), READ8());
+ do_f0_to_f7_opcode(opbyte0, dstaddr);
+}
+
+void tlcs870_device::do_f6_to_f7_opcode(const uint8_t opbyte0)
+{
+ // 0xf6: 1110 0110 0101 0rrr
+ // 0xf7: 1111 0111 0101 0rrr
+ // destination memory prefix (dst)
+ const uint16_t dstaddr = get_addr((opbyte0 & 0x7), 0);
+ do_f0_to_f7_opcode(opbyte0, dstaddr);
+}
+
+// f0 - f7 use this table
+// note, same table is shown as above in manual, there's no overlap between src/dest, but they're not compatible
+void tlcs870_device::do_f0_to_f7_opcode(const uint8_t opbyte0, const uint16_t dstaddr)
+{
+ const uint8_t opbyte1 = READ8();
+
+ switch (opbyte1)
+ {
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ do_LD_indst_rr(opbyte0, opbyte1, dstaddr); break;
+ case 0x2c:
+ do_LD_indst_n(opbyte0, opbyte1, dstaddr); break;
+ case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
+ do_LD_indst_r(opbyte0, opbyte1, dstaddr); break;
+ default:
+ do_f0_to_f7_oprand_illegal_opcode(opbyte0, opbyte1, dstaddr); break;
+ }
+}
+
+// Actual handlers
+
+/**********************************************************************************************************************/
+// (16-bit)
+/**********************************************************************************************************************/
+
+void tlcs870_device::do_LD_indst_rr(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr)
+{
+ // LD (dst),rr
+ // (dst) can only be (x) (pp) or (HL+d) ? not (HL+) or (-HL) ?
+ const uint16_t val = get_reg16(opbyte1 & 0x3);
+ WM16(dstaddr, val);
+
+ set_JF();
+}
+
+/**********************************************************************************************************************/
+// (8-bit)
+/**********************************************************************************************************************/
+
+void tlcs870_device::do_LD_indst_n(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr)
+{
+ // LD (dst),n
+ // (dst) can only be (DE), (HL+), (-HL), or (HL+d) because (x) and (HL) are redundant encodings?
+ const uint16_t n = READ8();
+ WM8(dstaddr, n);
+
+ set_JF();
+}
+
+void tlcs870_device::do_LD_indst_r(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr)
+{
+ // LD (dst),r
+ const uint8_t reg = get_reg8(opbyte1 & 0x7);
+ WM8(dstaddr, reg);
+
+ set_JF();
+}
+
+void tlcs870_device::do_f0_to_f7_oprand_illegal_opcode(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr)
+{
+ logerror("illegal dst prefix opcode %02x %02x (dst addr %04x)\n", opbyte0, opbyte1, dstaddr);
+}
diff --git a/src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp b/src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp
new file mode 100644
index 00000000000..e2a11b57661
--- /dev/null
+++ b/src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp
@@ -0,0 +1,500 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+/*************************************************************************************************************
+
+ Toshiba TLCS-870 Series MCUs
+
+*************************************************************************************************************/
+
+#include "emu.h"
+#include "tlcs870.h"
+#include "tlcs870d.h"
+#include "debugger.h"
+
+
+// General Helpers
+
+const uint8_t tlcs870_device::get_reg8(const int reg)
+{
+ return m_intram[((m_RBS & 0xf) * 8) + (reg & 0x7)];
+}
+
+void tlcs870_device::set_reg8(const int reg, uint8_t val)
+{
+ m_intram[((m_RBS & 0xf) * 8) + (reg & 0x7)] = val;
+}
+
+const uint16_t tlcs870_device::get_reg16(const int reg)
+{
+ uint16_t res = 0;
+ res |= get_reg8(((reg & 0x3) * 2) + 1) << 8;
+ res |= get_reg8(((reg & 0x3) * 2) + 0) << 0;
+ return res;
+}
+
+void tlcs870_device::set_reg16(const int reg, uint16_t val)
+{
+ set_reg8(((reg & 0x3) * 2) + 1, (val & 0xff00) >> 8);
+ set_reg8(((reg & 0x3) * 2) + 0, (val & 0x00ff) >> 0);
+}
+
+const uint8_t tlcs870_device::get_PSW()
+{
+ return (m_F & 0xf0) | (m_RBS & 0x0f);
+}
+
+void tlcs870_device::set_PSW(uint8_t data)
+{
+ // used by the push/pop opcodes, flags can't be written by memory access
+ m_F = data & 0xf0;
+ m_RBS = data & 0xf0;
+}
+
+void tlcs870_device::handle_div(const int reg)
+{
+ const uint16_t temp16 = get_reg16(reg);
+ const uint8_t temp8 = get_reg8(REG_C);
+
+ if (!temp8)
+ {
+ // divide by zero
+ set_CF();
+ // does the ZF change too?
+ }
+ else
+ {
+ const uint16_t tempres16 = temp16 / temp8;
+ const uint8_t tempres8 = temp16 % temp8;
+
+ const uint16_t tempfull = (tempres8 << 8) | (tempres16 & 0x00ff);
+
+ set_reg16(reg, tempfull);
+
+ if (tempres16 & 0xff00)
+ {
+ // result is also 'undefined' in this case
+ set_CF();
+ }
+ else
+ {
+ clear_CF();
+ }
+
+ if (!tempres8)
+ {
+ set_ZF();
+ set_JF();
+ }
+ else
+ {
+ clear_ZF();
+ clear_JF();
+ }
+ }
+}
+
+void tlcs870_device::handle_mul(const int reg)
+{
+ const uint16_t temp16 = get_reg16(reg);
+ const uint16_t tempres = (temp16 & 0xff) * ((temp16 & 0xff00) >> 8);
+ set_reg16(reg, temp16);
+
+ if (!(tempres & 0xff00))
+ {
+ set_ZF();
+ set_JF();
+ }
+ else
+ {
+ clear_ZF();
+ clear_JF();
+ }
+}
+
+void tlcs870_device::handle_swap(const int reg)
+{
+ uint8_t temp = get_reg8(reg);
+ temp = ((temp & 0x0f) << 4) | ((temp & 0xf0) >> 4);
+ set_reg8(reg, temp);
+
+ set_JF();
+}
+
+
+uint16_t tlcs870_device::get_addr(uint16_t opbyte0, uint16_t val)
+{
+ uint16_t addr = 0x0000;
+
+ switch (opbyte0)
+ {
+ case ADDR_IN_IMM_X:
+ addr = val;
+ break;
+ case ADDR_IN_PC_PLUS_REG_A:
+ addr = m_tmppc + 2 + get_reg8(REG_A);
+ break;
+ case ADDR_IN_DE:
+ addr = get_reg16(REG_DE);
+ break;
+ case ADDR_IN_HL:
+ addr = get_reg16(REG_HL);
+ break;
+ case ADDR_IN_HL_PLUS_IMM_D:
+ addr = get_reg16(REG_HL) + val;
+ break;
+ case ADDR_IN_HL_PLUS_REG_C:
+ addr = get_reg16(REG_HL) + get_reg8(REG_C);
+ break;
+ case ADDR_IN_HLINC:
+ {
+ uint16_t tmpHL = get_reg16(REG_HL);
+ addr = tmpHL;
+ tmpHL++;
+ set_reg16(REG_HL, tmpHL);
+ break;
+ }
+ case ADDR_IN_DECHL:
+ {
+ uint16_t tmpHL = get_reg16(REG_HL);
+ tmpHL--;
+ set_reg16(REG_HL, tmpHL);
+ addr = tmpHL;
+ break;
+ }
+ }
+
+ return addr;
+}
+
+const bool tlcs870_device::check_jump_condition(int param1)
+{
+ bool takejump = true;
+
+ switch (param1)
+ {
+ case COND_EQ_Z:
+ if (is_ZF() == 1) takejump = true;
+ else takejump = false;
+ break;
+
+ case COND_NE_NZ:
+ if (is_ZF() == 0) takejump = true;
+ else takejump = false;
+ break;
+
+ case COND_LT_CS:
+ if (is_CF() == 1) takejump = true;
+ else takejump = false;
+ break;
+
+ case COND_GE_CC:
+ if (is_CF() == 0) takejump = true;
+ else takejump = false;
+ break;
+
+ case COND_LE:
+ if ((is_CF() || is_ZF()) == 1) takejump = true;
+ else takejump = false;
+ break;
+
+ case COND_GT:
+ if ((is_CF() || is_ZF()) == 0) takejump = true;
+ else takejump = false;
+ break;
+
+ case COND_T:
+ if (is_JF() == 1) takejump = true;
+ else takejump = false;
+ break;
+
+ case COND_F:
+ if (is_JF() == 0) takejump = true;
+ else takejump = false;
+ break;
+ }
+
+ return takejump;
+}
+
+
+uint16_t tlcs870_device::do_alu(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();
+ break;
+
+ case 0x1: // ADD
+ result = param1 + param2;
+ break;
+
+ case 0x2: // SUBB
+ result = param1 - param2;
+ result -= is_CF();
+ break;
+
+ case 0x3: // SUB
+ result = param1 - param2;
+ break;
+
+ case 0x4: // AND
+ result = param1 & param2;
+ break;
+
+ case 0x5: // XOR
+ result = param1 ^ param2;
+ break;
+
+ case 0x6: // OR
+ result = param1 | param2;
+ break;
+
+ case 0x7: // CMP
+ if (param1 < param2)
+ {
+ set_CF();
+ }
+ else
+ {
+ clear_CF();
+ }
+ break;
+
+ }
+
+ return result;
+}
+
+
+uint8_t tlcs870_device::handle_SHLC(uint8_t val)
+{
+ if (val & 0x80)
+ {
+ set_CF();
+ }
+ else
+ {
+ clear_CF();
+ }
+
+ val = (val << 1);
+
+ // JF gets set to CF
+ if (is_CF())
+ {
+ set_JF();
+ }
+ else
+ {
+ clear_JF();
+ }
+
+ if (val == 0)
+ {
+ set_ZF();
+ }
+ else
+ {
+ clear_ZF();
+ }
+
+ return val;
+}
+
+
+uint8_t tlcs870_device::handle_SHRC(uint8_t val)
+{
+ if (val & 0x01)
+ {
+ set_CF();
+ }
+ else
+ {
+ clear_CF();
+ }
+
+ val = (val >> 1);
+
+ // JF gets set to CF
+ if (is_CF())
+ {
+ set_JF();
+ }
+ else
+ {
+ clear_JF();
+ }
+
+ if (val == 0)
+ {
+ set_ZF();
+ }
+ else
+ {
+ clear_ZF();
+ }
+
+ return val;
+}
+
+uint8_t tlcs870_device::handle_DAS(uint8_t val)
+{
+ if (((val & 0x0f) > 9) || (is_HF() == 1))
+ {
+ val = val - 0x06;
+ set_HF();
+ }
+ else
+ {
+ clear_HF();
+ }
+
+ if ((val > 0x9f) || (is_CF() == 1))
+ {
+ val = val - 0x60;
+ set_CF();
+ }
+ else
+ {
+ clear_CF();
+ }
+
+ return val;
+}
+
+uint8_t tlcs870_device::handle_DAA(uint8_t val)
+{
+ if (((val & 0x0f) > 9) || (is_HF() == 1))
+ {
+ val = val + 0x06;
+ set_HF();
+ }
+ else
+ {
+ clear_HF();
+ }
+
+ if ((val > 0x9f) || (is_CF() == 1))
+ {
+ val = val + 0x60;
+ set_CF();
+ }
+ else
+ {
+ clear_CF();
+ }
+
+ return val;
+}
+
+uint8_t tlcs870_device::handle_ROLC(uint8_t val)
+{
+ const int tempcarry = is_CF();
+
+ if (val & 0x80)
+ {
+ set_CF();
+ }
+ else
+ {
+ clear_CF();
+ }
+
+ val = (val << 1) | tempcarry;
+
+ // JF gets set to CF
+ if (is_CF())
+ {
+ set_JF();
+ }
+ else
+ {
+ clear_JF();
+ }
+
+ if (val == 0)
+ {
+ set_ZF();
+ }
+ else
+ {
+ clear_ZF();
+ }
+
+ return val;
+}
+
+uint8_t tlcs870_device::handle_RORC(uint8_t val)
+{
+ const int tempcarry = (is_CF()) << 7;
+
+ if (val & 0x01)
+ {
+ set_CF();
+ }
+ else
+ {
+ clear_CF();
+ }
+
+ val = (val >> 1) | tempcarry;
+
+ // JF gets set to CF
+ if (is_CF())
+ {
+ set_JF();
+ }
+ else
+ {
+ clear_JF();
+ }
+
+ if (val == 0)
+ {
+ set_ZF();
+ }
+ else
+ {
+ clear_ZF();
+ }
+
+ return val;
+}
+
+/*
+
+(Priority Low - 15)
+FFE0 INT5 (External Interrupt 5)
+FFE2 INTTC2 (16-bit TC2 Interrupt)
+FFE4 INTSIO2 (Serial Interface 2 Interrupt)
+FFE6 INT4 (External Interrupt 4)
+FFE8 INT3 (External Interrupt 3)
+FFEA INTTC4 (8-bit TC4 Interrupt)
+FFEC INTSIO1 (Serial Interface 1 Interrupt)
+FFEE INTTC3 (8-bit TC3 Interrupt)
+FFF0 INT2 (External Interrupt 2)
+FFF2 INTTBT (Time Base Timer Interrupt)
+FFF4 INT1 (External Interrupt 1)
+FFF6 INTTC1 (16-bit TC1 Interrupt)
+FFF8 INT0 (External Interrupt 0)
+FFFA INTWDT (Watchdog Timer Interrupt)
+FFFC INTSW (Software Interrupt)
+FFFE RESET (Reset Vector)
+(Priority High - 0)
+
+*/
+
+void tlcs870_device::handle_take_interrupt(int level)
+{
+ WM8(m_sp.d - 1, get_PSW());
+ WM16(m_sp.d - 2, m_addr);
+ m_sp.d -= 3;
+
+ m_addr = RM16(0xffe0 + ((level &0xf)*2));
+}
+
diff --git a/src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp b/src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp
new file mode 100644
index 00000000000..e9073bc4c49
--- /dev/null
+++ b/src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp
@@ -0,0 +1,760 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+/*************************************************************************************************************
+
+ Toshiba TLCS-870 Series MCUs
+
+ (reg) prefix ops (e8 to ef subtable)
+
+ (reg) implies one of the follow registers
+
+ (8-bit mode operations)
+ E8 A
+ E9 W
+ EA C
+ EB B
+ EC E
+ ED D
+ EE L
+ EF H
+
+ (16-bit mode operations)
+ E8 invalid
+ E9 invalid
+ EA invalid
+ EB invalid
+ EC WA
+ ED BC
+ EE DE
+ EF HL
+
+ (RETN operation - special)
+ E8 RETN
+ E9-EF invalid
+
+*************************************************************************************************************/
+
+#include "emu.h"
+#include "tlcs870.h"
+#include "tlcs870d.h"
+#include "debugger.h"
+
+// Main dispatch handlers for these
+
+void tlcs870_device::do_regprefixtype_opcode(const uint8_t opbyte0)
+{
+ // register prefix: g/gg
+ uint8_t opbyte1 = READ8();
+
+ switch (opbyte1)
+ {
+ case 0x01:
+ do_SWAP_g(opbyte0, opbyte1); break;
+ case 0x02:
+ do_MUL_gg(opbyte0, opbyte1); break;
+ case 0x03:
+ do_DIV_gg_C(opbyte0, opbyte1); break;
+ case 0x04:
+ do_RETN(opbyte0, opbyte1); break;
+ case 0x06:
+ do_POP_gg(opbyte0, opbyte1); break;
+ case 0x07:
+ do_PUSH_gg(opbyte0, opbyte1); break;
+ case 0x0a:
+ do_DAA_g(opbyte0, opbyte1); break;
+ case 0x0b:
+ do_DAS_g(opbyte0, opbyte1); break;
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ do_XCH_rr_gg(opbyte0, opbyte1); break;
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ do_LD_rr_gg(opbyte0, opbyte1); break;
+ case 0x1c:
+ do_SHLC_g(opbyte0, opbyte1); break;
+ case 0x1d:
+ do_SHRC_g(opbyte0, opbyte1); break;
+ case 0x1e:
+ do_ROLC_g(opbyte0, opbyte1); break;
+ case 0x1f:
+ do_RORC_g(opbyte0, opbyte1); break;
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ do_ALUOP_WA_gg(opbyte0, opbyte1); break;
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ do_ALUOP_gg_mn(opbyte0, opbyte1); break;
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
+ do_SET_gbit(opbyte0, opbyte1); break;
+ case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ do_CLR_gbit(opbyte0, opbyte1); break;
+ case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+ do_LD_r_g(opbyte0, opbyte1); break;
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
+ do_ALUOP_A_g(opbyte0, opbyte1); break;
+ case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
+ do_ALUOP_g_A(opbyte0, opbyte1); break;
+ case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
+ do_ALUOP_g_n(opbyte0, opbyte1); break;
+ case 0x82: case 0x83:
+ do_SET_inppbit(opbyte0, opbyte1); break;
+ case 0x8a: case 0x8b:
+ do_CLR_inppbit(opbyte0, opbyte1); break;
+ case 0x92: case 0x93:
+ do_CPL_inppbit(opbyte0, opbyte1); break;
+ case 0x9a: case 0x9b:
+ do_LD_inppbit_CF(opbyte0, opbyte1); break;
+ case 0x9e: case 0x9f:
+ do_LD_CF_inppbit(opbyte0, opbyte1); break;
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ do_XCH_r_g(opbyte0, opbyte1); break;
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ do_CPL_gbit(opbyte0, opbyte1); break;
+ case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ do_LD_gbit_CF(opbyte0, opbyte1); break;
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ do_XOR_CF_gbit(opbyte0, opbyte1); break;
+ case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
+ do_LD_CF_gbit(opbyte0, opbyte1); break;
+ case 0xfa:
+ do_LD_SP_gg(opbyte0, opbyte1); break;
+ case 0xfb:
+ do_LD_gg_SP(opbyte0, opbyte1); break;
+ case 0xfc:
+ do_CALL_gg(opbyte0, opbyte1); break;
+ case 0xfe:
+ do_JP_gg(opbyte0, opbyte1); break;
+
+ default:
+ do_regprefixtype_oprand_illegal(opbyte0, opbyte1); break;
+ }
+}
+
+// Actual handlers
+
+/**********************************************************************************************************************/
+// (Special)
+/**********************************************************************************************************************/
+
+void tlcs870_device::do_regprefixtype_oprand_illegal(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ logerror("illegal reg prefix opcode %02x %02x\n", opbyte0, opbyte1);
+}
+
+
+void tlcs870_device::do_RETN(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // with E8 only
+ if (opbyte0 == 0xe8)
+ {
+ // RETN
+ // Return from non-maskable interrupt service (how does this differ from RETI?)
+ m_sp.d += 3;
+ m_addr = RM16(m_sp.d - 2);
+ set_PSW(RM8(m_sp.d - 1));
+ }
+ else
+ {
+ do_regprefixtype_oprand_illegal(opbyte0, opbyte1);
+ }
+}
+
+/**********************************************************************************************************************/
+// (8-bit)
+/**********************************************************************************************************************/
+
+void tlcs870_device::do_SWAP_g(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // SWAP g
+ const uint8_t reg = opbyte0 & 0x7;
+ handle_swap(reg);
+}
+
+void tlcs870_device::do_DAA_g(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // DAA g
+ // 1110 1ggg 0000 1010
+ uint8_t val = get_reg8(opbyte0 & 0x7);
+
+ val = handle_DAA(val);
+
+ set_reg8(opbyte0 & 0x7, val);
+}
+
+
+void tlcs870_device::do_DAS_g(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // DAS g
+ // 1110 1ggg 0000 1011
+ uint8_t val = get_reg8(opbyte0 & 0x7);
+
+ val = handle_DAS(val);
+
+ set_reg8(opbyte0 & 0x7, val);
+}
+
+
+void tlcs870_device::do_SHLC_g(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // SHLC g
+ // Logical Shift Left with Carry Flag
+ uint8_t val = get_reg8(opbyte0 & 0x7);
+
+ val = handle_SHLC(val);
+
+ set_reg8(opbyte0 & 0x7, val);
+}
+
+void tlcs870_device::do_SHRC_g(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // SHRC g
+ // Logical Shift Right with Carry Flag
+
+ uint8_t val = get_reg8(opbyte0 & 0x7);
+
+ val = handle_SHRC(val);
+
+ set_reg8(opbyte0 & 0x7, val);
+}
+
+void tlcs870_device::do_ROLC_g(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // ROLC g
+ // Rotate Left through Carry flag
+ uint8_t val = get_reg8(opbyte0 & 0x7);
+
+ val = handle_ROLC(val);
+
+ set_reg8(opbyte0 & 0x7, val);
+
+}
+
+void tlcs870_device::do_RORC_g(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // RORC g
+ // Rotate Right through Carry flag
+ uint8_t val = get_reg8(opbyte0 & 0x7);
+
+ val = handle_RORC(val);
+
+ set_reg8(opbyte0 & 0x7, val);
+}
+
+
+void tlcs870_device::do_LD_r_g(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // LD r,g
+ // 1110 1ggg 0101 1rrr
+ const uint8_t val = get_reg8(opbyte0 & 0x7);
+ set_reg8(opbyte1 & 0x7, val);
+
+ set_JF();
+
+ if (val == 0x00) set_ZF();
+ else clear_ZF();
+}
+
+void tlcs870_device::do_XCH_r_g(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // XCH r,g
+ // 1110 1ggg 1010 1rrr
+ const uint8_t val = get_reg8(opbyte0 & 0x7);
+ const uint8_t r = get_reg8(opbyte1 & 0x7);
+
+ set_reg8(opbyte1 & 0x7, val);
+ set_reg8(opbyte0 & 0x7, r);
+
+ set_JF();
+
+ if (val == 0x00) set_ZF();
+ else clear_ZF();
+}
+
+/**********************************************************************************************************************/
+// (ALU handlers)
+/**********************************************************************************************************************/
+
+void tlcs870_device::do_ALUOP_A_g(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // (ALU OP) A,g
+ /*
+ 1110 1ggg 0110 0000 ADDC A,g
+ 1110 1ggg 0110 0001 ADD A,g
+ 1110 1ggg 0110 0010 SUBB A,g
+ 1110 1ggg 0110 0011 SUB A,g
+ 1110 1ggg 0110 0100 AND A,g
+ 1110 1ggg 0110 0101 XOR A,g
+ 1110 1ggg 0110 0110 OR A,g
+ 1110 1ggg 0110 0111 CMP A,g
+ */
+
+ const int aluop = (opbyte1 & 0x7);
+
+ const uint8_t result = do_alu(aluop, get_reg8(REG_A), get_reg8(opbyte0 & 0x7));
+
+ if (aluop != 0x07) // CMP doesn't write back
+ {
+ set_reg8(REG_A, result);
+ }
+}
+
+void tlcs870_device::do_ALUOP_g_A(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // (ALU OP) g,A
+ /*
+ 1110 1ggg 0110 1000 ADDC A,g
+ 1110 1ggg 0110 1001 ADD A,g
+ 1110 1ggg 0110 1010 SUBB A,g
+ 1110 1ggg 0110 1011 SUB A,g
+ 1110 1ggg 0110 1100 AND A,g
+ 1110 1ggg 0110 1101 XOR A,g
+ 1110 1ggg 0110 1110 OR A,g
+ 1110 1ggg 0110 1111 CMP A,g
+ */
+
+ const int aluop = (opbyte1 & 0x7);
+ const uint8_t result = do_alu(aluop, get_reg8(opbyte0 & 0x7), get_reg8(REG_A));
+
+ if (aluop != 0x07) // CMP doesn't write back
+ {
+ set_reg8(opbyte0 & 0x7, result);
+ }
+}
+
+void tlcs870_device::do_ALUOP_g_n(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // (ALU OP) g,n
+ const int aluop = (opbyte1 & 0x7);
+
+ const uint8_t n = READ8();
+
+ const uint8_t result = do_alu(aluop, get_reg8(opbyte0 & 0x7), n);
+
+ if (aluop != 0x07) // CMP doesn't write back
+ {
+ set_reg8(opbyte0 & 0x7, result);
+ }
+}
+
+/**********************************************************************************************************************/
+// (16-bit ALU handlers)
+/**********************************************************************************************************************/
+
+void tlcs870_device::do_ALUOP_WA_gg(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // (ALU OP) WA,gg
+ /*
+ 1110 10gg 0011 0000 ADDC WA,gg
+ 1110 10gg 0011 0001 ADD WA,gg
+ 1110 10gg 0011 0010 SUBB WA,gg
+ 1110 10gg 0011 0011 SUB WA,gg
+ 1110 10gg 0011 0100 AND WA,gg
+ 1110 10gg 0011 0101 XOR WA,gg
+ 1110 10gg 0011 0110 OR WA,gg
+ 1110 10gg 0011 0111 CMP WA,gg
+ */
+
+ const int aluop = (opbyte1 & 0x7);
+
+ const uint16_t result = do_alu(aluop, get_reg16(REG_WA), get_reg16(opbyte0 & 0x3));
+
+ if (aluop != 0x07) // CMP doesn't write back
+ {
+ set_reg16(REG_WA, result);
+ }
+
+}
+
+void tlcs870_device::do_ALUOP_gg_mn(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // (ALU OP) gg,mn
+ const int aluop = (opbyte1 & 0x7);
+
+ const uint16_t mn = READ16();
+
+ const uint16_t result = do_alu(aluop, get_reg16(opbyte0 & 0x3), mn);
+
+ if (aluop != 0x07) // CMP doesn't write back
+ {
+ set_reg16(opbyte0 & 0x3, result);
+ }
+}
+
+/**********************************************************************************************************************/
+// bit accesses
+/**********************************************************************************************************************/
+
+// ops using (pp).g
+
+void tlcs870_device::do_SET_inppbit(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // SET (pp).g
+ const uint8_t bitpos = opbyte0 & 7;
+ const uint8_t bitused = 1 << bitpos;
+ const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
+ uint8_t val = RM8(addr);
+
+ if (val & bitused) // Zero flag gets set based on original value of bit?
+ {
+ clear_ZF();
+ clear_JF(); // 'Z' (so copy Z flag?)
+ }
+ else
+ {
+ set_ZF();
+ set_JF(); // 'Z'
+ }
+
+ val |= bitused;
+
+ WM8(addr, val);
+}
+
+void tlcs870_device::do_CLR_inppbit(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // CLR (pp).g
+ const uint8_t bitpos = opbyte0 & 7;
+ const uint8_t bitused = 1 << bitpos;
+ const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
+ uint8_t val = RM8(addr);
+
+ if (val & bitused) // Zero flag gets set based on original value of bit?
+ {
+ clear_ZF();
+ clear_JF(); // 'Z' (so copy Z flag?)
+ }
+ else
+ {
+ set_ZF();
+ set_JF(); // 'Z'
+ }
+
+ val &= ~bitused;
+
+ WM8(addr, val);
+}
+
+void tlcs870_device::do_CPL_inppbit(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // CPL (pp).g
+ const uint8_t bitpos = opbyte0 & 7;
+ const uint8_t bitused = 1 << bitpos;
+ const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
+ uint8_t val = RM8(addr);
+
+ uint8_t bit = val & bitused;
+
+ if (bit) // if the bit is set, clear the zero/jump flags and unset the bit
+ {
+ clear_ZF();
+ clear_JF();
+
+ val &= ~bitused;
+ }
+ else // if the bit isn't set, set the zero/jump flags and set the bit
+ {
+ set_ZF();
+ set_JF();
+
+ val |= bitused;
+ }
+
+ WM8(addr, val);
+}
+
+void tlcs870_device::do_LD_inppbit_CF(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // LD (pp).g,CF
+ const uint8_t bitpos = opbyte0 & 7;
+ const uint8_t bitused = 1 << bitpos;
+ const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
+ uint8_t val = RM8(addr);
+
+ if (is_CF()) // if carry flag is set, set the bit in val
+ {
+ val |= bitused;
+ }
+ else // if carry flag isn't set, clear the bit in val
+ {
+ val &= ~bitused;
+ }
+
+ // for this optype of operation ( LD *.b, CF ) the Jump Flag always ends up being 1
+ set_JF();
+
+ WM8(addr, val);
+
+}
+
+void tlcs870_device::do_LD_CF_inppbit(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // LD CF,(pp).g aka TEST (pp).g
+ // 1110 1ggg 1001 111p
+ const uint8_t bitpos = opbyte0 & 7;
+ const uint8_t bitused = 1 << bitpos;
+ const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
+ const uint8_t val = RM8(addr);
+
+ const uint8_t bit = val & bitused;
+
+ bit ? set_CF() : clear_CF();
+ // for this optype of operation ( LD CF, *.b ) the Jump Flag always ends up the inverse of the Carry Flag
+ bit ? clear_JF() : set_JF();
+}
+
+// ops using g.b
+
+void tlcs870_device::do_SET_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // SET g.b
+ // 1110 1ggg 0100 0bbb
+ uint8_t val = get_reg8(opbyte0 & 0x7);
+ const uint8_t bitpos = opbyte1 & 0x7;
+
+ const int bitused = (1 << bitpos);
+
+ if (val & bitused) // Zero flag gets set based on original value of bit?
+ {
+ clear_ZF();
+ clear_JF(); // 'Z' (so copy Z flag?)
+ }
+ else
+ {
+ set_ZF();
+ set_JF(); // 'Z'
+ }
+
+ val |= bitused;
+
+ set_reg8(opbyte0 & 0x7, val);
+}
+
+void tlcs870_device::do_CLR_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // CLR g.b
+ // 1110 1ggg 0100 1bbb
+ uint8_t val = get_reg8(opbyte0 & 0x7);
+ const uint8_t bitpos = opbyte1 & 0x7;
+
+ const int bitused = (1 << bitpos);
+
+ if (val & bitused) // Zero flag gets set based on original value of bit?
+ {
+ clear_ZF();
+ clear_JF(); // 'Z' (so copy Z flag?)
+ }
+ else
+ {
+ set_ZF();
+ set_JF(); // 'Z'
+ }
+
+ val &= ~bitused;
+
+ set_reg8(opbyte0 & 0x7, val);
+}
+
+void tlcs870_device::do_CPL_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // CPL g.b
+ // 1110 1ggg 1100 0bbb
+ uint8_t val = get_reg8(opbyte0 & 0x7);
+ const uint8_t bitpos = opbyte1 & 0x7;
+
+ const int bitused = (1 << bitpos);
+
+ uint8_t bit = val & bitused;
+
+ if (bit) // if the bit is set, clear the zero/jump flags and unset the bit
+ {
+ clear_ZF();
+ clear_JF();
+
+ val &= ~bitused;
+ }
+ else // if the bit isn't set, set the zero/jump flags and set the bit
+ {
+ set_ZF();
+ set_JF();
+
+ val |= bitused;
+ }
+
+ set_reg8(opbyte0 & 0x7, val);
+}
+
+void tlcs870_device::do_LD_gbit_CF(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // LD g.b,CF
+ // m_op = LD; // Flags / Cycles 1--- / 2
+ //m_flagsaffected |= FLAG_J;
+ uint8_t val = get_reg8(opbyte0 & 0x7);
+ const uint8_t bitpos = opbyte1 & 0x7;
+
+ const int bitused = (1 << bitpos);
+
+ if (is_CF()) // if carry flag is set, set the bit in val
+ {
+ val |= bitused;
+ }
+ else // if carry flag isn't set, clear the bit in val
+ {
+ val &= ~bitused;
+ }
+
+ // for this optype of operation ( LD *.b, CF ) the Jump Flag always ends up being 1
+ set_JF();
+
+ set_reg8(opbyte0 & 0x7, val);
+}
+
+
+void tlcs870_device::do_XOR_CF_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // XOR CF,g.b
+ const uint8_t bitpos = opbyte1 & 0x7;
+ const uint8_t bitused = 1 << bitpos;
+
+ const uint8_t g = get_reg8(opbyte0 & 0x7);
+
+ const uint8_t bit = g & bitused;
+
+ if (is_CF())
+ {
+ if (bit)
+ {
+ clear_CF();
+ }
+ else
+ {
+ set_CF();
+ }
+ }
+ else
+ {
+ if (bit)
+ {
+ set_CF();
+ }
+ else
+ {
+ clear_CF();
+ }
+ }
+
+ // JF ends up being whatever the new value of CF is
+ if (is_CF())
+ set_JF();
+ else
+ clear_JF();
+}
+
+
+void tlcs870_device::do_LD_CF_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // LD CF,g.b aka TEST g.b
+ const uint8_t bitpos = opbyte1 & 0x7;
+ const uint8_t bitused = 1 << bitpos;
+
+ const uint8_t g = get_reg8(opbyte0 & 0x7);
+
+ const uint8_t bit = g & bitused;
+
+ bit ? set_CF() : clear_CF();
+ // for this optype of operation ( LD CF, *.b ) the Jump Flag always ends up the inverse of the Carry Flag
+ bit ? clear_JF() : set_JF();
+}
+
+/**********************************************************************************************************************/
+// 16-bit
+/**********************************************************************************************************************/
+
+void tlcs870_device::do_MUL_gg(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // MUL ggH, ggL (odd syntax, basically MUL gg)
+ const uint8_t reg = opbyte0 & 0x3; // opbyte0 & 4 = invalid?
+ handle_mul(reg); // flag changes in handler
+}
+
+void tlcs870_device::do_DIV_gg_C(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // DIV gg,C
+ // (DIV BC,C is presumably an illegal / undefined result)
+ // (DIV WA,C is a redundant encoding)
+ const uint8_t reg = opbyte0 & 0x3; // opbyte0 & 4 = invalid?
+ handle_div(reg); // flag changes in handler
+}
+
+void tlcs870_device::do_POP_gg(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // POP gg
+ m_sp.d += 2;
+ const uint16_t val = RM16(m_sp.d - 1);
+ set_reg16(opbyte0 & 3, val);
+ // no flag changes
+}
+
+void tlcs870_device::do_PUSH_gg(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // PUSH gg
+ const uint16_t val = get_reg16(opbyte0 & 3);
+ WM16(m_sp.d - 1, val);
+ m_sp.d -= 2;
+ // no flag changes
+}
+
+
+void tlcs870_device::do_LD_SP_gg(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // LD SP,gg
+ m_sp.d = get_reg16(opbyte0 & 0x3);
+ set_JF(); // no other flag changes for this type of LD
+}
+
+void tlcs870_device::do_LD_gg_SP(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // LD gg,SP
+ set_reg16(opbyte0 & 0x3, m_sp.d);
+ set_JF(); // no other flag changes for this type of LD
+}
+
+void tlcs870_device::do_LD_rr_gg(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // LD rr,gg
+ const uint16_t gg = get_reg16(opbyte0 & 0x3);
+ set_reg16(opbyte1 & 0x3, gg);
+
+ set_JF(); // no other flag changes for this type of LD
+}
+
+
+void tlcs870_device::do_XCH_rr_gg(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // XCH rr,gg
+ const uint16_t gg = get_reg16(opbyte0 & 0x3);
+ const uint16_t rr = get_reg16(opbyte1 & 0x3);
+
+ set_reg16(opbyte1 & 0x3, gg);
+ set_reg16(opbyte0 & 0x3, rr);
+
+ // flags not done
+}
+
+
+void tlcs870_device::do_CALL_gg(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // CALL gg
+ const uint16_t val = get_reg16(opbyte0 & 3);
+
+ WM16(m_sp.d - 1, m_addr);
+ m_sp.d -= 2;
+
+ m_addr = val;
+
+ // no flag changes on call
+}
+
+void tlcs870_device::do_JP_gg(const uint8_t opbyte0, const uint8_t opbyte1)
+{
+ // JP gg
+ const uint16_t val = get_reg16(opbyte0 & 3);
+
+ m_addr = val;
+ set_JF();
+}
diff --git a/src/devices/cpu/tlcs870/tlcs870_ops_src.cpp b/src/devices/cpu/tlcs870/tlcs870_ops_src.cpp
new file mode 100644
index 00000000000..afb1c0c9ac0
--- /dev/null
+++ b/src/devices/cpu/tlcs870/tlcs870_ops_src.cpp
@@ -0,0 +1,548 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+/*************************************************************************************************************
+
+ Toshiba TLCS-870 Series MCUs
+
+ (src) prefix ops (e0 to e7 subtable)
+
+ (src) address depends on the first byte of the opcode
+
+ E0 (x)
+ E1 (PC+A)
+ E2 (DE)
+ E3 (HL)
+ E4 (HL+d)
+ E5 (HL+C)
+ E6 (HL+)
+ E7 (-HL)
+
+ note, in cases where the address is an immediate value, not a register (x) and (HL+d) the
+ immediate value is directly after the first byte of the opcode
+
+*************************************************************************************************************/
+
+#include "emu.h"
+#include "tlcs870.h"
+#include "tlcs870d.h"
+#include "debugger.h"
+
+// Main dispatch handlers for these
+
+void tlcs870_device::do_e0_opcode(const uint8_t opbyte0)
+{
+ const uint16_t srcaddr = get_addr((opbyte0 & 0x7), READ8());
+ do_e0_to_e7_opcode(opbyte0, srcaddr);
+}
+
+void tlcs870_device::do_e1_to_e3_opcode(const uint8_t opbyte0)
+{
+ const uint16_t srcaddr = get_addr((opbyte0 & 0x7), 0);
+ do_e0_to_e7_opcode(opbyte0, srcaddr);
+}
+
+void tlcs870_device::do_e4_opcode(const uint8_t opbyte0)
+{
+ const uint16_t srcaddr = get_addr((opbyte0 & 0x7), READ8());
+ do_e0_to_e7_opcode(opbyte0, srcaddr);
+}
+
+void tlcs870_device::do_e5_to_e7_opcode(const uint8_t opbyte0)
+{
+ const uint16_t srcaddr = get_addr((opbyte0 & 0x7), 0);
+ do_e0_to_e7_opcode(opbyte0, srcaddr);
+}
+
+// e0 - e7 use this table
+void tlcs870_device::do_e0_to_e7_opcode(uint8_t opbyte0, uint16_t srcaddr)
+{
+ const uint8_t opbyte1 = READ8();
+
+ switch (opbyte1)
+ {
+ case 0x08:
+ do_ROLD_A_insrc(opbyte0, opbyte1, srcaddr); break;
+ case 0x09:
+ do_RORD_A_insrc(opbyte0, opbyte1, srcaddr); break;
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ do_LD_rr_insrc(opbyte0, opbyte1, srcaddr); break;
+ case 0x20:
+ do_INC_insrc(opbyte0, opbyte1, srcaddr); break;
+ case 0x26:
+ do_LD_inx_insrc(opbyte0, opbyte1, srcaddr); break;
+ case 0x27:
+ do_LD_inHL_insrc(opbyte0, opbyte1, srcaddr); break;
+ case 0x28:
+ do_DEC_insrc(opbyte0, opbyte1, srcaddr); break;
+ case 0x2f:
+ do_MCMP_insrc_n(opbyte0, opbyte1, srcaddr); break;
+ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
+ do_SET_insrcbit(opbyte0, opbyte1, srcaddr); break;
+ case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ do_CLR_insrcbit(opbyte0, opbyte1, srcaddr); break;
+ case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
+ do_LD_r_insrc(opbyte0, opbyte1, srcaddr); break;
+ case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
+ do_ALUOP_insrc_inHL(opbyte0, opbyte1, srcaddr); break;
+ case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
+ do_ALUOP_insrc_n(opbyte0, opbyte1, srcaddr); break;
+ case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
+ do_ALUOP_A_insrc(opbyte0, opbyte1, srcaddr); break;
+ case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
+ do_XCH_r_insrc(opbyte0, opbyte1, srcaddr); break;
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ do_CPL_insrcbit(opbyte0, opbyte1, srcaddr); break;
+ case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ do_LD_insrcbit_CF(opbyte0, opbyte1, srcaddr); break;
+ case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
+ do_XOR_CF_insrcbit(opbyte0, opbyte1, srcaddr); break;
+ case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
+ do_LD_CF_insrcbit(opbyte0, opbyte1, srcaddr); break;
+ case 0xfc:
+ do_CALL_insrc(opbyte0, opbyte1, srcaddr); break;
+ case 0xfe:
+ do_JP_insrc(opbyte0, opbyte1, srcaddr); break;
+
+ default:
+ do_e0_to_e7_oprand_illegal(opbyte0, opbyte1, srcaddr); break;
+ }
+}
+
+// Actual handlers
+
+void tlcs870_device::do_e0_to_e7_oprand_illegal(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ logerror("illegal src prefix opcode %02x %02x (src addr %04x)\n", opbyte0, opbyte1, srcaddr);
+}
+
+/**********************************************************************************************************************/
+// (16-bit)
+/**********************************************************************************************************************/
+
+void tlcs870_device::do_LD_rr_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // LD rr, (src)
+ const uint16_t val = RM16(srcaddr);
+ set_reg16(opbyte1 & 0x3, val);
+ set_JF();
+}
+
+/**********************************************************************************************************************/
+// (8-bit)
+/**********************************************************************************************************************/
+
+void tlcs870_device::do_INC_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // INC (src)
+ uint8_t val = RM8(srcaddr);
+ val++;
+
+ if (val == 0)
+ {
+ set_ZF();
+ set_JF();
+ }
+ else
+ {
+ clear_ZF();
+ clear_JF();
+ }
+
+ WM8(srcaddr, val);
+}
+
+void tlcs870_device::do_DEC_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // DEC (src)
+ uint8_t val = RM8(srcaddr);
+ val--;
+
+ if (val == 0xff)
+ {
+ set_JF();
+ }
+ else
+ {
+ // do we clear?
+ clear_JF();
+ }
+
+ if (val == 0x00) // check
+ {
+ set_ZF();
+ }
+ else
+ {
+ set_ZF();
+ }
+
+ WM8(srcaddr, val);
+}
+
+void tlcs870_device::do_ROLD_A_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // ROLD A,(src)
+ // 12-bit left rotation using lower 4 bits of REG_A and content of (src)
+ const uint8_t val = RM8(srcaddr);
+ const uint8_t reg = get_reg8(REG_A);
+
+ uint8_t tempval = (val & 0x0f) << 4;
+ tempval |= reg & 0x0f;
+ const uint8_t tempa = (reg & 0xf0) | (val & 0xf0) >> 4;
+
+ set_reg8(REG_A, tempa);
+ WM8(srcaddr, tempval);
+
+ // TODO: flags
+}
+
+void tlcs870_device::do_RORD_A_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // RORD A,(src)
+ // 12-bit right rotation using lower 4 bits of REG_A and content of (src)
+ const uint8_t val = RM8(srcaddr);
+ const uint8_t reg = get_reg8(REG_A);
+
+ uint8_t tempval = (val & 0xf0) >> 4;
+ tempval |= ((reg & 0x0f) << 4);
+ const uint8_t tempa = (reg & 0xf0) | (val & 0x0f);
+
+ set_reg8(REG_A, tempa);
+ WM8(srcaddr, tempval);
+
+ // TODO: flags
+}
+
+
+
+void tlcs870_device::do_LD_inx_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // LD (x),(src)
+ // invalid if (src) is also (x) ? (not specified)
+ const uint16_t x = READ8(); // get address x
+ const uint8_t val = RM8(srcaddr);
+ WM8(x, val);
+
+ set_JF();
+ // z-flag is undefined, check real behavior
+}
+
+void tlcs870_device::do_LD_inHL_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // LD (HL),(src)
+ const uint8_t val = RM8(srcaddr);
+
+ const uint16_t dstaddr = get_reg16(REG_HL);
+
+ WM8(dstaddr, val);
+
+ set_JF();
+
+ if (val == 0x00) set_ZF();
+ else clear_ZF();
+}
+
+void tlcs870_device::do_LD_r_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // LD r, (src)
+ const uint8_t val = RM8(srcaddr);
+
+ set_reg8(opbyte1 & 0x7, val);
+
+ set_JF();
+
+ if (val == 0x00) set_ZF();
+ else clear_ZF();
+}
+
+void tlcs870_device::do_MCMP_insrc_n(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // MCMP (src), n
+ const uint8_t n = READ8();
+ const uint8_t val = RM8(srcaddr);
+
+ const uint8_t temp = n & val;
+ const uint8_t a = get_reg8(REG_A);
+
+ // ZF and JF set conditionally
+ if (a == temp)
+ {
+ // if n & val is equal to accumulator
+ set_ZF();
+ set_JF();
+ }
+ else
+ {
+ clear_ZF();
+ clear_JF();
+ }
+
+ // C gets set conditionally (like CMP?)
+ if (a < temp)
+ {
+ set_CF();
+ }
+ else
+ {
+ clear_CF();
+ }
+
+ // apparently H gets set conditionally too? (like CMP?)
+}
+
+void tlcs870_device::do_XCH_r_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // XCH r,(src)
+ const uint8_t val = RM8(srcaddr);
+ const uint8_t temp = get_reg8(opbyte1 & 0x7);
+
+ WM8(srcaddr, temp);
+ set_reg8(opbyte1 & 0x7, val);
+
+ set_JF();
+
+ if (val == 0)
+ {
+ set_ZF();
+ }
+ else
+ {
+ // do we clear?
+ clear_ZF();
+ }
+}
+
+/**********************************************************************************************************************/
+// ALU Operations
+/**********************************************************************************************************************/
+
+void tlcs870_device::do_ALUOP_insrc_inHL(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // (ALU OP) (src), (HL)
+ const int aluop = (opbyte1 & 0x7);
+ const uint8_t val = RM8(srcaddr);
+
+ const uint16_t HL = get_reg16(REG_HL);
+
+ const uint8_t result = do_alu(aluop, val, RM8(HL));
+
+ if (aluop != 0x07) // CMP doesn't write back
+ {
+ WM8(srcaddr, result);
+ }
+}
+
+void tlcs870_device::do_ALUOP_insrc_n(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // (ALU OP) (src), n
+ const uint8_t n = READ8();
+
+ const int aluop = (opbyte1 & 0x7);
+ const uint8_t val = RM8(srcaddr);
+
+ const uint8_t result = do_alu(aluop, val, n);
+
+ if (aluop != 0x07) // CMP doesn't write back
+ {
+ WM8(srcaddr, result);
+ }
+}
+
+void tlcs870_device::do_ALUOP_A_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // (ALU OP) A, (src)
+ const int aluop = (opbyte1 & 0x7);
+ const uint8_t val = RM8(srcaddr);
+
+ const uint8_t result = do_alu(aluop, get_reg8(REG_A), val);
+
+ if (aluop != 0x07) // CMP doesn't write back
+ {
+ set_reg8(REG_A, result);
+ }
+}
+
+/**********************************************************************************************************************/
+// jumps / calls
+/**********************************************************************************************************************/
+
+void tlcs870_device::do_CALL_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // CALL (src)
+ const uint16_t val = RM16(srcaddr);
+
+ WM16(m_sp.d - 1, m_addr);
+ m_sp.d -= 2;
+
+ m_addr = val;
+
+ // no flag changes on call
+}
+
+void tlcs870_device::do_JP_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // JP (src)
+ const uint16_t val = RM16(srcaddr);
+ m_addr = val;
+ set_JF();
+}
+
+/**********************************************************************************************************************/
+// (8-bit) bit operations
+/**********************************************************************************************************************/
+
+void tlcs870_device::do_XOR_CF_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // XOR CF,(src).b
+ const uint8_t val = RM8(srcaddr);
+ const uint8_t bitpos = opbyte1 & 0x7;
+
+ int bitused = (1 << bitpos);
+
+ const uint8_t bit = val & bitused;
+
+ if (is_CF())
+ {
+ if (bit)
+ {
+ clear_CF();
+ }
+ else
+ {
+ set_CF();
+ }
+ }
+ else
+ {
+ if (bit)
+ {
+ set_CF();
+ }
+ else
+ {
+ clear_CF();
+ }
+ }
+
+ // JF ends up being whatever the new value of CF is
+ if (is_CF())
+ set_JF();
+ else
+ clear_JF();
+}
+
+
+void tlcs870_device::do_LD_insrcbit_CF(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // LD (src).b,CF
+ uint8_t val = RM8(srcaddr);
+ const uint8_t bitpos = opbyte1 & 0x7;
+
+ const int bitused = (1 << bitpos);
+
+ if (is_CF()) // if carry flag is set, set the bit in val
+ {
+ val |= bitused;
+ }
+ else // if carry flag isn't set, clear the bit in val
+ {
+ val &= ~bitused;
+ }
+
+ // for this optype of operation ( LD *.b, CF ) the Jump Flag always ends up being 1
+ set_JF();
+
+ WM8(srcaddr, val);
+}
+
+void tlcs870_device::do_CPL_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // CPL (src).b
+ uint8_t val = RM8(srcaddr);
+ const uint8_t bitpos = opbyte1 & 0x7;
+
+ const int bitused = (1 << bitpos);
+
+ const uint8_t bit = val & bitused;
+
+ if (bit) // if the bit is set, clear the zero/jump flags and unset the bit
+ {
+ clear_ZF();
+ clear_JF();
+
+ val &= ~bitused;
+ }
+ else // if the bit isn't set, set the zero/jump flags and set the bit
+ {
+ set_ZF();
+ set_JF();
+
+ val |= bitused;
+ }
+
+ WM8(srcaddr, val);
+}
+
+void tlcs870_device::do_LD_CF_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // LD CF,(src).b aka TEST (src).b
+ const uint8_t val = RM8(srcaddr);
+ const uint8_t bitpos = opbyte1 & 0x7;
+
+ const int bitused = (1 << bitpos);
+
+ const uint8_t bit = val & bitused;
+
+ bit ? set_CF() : clear_CF();
+ // for this optype of operation ( LD CF, *.b ) the Jump Flag always ends up the inverse of the Carry Flag
+ bit ? clear_JF() : set_JF();
+}
+
+void tlcs870_device::do_SET_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // SET (src).b
+ uint8_t val = RM8(srcaddr);
+ const uint8_t bitpos = opbyte1 & 0x7;
+
+ const int bitused = (1 << bitpos);
+
+ if (val & bitused) // Zero flag gets set based on original value of bit?
+ {
+ clear_ZF();
+ clear_JF(); // 'Z' (so copy Z flag?)
+ }
+ else
+ {
+ set_ZF();
+ set_JF(); // 'Z'
+ }
+
+ val |= bitused;
+
+ WM8(srcaddr, val);
+}
+
+void tlcs870_device::do_CLR_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
+{
+ // CLR (src).b
+ uint8_t val = RM8(srcaddr);
+ const uint8_t bitpos = opbyte1 & 0x7;
+
+ const int bitused = (1 << bitpos);
+
+ if (val & bitused) // Zero flag gets set based on original value of bit?
+ {
+ clear_ZF();
+ clear_JF(); // 'Z' (so copy Z flag?)
+ }
+ else
+ {
+ set_ZF();
+ set_JF(); // 'Z'
+ }
+
+ val &= ~bitused;
+
+ WM8(srcaddr, val);
+}
+
diff --git a/src/devices/cpu/tlcs870/tlcs870d.cpp b/src/devices/cpu/tlcs870/tlcs870d.cpp
index 0017caab950..50b7b12f05d 100644
--- a/src/devices/cpu/tlcs870/tlcs870d.cpp
+++ b/src/devices/cpu/tlcs870/tlcs870d.cpp
@@ -8,8 +8,6 @@
The TLCS-870/C appears to have a completely different encoding.
- loosely baesd on the tlcs90 core by Luca Elia
-
*************************************************************************************************************/
#include "emu.h"
@@ -1020,7 +1018,7 @@ void tlcs870_disassembler::decode_register_prefix(uint8_t b0)
break;
case 0x02:
- // MUL ggG, ggL
+ // MUL ggH, ggL
m_op = MUL;
m_param1_type = REG_16BIT; // odd syntax
@@ -1416,6 +1414,10 @@ void tlcs870_disassembler::decode_register_prefix(uint8_t b0)
case 0x97:
break;
+ case 0x98:
+ case 0x99:
+ break;
+
case 0x9a:
case 0x9b:
// LD (pp).g,CF
@@ -1458,6 +1460,25 @@ void tlcs870_disassembler::decode_register_prefix(uint8_t b0)
case 0xa7:
break;
+ case 0xa8:
+ case 0xa9:
+ case 0xaa:
+ case 0xab:
+ case 0xac:
+ case 0xad:
+ case 0xae:
+ case 0xaf:
+ // XCH r,g
+ m_op = XCH;
+
+ //m_flagsaffected |= FLAG_J | FLAG_Z;
+
+ m_param1_type = REG_8BIT;
+ m_param1 = bx & 0x7;
+
+ m_param2_type = REG_8BIT;
+ m_param2 = b0 & 0x7;
+ break;
case 0xb0:
case 0xb1:
case 0xb2:
diff --git a/src/mame/drivers/hng64.cpp b/src/mame/drivers/hng64.cpp
index 6db4675d2b9..6c4df6876cc 100644
--- a/src/mame/drivers/hng64.cpp
+++ b/src/mame/drivers/hng64.cpp
@@ -1558,7 +1558,6 @@ MACHINE_CONFIG_START(hng64_state::hng64)
hng64_network(config);
MCFG_DEVICE_ADD("iomcu", TMP87PH40AN, 8000000)
- MCFG_DEVICE_DISABLE() // work in progress
MACHINE_CONFIG_END
@@ -1566,9 +1565,18 @@ MACHINE_CONFIG_END
#define ROM_LOAD_HNG64_BIOS(bios,name,offset,length,hash) \
ROMX_LOAD(name, offset, length, hash, ROM_BIOS(bios))
-// all BIOS roms are said to be from 'fighting' type PCB, it is unknown if the actual MIPS BIOS differs on the others, or only the MCU internal ROM
+/* All main BIOS roms are said to be from 'fighting' type PCB, it is unknown if the actual MIPS BIOS differs on the others, but it appears unlikely.
+
+ The IO MCU was dumped from a TMP87PH40AN type chip taken from an unknown IO board type.
+
+ Some boards instead use a TMP87CH40N but in all cases they're stickered SNK-IOJ1.00A so the content is possibly the same on all types.
+
+ This needs further studying of the MCU code as it is known that the different IO boards return a different ident value.
+*/
+
#define HNG64_BIOS \
- ROM_REGION32_BE( 0x0100000, "user1", 0 ) /* 512k for R4300 BIOS code */ \
+ /* R4300 BIOS code (main CPU) */ \
+ ROM_REGION32_BE( 0x0100000, "user1", 0 ) \
ROM_SYSTEM_BIOS( 0, "japan", "Japan" ) \
ROM_LOAD_HNG64_BIOS( 0, "brom1.bin", 0x00000, 0x080000, CRC(a30dd3de) SHA1(3e2fd0a56214e6f5dcb93687e409af13d065ea30) ) \
ROM_SYSTEM_BIOS( 1, "us", "USA" ) \
@@ -1577,12 +1585,14 @@ MACHINE_CONFIG_END
ROM_LOAD_HNG64_BIOS( 2, "bios_export.bin", 0x00000, 0x080000, CRC(bbf07ec6) SHA1(5656aa077f6a6d43953f15b5123eea102a9d5313) ) \
ROM_SYSTEM_BIOS( 3, "korea", "Korea" ) \
ROM_LOAD_HNG64_BIOS( 3, "bios_korea.bin", 0x00000, 0x080000, CRC(ac953e2e) SHA1(f502188ef252b7c9d04934c4b525730a116de48b) ) \
- ROM_REGION( 0x0100000, "user2", 0 ) /* KL5C80 BIOS */ \
+ /* KL5C80 BIOS (network CPU) */ \
+ ROM_REGION( 0x0100000, "user2", 0 ) \
ROM_LOAD ( "from1.bin", 0x000000, 0x080000, CRC(6b933005) SHA1(e992747f46c48b66e5509fe0adf19c91250b00c7) ) \
+ /* FPGA (unknown) */ \
ROM_REGION( 0x0100000, "fpga", 0 ) /* FPGA data */ \
ROM_LOAD ( "rom1.bin", 0x000000, 0x01ff32, CRC(4a6832dc) SHA1(ae504f7733c2f40450157cd1d3b85bc83fac8569) ) \
+ /* TMP87PH40AN (I/O MCU) */ \
ROM_REGION( 0x10000, "iomcu", 0 ) /* "64Bit I/O Controller Ver 1.0 1997.06.29(C)SNK" internal ID string */ \
- /* this was dumped from a TMP87PH40AN type chip. Some boards use a TMP87CH40N, in all cases they're stickered SNK-IOJ1.00A so likely the same content */ \
ROM_LOAD ( "tmp87ph40an.bin", 0x8000, 0x8000, CRC(b70df21f) SHA1(5b742e8a0bbf4c0ae4f4398d34c7058fb24acc92) )