From c14ad04c48d84d9ec3bdb6f82ef35f2a5d6e7016 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Wed, 27 Apr 2016 03:26:03 -0500 Subject: [PATCH] Simplify and fix index bit instructions in disassembler. --- src/disassembler/arguments.c | 141 +++++++++++++++++++++++++------------------ src/disassembler/mnemonics.c | 2 +- src/z80_ops.inc.c | 38 +++++++++--- 3 files changed, 115 insertions(+), 66 deletions(-) diff --git a/src/disassembler/arguments.c b/src/disassembler/arguments.c index 213a698..8177148 100644 --- a/src/disassembler/arguments.c +++ b/src/disassembler/arguments.c @@ -9,6 +9,8 @@ #define MAX_ARG_SIZE 256 +/* Internal structs, enums, etc. */ + typedef enum { AT_NONE = 0, /* Register */ @@ -28,6 +30,15 @@ typedef enum { AT_PORT_C, AT_PORT_IM, AT_PORT_0 } ArgType; +typedef ArgType ArgTable[3][256]; + +typedef struct { + uint8_t index, opcode, arg1, arg2; + ArgTable *table; +} Instr; + +/* Temporary aliases to make table definitions concise */ + #define __ AT_NONE #define A_ AT_REG_A #define B_ AT_REG_B @@ -72,7 +83,9 @@ typedef enum { #define PM AT_PORT_IM #define R0 AT_PORT_0 -static ArgType instr_args[3][256] = { +/* Argument tables */ + +static ArgTable instr_args = { { __, BC, NB, BC, B_, B_, B_, __, AF, HL, A_, BC, C_, C_, C_, __, ML, DE, ND, DE, D_, D_, D_, __, ML, HL, A_, DE, E_, E_, E_, __, @@ -112,7 +125,7 @@ static ArgType instr_args[3][256] = { { __ } }; -static ArgType instr_args_extended[3][256] = { +static ArgTable instr_args_extended = { { __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, @@ -152,7 +165,7 @@ static ArgType instr_args_extended[3][256] = { { __ } }; -static ArgType instr_args_bits[3][256] = { +static ArgTable instr_args_bits = { { B_, C_, D_, E_, H_, L_, NH, A_, B_, C_, D_, E_, H_, L_, NH, A_, B_, C_, D_, E_, H_, L_, NH, A_, B_, C_, D_, E_, H_, L_, NH, A_, @@ -192,7 +205,7 @@ static ArgType instr_args_bits[3][256] = { { __ } }; -static ArgType instr_args_index[3][256] = { +static ArgTable instr_args_index = { { __, __, __, __, __, __, __, __, __, XY, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, XY, __, __, __, __, __, __, @@ -232,7 +245,7 @@ static ArgType instr_args_index[3][256] = { { __ } }; -static ArgType instr_args_index_bits[3][256] = { +static ArgTable instr_args_index_bits = { { II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, II, @@ -289,6 +302,8 @@ static ArgType instr_args_index_bits[3][256] = { } }; +/* Remove temporary aliases */ + #undef __ #undef A_ #undef B_ @@ -336,52 +351,50 @@ static ArgType instr_args_index_bits[3][256] = { /* Decode an immediate argument. */ -static void decode_immediate( - char *arg, ArgType type, const uint8_t *bytes, size_t shift) +static void decode_immediate(char *arg, Instr *instr, ArgType type) { - char *format; - size_t take; - uint8_t b = bytes[shift]; + uint8_t op = instr->opcode, take; + bool ix = instr->index == 0xDD; switch (type) { case AT_IMM_U16: // 16-bit immediate - sprintf(arg, "$%04X", bytes[shift + 1] + (bytes[shift + 2] << 8)); + sprintf(arg, "$%04X", instr->arg1 + (instr->arg2 << 8)); break; case AT_IMM_U8: // 8-bit unsigned immediate - if ((bytes[0] == 0xDD || bytes[0] == 0xFD) && bytes[1] == 0x36) - take = 2; + if (instr->index != 0x00 && op == 0x36) + take = instr->arg2; else - take = 1; - sprintf(arg, "$%02X", bytes[shift + take]); + take = instr->arg1; + sprintf(arg, "$%02X", take); break; case AT_IMM_REL: // 8-bit relative offset (JP and DJNZ) - sprintf(arg, "%hhd", (int8_t) (bytes[shift + 1] + 2)); + sprintf(arg, "%hhd", (int8_t) (instr->arg1 + 2)); break; case AT_IMM_BIT: // Bit position - sprintf(arg, "%d", (b & 0x38) >> 3); + sprintf(arg, "%d", (op & 0x38) >> 3); break; case AT_IMM_RST: // Reset - sprintf(arg, "$%02X", b & 0x38); + sprintf(arg, "$%02X", op & 0x38); break; case AT_IMM_IM: // Interrupt mode - sprintf(arg, "%d", !(b & (1 << 4)) ? 0 : !(b & (1 << 3)) ? 1 : 2); + sprintf(arg, "%d", !(op & (1 << 4)) ? 0 : !(op & (1 << 3)) ? 1 : 2); break; case AT_IDR_IMM: // Indirect immediate - sprintf(arg, "($%04X)", bytes[shift + 1] + (bytes[shift + 2] << 8)); + sprintf(arg, "($%04X)", instr->arg1 + (instr->arg2 << 8)); break; case AT_IX_IY: // Indexed offset - if (bytes[shift + 1]) { - format = bytes[0] == 0xDD ? "(ix%+hhd)" : "(iy%+hhd)"; - sprintf(arg, format, (int8_t) bytes[shift + 1]); + if (instr->arg1) { + char *format = ix ? "(ix%+hhd)" : "(iy%+hhd)"; + sprintf(arg, format, (int8_t) instr->arg1); } else { - sprintf(arg, bytes[0] == 0xDD ? "(ix)" : "(iy)"); + sprintf(arg, ix ? "(ix)" : "(iy)"); } break; case AT_PORT_IM: // Immediate port - sprintf(arg, "($%02X)", bytes[shift + 1]); + sprintf(arg, "($%02X)", instr->arg1); break; default: - FATAL("invalid call: decode_immediate(arg, %d, ...)", type) + FATAL("invalid call: decode_immediate(arg, ..., %d)", type) return; } } @@ -389,10 +402,10 @@ static void decode_immediate( /* Decode a single argument, given its type. */ -static void decode_argument( - char *arg, ArgType type, const uint8_t *bytes, size_t shift) +static void decode_argument(char *arg, Instr *instr, ArgType type) { const char *value; + bool ix = instr->index == 0xDD; switch (type) { case AT_NONE: @@ -427,10 +440,10 @@ static void decode_argument( case AT_COND_M: value = "m"; break; case AT_PORT_C: value = "(c)"; break; case AT_PORT_0: value = "0"; break; - case AT_REG_IXY: value = (bytes[0] == 0xDD) ? "ix" : "iy"; break; - case AT_REG_IH: value = (bytes[0] == 0xDD) ? "ixh" : "iyh"; break; - case AT_REG_IL: value = (bytes[0] == 0xDD) ? "ixl" : "iyl"; break; - case AT_IDR_IXY: value = (bytes[0] == 0xDD) ? "(ix)" : "(iy)"; break; + case AT_REG_IXY: value = ix ? "ix" : "iy"; break; + case AT_REG_IH: value = ix ? "ixh" : "iyh"; break; + case AT_REG_IL: value = ix ? "ixl" : "iyl"; break; + case AT_IDR_IXY: value = ix ? "(ix)" : "(iy)"; break; case AT_IMM_U16: case AT_IMM_U8: case AT_IMM_REL: @@ -440,40 +453,51 @@ static void decode_argument( case AT_IDR_IMM: case AT_IX_IY: case AT_PORT_IM: - decode_immediate(arg, type, bytes, shift); + decode_immediate(arg, instr, type); return; default: - FATAL("invalid call: decode_argument(arg, %d, ...)", type) + FATAL("invalid call: decode_argument(arg, ..., %d)", type) return; } strcpy(arg, value); } /* - Return the appropriate argument table for the given instruction. - - This function also adds the number of instruction bytes to skip to its - shift argument (corresponding to any prefix bits), so bytes[*shift] will - always be the instruction opcode. - - This function return type is ridiculous, but it returns a pointer to an - array of 3 arrays of 256 ArgTypes. + Fill an Instruction object with the appropriate fields. */ -static inline ArgType (*get_table_and_shift( - const uint8_t *bytes, size_t *shift))[3][256] +static inline void load_instr(Instr *instr, const uint8_t *bytes) { uint8_t b = bytes[0]; + bool extend = b == 0xED; + bool bit = b == 0xCB; + bool index = b == 0xDD || b == 0xFD; + bool indexbit = index && bytes[1] == 0xCB; + + instr->index = index ? b : 0x00; - if (b == 0xED) - return (*shift)++, &instr_args_extended; - if (b == 0xCB) - return (*shift)++, &instr_args_bits; - if (b == 0xDD || b == 0xFD) { - if (bytes[1] == 0xCB) - return (*shift) += 2, &instr_args_index_bits; - return (*shift)++, &instr_args_index; + if (indexbit) { + instr->opcode = bytes[3]; + instr->arg1 = bytes[2]; + } else if (extend || bit || index) { + instr->opcode = bytes[1]; + instr->arg1 = bytes[2]; + instr->arg2 = bytes[3]; + } else { + instr->opcode = bytes[0]; + instr->arg1 = bytes[1]; + instr->arg2 = bytes[2]; } - return &instr_args; + + if (extend) + instr->table = &instr_args_extended; + else if (bit) + instr->table = &instr_args_bits; + else if (indexbit) + instr->table = &instr_args_index_bits; + else if (index) + instr->table = &instr_args_index; + else + instr->table = &instr_args; } /* @@ -484,13 +508,14 @@ static inline ArgType (*get_table_and_shift( char* decode_arguments(const uint8_t *bytes) { char args[3][MAX_ARG_SIZE], *result; - ArgType (*table)[3][256], type; - size_t shift = 0, i, len; + Instr instr; + ArgType type; + size_t i, len; - table = get_table_and_shift(bytes, &shift); + load_instr(&instr, bytes); for (i = 0; i < 3; i++) { - type = (*table)[i][bytes[shift]]; - decode_argument(args[i], type, bytes, shift); + type = (*instr.table)[i][instr.opcode]; + decode_argument(args[i], &instr, type); } if (!*args[0]) diff --git a/src/disassembler/mnemonics.c b/src/disassembler/mnemonics.c index abeb9e7..b94d701 100644 --- a/src/disassembler/mnemonics.c +++ b/src/disassembler/mnemonics.c @@ -158,7 +158,7 @@ char* decode_mnemonic(const uint8_t *bytes) return instr_mnemonics_bits[bytes[1]]; if (b == 0xDD || b == 0xFD) { if (bytes[1] == 0xCB) - return instr_mnemonics_bits[bytes[2]]; + return instr_mnemonics_bits[bytes[3]]; return instr_mnemonics_index[bytes[1]]; } return instr_mnemonics[b]; diff --git a/src/z80_ops.inc.c b/src/z80_ops.inc.c index 288e56f..21a2ef8 100644 --- a/src/z80_ops.inc.c +++ b/src/z80_ops.inc.c @@ -936,17 +936,41 @@ static uint8_t z80_inst_dec_ss(Z80 *z80, uint8_t opcode) // RLC (IXY+d) -// RL m +// RL r -// RRC m +// RL (HL) -// RR m +// RL (IXY+d) -// SLA m +// RRC r -// SRA m +// RRC (HL) -// SRL m +// RRC (IXY+d) + +// RR r + +// RR (HL) + +// RR (IXY+d) + +// SLA r + +// SLA (HL) + +// SLA (IXY+d) + +// SRA r + +// SRA (HL) + +// SRA (IXY+d) + +// SRL r + +// SRL (HL) + +// SRL (IXY+d) // RLD @@ -1408,7 +1432,7 @@ static uint8_t z80_prefix_index(Z80 *z80, uint8_t opcode) */ static uint8_t z80_prefix_index_bits(Z80 *z80, uint8_t opcode) { - opcode = mmu_read_byte(z80->mmu, ++z80->regfile.pc); + opcode = mmu_read_byte(z80->mmu, z80->regfile.pc += 2); return (*instruction_table_index_bits[opcode])(z80, opcode); }