From 18d57acbf4ccd7220e59fe1f2ac1556837c5da83 Mon Sep 17 00:00:00 2001 From: "Leo C." Date: Wed, 10 Jul 2024 20:02:26 +0200 Subject: [PATCH] new command: dissassemle - Disassemble Z180 code from memory --- avr/Makefile | 2 +- avr/cmd_mem.c | 48 +++ avr/command_tbl.c | 6 +- avr/disas_z180.c | 725 +++++++++++++++++++++++++++++++++++++++++++ include/cmd_mem.h | 1 + include/disas_z180.h | 13 + 6 files changed, 793 insertions(+), 2 deletions(-) create mode 100644 avr/disas_z180.c create mode 100644 include/disas_z180.h diff --git a/avr/Makefile b/avr/Makefile index 89d13a0..d6c2e0f 100644 --- a/avr/Makefile +++ b/avr/Makefile @@ -15,7 +15,7 @@ SRC += cmd_date.c cmd_mem.c cmd_gpio.c cmd_attach.c SRC += cmd_loadihex.c cmd_loadcpm3.c cmd_sd.c cmd_fat.c SRC += env.c con-utils.c print-utils.c getopt-min.c eval_arg.c SRC += timer.c serial.c i2c.c bcd.c pcf8583.c mmc.c strerror.c -SRC += background.c z180-serv.c z80-if.c gpio.c +SRC += background.c z180-serv.c z80-if.c gpio.c disas_z180.c FATFSDIR := ../fatfs/source FATFS := $(FATFSDIR)/ff.c $(FATFSDIR)/ffunicode.c diff --git a/avr/cmd_mem.c b/avr/cmd_mem.c index 3e18770..85b5a44 100644 --- a/avr/cmd_mem.c +++ b/avr/cmd_mem.c @@ -23,6 +23,7 @@ #include "eval_arg.h" #include "timer.h" #include "z80-if.h" +#include "disas_z180.h" #include "debug.h" @@ -33,6 +34,7 @@ /* Display values from last command. * Memory modify remembered values are different from display memory. */ +static uint32_t disas_last_addr; static uint32_t dp_last_addr; static uint32_t dp_last_length = 0x100; static uint32_t mm_last_addr; @@ -66,6 +68,52 @@ command_ret_t do_mem_size(cmd_tbl_t *cmdtp UNUSED, uint_fast8_t flag UNUSED, int return CMD_RET_SUCCESS; } +/* +* Disassemble code from memory +* +* Usage: +* disassemble address [# of lines] +* + */ +command_ret_t do_disas(cmd_tbl_t *cmdtp, uint_fast8_t flag, int argc, char * const argv[]) +{ + (void) cmdtp; + + /* We use the last specified parameters, unless new ones are + * entered. + */ + uint32_t addr = disas_last_addr; + int length = 16; + int ret = CMD_RET_SUCCESS; + + if (argc < 2) + return CMD_RET_USAGE; + + if ((flag & CMD_FLAG_REPEAT) == 0) { + /* Address is specified since argc > 1 */ + addr = eval_arg(argv[1], NULL); + addr += base_address; + + /* If another parameter, it is the length (Number of lines) to display. */ + if (argc > 2) + length = (int) eval_arg(argv[2], NULL); + } + + z80_bus_request_or_exit(); + clear_ctrlc(); /* forget any previous Control-C */ + for (; length > 0; --length) { + addr = dis_decode(addr); + if (had_ctrlc() || ctrlc()) { + ret = CMD_RET_FAILURE; + break; + } + } + z80_bus_cmd(Release); + disas_last_addr = addr; + + return ret; +} + /* Memory Display * * Syntax: diff --git a/avr/command_tbl.c b/avr/command_tbl.c index 5a63e76..053b856 100644 --- a/avr/command_tbl.c +++ b/avr/command_tbl.c @@ -248,7 +248,11 @@ CMD_TBL_ITEM( "\n" " is a comma separated list of numbers or ranges, i.e. \"0,9,3-6\"\n" ), - +CMD_TBL_ITEM( + disasemble, 3, CTBL_RPT, do_disas, + "Disassemble from memory", + "address [# of lines]" +), CMD_TBL_ITEM( md, 3, CTBL_RPT, do_mem_md, "memory display", diff --git a/avr/disas_z180.c b/avr/disas_z180.c new file mode 100644 index 0000000..b7a7eae --- /dev/null +++ b/avr/disas_z180.c @@ -0,0 +1,725 @@ +/* + * (C) Copyright 2014,2018 Leo C. + * + */ + +#include "common.h" +#include "z80-if.h" +#include "disas_z180.h" + +/* + * t_MNEMONICS + */ +enum { + /* 1-byte other */ + i_, iNOP, iLD, iINC, iDEC, iDJNZ, iJR, iHALT, /* 0 .. 7 */ + iRET, iPOP, iJP, iCALL, iPUSH, iRST, iOUT, iEXX, /* 8 .. 15 */ + iIN, iEX, iDI, iEI, /* 16 .. 19 */ + /* CB bit */ + iBIT, iRES, iSET, /* 20 .. 22 */ + /* ED */ + iNEG, iRETN, iRETI, iIM, iRRD, iRLD, /* 23 .. 28 */ + /* ED Z180 */ + iIN0, iOUT0, iTST, iMLT, iTSTIO, + iSLP, iOTIM, iOTDM, iOTIMR, iOTDMR, /* 29 .. 38 */ + +//i_opc_alu equ opc_index + /* 1-byte "alu" */ + iADD, iADC, iSUB, iSBC, iAND, iXOR, iOR, iCP, /* 39 .. 46 */ + /* 1-byte no arguments */ + iRLCA, iRRCA, iRLA, iRRA, iDAA, iCPL, iSCF, iCCF, /* 47 .. 54 */ + /* CB rot */ + iRLC, iRRC, iRL, iRR, iSLA, iSRA, iSLL, iSRL, /* 55 .. 62 */ + +//i_opc_bli equ opc_index + /* ED Block instr (bli) */ + iLDI, iCPI, iINI, iOUTI, iLDD, iCPD, iIND, iOUTD, /* 63 .. 70 */ + iLDIR,iCPIR,iINIR,iOTIR, iLDDR,iCPDR,iINDR,iOTDR /* 71 .. 78 */ +} mnemo_index; + +#define i_opc_alu 39 +#define i_opc_bli 63 + +//t_MNEMONICS: +const FLASH uint8_t mnemonics[] = { + '?' + 0x80, /* 1-byte other */ + 'N','O','P', + 0x80, + 'L','D' + 0x80, + 'I','N','C' + 0x80, + 'D','E','C' + 0x80, + 'D','J','N','Z' + 0x80, + 'J','R' + 0x80, + 'H','A','L','T' + 0x80, + 'R','E','T' + 0x80, + 'P','O','P' + 0x80, + 'J','P' + 0x80, + 'C','A','L','L' + 0x80, + 'P','U','S','H' + 0x80, + 'R','S','T' + 0x80, + 'O','U','T' + 0x80, + 'E','X','X' + 0x80, + 'I','N' + 0x80, + 'E','X' + 0x80, + 'D','I' + 0x80, + 'E','I' + 0x80, + 'B','I','T' + 0x80, /* CB bit */ + 'R','E','S' + 0x80, + 'S','E','T' + 0x80, + 'N','E','G' + 0x80, + 'R','E','T','N' + 0x80, + 'R','E','T','I' + 0x80, + 'I','M' + 0x80, + 'R','R','D' + 0x80, + 'R','L','D' + 0x80, + 'I','N','0' + 0x80, /* Z180 */ + 'O','U','T','0' + 0x80, + 'T','S','T' + 0x80, + 'M','L','T' + 0x80, + 'T','S','T','I','O' + 0x80, + 'S','L','P' + 0x80, + 'O','T','I','M' + 0x80, + 'O','T','D','M' + 0x80, + 'O','T','I','M','R' + 0x80, + 'O','T','D','M','R' + 0x80, + 'A','D','D' + 0x80, /* 1-byte "alu" */ + 'A','D','C' + 0x80, + 'S','U','B' + 0x80, + 'S','B','C' + 0x80, + 'A','N','D' + 0x80, + 'X','O','R' + 0x80, + 'O','R' + 0x80, + 'C','P' + 0x80, + 'R','L','C','A' + 0x80, /* 1-byte no arguments */ + 'R','R','C','A' + 0x80, + 'R','L','A' + 0x80, + 'R','R','A' + 0x80, + 'D','A','A' + 0x80, + 'C','P','L' + 0x80, + 'S','C','F' + 0x80, + 'C','C','F' + 0x80, + 'R','L','C' + 0x80, /* CB rot */ + 'R','R','C' + 0x80, + 'R','L' + 0x80, + 'R','R' + 0x80, + 'S','L','A' + 0x80, + 'S','R','A' + 0x80, + 'S','L','L' + 0x80, + 'S','R','L' + 0x80, + 'L','D','I' + 0x80, /* ED Block instr (bli) */ + 'C','P','I' + 0x80, + 'I','N','I' + 0x80, + 'O','U','T','I' + 0x80, + 'L','D','D' + 0x80, + 'C','P','D' + 0x80, + 'I','N','D' + 0x80, + 'O','U','T','D' + 0x80, + 'L','D','I','R' + 0x80, + 'C','P','I','R' + 0x80, + 'I','N','I','R' + 0x80, + 'O','T','I','R' + 0x80, + 'L','D','D','R' + 0x80, + 'C','P','D','R' + 0x80, + 'I','N','D','R' + 0x80, + 'O','T','D','R' + 0x80, +}; + +//------------------------------------------------------------------------------- +// +// GROUP2, GROUP1 and GROUP3 are instruction decoding tables and have +// the following structure: +// +// [ mask { mode ( match , index ) } 0FFH ] 0. +// +// The repeating group ( match , index ) terminates when the MSB of the +// index byte is set. The interpretation of the "mode" byte is +// explained in the documentation to datasheet OPRNDZ. +// + +// + +//const FLASH uint8_t dec_tab2 + +struct dec_tab { + uint8_t group2[18]; /* GROUP2: CB group */ + uint8_t group1[123]; /* GROUP1: Main group */ + uint8_t group3[92]; /* GROUP3, ED group */ +} __attribute__((__packed__)); + +const FLASH struct dec_tab dec_tab = { + .group2 = { + 0xC0,0x36, //mask, mode + 0x40,iBIT, // bit b,g + 0x80,iRES, // res b,g + 0xC0,iSET+0x80, // set b,g + 0xFF, // + 0xF8,0x00, //mask, mode + 0x30,i_+0x80, // (sll g) + 0xFF, // + 0xC0,0x06, //mask, mode + 0x00,iRLC+0x80, // rlc g ... srl g + }, + .group1 = { + 0xFF,0x00, //mask, mode + 0x00,iNOP, // NOP + 0x76,iHALT, // HALT + 0xC9,iRET, // RET + 0xD9,iEXX, // EXX + 0xF3,iDI, // DI + 0xFB,iEI+0x80, // EI //14 + 0x04, //mode + 0x08,iEX+0x80, // + 0x01, + 0x10,iDJNZ, + 0x18,iJR+0x80, + 0xAF, + 0x22,iLD+0x80, + 0xFA, + 0x2A,iLD+0x80, + 0xA7, + 0x32,iLD+0x80, + 0x7A, + 0x3A,iLD+0x80, + 0x03, + 0xC3,iJP, + 0xCD,iCALL+0x80, + 0x97, + 0xD3,iOUT+0x80, + 0x79, + 0xDB,iIN+0x80, + 0x5F, + 0xE3,iEX+0x80, + 0x0E, + 0xE9,iJP+0x80, + 0x05, + 0xEB,iEX+0x80, // + 0xDF, + 0xF9,iLD+0x80, + 0xFF, //44 + + 0xC0, //mask + 0xB6, //mode r[y],r[z] + 0x40,iLD+0x80, + 0x06, //mode alu[y],r[z] + 0x80,iADD+0x80, + 0xFF, //8 + + 0xC7, //mask + 0x0B, + 0x04,iINC, // inc r[y] + 0x05,iDEC+0x80, // dec r[y] + 0xB2, + 0x06,iLD+0x80, // ld r[y],nn + 0x00, //mode + 0x07,iRLCA+0x80, // rlca ... + 0x20, + 0xC0,iRET+0x80, // ret cc + 0x23, + 0xC2,iJP, // jp cc,mn + 0xC4,iCALL+0x80, // call cc,mn + 0x10, + 0xC7,iRST+0x80, // rst + 0x02, //mode alu[y] n + 0xC6,iADD+0x80, // add ... + 0xFF, //27 + + 0xCF, + 0xD3, + 0x01,iLD+0x80, // ld ww,mn + 0x0D, + 0x03,iINC, // inc rp + 0x0B,iDEC+0x80, // dec rp + 0xFD, + 0x09,iADD+0x80, // add hl,rp + 0x60, + 0xC1,iPOP, // pop rp2 + 0xC5,iPUSH+0x80, // push rp2 + 0xFF, //18 + + 0xE7, + 0x21, + 0x20,iJR+0x80, //jr cc, + 0xFF, + + 0xEF, + 0xE7, + 0x02,iLD+0x80, // ld (rp),a //rp=bc,de + 0x7E, + 0x0A,iLD+0x80, // ld a,(rp) //rp=bc,de //12 + }, + .group3 = { + 0xFF,0x00, // + 0x44,iNEG, // NEG + 0x45,iRETN, // RETN + 0x4D,iRETI, // RETI + 0x4E,i_, // (IM 0) + 0x67,iRRD, // RRD + 0x6F,iRLD, // RLD + 0x76,iSLP, // slp + 0x83,iOTIM, // otim + 0x93,iOTIMR, // otimr + 0x8B,iOTDM, // otdm + 0x9B,iOTDMR, // otdmr + 0x31,i_, // (OUT0 (m),0) + 0x71,i_+0x80, // (OUT (C),0) + 0x09, + 0x30,iIN0+0x80, // in0 (m) + 0x02, + 0x64,iTST, // tst m + 0x74,iTSTIO+0x80, // tstio m + 0x80, + 0x70,iIN+0x80, // IN (C) + 0xFF, //40 + + 0xC7, + 0x0b, + 0x04,iTST+0x80, // tst r + 0xB8, + 0x40,iIN+0x80, // IN r,(C) + 0xB9, + 0x00,iIN0+0x80, // IN0 r,(m) + 0x8B, // + 0x41,iOUT+0x80, // OUT (C),r + 0x9B, // + 0x01,iOUT0+0x80, // UT0 (m),r + 0xFF, // //17 + + 0xCF, // + 0xFD, // + 0x42,iSBC, // sbc hl,rp + 0x4A,iADC+0x80, // adc hl,rp + 0xAD, // + 0x43,iLD+0x80, // LD (nn),rp + 0xDA, // + 0x4B,iLD+0x80, // LD rp,(nn) + 0x0D, + 0x4C,iMLT+0x80, //mlt rp + 0xFF, // //16 + + 0xE7, // + 0x40, // + 0x46,iIM+0x80, // IM x + 0xFF, // + + 0xF7, // + 0xC7, // + 0x47,iLD+0x80, // LD i|r,A + 0x7C, // + 0x57,iLD+0x80, // LD A,i|r + 0xFF, + + 0xE4, // + 0x00, // + 0xA0,iLDI+0x80, // LDI ... + 0xFF, // + + 0x00 //19 + } +}; + + +//------------------------------------------------------------------------------- +// +// Disassemble and output Z80 machine code operand +// +// Index OPRND1 OPRND2 +// ----------------------------------------------------------- +// 1 RST address Relative address +// 2 Condition Immediate byte +// 3 Bit number Immediate word +// 4 Interrupt mode AF,AF' +// 5 (SP) DE,HL +// 6 Register pair 8-bit source +// ----------------------------------------------------------- +// 7 A +// 8 (C) +// 9 (port number) +// A (Absolute address) +// B 8-bit destination +// C I or R +// D 16-bit register +// E Address in 16-bit register +// F Index register +// +// Input: +// A: opcode +// B: operand index +// DE: Address of next instruction byte +// HL: Address of next free byte in output buffer +// (iy+0): Bit = 1: Print opcodes +// (iy+1): index register flag (1=IX, 2=IY, else 0) +// (iy+2): displacement for any indexed instruction +// (iy+3): no. of instraction bytes fetched +// +// Output: +// Operand in output buffer +// DE, HL updated +// AF, BC destroyed +// +// +//------------------------------------------------------------------------------- + +enum { + irR8 = 0, irPA = 6, irRA = 7, irIR = 8, + irAFAF= 10, irDEHL = 11, irR16 = 12, irINDX = 16, + irSP = 19, irCOND = 20, irINTMOD= 28 +} reg_index; + +const FLASH uint8_t op_register[] = { + 'B' + 0x80, // 0 + 'C' + 0x80, // + 'D' + 0x80, // + 'E' + 0x80, // + 'H' + 0x80, // + 'L' + 0x80, // + '(','C',')' + 0x80, // 6 + 'A' + 0x80, // + 'I' + 0x80, // 8 + 'R' + 0x80, // + 'A','F',',','A','F','\'' + 0x80, //10 + 'D','E',',','H','L' + 0x80, // + 'B','C' + 0x80, //12 + 'D','E' + 0x80, // + 'A','F' + 0x80, // + 'S','P' + 0x80, // + 'H','L' + 0x80, //16 + 'I','X' + 0x80, // + 'I','Y' + 0x80, // + '(','S','P',')' + 0x80, //19 + 'N','Z' + 0x80, //20 + 'Z' + 0x80, // + 'N','C' + 0x80, // + 'C' + 0x80, // + 'P','O' + 0x80, // + 'P','E' + 0x80, // + 'P' + 0x80, // + 'M' + 0x80, // + '0' + 0x80, //28 + '?' + 0x80, // + '1' + 0x80, // + '2' + 0x80, // +}; + +//------------------------------------------------------------------------------- + +typedef struct disas_data_s disas_data_t; +struct disas_data_s { + uint32_t address; + uint8_t opcode; + int8_t opc_displacement; + uint8_t indexflag; + uint8_t bytes_fetched; + int8_t outbufpos; + char outbuf[18]; +}; + +static +void xtract(uint8_t index, const FLASH uint8_t *strlist, disas_data_t *dat) +{ + uint8_t ch; + + while (index != 0) { + while ((*strlist++ & 0x80) == 0) + ; + --index; + } + do { + ch = *strlist++; + dat->outbuf[dat->outbufpos++] = ch & 0x7f; + } while ((ch & 0x80) == 0); +} + +static +uint8_t op_fetch(uint32_t addr) +{ + uint8_t op = z80_read(addr); + + return op; +} + +static +uint8_t op_fetch_print(disas_data_t *dat) +{ + uint8_t opc = op_fetch(dat->address); + ++dat->address; + ++dat->bytes_fetched; + printf_P(PSTR("%02X "), opc); + + return opc; +} + + +static +void put_char(uint8_t ch, disas_data_t *dat) +{ + dat->outbuf[dat->outbufpos++] = ch; +} + +static +void put_digit(uint8_t digit, disas_data_t *dat) +{ + digit &= 0xf; + if (digit > 9) + digit += (-10 + 'A'-'0'); + digit += '0'; + + put_char(digit, dat); +} + + + +static +void put_hex(uint8_t byte, disas_data_t *dat) +{ + put_digit(byte >> 4, dat); + put_digit(byte, dat); +} + +static +void put_hex_16(uint16_t word, disas_data_t *dat) +{ + put_hex(word >> 8, dat); + put_hex(word, dat); +} + +static +void do_op_reg16(disas_data_t *dat) +{ + uint8_t op = dat->opcode >> 3; + op = ((op >> 1) & 0x3) + irR16; + if (op == 2 + irR16) + op = dat->indexflag + irINDX; + xtract(op, op_register, dat); +} + +static +void do_op_8bit_src_dst(uint8_t op, disas_data_t *dat) +{ + op = op & 0x07; + if (op == 6) { + put_char('(', dat); + xtract(dat->indexflag + irINDX, op_register, dat); + if (dat->indexflag != 0) { + char c = '+'; + int d = dat->opc_displacement; + if (d < 0) { + c = '-'; + d = -d; + } + put_char(c, dat); + put_hex (d & 0xff, dat); + } + put_char(')', dat); + } else + xtract(op, op_register, dat); +} + +static +void do_operand(uint8_t mode, disas_data_t *dat) +{ + uint8_t op1; + + switch(mode) { + case 0: + break; + case 1: /* RST address */ + put_hex (dat->opcode & 0x38, dat); + break; + case 2: /* Op1 i2: Condition */ + op1 = dat->opcode >> 3; + if ((op1 & 0x10) == 0) op1 &= 3; + op1 = (op1 & 7) + irCOND; + xtract(op1, op_register, dat); + break; + case 3: /* Bit number */ + op1 = dat->opcode >> 3; + op1 &= 0x7; + put_digit (op1, dat); + break; + case 4: /* Int mode */ + op1 = dat->opcode >> 3; + op1 = (op1 & 0x03) + irINTMOD; + xtract(op1, op_register, dat); + break; + case 5: /* (SP) */ + xtract(irSP, op_register, dat); + break; + case 6: /* Register pair */ + op1 = dat->opcode >> 3; + op1 = (op1 >> 1) & 0x03; + if (op1 == 2) { + op1 = dat->indexflag + irINDX; + } else { + if (op1 == 3) --op1; + op1 += irR16; + } + xtract(op1, op_register, dat); + break; + case 7: /* A */ + xtract(irRA, op_register, dat); + break; + case 8: /* (C) */ + xtract(irPA, op_register, dat); + break; + case 9: /* (port number) */ + put_char('(', dat); + op1 = op_fetch_print(dat); + put_hex(op1, dat); + put_char(')', dat); + break; + case 0xA: /* (Absolute address) */ + put_char('(', dat); + uint16_t arg16 = op_fetch_print(dat) + + (op_fetch_print(dat) << 8); + put_hex_16(arg16, dat); + put_char(')', dat); + break; + case 0xB: /* 8-bit destination */ + op1 = dat->opcode >> 3; + do_op_8bit_src_dst(op1,dat); + break; + case 0xC: /* I or R */ + op1 = dat->opcode >> 3; + op1 = op1 & 0x9; + xtract(op1, op_register, dat); + break; + case 0xD: /* 16-bit register */ + do_op_reg16(dat); + break; + case 0xE: /* Address in 16-bit register */ + put_char('(', dat); + do_op_reg16(dat); + put_char(')', dat); + break; + case 0xF: /* Index register */ + op1 = dat->indexflag + irINDX; + xtract(op1, op_register, dat); + break; + case 0x10: + break; + case 0x11: /* Relative address */ + op1 = op_fetch_print(dat); + uint16_t dst = dat->address + (int8_t) op1; + put_hex_16(dst, dat); + break; + case 0x12: /* Immediate byte */ + op1 = op_fetch_print(dat); + put_hex(op1, dat); + break; + case 0x13: ; /* Immediate word */ + uint16_t imm16 = op_fetch_print(dat) + + (op_fetch_print(dat) << 8); + put_hex_16(imm16, dat); + break; + case 0x14: /* AF,AF' */ + xtract(irAFAF, op_register, dat); + break; + case 0x15: /* DE,HL */ + xtract(irDEHL, op_register, dat); + break; + case 0x16: /* 8-bit source */ + do_op_8bit_src_dst(dat->opcode,dat); + break; + } +} + +uint32_t dis_decode(uint32_t addr) +{ + disas_data_t data; + + memset(&data, 0, sizeof(data)); + data.address = addr; + + uint8_t op; + uint8_t iflag; + uint8_t mnemi; + uint8_t mask; + uint8_t mode; + + printf_P(PSTR("%04X "), data.address); + + const FLASH uint8_t *decodep = dec_tab.group3; + + do { + iflag = 0; + op = op_fetch_print(&data); + if (op == 0xed) { + } else if (op == 0xdd) { + iflag = 1; + } else if (op == 0xfd) { + iflag = 2; + } else { + break; + } + data.indexflag = iflag; + } while (iflag != 0); + + if (op != 0xed) { + if (data.indexflag != 0) { + if ((op == 0xcb) || ((op & 0x44) == 0x04) || ((op & 0xc0) == 0x40)) { + data.opc_displacement = op_fetch_print(&data); + } + } + if (op != 0xcb) { + decodep = dec_tab.group1; + } else { + decodep = dec_tab.group2; + op = op_fetch_print(&data); + } + } else { + op = op_fetch_print(&data); + } + + data.opcode = op; + + mnemi = 0; + while ((mask = *decodep++) != 0) { //NEWMSK + + uint8_t opmask = op & mask; + + while ((mode = *decodep++) != 0xff) { //NEWMOD + + uint8_t opmatch; + uint8_t imatch; + do { + opmatch = *decodep++; + imatch = *decodep++; + if (opmatch == opmask) { + mnemi = imatch & 0x7f; + goto matchfound; + } + } while ((imatch & 0x80) == 0); + } + } //TABEND +matchfound: + + /* block instruction? */ + if (mnemi >= iLDI) { + mnemi = mnemi + (op & 0x03) + ((op >> 1) & 0x0c); + } else + /* Alu op? */ + if ((mnemi >= iADD) && ((mode & 0x80) == 0)) { + mnemi = mnemi + ((op >> 3) & 0x07); + } + + xtract(mnemi, mnemonics, &data); + while (data.outbufpos < 6) + put_char(' ', &data); + + uint8_t w = (mode & 0xf0) >> 4; + if (w != 0) { + do_operand(w, &data); + if (mode & 0x0f) + put_char(',', &data); + } + w = mode & 0x0f; + if (w != 0) { + if (w < 7) + w += 0x10; + do_operand(w, &data); + } + for (uint8_t i = data.bytes_fetched; i < 4; i++) + printf_P(PSTR(" ")); + printf_P(PSTR("%s\n"), data.outbuf); + + return data.address; +} diff --git a/include/cmd_mem.h b/include/cmd_mem.h index 4b370cc..43710c8 100644 --- a/include/cmd_mem.h +++ b/include/cmd_mem.h @@ -11,6 +11,7 @@ command_ret_t do_mem_size(cmd_tbl_t *, uint_fast8_t, int, char * const []); command_ret_t do_mem_md(cmd_tbl_t *, uint_fast8_t, int, char * const []); +command_ret_t do_disas(cmd_tbl_t *, uint_fast8_t, int, char * const []); command_ret_t do_mem_mm(cmd_tbl_t *, uint_fast8_t, int, char * const []); command_ret_t do_mem_nm(cmd_tbl_t *, uint_fast8_t, int, char * const []); command_ret_t do_mem_mw(cmd_tbl_t *, uint_fast8_t, int, char * const []); diff --git a/include/disas_z180.h b/include/disas_z180.h new file mode 100644 index 0000000..a4a0b58 --- /dev/null +++ b/include/disas_z180.h @@ -0,0 +1,13 @@ +/* + * (C) Copyright 2024 Leo C. + * + * SPDX-License-Identifier: GPL-2.0 + */ +#ifndef DISDAS_Z180_H +#define DISDAS_Z180_H + +#include + +uint32_t dis_decode(uint32_t addr); + +#endif -- 2.39.2