]> cloudbase.mooo.com Git - z180-stamp.git/commitdiff
new command: dissassemle - Disassemble Z180 code from memory
authorLeo C. <erbl259-lmu@yahoo.de>
Wed, 10 Jul 2024 18:02:26 +0000 (20:02 +0200)
committerLeo C. <erbl259-lmu@yahoo.de>
Wed, 10 Jul 2024 18:02:26 +0000 (20:02 +0200)
avr/Makefile
avr/cmd_mem.c
avr/command_tbl.c
avr/disas_z180.c [new file with mode: 0644]
include/cmd_mem.h
include/disas_z180.h [new file with mode: 0644]

index 89d13a0b5e5bb62f7058a2eea3f767b041365e46..d6c2e0f5cd1d201e93d58a8d9586ad0dff1aa6d5 100644 (file)
@@ -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
index 3e187701bb19e66968dc49caadbcd1186fe409df..85b5a44b1b149beca230c674cab2d98bf2dc600d 100644 (file)
@@ -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:
index 5a63e7636b740806d382f8fa3e719d7db182646d..053b856e5e32dde540649d8e8c461c57a7643c44 100644 (file)
@@ -248,7 +248,11 @@ CMD_TBL_ITEM(
        "\n"
        "<pins> 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 (file)
index 0000000..b7a7eae
--- /dev/null
@@ -0,0 +1,725 @@
+/*
+ * (C) Copyright 2014,2018 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ */
+
+#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;
+}
index 4b370cc7b9985ef8966d37fdc9c3251c68afbfd4..43710c86fcaf95de3eac027059e66f0960aacd62 100644 (file)
@@ -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 (file)
index 0000000..a4a0b58
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * (C) Copyright 2024 Leo C. <erbl259-lmu@yahoo.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+#ifndef DISDAS_Z180_H
+#define DISDAS_Z180_H
+
+#include <stdint.h>
+
+uint32_t dis_decode(uint32_t addr);
+
+#endif