# HG changeset patch # User Michael Pavone # Date 1469513764 25200 # Node ID 1625555e346e123528b5ddc015f83eaf9a89397f # Parent 3980ef0f6307d3c1497c550f81f0a68059077eed Properly handle redundant prefixes diff -r 3980ef0f6307 -r 1625555e346e z80_to_x86.c --- a/z80_to_x86.c Sun Jul 24 18:53:22 2016 -0700 +++ b/z80_to_x86.c Mon Jul 25 23:16:04 2016 -0700 @@ -343,6 +343,8 @@ if (context->breakpoint_flags[address / 8] & (1 << (address % 8))) { zbreakpoint_patch(context, address, start); } + num_cycles = 4 * inst->opcode_bytes; + //TODO: increment R register once for every opcode byte #ifdef Z80_LOG_ADDRESS log_address(&opts->gen, address, "Z80: %X @ %d\n"); #endif @@ -355,28 +357,24 @@ { case Z80_REG: case Z80_REG_INDIRECT: - num_cycles = size == SZ_B ? 4 : 6; - if (inst->ea_reg == Z80_IX || inst->ea_reg == Z80_IY || (inst->ea_reg >= Z80_IXL && inst->ea_reg <= Z80_IYH)) { - num_cycles += 4; + if (size != SZ_B) { + num_cycles += 2; } if (inst->reg == Z80_I || inst->ea_reg == Z80_I || inst->reg == Z80_R || inst->ea_reg == Z80_R) { - num_cycles += 5; + num_cycles += 1; } break; case Z80_IMMED: - num_cycles = size == SZ_B ? 7 : 10; + num_cycles += size == SZ_B ? 3 : 6; break; case Z80_IMMED_INDIRECT: - num_cycles = 10; + num_cycles += 6; break; case Z80_IX_DISPLACE: case Z80_IY_DISPLACE: - num_cycles = 16; + num_cycles = 8; //3 for displacement, 5 for address addition break; } - if ((inst->reg >= Z80_IXL && inst->reg <= Z80_IYH) || inst->reg == Z80_IX || inst->reg == Z80_IY) { - num_cycles += 4; - } cycles(&opts->gen, num_cycles); if (inst->addr_mode & Z80_DIR) { translate_z80_ea(inst, &dst_op, opts, DONT_READ, MODIFY); @@ -422,7 +420,7 @@ } break; case Z80_PUSH: - cycles(&opts->gen, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 9 : 5); + cycles(&opts->gen, num_cycles + 1); sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); if (inst->reg == Z80_AF) { zreg_to_native(opts, Z80_A, opts->gen.scratch1); @@ -447,7 +445,7 @@ //the upper half of a register pair break; case Z80_POP: - cycles(&opts->gen, (inst->reg == Z80_IX || inst->reg == Z80_IY) ? 8 : 4); + cycles(&opts->gen, num_cycles); mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); call(code, opts->read_16); add_ir(code, 2, opts->regs[Z80_SP], SZ_W); @@ -474,11 +472,6 @@ //the upper half of a register pair break; case Z80_EX: - if (inst->addr_mode == Z80_REG || inst->reg == Z80_HL) { - num_cycles = 4; - } else { - num_cycles = 8; - } cycles(&opts->gen, num_cycles); if (inst->addr_mode == Z80_REG) { if(inst->reg == Z80_AF) { @@ -543,7 +536,7 @@ } break; case Z80_EXX: - cycles(&opts->gen, 4); + cycles(&opts->gen, num_cycles); zreg_to_native(opts, Z80_BC, opts->gen.scratch1); mov_rdispr(code, opts->gen.context_reg, zar_off(Z80_BC), opts->gen.scratch2, SZ_W); mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zar_off(Z80_BC), SZ_W); @@ -560,7 +553,7 @@ native_to_zreg(opts, opts->gen.scratch2, Z80_DE); break; case Z80_LDI: { - cycles(&opts->gen, 8); + cycles(&opts->gen, num_cycles); zreg_to_native(opts, Z80_HL, opts->gen.scratch1); call(code, opts->read_8); zreg_to_native(opts, Z80_DE, opts->gen.scratch2); @@ -587,7 +580,7 @@ break; } case Z80_LDIR: { - cycles(&opts->gen, 8); + cycles(&opts->gen, num_cycles); zreg_to_native(opts, Z80_HL, opts->gen.scratch1); call(code, opts->read_8); zreg_to_native(opts, Z80_DE, opts->gen.scratch2); @@ -620,7 +613,7 @@ break; } case Z80_LDD: { - cycles(&opts->gen, 8); + cycles(&opts->gen, num_cycles); zreg_to_native(opts, Z80_HL, opts->gen.scratch1); call(code, opts->read_8); zreg_to_native(opts, Z80_DE, opts->gen.scratch2); @@ -647,7 +640,7 @@ break; } case Z80_LDDR: { - cycles(&opts->gen, 8); + cycles(&opts->gen, num_cycles); zreg_to_native(opts, Z80_HL, opts->gen.scratch1); call(code, opts->read_8); zreg_to_native(opts, Z80_DE, opts->gen.scratch2); @@ -680,7 +673,7 @@ break; } case Z80_CPI: - cycles(&opts->gen, 8);//T-States 4,4 + cycles(&opts->gen, num_cycles);//T-States 4,4 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); call(code, opts->read_8);//T-States 3 cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); @@ -702,7 +695,7 @@ setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV)); break; case Z80_CPIR: { - cycles(&opts->gen, 8);//T-States 4,4 + cycles(&opts->gen, num_cycles);//T-States 4,4 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); call(code, opts->read_8);//T-States 3 cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); @@ -735,7 +728,7 @@ break; } case Z80_CPD: - cycles(&opts->gen, 8);//T-States 4,4 + cycles(&opts->gen, num_cycles);//T-States 4,4 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); call(code, opts->read_8);//T-States 3 cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); @@ -757,7 +750,7 @@ setcc_rdisp(code, CC_NZ, opts->gen.context_reg, zf_off(ZF_PV)); break; case Z80_CPDR: { - cycles(&opts->gen, 8);//T-States 4,4 + cycles(&opts->gen, num_cycles);//T-States 4,4 zreg_to_native(opts, Z80_HL, opts->gen.scratch1); call(code, opts->read_8);//T-States 3 cmp_rr(code, opts->gen.scratch1, opts->regs[Z80_A], SZ_B); @@ -790,9 +783,8 @@ break; } case Z80_ADD: - num_cycles = 4; if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { - num_cycles += 12; + num_cycles += 8; } else if(inst->addr_mode == Z80_IMMED) { num_cycles += 3; } else if(z80_size(inst) == SZ_W) { @@ -831,9 +823,8 @@ z80_save_ea(code, inst, opts); break; case Z80_ADC: - num_cycles = 4; if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { - num_cycles += 12; + num_cycles += 8; } else if(inst->addr_mode == Z80_IMMED) { num_cycles += 3; } else if(z80_size(inst) == SZ_W) { @@ -871,9 +862,8 @@ z80_save_ea(code, inst, opts); break; case Z80_SUB: - num_cycles = 4; if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { - num_cycles += 12; + num_cycles += 8; } else if(inst->addr_mode == Z80_IMMED) { num_cycles += 3; } @@ -908,9 +898,8 @@ z80_save_ea(code, inst, opts); break; case Z80_SBC: - num_cycles = 4; if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { - num_cycles += 12; + num_cycles += 8; } else if(inst->addr_mode == Z80_IMMED) { num_cycles += 3; } else if(z80_size(inst) == SZ_W) { @@ -948,9 +937,8 @@ z80_save_ea(code, inst, opts); break; case Z80_AND: - num_cycles = 4; if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { - num_cycles += 12; + num_cycles += 8; } else if(inst->addr_mode == Z80_IMMED) { num_cycles += 3; } else if(z80_size(inst) == SZ_W) { @@ -976,9 +964,8 @@ z80_save_ea(code, inst, opts); break; case Z80_OR: - num_cycles = 4; if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { - num_cycles += 12; + num_cycles += 8; } else if(inst->addr_mode == Z80_IMMED) { num_cycles += 3; } else if(z80_size(inst) == SZ_W) { @@ -1004,9 +991,8 @@ z80_save_ea(code, inst, opts); break; case Z80_XOR: - num_cycles = 4; if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { - num_cycles += 12; + num_cycles += 8; } else if(inst->addr_mode == Z80_IMMED) { num_cycles += 3; } else if(z80_size(inst) == SZ_W) { @@ -1032,9 +1018,8 @@ z80_save_ea(code, inst, opts); break; case Z80_CP: - num_cycles = 4; if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { - num_cycles += 12; + num_cycles += 8; } else if(inst->addr_mode == Z80_IMMED) { num_cycles += 3; } @@ -1058,13 +1043,8 @@ z80_save_ea(code, inst, opts); break; case Z80_INC: - num_cycles = 4; - if (inst->reg == Z80_IX || inst->reg == Z80_IY) { - num_cycles += 6; - } else if(z80_size(inst) == SZ_W) { + if(z80_size(inst) == SZ_W) { num_cycles += 2; - } else if(inst->reg == Z80_IXH || inst->reg == Z80_IXL || inst->reg == Z80_IYH || inst->reg == Z80_IYL || inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { - num_cycles += 4; } cycles(&opts->gen, num_cycles); translate_z80_reg(inst, &dst_op, opts); @@ -1088,13 +1068,8 @@ z80_save_result(opts, inst); break; case Z80_DEC: - num_cycles = 4; - if (inst->reg == Z80_IX || inst->reg == Z80_IY) { - num_cycles += 6; - } else if(z80_size(inst) == SZ_W) { + if(z80_size(inst) == SZ_W) { num_cycles += 2; - } else if(inst->reg == Z80_IXH || inst->reg == Z80_IXL || inst->reg == Z80_IYH || inst->reg == Z80_IYL || inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { - num_cycles += 4; } cycles(&opts->gen, num_cycles); translate_z80_reg(inst, &dst_op, opts); @@ -1119,7 +1094,7 @@ z80_save_result(opts, inst); break; case Z80_DAA: - cycles(&opts->gen, 4); + cycles(&opts->gen, num_cycles); xor_rr(code, opts->gen.scratch2, opts->gen.scratch2, SZ_B); cmp_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); code_ptr corf_low = code->cur+1; @@ -1166,13 +1141,13 @@ //TODO: Implement half-carry flag break; case Z80_CPL: - cycles(&opts->gen, 4); + cycles(&opts->gen, num_cycles); not_r(code, opts->regs[Z80_A], SZ_B); mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_H), SZ_B); mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); break; case Z80_NEG: - cycles(&opts->gen, 8); + cycles(&opts->gen, num_cycles); neg_r(code, opts->regs[Z80_A], SZ_B); //TODO: Implement half-carry flag setcc_rdisp(code, CC_Z, opts->gen.context_reg, zf_off(ZF_Z)); @@ -1182,43 +1157,38 @@ mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_N), SZ_B); break; case Z80_CCF: - cycles(&opts->gen, 4); + cycles(&opts->gen, num_cycles); mov_rdispr(code, opts->gen.context_reg, zf_off(ZF_C), opts->gen.scratch1, SZ_B); xor_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B); mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); mov_rrdisp(code, opts->gen.scratch1, opts->gen.context_reg, zf_off(ZF_H), SZ_B); break; case Z80_SCF: - cycles(&opts->gen, 4); + cycles(&opts->gen, num_cycles); mov_irdisp(code, 1, opts->gen.context_reg, zf_off(ZF_C), SZ_B); mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_N), SZ_B); mov_irdisp(code, 0, opts->gen.context_reg, zf_off(ZF_H), SZ_B); break; case Z80_NOP: - if (inst->immed == 42) { - call(code, opts->gen.save_context); - call_args(code, (code_ptr)z80_print_regs_exit, 1, opts->gen.context_reg); - } else { - cycles(&opts->gen, 4 * inst->immed); - } + cycles(&opts->gen, num_cycles); break; case Z80_HALT: { code_ptr loop_top = code->cur; //this isn't terribly efficient, but it's good enough for now - cycles(&opts->gen, 4); + cycles(&opts->gen, num_cycles); check_cycles_int(&opts->gen, address); jmp(code, loop_top); break; } case Z80_DI: - cycles(&opts->gen, 4); + cycles(&opts->gen, num_cycles); mov_irdisp(code, 0, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B); mov_irdisp(code, 0, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B); mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, sync_cycle), opts->gen.limit, SZ_D); mov_irdisp(code, 0xFFFFFFFF, opts->gen.context_reg, offsetof(z80_context, int_cycle), SZ_D); break; case Z80_EI: - cycles(&opts->gen, 4); + cycles(&opts->gen, num_cycles); mov_rrdisp(code, opts->gen.cycles, opts->gen.context_reg, offsetof(z80_context, int_enable_cycle), SZ_D); mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B); mov_irdisp(code, 1, opts->gen.context_reg, offsetof(z80_context, iff2), SZ_B); @@ -1227,11 +1197,13 @@ call(code, opts->do_sync); break; case Z80_IM: - cycles(&opts->gen, 8); + cycles(&opts->gen, num_cycles); mov_irdisp(code, inst->immed, opts->gen.context_reg, offsetof(z80_context, im), SZ_B); break; case Z80_RLC: - num_cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8); + if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { + num_cycles += 8; + } cycles(&opts->gen, num_cycles); if (inst->addr_mode != Z80_UNUSED) { translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); @@ -1275,7 +1247,9 @@ } break; case Z80_RL: - num_cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8); + if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { + num_cycles += 8; + } cycles(&opts->gen, num_cycles); if (inst->addr_mode != Z80_UNUSED) { translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); @@ -1320,7 +1294,9 @@ } break; case Z80_RRC: - num_cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8); + if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { + num_cycles += 8; + } cycles(&opts->gen, num_cycles); if (inst->addr_mode != Z80_UNUSED) { translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); @@ -1364,7 +1340,9 @@ } break; case Z80_RR: - num_cycles = inst->immed == 0 ? 4 : (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8); + if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { + num_cycles += 8; + } cycles(&opts->gen, num_cycles); if (inst->addr_mode != Z80_UNUSED) { translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); @@ -1410,7 +1388,9 @@ break; case Z80_SLA: case Z80_SLL: - num_cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8; + if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { + num_cycles += 8; + } cycles(&opts->gen, num_cycles); if (inst->addr_mode != Z80_UNUSED) { translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); @@ -1458,7 +1438,9 @@ } break; case Z80_SRA: - num_cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8; + if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { + num_cycles += 8; + } cycles(&opts->gen, num_cycles); if (inst->addr_mode != Z80_UNUSED) { translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); @@ -1499,7 +1481,9 @@ } break; case Z80_SRL: - num_cycles = inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE ? 16 : 8; + if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { + num_cycles += 8; + } cycles(&opts->gen, num_cycles); if (inst->addr_mode != Z80_UNUSED) { translate_z80_ea(inst, &dst_op, opts, READ, MODIFY); @@ -1540,7 +1524,7 @@ } break; case Z80_RLD: - cycles(&opts->gen, 8); + cycles(&opts->gen, num_cycles); zreg_to_native(opts, Z80_HL, opts->gen.scratch1); call(code, opts->read_8); //Before: (HL) = 0x12, A = 0x34 @@ -1567,7 +1551,7 @@ call(code, opts->write_8); break; case Z80_RRD: - cycles(&opts->gen, 8); + cycles(&opts->gen, num_cycles); zreg_to_native(opts, Z80_HL, opts->gen.scratch1); call(code, opts->read_8); //Before: (HL) = 0x12, A = 0x34 @@ -1598,7 +1582,9 @@ call(code, opts->write_8); break; case Z80_BIT: { - num_cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16; + if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { + num_cycles += 8; + } cycles(&opts->gen, num_cycles); uint8_t bit; if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) { @@ -1637,7 +1623,9 @@ break; } case Z80_SET: { - num_cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16; + if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { + num_cycles += 8; + } cycles(&opts->gen, num_cycles); uint8_t bit; if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) { @@ -1704,7 +1692,9 @@ break; } case Z80_RES: { - num_cycles = (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) ? 8 : 16; + if (inst->addr_mode == Z80_IX_DISPLACE || inst->addr_mode == Z80_IY_DISPLACE) { + num_cycles += 8; + } cycles(&opts->gen, num_cycles); uint8_t bit; if ((inst->addr_mode & 0x1F) == Z80_REG && opts->regs[inst->ea_reg] >= AH && opts->regs[inst->ea_reg] <= BH) { @@ -1771,11 +1761,8 @@ break; } case Z80_JP: { - num_cycles = 4; if (inst->addr_mode != Z80_REG_INDIRECT) { num_cycles += 6; - } else if(inst->ea_reg == Z80_IX || inst->ea_reg == Z80_IY) { - num_cycles += 4; } cycles(&opts->gen, num_cycles); if (inst->addr_mode != Z80_REG_INDIRECT) { @@ -1798,7 +1785,7 @@ break; } case Z80_JPCC: { - cycles(&opts->gen, 7);//T States: 4,3 + cycles(&opts->gen, num_cycles + 3);//T States: 4,3 uint8_t cond = CC_Z; switch (inst->reg) { @@ -1838,7 +1825,7 @@ break; } case Z80_JR: { - cycles(&opts->gen, 12);//T States: 4,3,5 + cycles(&opts->gen, num_cycles + 8);//T States: 4,3,5 uint16_t dest_addr = address + inst->immed + 2; code_ptr call_dst = z80_get_native_address(context, dest_addr); if (!call_dst) { @@ -1850,7 +1837,7 @@ break; } case Z80_JRCC: { - cycles(&opts->gen, 7);//T States: 4,3 + cycles(&opts->gen, num_cycles + 3);//T States: 4,3 uint8_t cond = CC_Z; switch (inst->reg) { @@ -1880,7 +1867,7 @@ break; } case Z80_DJNZ: { - cycles(&opts->gen, 8);//T States: 5,3 + cycles(&opts->gen, num_cycles + 4);//T States: 5,3 if (opts->regs[Z80_B] >= 0) { sub_ir(code, 1, opts->regs[Z80_B], SZ_B); } else { @@ -1901,7 +1888,7 @@ break; } case Z80_CALL: { - cycles(&opts->gen, 11);//T States: 4,3,4 + cycles(&opts->gen, num_cycles + 7);//T States: 4,3,4 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); mov_ir(code, address + 3, opts->gen.scratch1, SZ_W); mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); @@ -1916,7 +1903,7 @@ break; } case Z80_CALLCC: { - cycles(&opts->gen, 10);//T States: 4,3,3 (false case) + cycles(&opts->gen, num_cycles + 6);//T States: 4,3,3 (false case) uint8_t cond = CC_Z; switch (inst->reg) { @@ -1959,7 +1946,7 @@ break; } case Z80_RET: - cycles(&opts->gen, 4);//T States: 4 + cycles(&opts->gen, num_cycles);//T States: 4 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); call(code, opts->read_16);//T STates: 3, 3 add_ir(code, 2, opts->regs[Z80_SP], SZ_W); @@ -1967,7 +1954,7 @@ jmp_r(code, opts->gen.scratch1); break; case Z80_RETCC: { - cycles(&opts->gen, 5);//T States: 5 + cycles(&opts->gen, num_cycles + 1);//T States: 5 uint8_t cond = CC_Z; switch (inst->reg) { @@ -2004,7 +1991,7 @@ } case Z80_RETI: //For some systems, this may need a callback for signalling interrupt routine completion - cycles(&opts->gen, 8);//T States: 4, 4 + cycles(&opts->gen, num_cycles);//T States: 4, 4 mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); call(code, opts->read_16);//T STates: 3, 3 add_ir(code, 2, opts->regs[Z80_SP], SZ_W); @@ -2012,7 +1999,7 @@ jmp_r(code, opts->gen.scratch1); break; case Z80_RETN: - cycles(&opts->gen, 8);//T States: 4, 4 + cycles(&opts->gen, num_cycles);//T States: 4, 4 mov_rdispr(code, opts->gen.context_reg, offsetof(z80_context, iff2), opts->gen.scratch2, SZ_B); mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch1, SZ_W); mov_rrdisp(code, opts->gen.scratch2, opts->gen.context_reg, offsetof(z80_context, iff1), SZ_B); @@ -2023,7 +2010,7 @@ break; case Z80_RST: { //RST is basically CALL to an address in page 0 - cycles(&opts->gen, 5);//T States: 5 + cycles(&opts->gen, num_cycles + 1);//T States: 5 sub_ir(code, 2, opts->regs[Z80_SP], SZ_W); mov_ir(code, address + 1, opts->gen.scratch1, SZ_W); mov_rr(code, opts->regs[Z80_SP], opts->gen.scratch2, SZ_W); @@ -2038,7 +2025,10 @@ break; } case Z80_IN: - cycles(&opts->gen, inst->reg == inst->addr_mode == Z80_IMMED_INDIRECT ? 7 : 8);//T States: 4 3/4 + if (inst->addr_mode == Z80_IMMED_INDIRECT) { + num_cycles += 3; + } + cycles(&opts->gen, num_cycles);//T States: 4 3/4 if (inst->addr_mode == Z80_IMMED_INDIRECT) { mov_ir(code, inst->immed, opts->gen.scratch1, SZ_B); } else { @@ -2068,7 +2058,10 @@ case Z80_IND: case Z80_INDR:*/ case Z80_OUT: - cycles(&opts->gen, inst->reg == Z80_A ? 7 : 8);//T States: 4 3/4 + if (inst->reg == Z80_A) { + num_cycles += 3; + } + cycles(&opts->gen, num_cycles);//T States: 4 3/4 if ((inst->addr_mode & 0x1F) == Z80_IMMED_INDIRECT) { mov_ir(code, inst->immed, opts->gen.scratch2, SZ_B); } else { @@ -2087,7 +2080,7 @@ z80_save_reg(inst, opts); break; case Z80_OUTI: - cycles(&opts->gen, 9);//T States: 4, 5 + cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 //read from (HL) zreg_to_native(opts, Z80_HL, opts->gen.scratch1); call(code, opts->read_8);//T states 3 @@ -2132,7 +2125,7 @@ break; case Z80_OTIR: { code_ptr start = code->cur; - cycles(&opts->gen, 9);//T States: 4, 5 + cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 //read from (HL) zreg_to_native(opts, Z80_HL, opts->gen.scratch1); call(code, opts->read_8);//T states 3 @@ -2187,7 +2180,7 @@ break; } case Z80_OUTD: - cycles(&opts->gen, 9);//T States: 4, 5 + cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 //read from (HL) zreg_to_native(opts, Z80_HL, opts->gen.scratch1); call(code, opts->read_8);//T states 3 @@ -2232,7 +2225,7 @@ break; case Z80_OTDR: { code_ptr start = code->cur; - cycles(&opts->gen, 9);//T States: 4, 5 + cycles(&opts->gen, num_cycles + 1);//T States: 4, 5 //read from (HL) zreg_to_native(opts, Z80_HL, opts->gen.scratch1); call(code, opts->read_8);//T states 3 @@ -2335,10 +2328,9 @@ //TODO: make this play well with the breakpoint code mov_ir(code, address, opts->gen.scratch1, SZ_W); call(code, opts->read_8); - //normal opcode fetch is already factored into instruction timing - //back out the base 3 cycles from a read here - //not quite perfect, but it will have to do for now - cycles(&opts->gen, -3); + //opcode fetch M-cycles have one extra T-state + cycles(&opts->gen, 1); + //TODO: increment R check_cycles_int(&opts->gen, address); call(code, opts->gen.save_context); mov_irdisp(code, address, opts->gen.context_reg, offsetof(z80_context, pc), SZ_W); diff -r 3980ef0f6307 -r 1625555e346e z80inst.c --- a/z80inst.c Sun Jul 24 18:53:22 2016 -0700 +++ b/z80inst.c Mon Jul 25 23:16:04 2016 -0700 @@ -6,9 +6,10 @@ #include "z80inst.h" #include #include +#include -#define NOP {Z80_NOP, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 1} -#define NOP2 {Z80_NOP, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 2} +#define NOP {Z80_NOP, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0} +#define USE_MAIN {Z80_USE_MAIN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0} z80inst z80_tbl_a[256] = { //0 @@ -345,7 +346,7 @@ {Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 1}, - NOP2, + NOP, {Z80_IN, Z80_A, Z80_REG_INDIRECT, Z80_C, 0}, {Z80_OUT, Z80_A, Z80_REG_INDIRECT | Z80_DIR, Z80_C, 0}, {Z80_ADC, Z80_HL, Z80_REG, Z80_SP, 0}, @@ -353,75 +354,75 @@ {Z80_NEG, Z80_A, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_RETN, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_IM, Z80_UNUSED, Z80_IMMED, Z80_UNUSED, 2}, - NOP2, + NOP, //8 - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, //9 - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, + NOP, //A {Z80_LDI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_CPI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_INI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_OUTI, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, - NOP2, - NOP2, - NOP2, - NOP2, + NOP, + NOP, + NOP, + NOP, {Z80_LDD, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_CPD, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_IND, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_OUTD, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, - NOP2, - NOP2, - NOP2, - NOP2, + NOP, + NOP, + NOP, + NOP, //B {Z80_LDIR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_CPIR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_INIR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_OTIR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, - NOP2, - NOP2, - NOP2, - NOP2, + NOP, + NOP, + NOP, + NOP, {Z80_LDDR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_CPDR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_INDR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_OTDR, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 0}, - NOP2, - NOP2, - NOP2, - NOP2 + NOP, + NOP, + NOP, + NOP }; #define SHIFT_BLOCK(op) \ @@ -497,107 +498,107 @@ z80inst z80_tbl_ix[256] = { //0 - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_ADD, Z80_IX, Z80_REG, Z80_BC, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, //1 - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_ADD, Z80_IX, Z80_REG, Z80_DE, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, //2 - NOP2, + USE_MAIN, {Z80_LD, Z80_IX, Z80_IMMED, Z80_UNUSED, 0}, {Z80_LD, Z80_IX, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0}, {Z80_INC, Z80_IX, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_INC, Z80_IXH, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_DEC, Z80_IXH, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_LD, Z80_IXH, Z80_IMMED, Z80_UNUSED, 0}, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, {Z80_ADD, Z80_IX, Z80_REG, Z80_IX, 0}, {Z80_LD, Z80_IX, Z80_IMMED_INDIRECT, Z80_UNUSED, 0}, {Z80_DEC, Z80_IX, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_INC, Z80_IXL, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_DEC, Z80_IXL, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_LD, Z80_IXL, Z80_IMMED, Z80_UNUSED, 0}, - NOP2, + USE_MAIN, //3 - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_INC, Z80_UNUSED, Z80_IX_DISPLACE, 0, 0}, {Z80_DEC, Z80_UNUSED, Z80_IX_DISPLACE, 0, 0}, {Z80_LD, Z80_USE_IMMED, Z80_IX_DISPLACE | Z80_DIR, 0, 0}, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, {Z80_ADD, Z80_IX, Z80_REG, Z80_SP, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, //4 - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_LD, Z80_B, Z80_REG, Z80_IXH, 0}, {Z80_LD, Z80_B, Z80_REG, Z80_IXL, 0}, {Z80_LD, Z80_B, Z80_IX_DISPLACE, 0, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_LD, Z80_C, Z80_REG, Z80_IXH, 0}, {Z80_LD, Z80_C, Z80_REG, Z80_IXL, 0}, {Z80_LD, Z80_C, Z80_IX_DISPLACE, 0, 0}, - NOP2, + USE_MAIN, //5 - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_LD, Z80_D, Z80_REG, Z80_IXH, 0}, {Z80_LD, Z80_D, Z80_REG, Z80_IXL, 0}, {Z80_LD, Z80_D, Z80_IX_DISPLACE, 0, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_LD, Z80_E, Z80_REG, Z80_IXH, 0}, {Z80_LD, Z80_E, Z80_REG, Z80_IXL, 0}, {Z80_LD, Z80_E, Z80_IX_DISPLACE, 0, 0}, - NOP2, + USE_MAIN, //6 {Z80_LD, Z80_IXH, Z80_REG, Z80_B, 0}, {Z80_LD, Z80_IXH, Z80_REG, Z80_C, 0}, @@ -622,152 +623,152 @@ {Z80_LD, Z80_E, Z80_IX_DISPLACE | Z80_DIR, 0, 0}, {Z80_LD, Z80_H, Z80_IX_DISPLACE | Z80_DIR, 0, 0}, {Z80_LD, Z80_L, Z80_IX_DISPLACE | Z80_DIR, 0, 0}, - NOP2, + USE_MAIN, {Z80_LD, Z80_A, Z80_IX_DISPLACE | Z80_DIR, 0, 0}, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_LD, Z80_A, Z80_REG, Z80_IXH, 0}, {Z80_LD, Z80_A, Z80_REG, Z80_IXL, 0}, {Z80_LD, Z80_A, Z80_IX_DISPLACE, 0, 0}, - NOP2, + USE_MAIN, //8 - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_ADD, Z80_A, Z80_REG, Z80_IXH, 0}, {Z80_ADD, Z80_A, Z80_REG, Z80_IXL, 0}, {Z80_ADD, Z80_A, Z80_IX_DISPLACE, 0, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_ADC, Z80_A, Z80_REG, Z80_IXH, 0}, {Z80_ADC, Z80_A, Z80_REG, Z80_IXL, 0}, {Z80_ADC, Z80_A, Z80_IX_DISPLACE, 0, 0}, - NOP2, + USE_MAIN, //9 - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_SUB, Z80_A, Z80_REG, Z80_IXH, 0}, {Z80_SUB, Z80_A, Z80_REG, Z80_IXL, 0}, {Z80_SUB, Z80_A, Z80_IX_DISPLACE, 0, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_SBC, Z80_A, Z80_REG, Z80_IXH, 0}, {Z80_SBC, Z80_A, Z80_REG, Z80_IXL, 0}, {Z80_SBC, Z80_A, Z80_IX_DISPLACE, 0, 0}, - NOP2, + USE_MAIN, //A - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_AND, Z80_A, Z80_REG, Z80_IXH, 0}, {Z80_AND, Z80_A, Z80_REG, Z80_IXL, 0}, {Z80_AND, Z80_A, Z80_IX_DISPLACE, 0, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_XOR, Z80_A, Z80_REG, Z80_IXH, 0}, {Z80_XOR, Z80_A, Z80_REG, Z80_IXL, 0}, {Z80_XOR, Z80_A, Z80_IX_DISPLACE, 0, 0}, - NOP2, + USE_MAIN, //B - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_OR, Z80_A, Z80_REG, Z80_IXH, 0}, {Z80_OR, Z80_A, Z80_REG, Z80_IXL, 0}, {Z80_OR, Z80_A, Z80_IX_DISPLACE, 0, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_CP, Z80_A, Z80_REG, Z80_IXH, 0}, {Z80_CP, Z80_A, Z80_REG, Z80_IXL, 0}, {Z80_CP, Z80_A, Z80_IX_DISPLACE, 0, 0}, - NOP2, + USE_MAIN, //C - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, //D - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, //E - NOP2, + USE_MAIN, {Z80_POP, Z80_IX, Z80_UNUSED, Z80_UNUSED, 0}, - NOP2, + USE_MAIN, {Z80_EX, Z80_IX, Z80_REG_INDIRECT | Z80_DIR, Z80_SP, 0}, - NOP2, + USE_MAIN, {Z80_PUSH, Z80_IX, Z80_UNUSED, Z80_UNUSED, 0}, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_JP, Z80_UNUSED, Z80_REG_INDIRECT, Z80_IX, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, //F - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_LD, Z80_SP, Z80_REG, Z80_IX, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2 + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN }; #define SHIFT_BLOCK_IX(op) \ @@ -853,107 +854,107 @@ z80inst z80_tbl_iy[256] = { //0 - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_ADD, Z80_IY, Z80_REG, Z80_BC, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, //1 - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_ADD, Z80_IY, Z80_REG, Z80_DE, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, //2 - NOP2, + USE_MAIN, {Z80_LD, Z80_IY, Z80_IMMED, Z80_UNUSED, 0}, {Z80_LD, Z80_IY, Z80_IMMED_INDIRECT | Z80_DIR, Z80_UNUSED, 0}, {Z80_INC, Z80_IY, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_INC, Z80_IYH, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_DEC, Z80_IYH, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_LD, Z80_IYH, Z80_IMMED, Z80_UNUSED, 0}, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, {Z80_ADD, Z80_IY, Z80_REG, Z80_IY, 0}, {Z80_LD, Z80_IY, Z80_IMMED_INDIRECT, Z80_UNUSED, 0}, {Z80_DEC, Z80_IY, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_INC, Z80_IYL, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_DEC, Z80_IYL, Z80_UNUSED, Z80_UNUSED, 0}, {Z80_LD, Z80_IYL, Z80_IMMED, Z80_UNUSED, 0}, - NOP2, + USE_MAIN, //3 - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_INC, Z80_UNUSED, Z80_IY_DISPLACE, 0, 0}, {Z80_DEC, Z80_UNUSED, Z80_IY_DISPLACE, 0, 0}, {Z80_LD, Z80_USE_IMMED, Z80_IY_DISPLACE | Z80_DIR, 0, 0}, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, {Z80_ADD, Z80_IY, Z80_REG, Z80_SP, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, //4 - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_LD, Z80_B, Z80_REG, Z80_IYH, 0}, {Z80_LD, Z80_B, Z80_REG, Z80_IYL, 0}, {Z80_LD, Z80_B, Z80_IY_DISPLACE, 0, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_LD, Z80_C, Z80_REG, Z80_IYH, 0}, {Z80_LD, Z80_C, Z80_REG, Z80_IYL, 0}, {Z80_LD, Z80_C, Z80_IY_DISPLACE, 0, 0}, - NOP2, + USE_MAIN, //5 - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_LD, Z80_D, Z80_REG, Z80_IYH, 0}, {Z80_LD, Z80_D, Z80_REG, Z80_IYL, 0}, {Z80_LD, Z80_D, Z80_IY_DISPLACE, 0, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_LD, Z80_E, Z80_REG, Z80_IYH, 0}, {Z80_LD, Z80_E, Z80_REG, Z80_IYL, 0}, {Z80_LD, Z80_E, Z80_IY_DISPLACE, 0, 0}, - NOP2, + USE_MAIN, //6 {Z80_LD, Z80_IYH, Z80_REG, Z80_B, 0}, {Z80_LD, Z80_IYH, Z80_REG, Z80_C, 0}, @@ -978,154 +979,152 @@ {Z80_LD, Z80_E, Z80_IY_DISPLACE | Z80_DIR, 0, 0}, {Z80_LD, Z80_H, Z80_IY_DISPLACE | Z80_DIR, 0, 0}, {Z80_LD, Z80_L, Z80_IY_DISPLACE | Z80_DIR, 0, 0}, - NOP2, + USE_MAIN, {Z80_LD, Z80_A, Z80_IY_DISPLACE | Z80_DIR, 0, 0}, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_LD, Z80_A, Z80_REG, Z80_IYH, 0}, {Z80_LD, Z80_A, Z80_REG, Z80_IYL, 0}, {Z80_LD, Z80_A, Z80_IY_DISPLACE, 0, 0}, - NOP2, + USE_MAIN, //8 - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_ADD, Z80_A, Z80_REG, Z80_IYH, 0}, {Z80_ADD, Z80_A, Z80_REG, Z80_IYL, 0}, {Z80_ADD, Z80_A, Z80_IY_DISPLACE, 0, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_ADC, Z80_A, Z80_REG, Z80_IYH, 0}, {Z80_ADC, Z80_A, Z80_REG, Z80_IYL, 0}, {Z80_ADC, Z80_A, Z80_IY_DISPLACE, 0, 0}, - NOP2, + USE_MAIN, //9 - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_SUB, Z80_A, Z80_REG, Z80_IYH, 0}, {Z80_SUB, Z80_A, Z80_REG, Z80_IYL, 0}, {Z80_SUB, Z80_A, Z80_IY_DISPLACE, 0, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_SBC, Z80_A, Z80_REG, Z80_IYH, 0}, {Z80_SBC, Z80_A, Z80_REG, Z80_IYL, 0}, {Z80_SBC, Z80_A, Z80_IY_DISPLACE, 0, 0}, - NOP2, + USE_MAIN, //A - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_AND, Z80_A, Z80_REG, Z80_IYH, 0}, {Z80_AND, Z80_A, Z80_REG, Z80_IYL, 0}, {Z80_AND, Z80_A, Z80_IY_DISPLACE, 0, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_XOR, Z80_A, Z80_REG, Z80_IYH, 0}, {Z80_XOR, Z80_A, Z80_REG, Z80_IYL, 0}, {Z80_XOR, Z80_A, Z80_IY_DISPLACE, 0, 0}, - NOP2, + USE_MAIN, //B - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_OR, Z80_A, Z80_REG, Z80_IYH, 0}, {Z80_OR, Z80_A, Z80_REG, Z80_IYL, 0}, {Z80_OR, Z80_A, Z80_IY_DISPLACE, 0, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_CP, Z80_A, Z80_REG, Z80_IYH, 0}, {Z80_CP, Z80_A, Z80_REG, Z80_IYL, 0}, {Z80_CP, Z80_A, Z80_IY_DISPLACE, 0, 0}, - NOP2, + USE_MAIN, //C - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, //D - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, //E - NOP2, + USE_MAIN, {Z80_POP, Z80_IY, Z80_UNUSED, Z80_UNUSED, 0}, - NOP2, + USE_MAIN, {Z80_EX, Z80_IY, Z80_REG_INDIRECT | Z80_DIR, Z80_SP, 0}, - NOP2, + USE_MAIN, {Z80_PUSH, Z80_IY, Z80_UNUSED, Z80_UNUSED, 0}, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_JP, Z80_UNUSED, Z80_REG_INDIRECT, Z80_IY, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, //F - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, {Z80_LD, Z80_SP, Z80_REG, Z80_IY, 0}, - NOP2, - NOP2, - NOP2, - NOP2, - NOP2, - //TODO: Enable this based on a define - {Z80_NOP, Z80_UNUSED, Z80_UNUSED, Z80_UNUSED, 42} - //NOP2 + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN, + USE_MAIN }; #define SHIFT_BLOCK_IY(op) \ @@ -1209,49 +1208,78 @@ BIT_BLOCK_IY_REG(Z80_SET, 7), }; +enum { + NORMAL, + USE_IX, + USE_IY +}; + uint8_t * z80_decode(uint8_t * istream, z80inst * decoded) { uint8_t tmp; - if (*istream == 0xCB) { - istream++; - memcpy(decoded, z80_tbl_bit + *istream, sizeof(z80inst)); - } else if (*istream == 0xDD) { - istream++; - if (*istream == 0xCB) { - tmp = *(++istream); + uint8_t *start = istream; + uint8_t ixiy = NORMAL; + uint16_t ixiy_disp = 0x100; + z80inst *base = NULL; + while(!base) + { + switch (*istream) + { + case 0xCB: + istream++; + if (ixiy == NORMAL) { + base = z80_tbl_bit + *istream; + } else if (ixiy == USE_IX) { + ixiy_disp = *(istream++); + base = z80_tbl_ix_bit + *istream; + } else { + ixiy_disp = *(istream++); + base = z80_tbl_iy_bit + *istream; + } + break; + case 0xED: istream++; - memcpy(decoded, z80_tbl_ix_bit + *istream, sizeof(z80inst)); - decoded->ea_reg = tmp; - } else { - memcpy(decoded, z80_tbl_ix + *istream, sizeof(z80inst)); - if ((decoded->addr_mode & 0x1F) == Z80_IX_DISPLACE) { - decoded->ea_reg = *(++istream); + ixiy = NORMAL; + if (*istream < 0x40 || *istream >= 0xC0) { + base = z80_tbl_extd + 0xBF; + } else { + base = z80_tbl_extd + *istream - 0x40; + } + break; + case 0xDD: + istream++; + ixiy = USE_IX; + break; + case 0xFD: + istream++; + ixiy = USE_IY; + break; + default: + if (ixiy == NORMAL) { + base = z80_tbl_a + *istream; + } else if (ixiy == USE_IX) { + base = z80_tbl_ix + *istream; + } else { + base = z80_tbl_iy + *istream; } } - } else if (*istream == 0xED) { - istream++; - if (*istream < 0x40 || *istream >= 0xC0) { - memcpy(decoded, z80_tbl_extd + 0xBF, sizeof(z80inst)); - } else { - memcpy(decoded, z80_tbl_extd + *istream-0x40, sizeof(z80inst)); + } + if (base->op == Z80_USE_MAIN) { + base = z80_tbl_a + *istream; + ixiy = NORMAL; + } + memcpy(decoded, base, offsetof(z80inst, opcode_bytes)); + decoded->opcode_bytes = istream - start + 1; + if (ixiy != NORMAL) { + if (ixiy_disp < 0x100) { + decoded->ea_reg = ixiy_disp; + //don't count displacement byte as an opcode byte + decoded->opcode_bytes--; + } else if ((decoded->addr_mode & 0x1F) == Z80_IX_DISPLACE || (decoded->addr_mode & 0x1F) == Z80_IY_DISPLACE) { + decoded->ea_reg = *(++istream); } - } else if (*istream == 0xFD) { - istream++; - if (*istream == 0xCB) { - tmp = *(++istream); - istream++; - memcpy(decoded, z80_tbl_iy_bit + *istream, sizeof(z80inst)); - decoded->ea_reg = tmp; - } else { - memcpy(decoded, z80_tbl_iy + *istream, sizeof(z80inst)); - if ((decoded->addr_mode & 0x1F) == Z80_IY_DISPLACE) { - decoded->ea_reg = *(++istream); - } - } - } else { - memcpy(decoded, z80_tbl_a + *istream, sizeof(z80inst)); - } + if ((decoded->addr_mode & 0x1F) == Z80_IMMED && decoded->op != Z80_RST && decoded->op != Z80_IM) { decoded->immed = *(++istream); if ((decoded->reg >= Z80_BC && decoded->reg < Z80_UNUSED) || decoded->op == Z80_CALL || decoded->op == Z80_CALLCC || decoded->op == Z80_JP || decoded->op == Z80_JPCC) { diff -r 3980ef0f6307 -r 1625555e346e z80inst.h --- a/z80inst.h Sun Jul 24 18:53:22 2016 -0700 +++ b/z80inst.h Mon Jul 25 23:16:04 2016 -0700 @@ -76,7 +76,8 @@ Z80_OUTI, Z80_OTIR, Z80_OUTD, - Z80_OTDR + Z80_OTDR, + Z80_USE_MAIN }; enum { @@ -133,6 +134,7 @@ uint8_t addr_mode; uint8_t ea_reg; uint16_t immed; + uint16_t opcode_bytes; } z80inst; uint8_t * z80_decode(uint8_t * istream, z80inst * decoded);