diff options
Diffstat (limited to 'src/devices/cpu/tlcs870/tlcs870d.cpp')
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870d.cpp | 2264 |
1 files changed, 2264 insertions, 0 deletions
diff --git a/src/devices/cpu/tlcs870/tlcs870d.cpp b/src/devices/cpu/tlcs870/tlcs870d.cpp new file mode 100644 index 00000000000..0017caab950 --- /dev/null +++ b/src/devices/cpu/tlcs870/tlcs870d.cpp @@ -0,0 +1,2264 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +/************************************************************************************************************* + + Toshiba TLCS-870 Series MCUs + + The TLCS-870/X expands on this instruction set using the same base encoding. + + The TLCS-870/C appears to have a completely different encoding. + + loosely baesd on the tlcs90 core by Luca Elia + +*************************************************************************************************************/ + +#include "emu.h" +#include "tlcs870d.h" + +#define IS16BIT 0x80 +#define BITPOS 0x40 +#define BITPOS_INDIRECT 0x20 + +#define ABSOLUTE_VAL_8 0x01 +#define REG_8BIT 0x02 +#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) + +u32 tlcs870_disassembler::opcode_alignment() const +{ + return 1; +} + + +uint8_t tlcs870_disassembler::READ8() +{ + uint8_t b0 = m_opcodes->r8( m_addr++ ); + m_addr &= 0xffff; + return b0; +} + +uint16_t tlcs870_disassembler::READ16() +{ + uint8_t b0 = READ8(); + return b0 | (READ8() << 8); +} + +// di, ei, j, and test are just 'alias' opcodes +const char *const tlcs870_disassembler::op_names[] = { + "??", + "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 operations + "addc", + "add", + "subb", + "sub", + "and", + "xor", + "or", + "cmp", +}; + + + + +const char *const tlcs870_disassembler::reg8[] = { + "A", + "W", + "C", + "B", + "E", + "D", + "L", + "H" +}; + +const char *const tlcs870_disassembler::type_x[] = { + "(x)", + "(PC+A)", + "(DE)", + "(HL)", + "(HL+d)", + "(HL+C)", + "(HL+)", + "(-HL)", +}; + +const char *const tlcs870_disassembler::conditions[] = { + "EQ/Z", + "NE/NZ", + "LT/CS", + "GE/CC", + "LE", + "GT", + "T", + "F", +}; + +const char *const tlcs870_disassembler::reg16[] = { + "WA", + "BC", + "DE", + "HL" +}; + +const char *const tlcs870_disassembler::reg16p[] = { + "DE", + "HL" +}; + +void tlcs870_disassembler::decode() +{ + 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; + + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + // CLR (x).b + b1 = READ8(); +#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; + 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(); + + 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; + + 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; + + 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: + // 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; + + case 0xfb: + { + // 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; + + case 0xff: + // SWI + m_op = SWI; + + break; + } +} + +// e8 - ef use this table +void tlcs870_disassembler::decode_register_prefix(uint8_t b0) +{ + uint8_t bx; + + bx = READ8(); + + switch (bx) + { + 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: + 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 g.b + m_op = CPL; + + m_param1_type = REG_8BIT | BITPOS; + m_param1 = b0 & 0x7; + m_bitpos = bx & 0x7; + 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; + + 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; + + 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; + + 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: + 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; + + 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; + 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? + + break; + + case 0xff: + break; + + } + +} + +// e0 - e7 use this table +void tlcs870_disassembler::decode_source(int type, uint16_t val) +{ + uint8_t bx; + + bx = READ8(); + + switch (bx) + { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + 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 + 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 + break; + + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + + case 0x10: + case 0x11: + case 0x12: + case 0x13: + // see dst + 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; + break; + + case 0x18: + case 0x19: + case 0x1a: + case 0x1b: + case 0x1c: + case 0x1d: + case 0x1e: + case 0x1f: + break; + + case 0x20: + // INC (src) + m_op = INC; + m_param1_type = type; + m_param1 = val; + + break; + + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + 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; + break; + + + case 0x28: + // DEC (src) + m_op = DEC; + m_param1_type = type; + m_param1 = val; + + break; + + case 0x29: + case 0x2a: + case 0x2b: + case 0x2c: + case 0x2d: + case 0x2e: + 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(); + 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_disassembler::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; + } +} + +void tlcs870_disassembler::disassemble_param(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms, int type, uint16_t val) +{ + int basetype = type & MODE_MASK; + + if (basetype==ADDR_IN_IMM_X) util::stream_format(stream, " ($%02x)", val); // direct + if (basetype==ADDR_IN_PC_PLUS_REG_A) util::stream_format(stream, " %s", type_x[1]); + if (basetype==ADDR_IN_DE) util::stream_format(stream, " %s", type_x[2]); + if (basetype==ADDR_IN_HL) util::stream_format(stream, " %s", type_x[3]); + if (basetype==ADDR_IN_HL_PLUS_IMM_D) util::stream_format(stream, " (HL+$%04x)", val); // todo, sign extend + if (basetype==ADDR_IN_HL_PLUS_REG_C) util::stream_format(stream, " %s", type_x[5]); + if (basetype==ADDR_IN_HLINC) util::stream_format(stream, " %s", type_x[6]); + if (basetype==ADDR_IN_DECHL) util::stream_format(stream, " %s", type_x[7]); + + if (basetype==REG_8BIT) + { + if (type&IS16BIT) util::stream_format(stream, " %s", reg16[val&3]); + else util::stream_format(stream, " %s", reg8[val & 7]); + } + + if (basetype==CONDITIONAL) util::stream_format(stream, " %s", conditions[val]); + if (basetype==(STACKPOINTER & MODE_MASK)) util::stream_format(stream, " SP"); + if (basetype==REGISTERBANK) util::stream_format(stream, " RBS"); + if (basetype==PROGRAMSTATUSWORD) util::stream_format(stream, " PSW"); + if (basetype==MEMVECTOR_16BIT) util::stream_format(stream, " ($%04x)", val); + if (basetype==ABSOLUTE_VAL_8) + { + if (type&IS16BIT) util::stream_format(stream, "$%04x", val); + else util::stream_format(stream, "$%02x", val); + } + + if (basetype == (CARRYFLAG & MODE_MASK)) + { + util::stream_format(stream, " CF"); + } + else if (type&BITPOS) + { + if (type & BITPOS_INDIRECT) util::stream_format(stream, ".BIT_%s", reg8[m_bitpos&7]); + else util::stream_format(stream, ".BIT_%d", m_bitpos); + } +} + +offs_t tlcs870_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) +{ + m_addr = pc; + m_opcodes = &opcodes; + + decode(); + + util::stream_format (stream, "%-5s", op_names[ m_op ] ); + + if (m_param1_type) + { + disassemble_param(stream, pc, opcodes, params, m_param1_type, m_param1); + } + + if (m_param2_type) + { + if (m_param1_type) util::stream_format(stream, ","); + + disassemble_param(stream, pc, opcodes, params, m_param2_type, m_param2); + + } + + return (m_addr - pc) | SUPPORTED; +} |