summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gen_x86.c53
-rw-r--r--z80_to_x86.c4
2 files changed, 55 insertions, 2 deletions
diff --git a/gen_x86.c b/gen_x86.c
index 8ba2136..aa68700 100644
--- a/gen_x86.c
+++ b/gen_x86.c
@@ -517,6 +517,54 @@ uint8_t * x86_irdisp8(uint8_t * out, uint8_t opcode, uint8_t op_ex, int32_t val,
return out;
}
+uint8_t * x86_irdisp32(uint8_t * out, uint8_t opcode, uint8_t op_ex, int32_t val, uint8_t dst, int32_t disp, uint8_t size)
+{
+ uint8_t sign_extend = 0;
+ if ((size == SZ_D || size == SZ_Q) && val <= 0x7F && val >= -0x80) {
+ sign_extend = 1;
+ opcode |= BIT_DIR;
+ }
+ if (size == SZ_W) {
+ *(out++) = PRE_SIZE;
+ }
+
+ if (size == SZ_Q || dst >= R8) {
+ *out = PRE_REX;
+ if (size == SZ_Q) {
+ *out |= REX_QUAD;
+ }
+ if (dst >= R8) {
+ *out |= REX_RM_FIELD;
+ dst -= (R8 - X86_R8);
+ }
+ out++;
+ }
+ if (size != SZ_B) {
+ opcode |= BIT_SIZE;
+ }
+ *(out++) = opcode;
+ *(out++) = MODE_REG_DISPLACE32 | dst | (op_ex << 3);
+ *(out++) = disp;
+ disp >>= 8;
+ *(out++) = disp;
+ disp >>= 8;
+ *(out++) = disp;
+ disp >>= 8;
+ *(out++) = disp;
+ *(out++) = val;
+ if (size != SZ_B && !sign_extend) {
+ val >>= 8;
+ *(out++) = val;
+ if (size != SZ_W) {
+ val >>= 8;
+ *(out++) = val;
+ val >>= 8;
+ *(out++) = val;
+ }
+ }
+ return out;
+}
+
uint8_t * x86_shiftrot_ir(uint8_t * out, uint8_t op_ex, uint8_t val, uint8_t dst, uint8_t size)
{
@@ -781,6 +829,11 @@ uint8_t * add_irdisp8(uint8_t * out, int32_t val, uint8_t dst_base, int8_t disp,
return x86_irdisp8(out, OP_IMMED_ARITH, OP_EX_ADDI, val, dst_base, disp, size);
}
+uint8_t * add_irdisp32(uint8_t * out, int32_t val, uint8_t dst_base, int32_t disp, uint8_t size)
+{
+ return x86_irdisp32(out, OP_IMMED_ARITH, OP_EX_ADDI, val, dst_base, disp, size);
+}
+
uint8_t * add_rrdisp8(uint8_t * out, uint8_t src, uint8_t dst_base, int8_t disp, uint8_t size)
{
return x86_rrdisp8_sizedir(out, OP_ADD, src, dst_base, disp, size, 0);
diff --git a/z80_to_x86.c b/z80_to_x86.c
index 4faf4cc..6ac701d 100644
--- a/z80_to_x86.c
+++ b/z80_to_x86.c
@@ -901,11 +901,11 @@ uint8_t * translate_z80inst(z80inst * inst, uint8_t * dst, z80_context * context
break;
case Z80_EI:
dst = zcycles(dst, 4);
- dst = mov_rrdisp8(dst, ZCYCLES, CONTEXT, offsetof(z80_context, int_enable_cycle), SZ_D);
+ dst = mov_rrdisp32(dst, ZCYCLES, CONTEXT, offsetof(z80_context, int_enable_cycle), SZ_D);
dst = mov_irdisp8(dst, 1, CONTEXT, offsetof(z80_context, iff1), SZ_B);
dst = mov_irdisp8(dst, 1, CONTEXT, offsetof(z80_context, iff2), SZ_B);
//interrupt enable has a one-instruction latency, minimum instruction duration is 4 cycles
- dst = add_irdisp8(dst, 4, CONTEXT, offsetof(z80_context, int_enable_cycle), SZ_D);
+ dst = add_irdisp32(dst, 4, CONTEXT, offsetof(z80_context, int_enable_cycle), SZ_D);
dst = call(dst, (uint8_t *)z80_do_sync);
break;
case Z80_IM: