home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************/
- /* */
- /* */
- /* CP/M emulator version 0.1 */
- /* */
- /* written by Michael Bischoff (mbi@mo.math.nat.tu-bs.de) */
- /* June-1994 */
- /* */
- /* This file is distributed under the GNU COPYRIGHT */
- /* see COPYRIGHT.GNU for Copyright details */
- /* */
- /* */
- /*****************************************************************************/
- #define _POSIX_SOURCE
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- /* 8-Bit registers */
- static const char *dtab1[] = { "B", "C", "D", "E", "H", "L", NULL, "A" };
- /* condition codes */
- static const char *dtab4[] = { "NZ", "Z", "NC", "C", "PO", "PE", "P", "M" };
- /* opcodes */
- static const char *dtab5[] = { "ADD A,", "ADC A,", "SUB ", "SBC A,", "AND ", "XOR ", "OR ", "CP " };
- static const char *dtabix[] = { "POP %s", "EX (SP),%s", "PUSH %s", "JP(%s)",
- "EX DE,%s", "LD SP,%s" };
- static const char *dtab2[] = { "BC", "DE", NULL, "SP" };
- /*static const char *dtab3[] = { "BC", "DE", NULL, "AF" }; */
-
- static const char *op1tab[] = { /* NULLs are handled explicitly */
- "NOP", NULL, "LD (BC),A", NULL, NULL, NULL, NULL, "RLCA",
- "EX AF,AF'", NULL, "LD A,(BC)", NULL, NULL, NULL, NULL, "RRCA",
- "DJNZ %04x", NULL, "LD (DE),A", NULL, NULL, NULL, NULL, "RLA",
- "JR %04x", NULL, "LD A,(DE)", NULL, NULL, NULL, NULL, "RRA",
- "JR NZ,%04x",NULL, NULL, NULL, NULL, NULL, NULL, "DAA",
- "JR Z,%04x", NULL, NULL, NULL, NULL, NULL, NULL, "CPL",
- "JR NC,%04x",NULL, NULL, NULL, NULL, NULL, NULL, "SCF",
- "JR C,%04x", NULL, NULL, NULL, NULL, NULL, NULL, "CCF" };
-
- static const char *op2tab[] = {
- NULL, "POP BC", NULL, "JP %04x", NULL, "PUSH BC", NULL, NULL, NULL, "RET", NULL, "???", NULL, "CALL %04x", NULL, NULL,
- NULL, "POP DE", NULL, "OUT (%03x),A", NULL, "PUSH DE", NULL, NULL, NULL, "EXX", NULL, "IN A,(%03x)", NULL, "???", NULL, NULL,
- NULL, "POP HL", NULL, "EX (SP),HL", NULL, "PUSH HL", NULL, NULL, NULL, "JP (HL)", NULL, "EX DE,HL", NULL, "???", NULL, NULL,
- NULL, "POP AF", NULL, "DI", NULL, "PUSH AF", NULL, NULL, NULL, "LD SP,HL",NULL, "EI", NULL, "???", NULL, NULL };
- static const char *cbtab1[] = {
- "RLC", "RRC", "RL", "RR", "SLA", "SRA", "? SLIA", "SRL" };
- static const char *cbtab2[] = {
- NULL, "BIT", "RES", "SET" };
- static unsigned char ixy_possible8[32] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00,
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xbf, 0x40,
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- static char edcmds[] = {
- 0x44, 0xa0, 0xa8, 0xb0, 0xb8, 0x47, 0x4f, 0x57,
- 0x5f, 0xa1, 0xb1, 0xa9, 0xb9, 0x46, 0x56, 0x5e,
- 0x67, 0x6f, 0xa3, 0xab, 0xb3, 0xbb, 0x45, 0x4d,
- 0 };
- static const char *edtxt[] = {
- "NEG", "LDI", "LDD", "LDIR", "LDDR", "LD I,A", "LD R,A", "LD A,I",
- "LD A,R", "CPI", "CPIR", "CPD", "CPDR", "IM 0", "IM 1", "IM 2", "RRD",
- "RLD", "OUTI", "OUTD", "OTIR", "OTDR", "RETN", "RETI"
- };
-
- static const unsigned char *edcommand(const unsigned char *PC, char *s) {
- unsigned o, w;
- const char *dr;
- o = *PC;
-
- dtab2[2] = "HL";
- dr = dtab2[(o & 0x30) >> 4];
-
- switch (o & 0xcf) {
- case 0x42:
- sprintf(s, "SBC HL,%s", dr);
- break;
- case 0x43:
- w = *++PC;
- w += *++PC << 8;
- sprintf(s, "LD (%04x),%s", w, dr);
- break;
- case 0x4a:
- sprintf(s, "ADC HL,%s", dr);
- break;
- case 0x4b:
- w = *++PC;
- w += *++PC << 8;
- sprintf(s, "LD %s,(%04x)", dr, w);
- break;
- default:
- if (o && (dr = strchr(edcmds, o))) {
- strcpy(s, edtxt[dr-edcmds]);
- break;
- }
- return PC-1;
- }
- return PC+1;
- }
-
-
- /* PC is only needed for JR instructions */
- const unsigned char *disz80(const unsigned char *PC, char *s, unsigned pc) {
- unsigned o, m, r;
- const char *regh, *regl, *ir;
- char i_offset[8];
- unsigned w;
-
- dtab1[6] = "(HL)";
- ir = "HL";
- o = *PC;
- redo:
- regh = dtab1[m = (o >> 3) & 7];
- regl = dtab1[r = o & 7];
-
- switch (o >> 6) {
- case 0: /* the lower block */
- switch(o & 7) {
- case 4:
- sprintf(s, "INC %s", regh);
- break;
- case 5:
- sprintf(s, "DEC %s", regh);
- break;
- case 6:
- sprintf(s, "LD %s,0%02x", regh, *++PC);
- break;
- default:
- dtab2[2] = ir;
- switch (o) {
- case 0x01: case 0x11: case 0x21: case 0x31:
- w = *++PC;
- w += *++PC << 8;
- sprintf(s, "LD %s,%04x", dtab2[o>>4], w);
- break;
- case 0x03: case 0x13: case 0x23: case 0x33:
- sprintf(s, "INC %s", dtab2[o>>4]);
- break;
- case 0x0b: case 0x1b: case 0x2b: case 0x3b:
- sprintf(s, "DEC %s", dtab2[o>>4]);
- break;
- case 0x09: case 0x19: case 0x29: case 0x39:
- sprintf(s, "ADD %s,%s", ir, dtab2[o>>4]);
- break;
- case 0x22: case 0x2a: case 0x32: case 0x3a:
- /* commands which use a 16 bit argument */
- w = *++PC;
- w += *++PC << 8;
- switch (o) {
- case 0x22:
- sprintf(s, "LD (%04x),%s", w, ir);
- break;
- case 0x2a:
- sprintf(s, "LD %s,(%04x)", ir, w);
- break;
- case 0x32:
- sprintf(s, "LD (%04x),A", w);
- break;
- case 0x3a:
- sprintf(s, "LD A,(%04x)", w);
- break;
- }
- break;
- case 0x10: case 0x18: case 0x20:
- case 0x28: case 0x30: case 0x38:
- /* jump relative */
- #if 1
- if ((w = *++PC) & 0x80)
- w -= 256;
- w += pc + 2;
- #else
- w = *++PC; /* no service for destination address */
- #endif
- sprintf(s, op1tab[o], w);
- break;
- default:
- strcpy(s, op1tab[o]);
- break;
- }
- }
- break; /* lower block done */
- case 1: /* second block is easy */
- if (o != 0x76)
- sprintf(s, "LD %s,%s", regh, regl);
- else
- strcpy(s, "HALT");
- break;
- case 2: /* third block is easy */
- strcpy(s, dtab5[m]);
- strcat(s, regl);
- break;
- case 3: /* fourth block */
- switch(o & 7) {
- case 0:
- sprintf(s, "RET %s", dtab4[m]);
- break;
- case 2:
- w = *++PC;
- w += *++PC << 8;
- sprintf(s, "JP %s,%04x", dtab4[m], w);
- break;
- case 4:
- w = *++PC;
- w += *++PC << 8;
- sprintf(s, "CALL %s,%04x", dtab4[m], w);
- break;
- case 6:
- sprintf(s, "%s0%02x", dtab5[m], *++PC);
- break;
- case 7:
- sprintf(s, "RST %03xH", m << 3);
- break;
- default:
- switch (o) {
- case 0xc3: case 0xcd:
- w = *++PC;
- w += *++PC << 8;
- break;
- case 0xd3: case 0xdb:
- w = *++PC;
- break;
-
- /* SPECIAL Z80 COMMANDS START HERE: */
- case 0xcb: /* rotate-commands */
- ddcb:
- o = *++PC;
- regl = dtab1[r = o & 7];
- m = (o >> 3) & 7;
- if (o & 0xc0)
- sprintf(s, "%s %d,%s", cbtab2[o >> 6], m, dtab1[r]);
- else
- sprintf(s, "%s %s", cbtab1[m], dtab1[r]);
- return PC+1;
- case 0xed:
- return edcommand(PC+1, s);
- case 0xdd:
- ir = "IX";
- goto ixiy;
- case 0xfd:
- ir = "IY";
- ixiy:
- dtab1[6] = i_offset;
- m = PC[2]; /* offset */
- sprintf(i_offset, "(%s%c%02x)", ir, m&0x80 ? '-' : '+',
- m&0x80 ? 256-m : m);
- o = *++PC;
- if (o == 0xcb) {
- /* rotate with index reg */
- o = PC[2];
- if ((o & 7) != 6)
- return PC-1; /* invalid opcode! */
- ++PC; /* skip offset */
- goto ddcb;
- }
- if (ixy_possible8[o >> 3] & (1<<(o&7))) {
- /* is a command which addresses 8 bit index+offset */
- ++PC; /* skip offset */
- goto redo;
- }
- { unsigned char *p, xtra1[] = {
- 0x21, 0x22, 0x2a, 0x09, 0x19, 0x29, 0x39, 0x23, 0x2b, 0
- }, xtra2[] = {
- 0xe1, 0xe3, 0xe5, 0xe9, 0xeb, 0xf9, 0 };
- if (o) {
- if ((p = strchr(xtra1, o)))
- goto redo;
- else if ((p = strchr(xtra2, o))) {
- sprintf(s, dtabix[p-xtra2], ir);
- return PC+1;
- }
- }
- }
- return PC-1; /* unknown opcode */
- }
- sprintf(s, op2tab[o & 63], w);
- break;
- }
- break;
- }
- return PC+1;
- }
-