summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--z80_to_x86.c202
-rw-r--r--z80inst.c888
-rw-r--r--z80inst.h4
3 files changed, 558 insertions, 536 deletions
diff --git a/z80_to_x86.c b/z80_to_x86.c
index 83cf938..e513426 100644
--- a/z80_to_x86.c
+++ b/z80_to_x86.c
@@ -343,6 +343,8 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
{
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
}
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
//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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
//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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
}
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
//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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
}
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
}
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
}
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
}
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
}
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
}
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
}
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ void translate_z80inst(z80inst * inst, z80_context * context, uint16_t address,
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 @@ code_info z80_make_interp_stub(z80_context * context, uint16_t address)
//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 --git a/z80inst.c b/z80inst.c
index cecce6e..6d00736 100644
--- a/z80inst.c
+++ b/z80inst.c
@@ -6,9 +6,10 @@
#include "z80inst.h"
#include <string.h>
#include <stdio.h>
+#include <stddef.h>
-#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 @@ z80inst z80_tbl_extd[0xC0-0x40] = {
{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 @@ z80inst z80_tbl_extd[0xC0-0x40] = {
{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_bit[256] = {
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 @@ z80inst z80_tbl_ix[256] = {
{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_ix_bit[256] = {
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 @@ z80inst z80_tbl_iy[256] = {
{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 @@ z80inst z80_tbl_iy_bit[256] = {
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++;
- 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);
+ 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;
}
- }
- } 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));
- }
- } else if (*istream == 0xFD) {
- istream++;
- if (*istream == 0xCB) {
- tmp = *(++istream);
+ break;
+ case 0xED:
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);
+ 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 {
- memcpy(decoded, z80_tbl_a + *istream, 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);
+ }
+ }
+
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 --git a/z80inst.h b/z80inst.h
index f2d7566..a5ad409 100644
--- a/z80inst.h
+++ b/z80inst.h
@@ -76,7 +76,8 @@ enum {
Z80_OUTI,
Z80_OTIR,
Z80_OUTD,
- Z80_OTDR
+ Z80_OTDR,
+ Z80_USE_MAIN
};
enum {
@@ -133,6 +134,7 @@ typedef struct {
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);