/* This file is in the public domain. */ #include #include "fnprintf.h" #include "machine.h" static const char *reg8[8] = { "b", "c", "d", "e", "h", "l", "(hl)", "a" }; static const char *reg16sp[4] = { "bc", "de", "hl", "sp" }; static const char *reg16af[4] = { "bc", "de", "hl", "af" }; static const char *cc[8] = { "nz", "z", "nc", "c", "po", "pe", "p", "m" }; static int do_dis_inst(ADDR addr, void (*fn)(char), CFLAG flg) { __label__ retm1; ADDR orig; unsigned char opc; unsigned char opc2; unsigned char v1; unsigned short int v2; signed int off; static unsigned char next1(void) { if (addr+1 >= coresize) goto retm1; return(corefetchu(addr++,1)); } static unsigned short int next2(void) { if (addr+2 >= coresize) goto retm1; addr += 2; return(corefetchu(addr-2,2)); } if (0) { retm1:; return(-1); } addr -= corebase; orig = addr; opc = next1(); switch (opc) { case 0x00: fnprintf(fn,"nop" ); break; case 0x02: fnprintf(fn,"ld (bc),a" ); break; case 0x07: fnprintf(fn,"rlca" ); break; case 0x08: fnprintf(fn,"ex af,af'" ); break; case 0x0a: fnprintf(fn,"ld a,(bc)" ); break; case 0x0f: fnprintf(fn,"rrca" ); break; case 0x12: fnprintf(fn,"ld (de),a" ); break; case 0x17: fnprintf(fn,"rla" ); break; case 0x1a: fnprintf(fn,"ld a,(de)" ); break; case 0x1f: fnprintf(fn,"rra" ); break; case 0x27: fnprintf(fn,"daa" ); break; case 0x2f: fnprintf(fn,"cpl" ); break; case 0x37: fnprintf(fn,"scf" ); break; case 0x3f: fnprintf(fn,"ccf" ); break; case 0x76: fnprintf(fn,"halt" ); break; case 0xc9: fnprintf(fn,"ret" ); break; case 0xd9: fnprintf(fn,"exx" ); break; case 0xe3: fnprintf(fn,"ex (sp),hl"); break; case 0xe9: fnprintf(fn,"jp (hl)" ); break; case 0xeb: fnprintf(fn,"ex de,hl" ); break; case 0xf3: fnprintf(fn,"di" ); break; case 0xf9: fnprintf(fn,"ld sp,hl" ); break; case 0xfb: fnprintf(fn,"ei" ); break; case 0xc6: case 0xce: case 0xd6: case 0xde: case 0xe6: case 0xee: case 0xf6: case 0xfe: case 0xd3: case 0xdb: v1 = next1(); switch (opc) { case 0xc6: fnprintf(fn,"add a,%02x",v1); break; case 0xce: fnprintf(fn,"adc a,%02x",v1); break; case 0xd3: fnprintf(fn,"out (%02x),a",v1); break; case 0xd6: fnprintf(fn,"sub %02x",v1); break; case 0xdb: fnprintf(fn,"in a,(%02x)",v1); break; case 0xde: fnprintf(fn,"sbc a,%02x",v1); break; case 0xe6: fnprintf(fn,"and %02x",v1); break; case 0xee: fnprintf(fn,"xor %02x",v1); break; case 0xf6: fnprintf(fn,"or %02x",v1); break; case 0xfe: fnprintf(fn,"cp %02x",v1); break; } break; case 0x10: case 0x18: off = (signed char) next1(); switch (opc) { case 0x10: fnprintf(fn,"djnz "); break; case 0x18: fnprintf(fn,"jr "); break; } print_symbol_or_hex(fn,corebase+addr+off); break; case 0x22: case 0x2a: case 0x32: case 0x3a: case 0xc3: case 0xcd: v2 = next2(); switch (opc) { case 0x22: fnprintf(fn,"ld (%04x),hl",v2); break; case 0x2a: fnprintf(fn,"ld hl,(%04x)",v2); break; case 0x32: fnprintf(fn,"ld (%04x),a",v2); break; case 0x3a: fnprintf(fn,"ld a,(%04x)",v2); break; case 0xc3: fnprintf(fn,"jp %04x",v2); break; case 0xcd: fnprintf(fn,"call %04x",v2); break; } break; case 0xcb: opc2 = next1(); switch (opc2 & 0xc0) { case 0x00: { static const char *pref[8] = { "rlc", "rrc", "rl", "rr", "sla", "sra", "slia", "srl" }; fnprintf(fn,"%-8s%s",pref[(opc2>>3)&7],reg8[opc2&7]); } break; default: { static const char *pref[4] = { "?0", "bit", "res", "set" }; fnprintf(fn,"%-8s%d,%s",pref[(opc2>>6)&3],(opc2>>3)&7,reg8[opc2&7]); } break; } break; case 0xdd: { const char *ireg; ireg = "x"; if (0) { case 0xfd: ireg = "y"; } opc2 = next1(); switch (opc2) { case 0x09: fnprintf(fn,"add i%s,bc",ireg); break; case 0x19: fnprintf(fn,"add i%s,de",ireg); break; case 0x23: fnprintf(fn,"inc i%s",ireg); break; case 0x24: fnprintf(fn,"inc h%s",ireg); break; case 0x25: fnprintf(fn,"dec h%s",ireg); break; case 0x29: fnprintf(fn,"add i%s,i%s",ireg,ireg); break; case 0x2b: fnprintf(fn,"dec i%s",ireg); break; case 0x2c: fnprintf(fn,"inc l%s",ireg); break; case 0x2d: fnprintf(fn,"dec l%s",ireg); break; case 0x39: fnprintf(fn,"add i%s,sp",ireg); break; case 0x44: fnprintf(fn,"ld b,h%s",ireg); break; case 0x45: fnprintf(fn,"ld b,l%s",ireg); break; case 0x4c: fnprintf(fn,"ld c,h%s",ireg); break; case 0x4d: fnprintf(fn,"ld c,l%s",ireg); break; case 0x54: fnprintf(fn,"ld d,h%s",ireg); break; case 0x55: fnprintf(fn,"ld d,l%s",ireg); break; case 0x5c: fnprintf(fn,"ld e,h%s",ireg); break; case 0x5d: fnprintf(fn,"ld e,l%s",ireg); break; case 0x60: fnprintf(fn,"ld h%s,b",ireg); break; case 0x61: fnprintf(fn,"ld h%s,c",ireg); break; case 0x62: fnprintf(fn,"ld h%s,d",ireg); break; case 0x63: fnprintf(fn,"ld h%s,e",ireg); break; case 0x64: fnprintf(fn,"ld h%s,h%s",ireg,ireg); break; case 0x65: fnprintf(fn,"ld h%s,l%s",ireg,ireg); break; case 0x67: fnprintf(fn,"ld h%s,a",ireg); break; case 0x68: fnprintf(fn,"ld l%s,b",ireg); break; case 0x69: fnprintf(fn,"ld l%s,c",ireg); break; case 0x6a: fnprintf(fn,"ld l%s,d",ireg); break; case 0x6b: fnprintf(fn,"ld l%s,e",ireg); break; case 0x6c: fnprintf(fn,"ld l%s,h%s",ireg,ireg); break; case 0x6d: fnprintf(fn,"ld l%s,l%s",ireg,ireg); break; case 0x6f: fnprintf(fn,"ld l%s,a",ireg); break; case 0x7c: fnprintf(fn,"ld a,h%s",ireg); break; case 0x7d: fnprintf(fn,"ld a,l%s",ireg); break; case 0x84: fnprintf(fn,"add a,h%s",ireg); break; case 0x85: fnprintf(fn,"add a,l%s",ireg); break; case 0x8c: fnprintf(fn,"adc a,h%s",ireg); break; case 0x8d: fnprintf(fn,"adc a,l%s",ireg); break; case 0x94: fnprintf(fn,"sub h%s",ireg); break; case 0x95: fnprintf(fn,"sub l%s",ireg); break; case 0x9c: fnprintf(fn,"sbc a,h%s",ireg); break; case 0x9d: fnprintf(fn,"sbc a,l%s",ireg); break; case 0xa4: fnprintf(fn,"and h%s",ireg); break; case 0xa5: fnprintf(fn,"and l%s",ireg); break; case 0xac: fnprintf(fn,"xor h%s",ireg); break; case 0xad: fnprintf(fn,"xor l%s",ireg); break; case 0xb4: fnprintf(fn,"or h%s",ireg); break; case 0xb5: fnprintf(fn,"or l%s",ireg); break; case 0xbc: fnprintf(fn,"cp h%s",ireg); break; case 0xbd: fnprintf(fn,"cp l%s",ireg); break; case 0xe1: fnprintf(fn,"pop i%s",ireg); break; case 0xe3: fnprintf(fn,"ex (sp),i%s",ireg); break; case 0xe5: fnprintf(fn,"push i%s",ireg); break; case 0xe9: fnprintf(fn,"jp (i%s)",ireg); break; case 0xf9: fnprintf(fn,"ld sp,i%s",ireg); break; case 0x26: case 0x2e: v1 = next1(); switch (opc2) { case 0x26: fnprintf(fn,"ld h%s,%02x",ireg,v1); break; case 0x2e: fnprintf(fn,"ld l%s,%02x",ireg,v1); break; } break; case 0x21: case 0x22: case 0x2a: v2 = next2(); switch (opc2) { case 0x21: fnprintf(fn,"ld i%s,%04x",ireg,v2); break; case 0x22: fnprintf(fn,"ld (%04x),i%s",v2,ireg); break; case 0x2a: fnprintf(fn,"ld i%s,(%04x)",ireg,v2); break; } break; case 0x36: off = (signed char) next1(); v1 = next1(); fnprintf(fn,"ld (i%s%+d),%02x",ireg,off,v1); break; case 0x34: case 0x35: case 0x46: case 0x4e: case 0x56: case 0x5e: case 0x66: case 0x6e: case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x77: case 0x7e: case 0x86: case 0x8e: case 0x96: case 0x9e: case 0xa6: case 0xae: case 0xb6: case 0xbe: off = (signed char) next1(); switch (opc2) { case 0x34: fnprintf(fn,"inc (i%s%+d)",ireg,off); break; case 0x35: fnprintf(fn,"dec (i%s%+d)",ireg,off); break; case 0x46: fnprintf(fn,"ld b,(i%s%+d)",ireg,off); break; case 0x4e: fnprintf(fn,"ld c,(i%s%+d)",ireg,off); break; case 0x56: fnprintf(fn,"ld d,(i%s%+d)",ireg,off); break; case 0x5e: fnprintf(fn,"ld e,(i%s%+d)",ireg,off); break; case 0x66: fnprintf(fn,"ld h,(i%s%+d)",ireg,off); break; case 0x6e: fnprintf(fn,"ld l,(i%s%+d)",ireg,off); break; case 0x70: fnprintf(fn,"ld (i%s%+d),b",ireg,off); break; case 0x71: fnprintf(fn,"ld (i%s%+d),c",ireg,off); break; case 0x72: fnprintf(fn,"ld (i%s%+d),d",ireg,off); break; case 0x73: fnprintf(fn,"ld (i%s%+d),e",ireg,off); break; case 0x74: fnprintf(fn,"ld (i%s%+d),h",ireg,off); break; case 0x75: fnprintf(fn,"ld (i%s%+d),l",ireg,off); break; case 0x77: fnprintf(fn,"ld (i%s%+d),a",ireg,off); break; case 0x7e: fnprintf(fn,"ld a,(i%s%+d)",ireg,off); break; case 0x86: fnprintf(fn,"add a,(i%s%+d)",ireg,off); break; case 0x8e: fnprintf(fn,"adc a,(i%s%+d)",ireg,off); break; case 0x96: fnprintf(fn,"sub (i%s%+d)",ireg,off); break; case 0x9e: fnprintf(fn,"sbc a,(i%s%+d)",ireg,off); break; case 0xa6: fnprintf(fn,"and (i%s%+d)",ireg,off); break; case 0xae: fnprintf(fn,"xor (i%s%+d)",ireg,off); break; case 0xb6: fnprintf(fn,"or (i%s%+d)",ireg,off); break; case 0xbe: fnprintf(fn,"cp (i%s%+d)",ireg,off); break; } break; case 0xcb: off = (signed char) next1(); opc2 = next1(); switch (opc2 & 0xc0) { case 0x00: { static const char *pref[8] = { "rlc", "rrc", "rl", "rr", "sla", "sra", "slia", "srl" }; if ((opc2 & 7) == 6) { fnprintf(fn,"%-8s(i%s%+d)",pref[(opc2>>3)&7],ireg,off); } else { fnprintf(fn,"%-8s(i%s%+d)->%s",pref[(opc2>>3)&7],ireg,off,reg8[opc2&7]); } } break; case 0x40: if ((opc2 & 7) == 6) { fnprintf(fn,"bit %d,(i%s%+d)",(opc2>>3)&7,ireg,off); } else { fnprintf(fn,"bit %d,(i%s%+d) ! ->%s (ignored)",(opc2>>3)&7,ireg,off,reg8[opc2&7]); } break; default: { static const char *pref[2] = { "res", "set" }; if ((opc2 & 7) == 6) { fnprintf(fn,"%-8s%d,(i%s%+d)",pref[(opc2>>6)&1],(opc2>>3)&7,ireg,off); } else { fnprintf(fn,"%-8s%d,(i%s%+d)->%s",pref[(opc2>>6)&1],(opc2>>3)&7,ireg,off,reg8[opc2&7]); } } break; } break; default: addr = orig + 1; fnprintf(fn,".byte %02x ! invalid prefix",opc); break; } } break; case 0xed: opc2 = next1(); switch (opc2) { case 0x04: case 0x0c: case 0x14: case 0x1c: case 0x24: case 0x2c: case 0x34: case 0x3c: fnprintf(fn,"tst %s",reg8[(opc2>>3)&7]); break; case 0x40: case 0x48: case 0x50: case 0x58: case 0x60: case 0x68: case 0x78: fnprintf(fn,"in %s,(c)",reg8[(opc2>>3)&7]); break; case 0x70: fnprintf(fn,"tsti (c)"); break; case 0x41: case 0x49: case 0x51: case 0x59: case 0x61: case 0x69: case 0x79: fnprintf(fn,"out (c),%s",reg8[(opc2>>3)&7]); break; case 0x71: fnprintf(fn,"out (c),0"); break; case 0x42: case 0x52: case 0x62: case 0x72: fnprintf(fn,"sbc hl,%s",reg16sp[(opc2>>4)&3]); break; case 0x4a: case 0x5a: case 0x6a: case 0x7a: fnprintf(fn,"adc hl,%s",reg16sp[(opc2>>4)&3]); break; case 0x4c: case 0x5c: case 0x6c: case 0x7c: fnprintf(fn,"mult %s",reg16sp[(opc2>>4)&3]); break; case 0x44: fnprintf(fn,"neg" ); break; case 0x45: fnprintf(fn,"retn" ); break; case 0x46: fnprintf(fn,"im 0" ); break; case 0x47: fnprintf(fn,"ld i,a"); break; case 0x4d: fnprintf(fn,"reti" ); break; case 0x4f: fnprintf(fn,"ld r,a"); break; case 0x56: fnprintf(fn,"im 1" ); break; case 0x57: fnprintf(fn,"ld a,i"); break; case 0x5e: fnprintf(fn,"im 2" ); break; case 0x5f: fnprintf(fn,"ld a,r"); break; case 0x67: fnprintf(fn,"rrd" ); break; case 0x6f: fnprintf(fn,"rld" ); break; case 0x76: fnprintf(fn,"slp" ); break; case 0x83: fnprintf(fn,"otim" ); break; case 0x8b: fnprintf(fn,"otdm" ); break; case 0x93: fnprintf(fn,"otimr" ); break; case 0x9b: fnprintf(fn,"otdmr" ); break; case 0xa0: fnprintf(fn,"ldi" ); break; case 0xa1: fnprintf(fn,"cpi" ); break; case 0xa2: fnprintf(fn,"ini" ); break; case 0xa3: fnprintf(fn,"outi" ); break; case 0xa8: fnprintf(fn,"ldd" ); break; case 0xa9: fnprintf(fn,"cpd" ); break; case 0xaa: fnprintf(fn,"ind" ); break; case 0xab: fnprintf(fn,"outd" ); break; case 0xb0: fnprintf(fn,"ldir" ); break; case 0xb1: fnprintf(fn,"cpir" ); break; case 0xb2: fnprintf(fn,"inir" ); break; case 0xb3: fnprintf(fn,"otir" ); break; case 0xb8: fnprintf(fn,"lddr" ); break; case 0xb9: fnprintf(fn,"cpdr" ); break; case 0xba: fnprintf(fn,"indr" ); break; case 0xbb: fnprintf(fn,"otdr" ); break; case 0x00: case 0x01: case 0x08: case 0x09: case 0x10: case 0x11: case 0x18: case 0x19: case 0x20: case 0x21: case 0x28: case 0x29: case 0x30: case 0x38: case 0x39: case 0x64: case 0x74: v1 = next1(); switch (opc2) { case 0x30: fnprintf(fn,"in0 (%02x)",v1); break; case 0x64: fnprintf(fn,"tst %02x",v1); break; case 0x74: fnprintf(fn,"tstio %02x",v1); break; default: if (opc2 & 1) { fnprintf(fn,"out0 (%02x),%s",v1,reg8[(opc2>>3)&7]); } else { fnprintf(fn,"in0 (%02x),%s",v1,reg8[(opc2>>3)&7]); } break; } break; case 0x43: case 0x53: case 0x63: case 0x73: v2 = next2(); fnprintf(fn,"ld (%04x),%s",v2,reg16sp[(opc2>>4)&3]); break; case 0x4b: case 0x5b: case 0x6b: case 0x7b: v2 = next2(); fnprintf(fn,"ld %s,(%04x)",reg16sp[(opc2>>4)&3],v2); break; case 0x4e: case 0x54: case 0x55: case 0x5d: case 0x65: case 0x66: case 0x6d: case 0x6e: case 0x75: case 0x77: case 0x7d: case 0x7e: case 0x7f: fnprintf(fn,".byte ed, %02x ! \"mirrored elsewhere\"?",opc2); break; default: addr = orig + 1; fnprintf(fn,".byte ed ! invalid prefix"); break; } break; default: switch (opc & 0xc0) { case 0x40: fnprintf(fn,"ld %s,%s",reg8[(opc>>3)&7],reg8[opc&7]); break; case 0x80: { static const char *pref[8] = { "add a,", "adc a,", "sub ", "sbc ", "and ", "xor ", "or ", "cp " }; fnprintf(fn,"%s%s",pref[(opc>>3)&7],reg8[opc&7]); } break; default: switch (opc & 0xc7) { case 0x04: fnprintf(fn,"inc %s",reg8[(opc>>3)&7]); break; case 0x05: fnprintf(fn,"dec %s",reg8[(opc>>3)&7]); break; case 0x06: v1 = next1(); fnprintf(fn,"ld %s,%02x",reg8[(opc>>3)&7],v1); break; case 0xc0: fnprintf(fn,"ret %s",cc[(opc>>3)&7]); break; case 0xc2: v2 = next2(); fnprintf(fn,"jp %s,%04x",cc[(opc>>3)&7],v2); break; case 0xc4: v2 = next2(); fnprintf(fn,"call %s,%04x",cc[(opc>>3)&7],v2); break; case 0xc7: fnprintf(fn,"rst %x",opc&0x38); break; default: switch (opc & 0xcf) { case 0x01: v2 = next2(); fnprintf(fn,"ld %s,%04x",reg16sp[(opc>>4)&3],v2); break; case 0x03: fnprintf(fn,"inc %s",reg16sp[(opc>>4)&3]); break; case 0x0b: fnprintf(fn,"dec %s",reg16sp[(opc>>4)&3]); break; case 0xc1: fnprintf(fn,"pop %s",reg16af[(opc>>4)&3]); break; case 0xc5: fnprintf(fn,"push %s",reg16af[(opc>>4)&3]); break; case 0x09: fnprintf(fn,"add hl,%s",reg16sp[(opc>>4)&3]); break; default: switch (opc & 0xe7) { case 0x20: off = (signed char) next1(); fnprintf(fn,"jr %s,",cc[(opc>>3)&3]); print_symbol_or_hex(fn,corebase+addr+off); break; default: fnprintf(fn,".byte %02x ! unknown",opc); break; } break; } break; } break; } break; } if (flg & CFF_INST_PARALLEL) { fnprintf(fn," {%lx}",(unsigned long int)(corebase+addr)); return(1); } else { int i; int n; n = addr - orig; for (i=1;i",(unsigned long int)flags[addr-corebase]); rv = 1; } return(rv); } static unsigned long int z80_fetch(const void *base, int size) #define bp(n) ((unsigned long int)(((const unsigned char *)base)[(n)])) { switch (size) { case 1: return(bp(0)); break; case 2: return((bp(1)<<8)|bp(0)); break; case 4: return((bp(3)<<24)|(bp(2)<<16)|(bp(1)<<8)|bp(0)); break; } abort(); } #undef bp static const char *z80_names[] = { "z80", "Z80", "z-80", "Z-80", 0 }; MACHINE machine_z80 = { &z80_names[0], 2, &z80_init, 0, &z80_dis, &z80_fetch, 0 };