Mercurial > repos > blastem
changeset 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 | 209a37eed3e7 |
children | d3066ceb29d1 |
files | Makefile z80inst.c z80inst.h zdis.c |
diffstat | 4 files changed, 770 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Sun Jan 20 19:10:29 2013 -0800 +++ b/Makefile Sun Jan 20 19:11:24 2013 -0800 @@ -7,6 +7,9 @@ dis : dis.o 68kinst.o $(CC) -o dis dis.o 68kinst.o + +zdis : zdis.o z80inst.o + $(CC) -o zdis zdis.o z80inst.o trans : trans.o 68kinst.o gen_x86.o m68k_to_x86.o runtime.o mem.o $(CC) -o trans trans.o 68kinst.o gen_x86.o m68k_to_x86.o runtime.o mem.o @@ -29,5 +32,8 @@ %.bin : %.s68 vasmm68k_mot -Fbin -m68000 -no-opt -spaces -o $@ $< +%.bin : %.sz8 + vasmz80_mot -Fbin -spaces -o $@ $< + clean : rm -rf dis trans stateview test_x86 gen_fib *.o
--- /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; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/z80inst.h Sun Jan 20 19:11:24 2013 -0800 @@ -0,0 +1,118 @@ +#include <stdint.h> + +enum { + Z80_LD, + Z80_PUSH, + Z80_POP, + Z80_EX, + Z80_EXX, + Z80_LDI, + Z80_LDIR, + Z80_LDD, + Z80_LDDR, + Z80_CPI, + Z80_CPIR, + Z80_CPD, + Z80_CPDR, + Z80_ADD, + Z80_ADC, + Z80_SUB, + Z80_SBC, + Z80_AND, + Z80_OR, + Z80_XOR, + Z80_CP, + Z80_INC, + Z80_DEC, + Z80_DAA, + Z80_CPL, + Z80_NEG, + Z80_CCF, + Z80_SCF, + Z80_NOP, + Z80_HALT, + Z80_DI, + Z80_EI, + Z80_IM, + Z80_RLC, + Z80_RL, + Z80_RRC, + Z80_RR, + Z80_SL, + Z80_RLD, + Z80_RRD, + Z80_BIT, + Z80_SET, + Z80_RES, + Z80_JP, + Z80_JPCC, + Z80_JR, + Z80_JRCC, + Z80_DJNZ, + Z80_CALL, + Z80_CALLCC, + Z80_RET, + Z80_RETCC, + Z80_RETI, + Z80_RETN, + Z80_RST, + Z80_IN, + Z80_INI, + Z80_INIR, + Z80_INDR, + Z80_OUT, + Z80_OUTI, + Z80_OTIR, + Z80_OUTD, + Z80_OTDR +}; + +enum { + Z80_B=0, + Z80_C, + Z80_D, + Z80_E, + Z80_H, + Z80_L, + Z80_A=7, + Z80_BC, + Z80_DE, + Z80_HL, + Z80_SP, + Z80_AF, + Z80_USE_IMMED, + Z80_UNUSED +}; + +enum { + Z80_CC_NZ, + Z80_CC_Z, + Z80_CC_NC, + Z80_CC_C, + Z80_CC_PO, + Z80_CC_PE, + Z80_CC_P, + Z80_CC_M +}; + +enum { + Z80_REG, + Z80_REG_INDIRECT, + Z80_IMMED, + Z80_IMMED_INDIRECT, + Z80_REG_DISPLACE +}; +#define Z80_DIR 0x80 + +typedef struct { + uint8_t op; + uint8_t reg; + uint8_t addr_mode; + uint8_t ea_reg; + uint16_t immed; +} z80inst; + +uint8_t * z80_decode(uint8_t * istream, z80inst * decoded); +int z80_disasm(z80inst * decoded, char * dst); + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/zdis.c Sun Jan 20 19:11:24 2013 -0800 @@ -0,0 +1,193 @@ +#include "z80inst.h" +#include <stdio.h> +#include <stdlib.h> + +uint8_t visited[(64*1024)/8]; +uint8_t label[(64*1024)/8]; + +void visit(uint16_t address) +{ + visited[address/8] |= 1 << (address % 8); +} + +void reference(uint16_t address) +{ + //printf("referenced: %X\n", address); + label[address/8] |= 1 << (address % 8); +} + +uint8_t is_visited(uint16_t address) +{ + return visited[address/8] & (1 << (address % 8)); +} + +uint8_t is_label(uint16_t address) +{ + return label[address/8] & (1 << (address % 8)); +} + +typedef struct deferred { + uint16_t address; + struct deferred *next; +} deferred; + +deferred * defer(uint16_t address, deferred * next) +{ + if (is_visited(address)) { + return next; + } + //printf("deferring %X\n", address); + deferred * d = malloc(sizeof(deferred)); + d->address = address; + d->next = next; + return d; +} + +uint8_t labels = 0; +uint8_t addr = 0; +uint8_t only = 0; + +int main(int argc, char ** argv) +{ + long filesize; + uint8_t *filebuf; + char disbuf[1024]; + z80inst instbuf; + uint8_t * cur; + FILE * f = fopen(argv[1], "rb"); + fseek(f, 0, SEEK_END); + filesize = ftell(f); + fseek(f, 0, SEEK_SET); + filebuf = malloc(filesize); + fread(filebuf, 1, filesize, f); + fclose(f); + deferred *def = NULL, *tmpd; + for(uint8_t opt = 2; opt < argc; ++opt) { + if (argv[opt][0] == '-') { + FILE * address_log; + switch (argv[opt][1]) + { + case 'l': + labels = 1; + break; + case 'a': + addr = 1; + break; + case 'o': + only = 1; + break; + case 'f': + opt++; + if (opt >= argc) { + fputs("-f must be followed by a filename\n", stderr); + exit(1); + } + address_log = fopen(argv[opt], "r"); + if (!address_log) { + fprintf(stderr, "Failed to open %s for reading\n", argv[opt]); + exit(1); + } + while (fgets(disbuf, sizeof(disbuf), address_log)) { + if (disbuf[0]) { + uint16_t address = strtol(disbuf, NULL, 16); + if (address) { + def = defer(address, def); + reference(address); + } + } + } + } + } else { + uint16_t address = strtol(argv[opt], NULL, 16); + def = defer(address, def); + reference(address); + } + } + uint16_t start = 0; + uint8_t *encoded, *next; + uint32_t size; + if (!def || !only) { + def = defer(start, def); + } + uint16_t address; + while(def) { + do { + encoded = NULL; + address = def->address; + if (!is_visited(address)) { + encoded = filebuf + address; + } + tmpd = def; + def = def->next; + free(tmpd); + } while(def && encoded == NULL); + if (!encoded) { + break; + } + for(;;) { + if (address > filesize) { + break; + } + visit(address); + next = z80_decode(encoded, &instbuf); + address += (next-encoded); + encoded = next; + + //m68k_disasm(&instbuf, disbuf); + //printf("%X: %s\n", instbuf.address, disbuf); + if (instbuf.op == Z80_HALT || instbuf.op == Z80_RET || instbuf.op == Z80_RETI || instbuf.op == Z80_RETN || instbuf.op == Z80_RST) { + break; + } + switch (instbuf.op) + { + case Z80_JR: + address += instbuf.immed; + encoded = filebuf + address; + break; + case Z80_JRCC: + reference(address + instbuf.immed); + def = defer(address + instbuf.immed, def); + break; + case Z80_JP: + address = instbuf.immed; + encoded = filebuf + address; + break; + case Z80_JPCC: + case Z80_CALL: + case Z80_CALLCC: + reference(instbuf.immed); + def = defer(instbuf.immed, def); + break; + } + } + } + if (labels) { + for (address = filesize; address < (64*1024); address++) { + if (is_label(address)) { + printf("ADR_%X equ $%X\n", address, address); + } + } + puts(""); + } + for (address = 0; address < filesize; address++) { + if (is_visited(address)) { + encoded = filebuf + address; + z80_decode(encoded, &instbuf); + if (labels) { + /*m68k_disasm_labels(&instbuf, disbuf); + if (is_label(instbuf.address)) { + printf("ADR_%X:\n", instbuf.address); + } + if (addr) { + printf("\t%s\t;%X\n", disbuf, instbuf.address); + } else { + printf("\t%s\n", disbuf); + }*/ + } else { + z80_disasm(&instbuf, disbuf); + printf("%X: %s\n", address, disbuf); + } + } + } + return 0; +}