diff options
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 |
commit | 88b1546f30a6384cdbc3dcd8e26389a9208e3aba (patch) | |
tree | 79ced1df7efab420e45c9e37dd99599cfbeeb38d | |
parent | fedf58aa42846315d2acb4499743835676dc6135 (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.lua | 5 | ||||
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870.cpp | 3026 | ||||
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870.h | 362 | ||||
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870_ops.cpp | 951 | ||||
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870_ops_dst.cpp | 127 | ||||
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp | 500 | ||||
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp | 760 | ||||
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870_ops_src.cpp | 548 | ||||
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870d.cpp | 27 | ||||
-rw-r--r-- | src/mame/drivers/hng64.cpp | 20 |
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) ) |