Mercurial > repos > blastem
diff z80inst.c @ 199:69585e7d474f
Add initial stab at Z80 decoder and disassembler
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 20 Jan 2013 19:11:24 -0800 |
parents | |
children | d3066ceb29d1 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/z80inst.c Sun Jan 20 19:11:24 2013 -0800 @@ -0,0 +1,453 @@ +#include "z80inst.h" +#include <string.h> +#include <stdio.h> + +z80inst z80_tbl_a[256] = { + //0 + {Z80_NOP, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_LD, Z80_BC, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_LD, Z80_A, Z80_REG_INDIRECT | Z80_DIR, Z80_BC, 0}, + {Z80_INC, Z80_BC, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_INC, Z80_B, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_DEC, Z80_B, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_LD, Z80_B, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_RLC, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_EX, Z80_AF, Z80_REG, Z80_AF, 0}, + {Z80_ADD, Z80_HL, Z80_REG, Z80_BC, 0}, + {Z80_LD, Z80_A, Z80_REG_INDIRECT, Z80_BC, 0}, + {Z80_DEC, Z80_BC, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_INC, Z80_C, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_DEC, Z80_C, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_LD, Z80_C, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_RRC, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, + //1 + {Z80_DJNZ, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_LD, Z80_DE, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_LD, Z80_A, Z80_REG_INDIRECT | Z80_DIR, Z80_DE, 0}, + {Z80_INC, Z80_DE, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_INC, Z80_D, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_DEC, Z80_D, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_LD, Z80_D, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_RL, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_JR, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_ADD, Z80_HL, Z80_REG, Z80_DE, 0}, + {Z80_LD, Z80_A, Z80_REG_INDIRECT, Z80_DE, 0}, + {Z80_DEC, Z80_DE, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_INC, Z80_E, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_DEC, Z80_E, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_LD, Z80_E, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_RR, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, + //2 + {Z80_JRCC, Z80_CC_NZ, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_LD, Z80_HL, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_LD, Z80_HL, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0}, + {Z80_INC, Z80_HL, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_INC, Z80_H, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_DEC, Z80_H, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_LD, Z80_H, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_DAA, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_JRCC, Z80_CC_Z, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_ADD, Z80_HL, Z80_REG, Z80_HL, 0}, + {Z80_LD, Z80_HL, Z80_IMMED_INDIRECT, Z80_IMMED, 0}, + {Z80_DEC, Z80_HL, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_INC, Z80_L, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_DEC, Z80_L, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_LD, Z80_L, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_CPL, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, + //3 + {Z80_JRCC, Z80_CC_NC, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_LD, Z80_SP, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_LD, Z80_A, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0}, + {Z80_INC, Z80_SP, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_INC, Z80_UNUSED, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_DEC, Z80_UNUSED, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_LD, Z80_USE_IMMED, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0}, + {Z80_SCF, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_JRCC, Z80_CC_C, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_ADD, Z80_HL, Z80_REG, Z80_SP, 0}, + {Z80_LD, Z80_A, Z80_IMMED_INDIRECT, Z80_IMMED, 0}, + {Z80_DEC, Z80_SP, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_INC, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_DEC, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_LD, Z80_A, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_CCF, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, + //4 + {Z80_LD, Z80_B, Z80_REG, Z80_B, 0}, + {Z80_LD, Z80_B, Z80_REG, Z80_C, 0}, + {Z80_LD, Z80_B, Z80_REG, Z80_D, 0}, + {Z80_LD, Z80_B, Z80_REG, Z80_E, 0}, + {Z80_LD, Z80_B, Z80_REG, Z80_H, 0}, + {Z80_LD, Z80_B, Z80_REG, Z80_L, 0}, + {Z80_LD, Z80_B, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_LD, Z80_B, Z80_REG, Z80_A, 0}, + {Z80_LD, Z80_C, Z80_REG, Z80_B, 0}, + {Z80_LD, Z80_C, Z80_REG, Z80_C, 0}, + {Z80_LD, Z80_C, Z80_REG, Z80_D, 0}, + {Z80_LD, Z80_C, Z80_REG, Z80_E, 0}, + {Z80_LD, Z80_C, Z80_REG, Z80_H, 0}, + {Z80_LD, Z80_C, Z80_REG, Z80_L, 0}, + {Z80_LD, Z80_C, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_LD, Z80_C, Z80_REG, Z80_A, 0}, + //5 + {Z80_LD, Z80_D, Z80_REG, Z80_B, 0}, + {Z80_LD, Z80_D, Z80_REG, Z80_C, 0}, + {Z80_LD, Z80_D, Z80_REG, Z80_D, 0}, + {Z80_LD, Z80_D, Z80_REG, Z80_E, 0}, + {Z80_LD, Z80_D, Z80_REG, Z80_H, 0}, + {Z80_LD, Z80_D, Z80_REG, Z80_L, 0}, + {Z80_LD, Z80_D, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_LD, Z80_D, Z80_REG, Z80_A, 0}, + {Z80_LD, Z80_E, Z80_REG, Z80_B, 0}, + {Z80_LD, Z80_E, Z80_REG, Z80_C, 0}, + {Z80_LD, Z80_E, Z80_REG, Z80_D, 0}, + {Z80_LD, Z80_E, Z80_REG, Z80_E, 0}, + {Z80_LD, Z80_E, Z80_REG, Z80_H, 0}, + {Z80_LD, Z80_E, Z80_REG, Z80_L, 0}, + {Z80_LD, Z80_E, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_LD, Z80_E, Z80_REG, Z80_A, 0}, + //6 + {Z80_LD, Z80_H, Z80_REG, Z80_B, 0}, + {Z80_LD, Z80_H, Z80_REG, Z80_C, 0}, + {Z80_LD, Z80_H, Z80_REG, Z80_D, 0}, + {Z80_LD, Z80_H, Z80_REG, Z80_E, 0}, + {Z80_LD, Z80_H, Z80_REG, Z80_H, 0}, + {Z80_LD, Z80_H, Z80_REG, Z80_L, 0}, + {Z80_LD, Z80_H, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_LD, Z80_H, Z80_REG, Z80_A, 0}, + {Z80_LD, Z80_L, Z80_REG, Z80_B, 0}, + {Z80_LD, Z80_L, Z80_REG, Z80_C, 0}, + {Z80_LD, Z80_L, Z80_REG, Z80_D, 0}, + {Z80_LD, Z80_L, Z80_REG, Z80_E, 0}, + {Z80_LD, Z80_L, Z80_REG, Z80_H, 0}, + {Z80_LD, Z80_L, Z80_REG, Z80_L, 0}, + {Z80_LD, Z80_L, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_LD, Z80_L, Z80_REG, Z80_A, 0}, + //7 + {Z80_LD, Z80_B, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0}, + {Z80_LD, Z80_C, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0}, + {Z80_LD, Z80_D, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0}, + {Z80_LD, Z80_E, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0}, + {Z80_LD, Z80_H, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0}, + {Z80_LD, Z80_L, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0}, + {Z80_HALT, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_LD, Z80_A, Z80_REG_INDIRECT | Z80_DIR, Z80_HL, 0}, + {Z80_LD, Z80_A, Z80_REG, Z80_B, 0}, + {Z80_LD, Z80_A, Z80_REG, Z80_C, 0}, + {Z80_LD, Z80_A, Z80_REG, Z80_D, 0}, + {Z80_LD, Z80_A, Z80_REG, Z80_E, 0}, + {Z80_LD, Z80_A, Z80_REG, Z80_H, 0}, + {Z80_LD, Z80_A, Z80_REG, Z80_L, 0}, + {Z80_LD, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_LD, Z80_A, Z80_REG, Z80_A, 0}, + //8 + {Z80_ADD, Z80_A, Z80_REG, Z80_B, 0}, + {Z80_ADD, Z80_A, Z80_REG, Z80_C, 0}, + {Z80_ADD, Z80_A, Z80_REG, Z80_D, 0}, + {Z80_ADD, Z80_A, Z80_REG, Z80_E, 0}, + {Z80_ADD, Z80_A, Z80_REG, Z80_H, 0}, + {Z80_ADD, Z80_A, Z80_REG, Z80_L, 0}, + {Z80_ADD, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_ADD, Z80_A, Z80_REG, Z80_A, 0}, + {Z80_ADC, Z80_A, Z80_REG, Z80_B, 0}, + {Z80_ADC, Z80_A, Z80_REG, Z80_C, 0}, + {Z80_ADC, Z80_A, Z80_REG, Z80_D, 0}, + {Z80_ADC, Z80_A, Z80_REG, Z80_E, 0}, + {Z80_ADC, Z80_A, Z80_REG, Z80_H, 0}, + {Z80_ADC, Z80_A, Z80_REG, Z80_L, 0}, + {Z80_ADC, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_ADC, Z80_A, Z80_REG, Z80_A, 0}, + //9 + {Z80_SUB, Z80_A, Z80_REG, Z80_B, 0}, + {Z80_SUB, Z80_A, Z80_REG, Z80_C, 0}, + {Z80_SUB, Z80_A, Z80_REG, Z80_D, 0}, + {Z80_SUB, Z80_A, Z80_REG, Z80_E, 0}, + {Z80_SUB, Z80_A, Z80_REG, Z80_H, 0}, + {Z80_SUB, Z80_A, Z80_REG, Z80_L, 0}, + {Z80_SUB, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_SUB, Z80_A, Z80_REG, Z80_A, 0}, + {Z80_SBC, Z80_A, Z80_REG, Z80_B, 0}, + {Z80_SBC, Z80_A, Z80_REG, Z80_C, 0}, + {Z80_SBC, Z80_A, Z80_REG, Z80_D, 0}, + {Z80_SBC, Z80_A, Z80_REG, Z80_E, 0}, + {Z80_SBC, Z80_A, Z80_REG, Z80_H, 0}, + {Z80_SBC, Z80_A, Z80_REG, Z80_L, 0}, + {Z80_SBC, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_SBC, Z80_A, Z80_REG, Z80_A, 0}, + //A + {Z80_AND, Z80_A, Z80_REG, Z80_B, 0}, + {Z80_AND, Z80_A, Z80_REG, Z80_C, 0}, + {Z80_AND, Z80_A, Z80_REG, Z80_D, 0}, + {Z80_AND, Z80_A, Z80_REG, Z80_E, 0}, + {Z80_AND, Z80_A, Z80_REG, Z80_H, 0}, + {Z80_AND, Z80_A, Z80_REG, Z80_L, 0}, + {Z80_AND, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_AND, Z80_A, Z80_REG, Z80_A, 0}, + {Z80_XOR, Z80_A, Z80_REG, Z80_B, 0}, + {Z80_XOR, Z80_A, Z80_REG, Z80_C, 0}, + {Z80_XOR, Z80_A, Z80_REG, Z80_D, 0}, + {Z80_XOR, Z80_A, Z80_REG, Z80_E, 0}, + {Z80_XOR, Z80_A, Z80_REG, Z80_H, 0}, + {Z80_XOR, Z80_A, Z80_REG, Z80_L, 0}, + {Z80_XOR, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_XOR, Z80_A, Z80_REG, Z80_A, 0}, + //B + {Z80_OR, Z80_A, Z80_REG, Z80_B, 0}, + {Z80_OR, Z80_A, Z80_REG, Z80_C, 0}, + {Z80_OR, Z80_A, Z80_REG, Z80_D, 0}, + {Z80_OR, Z80_A, Z80_REG, Z80_E, 0}, + {Z80_OR, Z80_A, Z80_REG, Z80_H, 0}, + {Z80_OR, Z80_A, Z80_REG, Z80_L, 0}, + {Z80_OR, Z80_A, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_OR, Z80_A, Z80_REG, Z80_A, 0}, + {Z80_OR, Z80_CP, Z80_REG, Z80_B, 0}, + {Z80_OR, Z80_CP, Z80_REG, Z80_C, 0}, + {Z80_OR, Z80_CP, Z80_REG, Z80_D, 0}, + {Z80_OR, Z80_CP, Z80_REG, Z80_E, 0}, + {Z80_OR, Z80_CP, Z80_REG, Z80_H, 0}, + {Z80_OR, Z80_CP, Z80_REG, Z80_L, 0}, + {Z80_OR, Z80_CP, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_OR, Z80_CP, Z80_REG, Z80_A, 0}, + //C + {Z80_RETCC, Z80_CC_NZ, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_POP, Z80_BC, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_JPCC, Z80_CC_NZ, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_JP, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_CALLCC, Z80_CC_NZ, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_PUSH, Z80_BC, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_ADD, Z80_A, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x0}, + {Z80_RETCC, Z80_CC_Z, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_RET, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_JPCC, Z80_CC_Z, Z80_IMMED, Z80_UNUSED, 0}, + {0, 0, 0, 0, 0},//BITS Prefix + {Z80_CALLCC, Z80_CC_Z, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_CALL, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_ADC, Z80_A, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x8}, + //D + {Z80_RETCC, Z80_CC_NC, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_POP, Z80_DE, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_JPCC, Z80_CC_NC, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_OUT, Z80_A, Z80_IMMED_INDIRECT, Z80_UNUSED, 0}, + {Z80_CALLCC, Z80_CC_NC, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_PUSH, Z80_DE, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_SUB, Z80_A, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x10}, + {Z80_RETCC, Z80_CC_C, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_EXX, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_JPCC, Z80_CC_C, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_IN, Z80_A, Z80_IMMED_INDIRECT, Z80_UNUSED, 0}, + {Z80_CALLCC, Z80_CC_C, Z80_IMMED, Z80_UNUSED, 0}, + {0, 0, 0, 0, 0},//IX Prefix + {Z80_SBC, Z80_A, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x18}, + //E + {Z80_RETCC, Z80_CC_PO, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_POP, Z80_HL, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_JPCC, Z80_CC_PO, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_EX, Z80_HL, Z80_REG_INDIRECT | Z80_DIR, Z80_SP, 0}, + {Z80_CALLCC, Z80_CC_PO, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_PUSH, Z80_HL, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_AND, Z80_A, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x20}, + {Z80_RETCC, Z80_CC_PE, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_JP, Z80_UNUSED, Z80_REG_INDIRECT, Z80_HL, 0}, + {Z80_JPCC, Z80_CC_PE, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_EX, Z80_DE, Z80_REG, Z80_HL, 0}, + {Z80_CALLCC, Z80_CC_PE, Z80_IMMED, Z80_UNUSED, 0}, + {0, 0, 0, 0, 0},//EXTD Prefix + {Z80_XOR, Z80_A, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x28}, + //F + {Z80_RETCC, Z80_CC_P, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_POP, Z80_AF, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_JPCC, Z80_CC_P, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_DI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_CALLCC, Z80_CC_P, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_PUSH, Z80_AF, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_OR, Z80_A, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x30}, + {Z80_RETCC, Z80_CC_M, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_LD, Z80_SP, Z80_REG, Z80_HL, 0}, + {Z80_JPCC, Z80_CC_M, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_EI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, + {Z80_CALLCC, Z80_CC_M, Z80_IMMED, Z80_UNUSED, 0}, + {0, 0, 0, 0, 0},//IY Prefix + {Z80_CP, Z80_A, Z80_IMMED, Z80_UNUSED, 0}, + {Z80_RST, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 0x38} +}; + +uint8_t * z80_decode(uint8_t * istream, z80inst * decoded) +{ + if (*istream == 0xCB) { + } else if (*istream == 0xDD) { + } else if (*istream == 0xED) { + } else if (*istream == 0xFD) { + } else { + memcpy(decoded, z80_tbl_a + *istream, sizeof(z80inst)); + if (decoded->addr_mode == Z80_IMMED && decoded->op != Z80_RST) { + decoded->immed = *(++istream); + if (decoded->reg >= Z80_BC) { + decoded->immed |= *(++istream) << 8; + } else if (decoded->immed & 0x80) { + decoded->immed |= 0xFF00; + } + } else if (decoded->addr_mode == Z80_IMMED_INDIRECT) { + decoded->immed = *(++istream); + if (decoded->op != Z80_OUT && decoded->op != Z80_IN) { + decoded->immed |= *(++istream) << 8; + } + } else if (decoded->reg == Z80_USE_IMMED) { + decoded->immed = *(++istream); + } + } + return istream+1; +} + +char *z80_mnemonics[Z80_OTDR+1] = { + "ld", + "push", + "pop", + "ex", + "exx", + "ldi", + "ldir", + "ldd", + "lddr", + "cpi", + "cpir", + "cpd", + "cpdr", + "add", + "adc", + "sub", + "sbc", + "and", + "or", + "xor", + "cp", + "inc", + "dec", + "daa", + "cpl", + "neg", + "ccf", + "scf", + "nop", + "halt", + "di", + "ei", + "im", + "rlc", + "rl", + "rrc", + "rr", + "sl", + "rld", + "rrd", + "bit", + "set", + "res", + "jp", + "jp", + "jr", + "jr", + "djnz", + "call", + "call", + "ret", + "ret", + "reti", + "retn", + "rst", + "in", + "ini", + "inir", + "indr", + "out", + "outi", + "otir", + "outd", + "otdr" +}; + +char * z80_regs[Z80_USE_IMMED] = { + "b", + "c", + "d", + "e", + "h", + "l", + "", + "a", + "bc", + "de", + "hl", + "sp", + "af", +}; + +char * z80_conditions[Z80_CC_M+1] = { + "nz", + "z", + "nc", + "c", + "po", + "pe", + "p", + "m" +}; + +int z80_disasm(z80inst * decoded, char * dst) +{ + int len = sprintf(dst, "%s", z80_mnemonics[decoded->op]); + if (decoded->addr_mode & Z80_DIR) { + switch (decoded->addr_mode) + { + case Z80_REG: + len += sprintf(dst+len, " %s", z80_regs[decoded->ea_reg]); + break; + case Z80_REG_INDIRECT: + len += sprintf(dst+len, " (%s)", z80_regs[decoded->ea_reg]); + break; + case Z80_IMMED: + len += sprintf(dst+len, " %d", decoded->immed); + break; + case Z80_IMMED_INDIRECT: + len += sprintf(dst+len, " (%d)", decoded->immed); + break; + } + if (decoded->reg != Z80_UNUSED) { + if (decoded->op == Z80_JRCC || decoded->op == Z80_JPCC || decoded->op == Z80_CALLCC || decoded->op == Z80_RETCC) { + len += sprintf(dst+len, "%s %s", decoded->reg == Z80_UNUSED ? "" : "," , z80_conditions[decoded->reg]); + } else { + len += sprintf(dst+len, "%s %s", decoded->reg == Z80_UNUSED ? "" : "," , z80_regs[decoded->reg]); + } + } + } else { + if (decoded->reg != Z80_UNUSED) { + if (decoded->op == Z80_JRCC || decoded->op == Z80_JPCC || decoded->op == Z80_CALLCC || decoded->op == Z80_RETCC) { + len += sprintf(dst+len, " %s", z80_conditions[decoded->reg]); + } else { + len += sprintf(dst+len, " %s", z80_regs[decoded->reg]); + } + } + switch (decoded->addr_mode) + { + case Z80_REG: + len += sprintf(dst+len, "%s %s", decoded->reg == Z80_UNUSED ? "" : "," , z80_regs[decoded->ea_reg]); + break; + case Z80_REG_INDIRECT: + len += sprintf(dst+len, "%s (%s)", decoded->reg == Z80_UNUSED ? "" : "," , z80_regs[decoded->ea_reg]); + break; + case Z80_IMMED: + len += sprintf(dst+len, "%s %d", decoded->reg == Z80_UNUSED ? "" : "," , decoded->immed); + break; + case Z80_IMMED_INDIRECT: + len += sprintf(dst+len, "%s (%d)", decoded->reg == Z80_UNUSED ? "" : "," , decoded->immed); + break; + } + } + return len; +} +