home *** CD-ROM | disk | FTP | other *** search
- /*
- dasm
-
- CP/M emulator - instruction disassembler
- Written by D'Arcy J.M. Cain
- darcy@druid
-
- */
-
- #include <stdio.h>
- #include <string.h>
- #include "cpm.h"
-
- #define get_prog_word(buf) (buf[1] + (buf[2] << 8))
- #define get_prog_byte(buf) (*buf)
-
- static char *get_b_reg(int reg)
- {
- switch(reg & 0x07)
- {
- case 7: return("A");
- case 6: return("(HL)");
- case 0: return("B");
- case 1: return("C");
- case 2: return("D");
- case 3: return("E");
- case 4: return("H");
- case 5: return("L");
- }
-
- return(NULL);
- }
-
- static char *get_w_reg(int reg)
- {
- switch (reg & 0x03)
- {
- case 2: return("HL");
- case 1: return("DE");
- case 0: return("BC");
- case 3: return("SP");
- }
-
- return(NULL);
- }
-
- static char *get_s_reg(int reg)
- {
- switch (reg & 0x03)
- {
- case 2: return("HL");
- case 1: return("DE");
- case 0: return("BC");
- case 3: return("AF");
- }
-
- return(NULL);
- }
-
- static int relative(int r)
- {
- if (r & 0x80)
- r |= -256;
-
- return(PC + r + 2);
- }
-
- static char *condition(int word)
- {
- switch (word & 0x07)
- {
- case 0: return("NZ");
- case 1: return("Z");
- case 2: return("NC");
- case 3: return("C");
- case 4: return("PO");
- case 5: return("PE");
- case 6: return("P");
- case 7: return("M");
- }
-
- return("\a* * * Internal error (condition()) * * *");
- }
-
- const char *dasm(const byte *buf)
- {
- static char str[32];
- char s[32];
-
- switch (*buf & 0xc0) /* get class of opcode */
- {
- case 0x40: /* data transfer */
- if (*buf == 0x76) /* HALT - special case */
- return("HALT");
-
- sprintf(str, "LD\t%s, %s", get_b_reg(*buf >> 3), get_b_reg(*buf));
- return(str);
-
- case 0x80: /* 8 bit math & logic */
- strcpy(s, get_b_reg(*buf));
- strcpy(str, "* * * Internal error * * *");
-
- math_immediate: /* comes from misc instructions */
- switch ((*buf >> 3) & 7) /* logic op */
- {
- case 1: /* ADC */
- sprintf(str, "ADC\tA, %s", s);
- break;
-
- case 0: /* ADD */
- sprintf(str, "ADD\tA, %s", s);
- break;
-
- case 3: /* SBC */
- sprintf(str, "SBC\tA, %s", s);
- break;
-
- case 2: /* SUB */
- sprintf(str, "SUB\tA, %s", s);
- break;
-
- case 4: /* AND */
- sprintf(str, "AND\tA, %s", s);
- break;
-
- case 5: /* XOR */
- sprintf(str, "XOR\tA, %s", s);
- break;
-
- case 6: /* OR */
- sprintf(str, "OR\tA, %s", s);
- break;
-
- case 7: /* CP */
- sprintf(str, "CP\tA, %s", s);
- break;
- } /* end - logic op */
-
- return(str);
-
- case 0xc0: /* Misc */
- if ((*buf & 0x07) == 0x06)
- {
- sprintf(s, "0%02.2xH", buf[1]);
- goto math_immediate; /* sometimes they're necessary */
- }
-
- if ((*buf & 0x0f) == 1) /* POP */
- {
- sprintf(str, "POP\t%s", get_s_reg(*buf >> 4));
- return(str);
- }
-
- if ((*buf & 0x0f) == 5) /* PUSH */
- {
- sprintf(str, "PUSH\t%s", get_s_reg(*buf >> 4));
- return(str);
- }
-
-
- switch (*buf & 0x07) /* BRANCH */
- {
- case 0: /* RET cc */
- sprintf(str, "RET\t%s", condition(*buf >> 3));
- return(str);
-
- case 2: /* JP cc */
- sprintf(str, "JP\t%s, 0%02.2x%02.2xH",
- condition(*buf >> 3), buf[2], buf[1]);
- return(str);
-
- case 4: /* CALL cc */
- sprintf(str, "CALL\t%s, 0%02.2x%02.2xH",
- condition(*buf >> 3), buf[2], buf[1]);
- return(str);
-
- case 7: /* RST n */
- sprintf(str, "RST\t%d", (*buf >> 3) & 0x07);
- return(str);
- } /* end - BRANCH */
-
- switch (*buf) /* misc */
- {
- case 0xcd: /* CALL */
- sprintf(str, "CALL\t0%02.2x%02.2xH", buf[2], buf[1]);
- return(str);
-
- case 0xc3: /* JP */
- sprintf(str, "JP\t0%02.2x%02.2xH", buf[2], buf[1]);
- return(str);
-
- case 0xc9: /* RET */
- sprintf(str, "RET");
- return(str);
-
- case 0xeb: /* EX DE, HL */
- return("EX\tDE, HL");
-
- case 0xe9: /* JP (HL) */
- return("JP\t(HL)");
-
- case 0xe3: /* EX (SP), HL */
- return("EX\t(SP), HL");
-
- case 0xf9: /* LD SP, HL */
- return("LD\tSP, HL");
-
- case 0xf3: /* DI */
- return("DI");
-
- case 0xfb: /* EI */
- return("EI");
- } /* misc */
-
- sprintf(str, "Unrecognized command (0x%02.2x)", *buf);
- return(str);
-
- case 0:
- switch (*buf & 0x07) /* misc data (3) */
- {
- case 4: /* INC byte */
- sprintf(str, "INC\t%s", get_b_reg(*buf >> 3));
- return(str);
-
- case 5: /* DEC byte */
- sprintf(str, "DEC\t%s", get_b_reg(*buf >> 3));
- return(str);
-
- case 6: /* LD byte immediate */
- sprintf(str, "LD\t%s, 0%02.2xH",
- get_b_reg(*buf >> 3), buf[1]);
- return(str);
- } /* end - misc data (3) */
-
- switch (*buf & 0x0f) /* misc data (4) */
- {
- case 1: /* LD word immediate */
- sprintf(str, "LD\t%s, 0%02.2x%02.2xH",
- get_w_reg(*buf >> 4), buf[2], buf[1]);
- return(str);
-
- case 0x03: /* INC word */
- sprintf(str, "INC\t%s", get_w_reg(*buf >> 4));
- return(str);
-
- case 0x0b: /* DEC word */
- sprintf(str, "DEC\t%s", get_w_reg(*buf >> 4));
- return(str);
-
- case 0x09: /* ADD HL, ss */
- sprintf(str, "ADD\tHL, %s", get_w_reg(*buf >> 4));
- return(str);
- } /* end - misc date (4) */
-
- switch (*buf) /* misc data */
- {
- case 0: /* NOP */
- return("NOP");
-
- case 0x02: /* LD (BC), A */
- return("LD\t(BC), A");
-
- case 0x10:
- sprintf(str, "DJNZ\t0%04.4xH", relative(buf[1]));
- return(str);
-
- case 0x20:
- sprintf(str, "JR\tNZ, 0%04.4xH", relative(buf[1]));
- return(str);
-
- case 0x30:
- sprintf(str, "JR\tNC, 0%04.4xH", relative(buf[1]));
- return(str);
-
- case 0x18:
- sprintf(str, "JR\t, 0%04.4xH", relative(buf[1]));
- return(str);
-
- case 0x28:
- sprintf(str, "JR\tZ, 0%04.4xH", relative(buf[1]));
- return(str);
-
- case 0x38:
- sprintf(str, "JR\tC, 0%04.4xH", relative(buf[1]));
- return(str);
-
- case 0x12: /* LD (DE), A */
- return("LD\t(DE), A");
-
- case 0x22: /* LD (nn), HL */
- sprintf(str, "LD\t(0%02.2x%02.2xH), HL", buf[2], buf[1]);
- return(str);
-
- case 0x32: /* LD (nn), A */
- sprintf(str, "LD\t(0%02.2x%02.2xH), A", buf[2], buf[1]);
- return(str);
-
- case 0x0a: /* LD A, (BC) */
- return("LD\tA, (BC)");
-
- case 0x1a: /* LD A, (DE) */
- return("LD\tA, (DE)");
-
- case 0x2a: /* LD HL, (nn) */
- sprintf(str, "LD\tHL, (0%02.2x%02.2xH)", buf[2], buf[1]);
- return(str);
-
- case 0x3a: /* LD A, (nn) */
- sprintf(str, "LD\tA, (0%02.2x%02.2xH)", buf[2], buf[1]);
- return(str);
-
- case 7: /* RLCA */
- return("RLCA");
-
- case 0x0f: /* RRCA */
- return("RRCA");
-
- case 0x17: /* RLA */
- return("RLA");
-
- case 0x1f: /* RRA */
- return("RRA");
-
- case 0x27: /* DAA */
- return("DAA");
-
- case 0x2f: /* CPL */
- return("CPL");
-
- case 0x37: /* SCF */
- return("SCF");
-
- case 0x3f: /* CCF */
- return("CCF");
- } /* end - misc date */
-
- return("* * * Internal error * * *");
- } /* end class */
-
- return("* * * Internal error * * *");
- }
-