diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 2e6b6fe..da48116 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -9,7 +9,12 @@ #include "cpu.h" #include "codegen.h" #include "codegen_ops.h" + +#ifdef __amd64__ +#include "codegen_ops_x86-64.h" +#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 #include "codegen_ops_x86.h" +#endif #include "codegen_ops_arith.h" #include "codegen_ops_fpu.h" diff --git a/src/codegen_ops_arith.h b/src/codegen_ops_arith.h index fcdc4c7..0a15d93 100644 --- a/src/codegen_ops_arith.h +++ b/src/codegen_ops_arith.h @@ -6,12 +6,12 @@ static uint32_t ropINC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin host_reg = LOAD_REG_W(opcode & 7); - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, host_reg); ADD_HOST_REG_IMM(host_reg, 1); STORE_IMM_ADDR_L((uint32_t)&flags_op2, 1); AND_HOST_REG_IMM(host_reg, 0xffff); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_INC16); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_res, host_reg); STORE_REG_W_RELEASE(host_reg); codegen_flags_changed = 1; @@ -45,12 +45,12 @@ static uint32_t ropDEC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin host_reg = LOAD_REG_W(opcode & 7); - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, host_reg); SUB_HOST_REG_IMM(host_reg, 1); STORE_IMM_ADDR_L((uint32_t)&flags_op2, 1); AND_HOST_REG_IMM(host_reg, 0xffff); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_DEC16); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_res, host_reg); STORE_REG_W_RELEASE(host_reg); codegen_flags_changed = 1; @@ -88,10 +88,10 @@ static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin dst_reg = LOAD_REG_B(fetchdat & 7); \ STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ ## op ## 8); \ src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_op2, src_reg); \ op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \ + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_res, dst_reg); \ if (writeback) STORE_REG_B_RELEASE(dst_reg); \ else RELEASE_REG(dst_reg); \ RELEASE_REG(src_reg); \ @@ -109,10 +109,10 @@ static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin dst_reg = LOAD_REG_W(fetchdat & 7); \ STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ ## op ## 16); \ src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op2, src_reg); \ op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \ + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_res, dst_reg); \ if (writeback) STORE_REG_W_RELEASE(dst_reg); \ else RELEASE_REG(dst_reg); \ RELEASE_REG(src_reg); \ @@ -131,8 +131,8 @@ static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ ## op ## 32); \ src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); \ - op ## _HOST_REG_L(dst_reg, src_reg); \ STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); \ + op ## _HOST_REG_L(dst_reg, src_reg); \ STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \ if (writeback) STORE_REG_L_RELEASE(dst_reg); \ else RELEASE_REG(dst_reg); \ @@ -161,10 +161,10 @@ static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin \ dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ ## op ## 8); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_op2, src_reg); \ op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \ + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_res, dst_reg); \ if (writeback) STORE_REG_B_RELEASE(dst_reg); \ else RELEASE_REG(dst_reg); \ RELEASE_REG(src_reg); \ @@ -190,10 +190,10 @@ static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin \ dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ ## op ## 16); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, dst_reg); \ + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op2, src_reg); \ op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \ + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_res, dst_reg); \ if (writeback) STORE_REG_W_RELEASE(dst_reg); \ else RELEASE_REG(dst_reg); \ RELEASE_REG(src_reg); \ @@ -220,8 +220,8 @@ static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ ## op ## 32); \ STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); \ - op ## _HOST_REG_L(dst_reg, src_reg); \ STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); \ + op ## _HOST_REG_L(dst_reg, src_reg); \ STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \ if (writeback) STORE_REG_L_RELEASE(dst_reg); \ else RELEASE_REG(dst_reg); \ @@ -235,7 +235,91 @@ ROP_ARITH_RMW(ADD, ADD, 1) ROP_ARITH_RMW(SUB, SUB, 1) ROP_ARITH_RM(ADD, ADD, 1) ROP_ARITH_RM(SUB, SUB, 1) -ROP_ARITH_RM(CMP, SUB, 0) + +static uint32_t ropCMP_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int src_reg, dst_reg; + + if ((fetchdat & 0xc0) == 0xc0) + { + src_reg = LOAD_REG_B(fetchdat & 7); + } + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_B(target_seg); + src_reg = 0; + } + + dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB8); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_B(dst_reg, src_reg); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_op2, src_reg); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + codegen_flags_changed = 1; + return op_pc + 1; +} +static uint32_t ropCMP_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int src_reg, dst_reg; + + if ((fetchdat & 0xc0) == 0xc0) + { + src_reg = LOAD_REG_W(fetchdat & 7); + } + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_W(target_seg); + src_reg = 0; + } + + dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_W(dst_reg, src_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op2, src_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + codegen_flags_changed = 1; + return op_pc + 1; +} +static uint32_t ropCMP_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int src_reg, dst_reg; + + if ((fetchdat & 0xc0) == 0xc0) + { + src_reg = LOAD_REG_L(fetchdat & 7); + } + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_L(target_seg); + src_reg = 0; + } + + dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB32); + STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_L(dst_reg, src_reg); + STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); + STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + codegen_flags_changed = 1; + return op_pc + 1; +} static uint32_t ropCMP_b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { @@ -255,10 +339,10 @@ static uint32_t ropCMP_b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB8); src_reg = LOAD_REG_B((fetchdat >> 3) & 7); - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); - SUB_HOST_REG_B(dst_reg, src_reg); - STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_B(dst_reg, src_reg); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_op2, src_reg); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_res, dst_reg); RELEASE_REG(dst_reg); RELEASE_REG(src_reg); @@ -283,10 +367,10 @@ static uint32_t ropCMP_w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16); src_reg = LOAD_REG_W((fetchdat >> 3) & 7); - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); - SUB_HOST_REG_W(dst_reg, src_reg); - STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, dst_reg); + dst_reg = CMP_HOST_REG_W(dst_reg, src_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op2, src_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_res, dst_reg); RELEASE_REG(dst_reg); RELEASE_REG(src_reg); @@ -312,7 +396,7 @@ static uint32_t ropCMP_l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB32); src_reg = LOAD_REG_L((fetchdat >> 3) & 7); STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); - SUB_HOST_REG_L(dst_reg, src_reg); + dst_reg = CMP_HOST_REG_L(dst_reg, src_reg); STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); RELEASE_REG(dst_reg); @@ -327,11 +411,11 @@ static uint32_t ropADD_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, { int host_reg = LOAD_REG_B(REG_AL); - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_op1, host_reg); ADD_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat & 0xff); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD8); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_res, host_reg); STORE_REG_B_RELEASE(host_reg); codegen_flags_changed = 1; @@ -341,11 +425,11 @@ static uint32_t ropADD_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, { int host_reg = LOAD_REG_W(REG_AX); - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, host_reg); ADD_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat & 0xffff); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD16); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_res, host_reg); STORE_REG_W_RELEASE(host_reg); codegen_flags_changed = 1; @@ -371,11 +455,11 @@ static uint32_t ropCMP_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, { int host_reg = LOAD_REG_B(REG_AL); - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); - SUB_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat & 0xff); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB8); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_res, host_reg); RELEASE_REG(host_reg); codegen_flags_changed = 1; @@ -384,12 +468,12 @@ static uint32_t ropCMP_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, static uint32_t ropCMP_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { int host_reg = LOAD_REG_W(REG_AX); - - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); + + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat & 0xffff); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_res, host_reg); RELEASE_REG(host_reg); codegen_flags_changed = 1; @@ -401,7 +485,7 @@ static uint32_t ropCMP_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32 STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); fetchdat = fastreadl(cs + op_pc); - SUB_HOST_REG_IMM(host_reg, fetchdat); + host_reg = CMP_HOST_REG_IMM_L(host_reg, fetchdat); STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB32); STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); @@ -415,11 +499,11 @@ static uint32_t ropSUB_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, { int host_reg = LOAD_REG_B(REG_AL); - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_op1, host_reg); SUB_HOST_REG_IMM_B(host_reg, fetchdat & 0xff); STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat & 0xff); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB8); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_res, host_reg); STORE_REG_B_RELEASE(host_reg); codegen_flags_changed = 1; @@ -429,11 +513,11 @@ static uint32_t ropSUB_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, { int host_reg = LOAD_REG_W(REG_AX); - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, host_reg); SUB_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff); STORE_IMM_ADDR_L((uint32_t)&flags_op2, fetchdat & 0xffff); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_res, host_reg); STORE_REG_W_RELEASE(host_reg); codegen_flags_changed = 1; @@ -469,7 +553,7 @@ static uint32_t rop80(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_ switch (fetchdat & 0x38) { case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_op1, host_reg); ADD_HOST_REG_IMM_B(host_reg, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD8); @@ -479,11 +563,11 @@ static uint32_t rop80(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_ STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8); break; case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm); + AND_HOST_REG_IMM(host_reg, imm | 0xffffff00); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8); break; case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_op1, host_reg); SUB_HOST_REG_IMM_B(host_reg, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB8); @@ -493,14 +577,14 @@ static uint32_t rop80(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_ STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8); break; case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); - SUB_HOST_REG_IMM_B(host_reg, imm); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_B(host_reg, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB8); break; } - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_HOST_REG_ADDR_BL((uint32_t)&flags_res, host_reg); if ((fetchdat & 0x38) != 0x38) STORE_REG_B_RELEASE(host_reg); else @@ -524,7 +608,7 @@ static uint32_t rop81_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 switch (fetchdat & 0x38) { case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, host_reg); ADD_HOST_REG_IMM_W(host_reg, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD16); @@ -534,11 +618,11 @@ static uint32_t rop81_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16); break; case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm); + AND_HOST_REG_IMM(host_reg, imm | 0xffff0000); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16); break; case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, host_reg); SUB_HOST_REG_IMM_W(host_reg, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16); @@ -548,14 +632,14 @@ static uint32_t rop81_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16); break; case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, imm); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_W(host_reg, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16); break; } - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_res, host_reg); if ((fetchdat & 0x38) != 0x38) STORE_REG_W_RELEASE(host_reg); else @@ -604,7 +688,7 @@ static uint32_t rop81_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 break; case 0x38: /*CMP*/ STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); - SUB_HOST_REG_IMM(host_reg, imm); + host_reg = CMP_HOST_REG_IMM_L(host_reg, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB32); break; @@ -636,7 +720,7 @@ static uint32_t rop83_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 switch (fetchdat & 0x38) { case 0x00: /*ADD*/ - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, host_reg); ADD_HOST_REG_IMM_W(host_reg, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ADD16); @@ -646,11 +730,11 @@ static uint32_t rop83_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16); break; case 0x20: /*AND*/ - AND_HOST_REG_IMM(host_reg, imm); + AND_HOST_REG_IMM(host_reg, imm | 0xffff0000); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16); break; case 0x28: /*SUB*/ - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, host_reg); SUB_HOST_REG_IMM_W(host_reg, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16); @@ -660,14 +744,14 @@ static uint32_t rop83_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16); break; case 0x38: /*CMP*/ - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); - SUB_HOST_REG_IMM_W(host_reg, imm); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_op1, host_reg); + host_reg = CMP_HOST_REG_IMM_W(host_reg, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16); break; } - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_HOST_REG_ADDR_WL((uint32_t)&flags_res, host_reg); if ((fetchdat & 0x38) != 0x38) STORE_REG_W_RELEASE(host_reg); else @@ -717,7 +801,7 @@ static uint32_t rop83_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 break; case 0x38: /*CMP*/ STORE_HOST_REG_ADDR((uint32_t)&flags_op1, host_reg); - SUB_HOST_REG_IMM(host_reg, imm); + host_reg = CMP_HOST_REG_IMM_L(host_reg, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op2, imm); STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB32); break; diff --git a/src/codegen_ops_logic.h b/src/codegen_ops_logic.h index 51b78d8..159a5bc 100644 --- a/src/codegen_ops_logic.h +++ b/src/codegen_ops_logic.h @@ -7,10 +7,10 @@ return 0; \ \ dst_reg = LOAD_REG_B(fetchdat & 7); \ - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8); \ + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN8); \ src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \ + STORE_HOST_REG_ADDR_BL((uintptr_t)&flags_res, dst_reg); \ if (writeback) STORE_REG_B_RELEASE(dst_reg); \ else RELEASE_REG(dst_reg); \ RELEASE_REG(src_reg); \ @@ -25,10 +25,10 @@ return 0; \ \ dst_reg = LOAD_REG_W(fetchdat & 7); \ - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16); \ + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN16); \ src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \ + STORE_HOST_REG_ADDR_WL((uintptr_t)&flags_res, dst_reg); \ if (writeback) STORE_REG_W_RELEASE(dst_reg); \ else RELEASE_REG(dst_reg); \ RELEASE_REG(src_reg); \ @@ -43,10 +43,10 @@ return 0; \ \ dst_reg = LOAD_REG_L(fetchdat & 7); \ - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32); \ + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN32); \ src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ op ## _HOST_REG_L(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \ + STORE_HOST_REG_ADDR((uintptr_t)&flags_res, dst_reg); \ if (writeback) STORE_REG_L_RELEASE(dst_reg); \ else RELEASE_REG(dst_reg); \ RELEASE_REG(src_reg); \ @@ -70,9 +70,9 @@ } \ \ dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8); \ + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN8); \ op ## _HOST_REG_B(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \ + STORE_HOST_REG_ADDR_BL((uintptr_t)&flags_res, dst_reg); \ if (writeback) STORE_REG_B_RELEASE(dst_reg); \ else RELEASE_REG(dst_reg); \ RELEASE_REG(src_reg); \ @@ -96,9 +96,9 @@ } \ \ dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16); \ + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN16); \ op ## _HOST_REG_W(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \ + STORE_HOST_REG_ADDR_WL((uintptr_t)&flags_res, dst_reg); \ if (writeback) STORE_REG_W_RELEASE(dst_reg); \ else RELEASE_REG(dst_reg); \ RELEASE_REG(src_reg); \ @@ -122,9 +122,9 @@ } \ \ dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \ - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32); \ + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN32); \ op ## _HOST_REG_L(dst_reg, src_reg); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_res, dst_reg); \ + STORE_HOST_REG_ADDR((uintptr_t)&flags_res, dst_reg); \ if (writeback) STORE_REG_L_RELEASE(dst_reg); \ else RELEASE_REG(dst_reg); \ RELEASE_REG(src_reg); \ @@ -134,16 +134,91 @@ ROP_LOGIC(AND, AND, 1) ROP_LOGIC(OR, OR, 1) -ROP_LOGIC(TEST, AND, 0) ROP_LOGIC(XOR, XOR, 1) +static uint32_t ropTEST_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int src_reg, dst_reg; + + if ((fetchdat & 0xc0) == 0xc0) + { + src_reg = LOAD_REG_B(fetchdat & 7); + } + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_B(target_seg); + src_reg = 0; + } + + dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN8); + dst_reg = TEST_HOST_REG_B(dst_reg, src_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t)&flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + return op_pc + 1; +} +static uint32_t ropTEST_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int src_reg, dst_reg; + + if ((fetchdat & 0xc0) == 0xc0) + { + src_reg = LOAD_REG_W(fetchdat & 7); + } + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_W(target_seg); + src_reg = 0; + } + + dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN16); + dst_reg = TEST_HOST_REG_W(dst_reg, src_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t)&flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + return op_pc + 1; +} +static uint32_t ropTEST_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) +{ + int src_reg, dst_reg; + + if ((fetchdat & 0xc0) == 0xc0) + { + src_reg = LOAD_REG_L(fetchdat & 7); + } + else + { + x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); + STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); + MEM_LOAD_ADDR_EA_L(target_seg); + src_reg = 0; + } + + dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN32); + dst_reg = TEST_HOST_REG_L(dst_reg, src_reg); + STORE_HOST_REG_ADDR((uintptr_t)&flags_res, dst_reg); + RELEASE_REG(dst_reg); + RELEASE_REG(src_reg); + + return op_pc + 1; +} + static uint32_t ropAND_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { int host_reg = LOAD_REG_B(REG_AL); - AND_HOST_REG_IMM(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + AND_HOST_REG_IMM(host_reg, (fetchdat & 0xff) | 0xffffff00); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN8); + STORE_HOST_REG_ADDR_BL((uintptr_t)&flags_res, host_reg); STORE_REG_B_RELEASE(host_reg); return op_pc + 1; @@ -152,9 +227,9 @@ static uint32_t ropAND_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, { int host_reg = LOAD_REG_W(REG_AX); - AND_HOST_REG_IMM(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + AND_HOST_REG_IMM(host_reg, (fetchdat & 0xffff) | 0xffff0000); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN16); + STORE_HOST_REG_ADDR_WL((uintptr_t)&flags_res, host_reg); STORE_REG_W_RELEASE(host_reg); return op_pc + 2; @@ -165,8 +240,8 @@ static uint32_t ropAND_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32 fetchdat = fastreadl(cs + op_pc); AND_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN32); + STORE_HOST_REG_ADDR((uintptr_t)&flags_res, host_reg); STORE_REG_L_RELEASE(host_reg); return op_pc + 4; @@ -177,8 +252,8 @@ static uint32_t ropOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, int host_reg = LOAD_REG_B(REG_AL); OR_HOST_REG_IMM(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN8); + STORE_HOST_REG_ADDR_BL((uintptr_t)&flags_res, host_reg); STORE_REG_B_RELEASE(host_reg); return op_pc + 1; @@ -188,8 +263,8 @@ static uint32_t ropOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, int host_reg = LOAD_REG_W(REG_AX); OR_HOST_REG_IMM(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN16); + STORE_HOST_REG_ADDR_WL((uintptr_t)&flags_res, host_reg); STORE_REG_W_RELEASE(host_reg); return op_pc + 2; @@ -200,8 +275,8 @@ static uint32_t ropOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, fetchdat = fastreadl(cs + op_pc); OR_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN32); + STORE_HOST_REG_ADDR((uintptr_t)&flags_res, host_reg); STORE_REG_L_RELEASE(host_reg); return op_pc + 4; @@ -211,9 +286,9 @@ static uint32_t ropTEST_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32 { int host_reg = LOAD_REG_B(REG_AL); - AND_HOST_REG_IMM(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xff); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN8); + STORE_HOST_REG_ADDR((uintptr_t)&flags_res, host_reg); RELEASE_REG(host_reg); return op_pc + 1; @@ -222,9 +297,9 @@ static uint32_t ropTEST_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32 { int host_reg = LOAD_REG_W(REG_AX); - AND_HOST_REG_IMM(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xffff); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN16); + STORE_HOST_REG_ADDR((uintptr_t)&flags_res, host_reg); RELEASE_REG(host_reg); return op_pc + 2; @@ -234,9 +309,9 @@ static uint32_t ropTEST_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_3 int host_reg = LOAD_REG_L(REG_EAX); fetchdat = fastreadl(cs + op_pc); - AND_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN32); + STORE_HOST_REG_ADDR((uintptr_t)&flags_res, host_reg); RELEASE_REG(host_reg); return op_pc + 4; @@ -247,8 +322,8 @@ static uint32_t ropXOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, int host_reg = LOAD_REG_B(REG_AL); XOR_HOST_REG_IMM(host_reg, fetchdat & 0xff); - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN8); + STORE_HOST_REG_ADDR_BL((uintptr_t)&flags_res, host_reg); STORE_REG_B_RELEASE(host_reg); return op_pc + 1; @@ -258,8 +333,8 @@ static uint32_t ropXOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, int host_reg = LOAD_REG_W(REG_AX); XOR_HOST_REG_IMM(host_reg, fetchdat & 0xffff); - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN16); + STORE_HOST_REG_ADDR_WL((uintptr_t)&flags_res, host_reg); STORE_REG_W_RELEASE(host_reg); return op_pc + 2; @@ -270,8 +345,8 @@ static uint32_t ropXOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32 fetchdat = fastreadl(cs + op_pc); XOR_HOST_REG_IMM(host_reg, fetchdat); - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN32); + STORE_HOST_REG_ADDR((uintptr_t)&flags_res, host_reg); STORE_REG_L_RELEASE(host_reg); return op_pc + 4; @@ -299,9 +374,9 @@ static uint32_t ropF6(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_ MEM_LOAD_ADDR_EA_B(target_seg); host_reg = 0; } - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN8); - AND_HOST_REG_IMM(host_reg, imm); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN8); + host_reg = TEST_HOST_REG_IMM(host_reg, imm); + STORE_HOST_REG_ADDR_BL((uintptr_t)&flags_res, host_reg); RELEASE_REG(host_reg); return op_pc + 2; @@ -317,13 +392,13 @@ static uint32_t ropF6(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_ if ((fetchdat & 0xc0) != 0xc0) return 0; imm_reg = LOAD_REG_IMM(0); - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB8); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_SUB8); host_reg = LOAD_REG_B(fetchdat & 7); - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, imm_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t)&flags_op1, imm_reg); SUB_HOST_REG_B(imm_reg, host_reg); - STORE_HOST_REG_ADDR((uint32_t)&flags_op2, host_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t)&flags_op2, host_reg); STORE_REG_TARGET_B_RELEASE(imm_reg, fetchdat & 7); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, imm_reg); + STORE_HOST_REG_ADDR_BL((uintptr_t)&flags_res, imm_reg); return op_pc + 1; } @@ -351,9 +426,9 @@ static uint32_t ropF7_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 MEM_LOAD_ADDR_EA_W(target_seg); host_reg = 0; } - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN16); - AND_HOST_REG_IMM(host_reg, imm); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN16); + host_reg = TEST_HOST_REG_IMM(host_reg, imm); + STORE_HOST_REG_ADDR_WL((uintptr_t)&flags_res, host_reg); RELEASE_REG(host_reg); return op_pc + 3; @@ -369,13 +444,13 @@ static uint32_t ropF7_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 if ((fetchdat & 0xc0) != 0xc0) return 0; imm_reg = LOAD_REG_IMM(0); - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_SUB16); host_reg = LOAD_REG_W(fetchdat & 7); - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, imm_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t)&flags_op1, imm_reg); SUB_HOST_REG_W(imm_reg, host_reg); - STORE_HOST_REG_ADDR((uint32_t)&flags_op2, host_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t)&flags_op2, host_reg); STORE_REG_TARGET_W_RELEASE(imm_reg, fetchdat & 7); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, imm_reg); + STORE_HOST_REG_ADDR_WL((uintptr_t)&flags_res, imm_reg); return op_pc + 1; } @@ -403,9 +478,9 @@ static uint32_t ropF7_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 MEM_LOAD_ADDR_EA_L(target_seg); host_reg = 0; } - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_ZN32); - AND_HOST_REG_IMM(host_reg, imm); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, host_reg); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_ZN32); + host_reg = TEST_HOST_REG_IMM(host_reg, imm); + STORE_HOST_REG_ADDR((uintptr_t)&flags_res, host_reg); RELEASE_REG(host_reg); return op_pc + 5; @@ -421,13 +496,13 @@ static uint32_t ropF7_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 if ((fetchdat & 0xc0) != 0xc0) return 0; imm_reg = LOAD_REG_IMM(0); - STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB32); + STORE_IMM_ADDR_L((uintptr_t)&flags_op, FLAGS_SUB32); host_reg = LOAD_REG_L(fetchdat & 7); - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, imm_reg); + STORE_HOST_REG_ADDR((uintptr_t)&flags_op1, imm_reg); SUB_HOST_REG_L(imm_reg, host_reg); - STORE_HOST_REG_ADDR((uint32_t)&flags_op2, host_reg); + STORE_HOST_REG_ADDR((uintptr_t)&flags_op2, host_reg); STORE_REG_TARGET_L_RELEASE(imm_reg, fetchdat & 7); - STORE_HOST_REG_ADDR((uint32_t)&flags_res, imm_reg); + STORE_HOST_REG_ADDR((uintptr_t)&flags_res, imm_reg); return op_pc + 1; } diff --git a/src/codegen_ops_mov.h b/src/codegen_ops_mov.h index 73863fb..32ccfa6 100644 --- a/src/codegen_ops_mov.h +++ b/src/codegen_ops_mov.h @@ -370,7 +370,7 @@ static uint32_t ropMOVZX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, if ((fetchdat & 0xc0) == 0xc0) { int host_reg = LOAD_REG_B(fetchdat & 7); - ZERO_EXTEND_W_B(host_reg); + host_reg = ZERO_EXTEND_W_B(host_reg); STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); } else @@ -393,7 +393,7 @@ static uint32_t ropMOVZX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, if ((fetchdat & 0xc0) == 0xc0) { int host_reg = LOAD_REG_B(fetchdat & 7); - ZERO_EXTEND_L_B(host_reg); + host_reg = ZERO_EXTEND_L_B(host_reg); STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); } else @@ -416,7 +416,7 @@ static uint32_t ropMOVZX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, if ((fetchdat & 0xc0) == 0xc0) { int host_reg = LOAD_REG_W(fetchdat & 7); - ZERO_EXTEND_L_W(host_reg); + host_reg = ZERO_EXTEND_L_W(host_reg); STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); } else @@ -440,7 +440,7 @@ static uint32_t ropMOVSX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, if ((fetchdat & 0xc0) == 0xc0) { int host_reg = LOAD_REG_B(fetchdat & 7); - SIGN_EXTEND_W_B(host_reg); + host_reg = SIGN_EXTEND_W_B(host_reg); STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7); } else @@ -463,7 +463,7 @@ static uint32_t ropMOVSX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, if ((fetchdat & 0xc0) == 0xc0) { int host_reg = LOAD_REG_B(fetchdat & 7); - SIGN_EXTEND_L_B(host_reg); + host_reg = SIGN_EXTEND_L_B(host_reg); STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); } else @@ -486,7 +486,7 @@ static uint32_t ropMOVSX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, if ((fetchdat & 0xc0) == 0xc0) { int host_reg = LOAD_REG_W(fetchdat & 7); - SIGN_EXTEND_L_W(host_reg); + host_reg = SIGN_EXTEND_L_W(host_reg); STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7); } else diff --git a/src/codegen_ops_shift.h b/src/codegen_ops_shift.h index 4c61f19..d8de5df 100644 --- a/src/codegen_ops_shift.h +++ b/src/codegen_ops_shift.h @@ -1,7 +1,7 @@ -#define SHIFT(size, size2, count) \ - STORE_IMM_ADDR_ ## size((uint32_t)&flags_op2, count); \ +#define SHIFT(size, size2, count, res_store) \ + STORE_IMM_ADDR_L((uint32_t)&flags_op2, count); \ reg = LOAD_REG_ ## size(fetchdat & 7); \ - STORE_HOST_REG_ADDR((uint32_t)&flags_op1, reg); \ + res_store((uint32_t)&flags_op1, reg); \ \ switch (fetchdat & 0x38) \ { \ @@ -21,7 +21,7 @@ break; \ } \ \ - STORE_HOST_REG_ADDR((uint32_t)&flags_res, reg); \ + res_store((uint32_t)&flags_res, reg); \ STORE_REG_ ## size ## _RELEASE(reg); static uint32_t ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) @@ -36,7 +36,7 @@ static uint32_t ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_ count = (fetchdat >> 8) & 0x1f; - SHIFT(B, 8, count); + SHIFT(B, 8, count, STORE_HOST_REG_ADDR_BL); return op_pc + 2; } @@ -52,7 +52,7 @@ static uint32_t ropC1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 count = (fetchdat >> 8) & 0x1f; - SHIFT(W, 16, count); + SHIFT(W, 16, count, STORE_HOST_REG_ADDR_WL); return op_pc + 2; } @@ -68,7 +68,7 @@ static uint32_t ropC1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 count = (fetchdat >> 8) & 0x1f; - SHIFT(L, 32, count); + SHIFT(L, 32, count, STORE_HOST_REG_ADDR); return op_pc + 2; } @@ -82,7 +82,7 @@ static uint32_t ropD0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_ if ((fetchdat & 0x38) < 0x20) return 0; - SHIFT(B, 8, 1); + SHIFT(B, 8, 1, STORE_HOST_REG_ADDR_BL); return op_pc + 1; } @@ -95,7 +95,7 @@ static uint32_t ropD1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 if ((fetchdat & 0x38) < 0x20) return 0; - SHIFT(W, 16, 1); + SHIFT(W, 16, 1, STORE_HOST_REG_ADDR_WL); return op_pc + 1; } @@ -108,7 +108,7 @@ static uint32_t ropD1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint3 if ((fetchdat & 0x38) < 0x20) return 0; - SHIFT(L, 32, 1); + SHIFT(L, 32, 1, STORE_HOST_REG_ADDR); return op_pc + 1; } diff --git a/src/codegen_ops_stack.h b/src/codegen_ops_stack.h index 115aa4d..6ac658f 100644 --- a/src/codegen_ops_stack.h +++ b/src/codegen_ops_stack.h @@ -197,9 +197,9 @@ static uint32_t ropLEAVE_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, u LOAD_EBP_TO_EA(0); MEM_LOAD_ADDR_EA_W(&_ss); host_reg = LOAD_REG_W(REG_BP); /*SP = BP + 2*/ - STORE_REG_TARGET_W_RELEASE(0, REG_BP); /*BP = POP_W()*/ ADD_HOST_REG_IMM_W(host_reg, 2); STORE_REG_TARGET_W_RELEASE(host_reg, REG_SP); + STORE_REG_TARGET_W_RELEASE(0, REG_BP); /*BP = POP_W()*/ return op_pc; } @@ -211,9 +211,9 @@ static uint32_t ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, u LOAD_EBP_TO_EA(0); MEM_LOAD_ADDR_EA_L(&_ss); host_reg = LOAD_REG_L(REG_EBP); /*ESP = EBP + 4*/ - STORE_REG_TARGET_L_RELEASE(0, REG_EBP); /*EBP = POP_L()*/ ADD_HOST_REG_IMM(host_reg, 4); STORE_REG_TARGET_L_RELEASE(host_reg, REG_ESP); - + STORE_REG_TARGET_L_RELEASE(0, REG_EBP); /*EBP = POP_L()*/ + return op_pc; } diff --git a/src/codegen_ops_x86-64.h b/src/codegen_ops_x86-64.h new file mode 100644 index 0000000..d4a0e1c --- /dev/null +++ b/src/codegen_ops_x86-64.h @@ -0,0 +1,4185 @@ +/*Register allocation : + R8-R15 - emulated registers +*/ + +static void call(codeblock_t *block, uintptr_t func) +{ + uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; + + if (diff >= -0x80000000 && diff < 0x7fffffff) + { + addbyte(0xE8); /*CALL*/ + addlong((uint32_t)diff); + } + else + { + addbyte(0x48); /*MOV RAX, func*/ + addbyte(0xb8); + addquad(func); + addbyte(0xff); /*CALL RAX*/ + addbyte(0xd0); + } +} + +static void call_long(uintptr_t func) +{ + addbyte(0x48); /*MOV RAX, func*/ + addbyte(0xb8); + addquad(func); + addbyte(0xff); /*CALL RAX*/ + addbyte(0xd0); +} + +static void load_param_1_32(codeblock_t *block, uint32_t param) +{ +#if WIN64 + addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ +#else + addbyte(0xbf); /*MOVL $fetchdat,%edi*/ +#endif + addlong(param); +} +static void load_param_1_reg_32(int reg) +{ +#if WIN64 + if (reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOV ECX, EAX*/ + addbyte(0xc0 | REG_ECX | (reg << 3)); +#else + if (reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOV EDI, EAX*/ + addbyte(0xc0 | REG_EDI | (reg << 3)); +#endif +} +static void load_param_1_64(codeblock_t *block, uint64_t param) +{ + addbyte(0x48); +#if WIN64 + addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ +#else + addbyte(0xbf); /*MOVL $fetchdat,%edi*/ +#endif + addquad(param); +} + +static void load_param_2_32(codeblock_t *block, uint32_t param) +{ +#if WIN64 + addbyte(0xba); /*MOVL $fetchdat,%edx*/ +#else + addbyte(0xbe); /*MOVL $fetchdat,%esi*/ +#endif + addlong(param); +} +static void load_param_2_reg_32(int reg) +{ +#if WIN64 + if (reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOV EDX, EAX*/ + addbyte(0xc0 | REG_EDX | (reg << 3)); +#else + if (reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOV ESI, EAX*/ + addbyte(0xc0 | REG_ESI | (reg << 3)); +#endif +} +static void load_param_2_64(codeblock_t *block, uint64_t param) +{ + addbyte(0x48); +#if WIN64 + addbyte(0xba); /*MOVL $fetchdat,%edx*/ +#else + addbyte(0xbe); /*MOVL $fetchdat,%esi*/ +#endif + addquad(param); +} + +static void load_param_3_reg_32(int reg) +{ + if (reg & 8) + { +#if WIN64 + addbyte(0x45); /*MOVL R8,reg*/ + addbyte(0x89); + addbyte(0xc0 | ((reg & 7) << 3)); +#else + addbyte(0x44); /*MOV EDX, reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EDX | (reg << 3)); +#endif + } + else + { +#if WIN64 + addbyte(0x41); /*MOVL R8,reg*/ + addbyte(0x89); + addbyte(0xc0 | ((reg & 7) << 3)); +#else + addbyte(0x90); + addbyte(0x89); /*MOV EDX, reg*/ + addbyte(0xc0 | REG_EDX | (reg << 3)); +#endif + } +} +static void load_param_3_reg_64(int reg) +{ + if (reg & 8) + { +#if WIN64 + addbyte(0x4d); /*MOVL R8,reg*/ + addbyte(0x89); + addbyte(0xc0 | ((reg & 7) << 3)); +#else + addbyte(0x4c); /*MOVL EDX,reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); +#endif + } + else + { +#if WIN64 + addbyte(0x49); /*MOVL R8,reg*/ + addbyte(0x89); + addbyte(0xc0 | ((reg & 7) << 3)); +#else + addbyte(0x48); /*MOVL EDX,reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EDX | ((reg & 7) << 3)); +#endif + } +} + +static void CALL_FUNC(uintptr_t func) +{ + addbyte(0x48); /*MOV RAX, func*/ + addbyte(0xb8); + addquad(func); + addbyte(0xff); /*CALL RAX*/ + addbyte(0xd0); +} + +static void RELEASE_REG(int host_reg) +{ +} + +static int LOAD_REG_B(int reg) +{ + int host_reg = reg & 3; +// host_reg_mapping[host_reg] = reg; + + addbyte(0x44); /*MOVZX W[reg],host_reg*/ + addbyte(0x0f); + addbyte(0xb7); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint32_t)®s[reg & 3].w - (uint32_t)&EAX); + + if (reg & 4) + return host_reg | 0x18; + + return host_reg | 8; +} +static int LOAD_REG_W(int reg) +{ + int host_reg = reg; +// host_reg_mapping[host_reg] = reg; + + addbyte(0x44); /*MOVZX W[reg],host_reg*/ + addbyte(0x0f); + addbyte(0xb7); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint32_t)®s[reg & 7].w - (uint32_t)&EAX); + + return host_reg | 8; +} +static int LOAD_REG_L(int reg) +{ + int host_reg = reg; +// host_reg_mapping[host_reg] = reg; + + addbyte(0x44); /*MOVZX W[reg],host_reg*/ + addbyte(0x8b); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint32_t)®s[reg & 7].w - (uint32_t)&EAX); + + return host_reg | 8; +} + +static int LOAD_REG_IMM(uint32_t imm) +{ + int host_reg = REG_EBX; + + addbyte(0xbb); /*MOVL EBX, imm*/ + addlong(imm); + + return host_reg; +} + +static void STORE_REG_TARGET_B_RELEASE(int host_reg, int guest_reg) +{ + int dest_reg = LOAD_REG_L(guest_reg & 3) & 7; + + if (guest_reg & 4) + { + if (host_reg & 8) + { + addbyte(0x66); /*MOV AX, host_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((host_reg & 3) << 3)); + if (host_reg & 0x10) + { + addbyte(0x66); /*AND AX, 0xff00*/ + addbyte(0x25); + addword(0xff00); + } + else + { + addbyte(0x66); /*SHL AX, 8*/ + addbyte(0xc1); + addbyte(0xe0); + addbyte(0x08); + } + } + else + { + if (host_reg) + { + addbyte(0x66); /*MOV AX, host_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((host_reg & 3) << 3)); + } + addbyte(0x66); /*SHL AX, 8*/ + addbyte(0xc1); + addbyte(0xe0); + addbyte(0x08); + } + addbyte(0x66); /*AND dest_reg, 0x00ff*/ + addbyte(0x41); + addbyte(0x81); + addbyte(0xe0 | dest_reg); + addword(0x00ff); + addbyte(0x66); /*OR dest_reg, AX*/ + addbyte(0x41); + addbyte(0x09); + addbyte(0xc0 | dest_reg); + addbyte(0x66); /*MOVW regs[guest_reg].w, dest_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0x45 | (dest_reg << 3)); + addbyte((uint32_t)®s[guest_reg & 3].w - (uint32_t)&EAX); + } + else + { + if (host_reg & 8) + { + if (host_reg & 0x10) + { + addbyte(0x66); /*MOV AX, host_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((host_reg & 3) << 3)); + addbyte(0x88); /*MOVB regs[reg].b, AH*/ + addbyte(0x65); + addbyte((uint32_t)®s[guest_reg & 3].b - (uint32_t)&EAX); + } + else + { + addbyte(0x44); /*MOVB regs[guest_reg].b, host_reg*/ + addbyte(0x88); + addbyte(0x45 | ((host_reg & 3) << 3)); + addbyte((uint32_t)®s[guest_reg & 3].b - (uint32_t)&EAX); + } + } + else + { + if (host_reg & 0x10) + { + addbyte(0xc1); /*SHR host_reg, 8*/ + addbyte(0xe8 | (host_reg & 7)); + addbyte(8); + } + addbyte(0x88); /*MOVB regs[guest_reg].b, host_reg*/ + addbyte(0x45 | ((host_reg & 3) << 3)); + addbyte((uint32_t)®s[guest_reg & 3].b - (uint32_t)&EAX); + } + } +} +static void STORE_REG_TARGET_W_RELEASE(int host_reg, int guest_reg) +{ + int dest_reg = LOAD_REG_L(guest_reg & 7) & 7; + + if (host_reg & 8) + { + addbyte(0x66); /*MOVW guest_reg, host_reg*/ + addbyte(0x45); + addbyte(0x89); + addbyte(0xc0 | dest_reg | ((host_reg & 7) << 3)); + addbyte(0x66); /*MOVW regs[guest_reg].w, host_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0x45 | ((host_reg & 7) << 3)); + addbyte((uint32_t)®s[guest_reg & 7].w - (uint32_t)&EAX); + } + else + { + addbyte(0x66); /*MOVW guest_reg, host_reg*/ + addbyte(0x41); + addbyte(0x89); + addbyte(0xc0 | dest_reg | (host_reg << 3)); + addbyte(0x66); /*MOVW regs[guest_reg].w, host_reg*/ + addbyte(0x89); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint32_t)®s[guest_reg & 7].w - (uint32_t)&EAX); + } +} +static void STORE_REG_TARGET_L_RELEASE(int host_reg, int guest_reg) +{ + if (host_reg & 8) + { + addbyte(0x45); /*MOVL guest_reg, host_reg*/ + addbyte(0x89); + addbyte(0xc0 | guest_reg | (host_reg << 3)); + addbyte(0x44); /*MOVL regs[guest_reg].l, host_reg*/ + addbyte(0x89); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint32_t)®s[guest_reg & 7].l - (uint32_t)&EAX); + } + else + { + addbyte(0x41); /*MOVL guest_reg, host_reg*/ + addbyte(0x89); + addbyte(0xc0 | guest_reg | (host_reg << 3)); + addbyte(0x89); /*MOVL regs[guest_reg].l, host_reg*/ + addbyte(0x45 | (host_reg << 3)); + addbyte((uint32_t)®s[guest_reg & 7].l - (uint32_t)&EAX); + } +} + +static void STORE_REG_B_RELEASE(int host_reg) +{ + if (host_reg & 0x10) + { + addbyte(0x66); /*MOVW [reg],host_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0x45 | ((host_reg & 7) << 3)); + addbyte((uint32_t)®s[host_reg & 7].w - (uint32_t)&EAX); + } + else + { + addbyte(0x44); /*MOVB [reg],host_reg*/ + addbyte(0x88); + addbyte(0x45 | ((host_reg & 7) << 3)); + addbyte((uint32_t)®s[host_reg & 7].b - (uint32_t)&EAX); + } +} +static void STORE_REG_W_RELEASE(int host_reg) +{ + addbyte(0x66); /*MOVW [reg],host_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0x45 | ((host_reg & 7) << 3)); + addbyte((uint32_t)®s[host_reg & 7].w - (uint32_t)&EAX); +} +static void STORE_REG_L_RELEASE(int host_reg) +{ + addbyte(0x44); /*MOVL [reg],host_reg*/ + addbyte(0x89); + addbyte(0x45 | ((host_reg & 7) << 3)); + addbyte((uint32_t)®s[host_reg & 7].l - (uint32_t)&EAX); +} + +static void STORE_IMM_REG_B(int reg, uint8_t val) +{ + if (reg & 4) + { + int host_reg = LOAD_REG_W(reg & 3) & 7; + addbyte(0x66); /*AND host_reg, 0x00ff*/ + addbyte(0x41); + addbyte(0x81); + addbyte(0xe0 | host_reg); + addword(0x00ff); + addbyte(0x66); /*OR host_reg, val << 8*/ + addbyte(0x41); + addbyte(0x81); + addbyte(0xc8 | host_reg); + addword(val << 8); + addbyte(0x66); /*MOVW host_reg, regs[host_reg].w*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0x45 | (host_reg << 3)); + addbyte((uint32_t)®s[reg & 3].w - (uint32_t)&EAX); + } + else + { + addbyte(0x41); /*MOVB reg, imm*/ + addbyte(0xb0 | reg); + addbyte(val); + addbyte(0x44); /*MOVB reg, regs[reg].b*/ + addbyte(0x88); + addbyte(0x45 | (reg << 3)); + addbyte((uint32_t)®s[reg & 7].b - (uint32_t)&EAX); + } +} +static void STORE_IMM_REG_W(int reg, uint16_t val) +{ + addbyte(0x66); /*MOVW reg, imm*/ + addbyte(0x41); + addbyte(0xb8 | reg); + addword(val); + addbyte(0x66); /*MOVW reg, regs[reg].w*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0x45 | (reg << 3)); + addbyte((uint32_t)®s[reg & 7].w - (uint32_t)&EAX); +} +static void STORE_IMM_REG_L(int reg, uint32_t val) +{ + addbyte(0x41); /*MOVL reg, imm*/ + addbyte(0xb8 | reg); + addlong(val); + addbyte(0x44); /*MOVL reg, regs[reg].l*/ + addbyte(0x89); + addbyte(0x45 | (reg << 3)); + addbyte((uint32_t)®s[reg & 7].l - (uint32_t)&EAX); +} + +static void STORE_IMM_ADDR_L(uintptr_t addr, uint32_t val) +{ + if (addr < 0x100000000) + { + addbyte(0xC7); /*MOVL [addr],val*/ + addbyte(0x04); + addbyte(0x25); + addlong(addr); + addlong(val); + } + else + { + fatal("addr > 32-bit\n"); + } +} + + + + +static x86seg *FETCH_EA_16(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +{ + int mod = (fetchdat >> 6) & 3; + int reg = (fetchdat >> 3) & 7; + int rm = fetchdat & 7; + + if (!mod && rm == 6) + { + addbyte(0xb8); /*MOVL EAX, imm*/ + addlong((fetchdat >> 8) & 0xffff); + (*op_pc) += 2; + } + else + { + int base_reg, index_reg; + + switch (rm) + { + case 0: case 1: case 7: + base_reg = LOAD_REG_W(REG_BX); + break; + case 2: case 3: case 6: + base_reg = LOAD_REG_W(REG_BP); + break; + case 4: + base_reg = LOAD_REG_W(REG_SI); + break; + case 5: + base_reg = LOAD_REG_W(REG_DI); + break; + } + if (!(rm & 4)) + { + if (rm & 1) + index_reg = LOAD_REG_W(REG_DI); + else + index_reg = LOAD_REG_W(REG_SI); + } + base_reg &= 7; + index_reg &= 7; + + switch (mod) + { + case 0: + if (rm & 4) + { + addbyte(0x41); /*MOVZX EAX, base_reg*/ + addbyte(0x0f); + addbyte(0xb7); + addbyte(0xc0 | base_reg); + } + else + { + addbyte(0x67); /*LEA EAX, base_reg+index_reg*/ + addbyte(0x43); + addbyte(0x8d); + if (base_reg == 5) + { + addbyte(0x44); + addbyte(base_reg | (index_reg << 3)); + addbyte(0); + } + else + { + addbyte(0x04); + addbyte(base_reg | (index_reg << 3)); + } + } + break; + case 1: + if (rm & 4) + { + addbyte(0x67); /*LEA EAX, base_reg+imm8*/ + addbyte(0x41); + addbyte(0x8d); + addbyte(0x40 | base_reg); + addbyte((fetchdat >> 8) & 0xff); + } + else + { + addbyte(0x67); /*LEA EAX, base_reg+index_reg+imm8*/ + addbyte(0x43); + addbyte(0x8d); + addbyte(0x44); + addbyte(base_reg | (index_reg << 3)); + addbyte((fetchdat >> 8) & 0xff); + } + (*op_pc)++; + break; + case 2: + if (rm & 4) + { + addbyte(0x67); /*LEA EAX, base_reg+imm8*/ + addbyte(0x41); + addbyte(0x8d); + addbyte(0x80 | base_reg); + addlong((fetchdat >> 8) & 0xffff); + } + else + { + addbyte(0x67); /*LEA EAX, base_reg+index_reg+imm16*/ + addbyte(0x43); + addbyte(0x8d); + addbyte(0x84); + addbyte(base_reg | (index_reg << 3)); + addlong((fetchdat >> 8) & 0xffff); + } + (*op_pc) += 2; + break; + + } + if (mod || !(rm & 4)) + { + addbyte(0x25); /*ANDL $0xffff, %eax*/ + addlong(0xffff); + } + + if (mod1seg[rm] == &ss && !op_ssegs) + op_ea_seg = &_ss; + } + return op_ea_seg; +} +static x86seg *FETCH_EA_32(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) +{ + int mod = (fetchdat >> 6) & 3; + int reg = (fetchdat >> 3) & 7; + int rm = fetchdat & 7; + uint32_t new_eaaddr; + + if (rm == 4) + { + uint8_t sib = fetchdat >> 8; + int base_reg = -1, index_reg = -1; + + (*op_pc)++; + + if (mod || (sib & 7) != 5) + base_reg = LOAD_REG_L(sib & 7) & 7; + + if (((sib >> 3) & 7) != 4) + index_reg = LOAD_REG_L((sib >> 3) & 7) & 7; + + if (index_reg == -1) + { + switch (mod) + { + case 0: + if ((sib & 7) == 5) + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOV EAX, imm32*/ + addlong(new_eaaddr); + (*op_pc) += 4; + } + else + { + addbyte(0x44); /*MOV EAX, base_reg*/ + addbyte(0x89); + addbyte(0xc0 | (base_reg << 3)); + } + break; + case 1: + addbyte(0x67); /*LEA EAX, imm8+base_reg*/ + addbyte(0x41); + addbyte(0x8d); + if (base_reg == 4) + { + addbyte(0x44); + addbyte(0x24); + } + else + { + addbyte(0x40 | base_reg); + } + addbyte((fetchdat >> 16) & 0xff); + (*op_pc)++; + break; + case 2: + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x67); /*LEA EAX, imm32+base_reg*/ + addbyte(0x41); + addbyte(0x8d); + if (base_reg == 4) + { + addbyte(0x84); + addbyte(0x24); + } + else + { + addbyte(0x80 | base_reg); + } + addlong(new_eaaddr); + (*op_pc) += 4; + break; + } + } + else + { + switch (mod) + { + case 0: + if ((sib & 7) == 5) + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + if (sib >> 6) + { + addbyte(0x67); /*LEA EAX, imm32+index_reg*scale*/ + addbyte(0x42); + addbyte(0x8d); + addbyte(0x04); + addbyte(0x05 | (sib & 0xc0) | (index_reg << 3)); + addlong(new_eaaddr); + } + else + { + addbyte(0x67); /*LEA EAX, imm32+index_reg*/ + addbyte(0x41); + addbyte(0x8d); + addbyte(0x80 | index_reg); + addlong(new_eaaddr); + } + (*op_pc) += 4; + } + else + { + addbyte(0x67); /*LEA EAX, base_reg+index_reg*scale*/ + addbyte(0x43); + addbyte(0x8d); + if (base_reg == 5) + { + addbyte(0x44); + addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); + addbyte(0); + } + else + { + addbyte(0x04); + addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); + } + } + break; + case 1: + addbyte(0x67); /*LEA EAX, imm8+base_reg+index_reg*scale*/ + addbyte(0x43); + addbyte(0x8d); + addbyte(0x44); + addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); + addbyte((fetchdat >> 16) & 0xff); + (*op_pc)++; + break; + case 2: + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x67); /*LEA EAX, imm32+base_reg+index_reg*scale*/ + addbyte(0x43); + addbyte(0x8d); + addbyte(0x84); + addbyte(base_reg | (index_reg << 3) | (sib & 0xc0)); + addlong(new_eaaddr); + (*op_pc) += 4; + break; + } + } + if (stack_offset && (sib & 7) == 4 && (mod || (sib & 7) != 5)) /*ESP*/ + { + addbyte(0x05); + addlong(stack_offset); + } + if (((sib & 7) == 4 || (mod && (sib & 7) == 5)) && !op_ssegs) + op_ea_seg = &_ss; + } + else + { + int base_reg; + + if (!mod && rm == 5) + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL EAX, new_eaaddr*/ + addlong(new_eaaddr); + (*op_pc) += 4; + return op_ea_seg; + } + base_reg = LOAD_REG_L(rm) & 7; + if (mod) + { + if (rm == 5 && !op_ssegs) + op_ea_seg = &_ss; + if (mod == 1) + { + addbyte(0x67); /*LEA EAX, base_reg+imm8*/ + addbyte(0x41); + addbyte(0x8d); + addbyte(0x40 | base_reg); + addbyte((fetchdat >> 8) & 0xff); + (*op_pc)++; + } + else + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x67); /*LEA EAX, base_reg+imm32*/ + addbyte(0x41); + addbyte(0x8d); + addbyte(0x80 | base_reg); + addlong(new_eaaddr); + (*op_pc) += 4; + } + } + else + { + addbyte(0x44); /*MOV EAX, base_reg*/ + addbyte(0x89); + addbyte(0xc0 | (base_reg << 3)); + } + } + return op_ea_seg; +} + +static x86seg *FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32) +{ + if (op_32 & 0x200) + return FETCH_EA_32(op_ea_seg, fetchdat, op_ssegs, op_pc, 0); + return FETCH_EA_16(op_ea_seg, fetchdat, op_ssegs, op_pc); +} + + + +static void CHECK_SEG_READ(x86seg *seg) +{ + /*Segments always valid in real/V86 mode*/ + if (!(cr0 & 1) || (eflags & VM_FLAG)) + return; + /*CS and SS must always be valid*/ + if (seg == &_cs || seg == &_ss) + return; + if (seg->checked) + return; + + addbyte(0x83); /*CMP seg->base, -1*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t)&seg->base); + addbyte(-1); + addbyte(0x0f); /*JE end*/ + addbyte(0x84); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + + seg->checked = 1; +} +static void CHECK_SEG_WRITE(x86seg *seg) +{ + /*Segments always valid in real/V86 mode*/ + if (!(cr0 & 1) || (eflags & VM_FLAG)) + return; + /*CS and SS must always be valid*/ + if (seg == &_cs || seg == &_ss) + return; + if (seg->checked) + return; + + addbyte(0x83); /*CMP seg->base, -1*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t)&seg->base); + addbyte(-1); + addbyte(0x0f); /*JE end*/ + addbyte(0x84); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + + seg->checked = 1; +} +static void CHECK_SEG_LIMITS(x86seg *seg, int end_offset) +{ + addbyte(0x3b); /*CMP EAX, seg->limit_low*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t)&seg->limit_low); + addbyte(0x0f); /*JB BLOCK_GPF_OFFSET*/ + addbyte(0x82); + addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + if (end_offset) + { + addbyte(0x83); /*ADD EAX, end_offset*/ + addbyte(0xc0); + addbyte(end_offset); + addbyte(0x3b); /*CMP EAX, seg->limit_high*/ + addbyte(0x04); + addbyte(0x25); + addlong((uint32_t)&seg->limit_high); + addbyte(0x0f); /*JNBE BLOCK_GPF_OFFSET*/ + addbyte(0x87); + addlong(BLOCK_GPF_OFFSET - (block_pos + 4)); + addbyte(0x83); /*SUB EAX, end_offset*/ + addbyte(0xe8); + addbyte(end_offset); + } +} + +#define IS_32_ADDR(x) !(((uintptr_t)x) & 0xffffffff00000000) + +static void MEM_LOAD_ADDR_EA_B(x86seg *seg) +{ + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t)&seg->base); + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + if (IS_32_ADDR(readlookup2)) + { + addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t)readlookup2); + } + else + { + addbyte(0x48); /*MOV RDX, readlookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t)readlookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(3+2); + addbyte(0x8b); /*MOV AL,[RDI+RSI]*/ + addbyte(0x04); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(0xeb); /*JMP done*/ + addbyte(2+2+12+8+6); + /*slowpath:*/ + load_param_1_reg_32(REG_ECX); + load_param_2_reg_32(REG_EAX); + call_long(readmemb386l); + addbyte(0x83); /*CMP abrt, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t)&abrt); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} +static void MEM_LOAD_ADDR_EA_W(x86seg *seg) +{ + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t)&seg->base); + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x67); /*LEA EDI, 1[ESI]*/ + addbyte(0x8d); + addbyte(0x7e); + addbyte(0x01); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 0xfff*/ + addbyte(0xc7); + addlong(0xfff); + if (IS_32_ADDR(readlookup2)) + { + addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t)readlookup2); + } + else + { + addbyte(0x48); /*MOV RDX, readlookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t)readlookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x74); /*JE slowpath*/ + addbyte(3+2+5+2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(5+2); + addbyte(0x66); /*MOV AX,-1[RDI+RSI]*/ + addbyte(0x8b); + addbyte(0x44); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(-1); + addbyte(0xeb); /*JMP done*/ + addbyte(2+2+12+8+6); + /*slowpath:*/ + load_param_1_reg_32(REG_ECX); + load_param_2_reg_32(REG_EAX); + call_long(readmemwl); + addbyte(0x83); /*CMP abrt, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t)&abrt); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} +static void MEM_LOAD_ADDR_EA_L(x86seg *seg) +{ + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t)&seg->base); + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x67); /*LEA EDI, 3[ESI]*/ + addbyte(0x8d); + addbyte(0x7e); + addbyte(0x03); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 0xffc*/ + addbyte(0xc7); + addlong(0xffc); + if (IS_32_ADDR(readlookup2)) + { + addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t)readlookup2); + } + else + { + addbyte(0x48); /*MOV RDX, readlookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t)readlookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x74); /*JE slowpath*/ + addbyte(3+2+4+2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(4+2); + addbyte(0x8b); /*MOV EAX,-3[RDI+RSI]*/ + addbyte(0x44); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(-3); + addbyte(0xeb); /*JMP done*/ + addbyte(2+2+12+8+6); + /*slowpath:*/ + load_param_1_reg_32(REG_ECX); + load_param_2_reg_32(REG_EAX); + call_long(readmemll); + addbyte(0x83); /*CMP abrt, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t)&abrt); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} +static void MEM_LOAD_ADDR_EA_Q(x86seg *seg) +{ + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t)&seg->base); + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x67); /*LEA EDI, 7[ESI]*/ + addbyte(0x8d); + addbyte(0x7e); + addbyte(0x07); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 0xff8*/ + addbyte(0xc7); + addlong(0xff8); + if (IS_32_ADDR(readlookup2)) + { + addbyte(0x67); /*MOV RSI, readlookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t)readlookup2); + } + else + { + addbyte(0x48); /*MOV RDX, readlookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t)readlookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x74); /*JE slowpath*/ + addbyte(3+2+5+2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(5+2); + addbyte(0x48); /*MOV RAX,-7[RDI+RSI]*/ + addbyte(0x8b); + addbyte(0x44); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(-7); + addbyte(0xeb); /*JMP done*/ + addbyte(2+2+12+8+6); + /*slowpath:*/ + load_param_1_reg_32(REG_ECX); + load_param_2_reg_32(REG_EAX); + call_long(readmemql); + addbyte(0x83); /*CMP abrt, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t)&abrt); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} + +static void MEM_LOAD_ADDR_IMM_B(x86seg *seg, uint32_t addr) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_LOAD_ADDR_EA_B(seg); +} +static void MEM_LOAD_ADDR_IMM_W(x86seg *seg, uint32_t addr) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_LOAD_ADDR_EA_W(seg); +} +static void MEM_LOAD_ADDR_IMM_L(x86seg *seg, uint32_t addr) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_LOAD_ADDR_EA_L(seg); +} + +static void MEM_STORE_ADDR_EA_B(x86seg *seg, int host_reg) +{ + if (host_reg & 0x10) + { + /*Handle high byte of register*/ + if (host_reg & 8) + { + addbyte(0x45); /*MOVL R8, host_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((host_reg & 7) << 3)); + } + else + { + addbyte(0x41); /*MOVL R8, host_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((host_reg & 7) << 3)); + } + addbyte(0x66); /*SHR R8, 8*/ + addbyte(0x41); + addbyte(0xc1); + addbyte(0xe8); + addbyte(8); + host_reg = 8; + } + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t)&seg->base); + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x89); /*MOV EDI, ESI*/ + addbyte(0xf7); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + if (IS_32_ADDR(writelookup2)) + { + addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t)writelookup2); + } + else + { + addbyte(0x48); /*MOV RDX, writelookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t)writelookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(((host_reg & 8) ? 4:3)+2); + if (host_reg & 8) + { + addbyte(0x44); /*MOV [RDI+RSI],host_reg*/ + addbyte(0x88); + addbyte(0x04 | ((host_reg & 7) << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + } + else + { + addbyte(0x88); /*MOV [RDI+RSI],host_reg*/ + addbyte(0x04 | (host_reg << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + } + addbyte(0xeb); /*JMP done*/ + addbyte(2+2+3+12+8+6); + /*slowpath:*/ + load_param_1_reg_32(REG_ECX); + load_param_2_reg_32(REG_EAX); + load_param_3_reg_32(host_reg); + call_long(writememb386l); + addbyte(0x83); /*CMP abrt, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t)&abrt); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} +static void MEM_STORE_ADDR_EA_W(x86seg *seg, int host_reg) +{ + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t)&seg->base); + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x67); /*LEA EDI, 1[ESI]*/ + addbyte(0x8d); + addbyte(0x7e); + addbyte(0x01); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 0xfff*/ + addbyte(0xc7); + addlong(0xfff); + if (IS_32_ADDR(writelookup2)) + { + addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t)writelookup2); + } + else + { + addbyte(0x48); /*MOV RDX, writelookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t)writelookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x74); /*JE slowpath*/ + addbyte(3+2+((host_reg & 8) ? 6:5)+2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(((host_reg & 8) ? 6:5)+2); + if (host_reg & 8) + { + addbyte(0x66); /*MOV -1[RDI+RSI],host_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0x44 | ((host_reg & 7) << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(-1); + } + else + { + addbyte(0x66); /*MOV -1[RDI+RSI],host_reg*/ + addbyte(0x89); + addbyte(0x44 | (host_reg << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(-1); + } + addbyte(0xeb); /*JMP done*/ + addbyte(2+2+3+12+8+6); + /*slowpath:*/ + load_param_1_reg_32(REG_ECX); + load_param_2_reg_32(REG_EAX); + load_param_3_reg_32(host_reg); + call_long(writememwl); + addbyte(0x83); /*CMP abrt, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t)&abrt); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} +static void MEM_STORE_ADDR_EA_L(x86seg *seg, int host_reg) +{ + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t)&seg->base); + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x67); /*LEA EDI, 3[ESI]*/ + addbyte(0x8d); + addbyte(0x7e); + addbyte(0x03); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 0xffc*/ + addbyte(0xc7); + addlong(0xffc); + if (IS_32_ADDR(writelookup2)) + { + addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t)writelookup2); + } + else + { + addbyte(0x48); /*MOV RDX, writelookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t)writelookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x74); /*JE slowpath*/ + addbyte(3+2+((host_reg & 8) ? 5:4)+2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(((host_reg & 8) ? 5:4)+2); + if (host_reg & 8) + { + addbyte(0x44); /*MOV -3[RDI+RSI],host_reg*/ + addbyte(0x89); + addbyte(0x44 | ((host_reg & 7) << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(-3); + } + else + { + addbyte(0x89); /*MOV -3[RDI+RSI],host_reg*/ + addbyte(0x44 | (host_reg << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(-3); + } + addbyte(0xeb); /*JMP done*/ + addbyte(2+2+3+12+8+6); + /*slowpath:*/ + load_param_1_reg_32(REG_ECX); + load_param_2_reg_32(REG_EAX); + load_param_3_reg_32(host_reg); + call_long(writememll); + addbyte(0x83); /*CMP abrt, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t)&abrt); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} +static void MEM_STORE_ADDR_EA_Q(x86seg *seg, int host_reg, int host_reg2) +{ + addbyte(0x8b); /*MOVL ECX, seg->base*/ + addbyte(0x0c); + addbyte(0x25); + addlong((uint32_t)&seg->base); + addbyte(0x67); /*LEA ESI, (EAX,ECX)*/ + addbyte(0x8d); + addbyte(0x34); + addbyte(0x08); + addbyte(0x67); /*LEA EDI, 7[ESI]*/ + addbyte(0x8d); + addbyte(0x7e); + addbyte(0x07); + addbyte(0xc1); /*SHR ESI, 12*/ + addbyte(0xe8 | REG_ESI); + addbyte(12); + addbyte(0xf7); /*TEST EDI, 0xff8*/ + addbyte(0xc7); + addlong(0xff8); + if (IS_32_ADDR(writelookup2)) + { + addbyte(0x67); /*MOV RSI, writelookup2[ESI*8]*/ + addbyte(0x48); + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf5); + addlong((uint32_t)writelookup2); + } + else + { + addbyte(0x48); /*MOV RDX, writelookup2*/ + addbyte(0xb8 | REG_EDX); + addquad((uint64_t)writelookup2); + addbyte(0x48); /*MOV RSI, [RDX+RSI*8]*/ + addbyte(0x8b); + addbyte(0x34); + addbyte(0xf2); + } + addbyte(0x74); /*JE slowpath*/ + addbyte(3+2+5+2); + addbyte(0x83); /*CMP ESI, -1*/ + addbyte(0xf8 | REG_ESI); + addbyte(-1); + addbyte(0x74); /*JE slowpath*/ + addbyte(5+2); + if (host_reg & 8) + { + addbyte(0x4c); /*MOV -7[RDI+RSI],host_reg*/ + addbyte(0x89); + addbyte(0x44 | ((host_reg & 7) << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(-7); + } + else + { + addbyte(0x48); /*MOV -3[RDI+RSI],host_reg*/ + addbyte(0x89); + addbyte(0x44 | (host_reg << 3)); + addbyte(REG_EDI | (REG_ESI << 3)); + addbyte(-7); + } + addbyte(0xeb); /*JMP done*/ + addbyte(2+2+3+12+8+6); + /*slowpath:*/ + load_param_1_reg_32(REG_ECX); + load_param_2_reg_32(REG_EAX); + load_param_3_reg_64(host_reg); + call_long(writememql); + addbyte(0x83); /*CMP abrt, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t)&abrt); + addbyte(0); + addbyte(0x0f); /*JNE end*/ + addbyte(0x85); + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + /*done:*/ +} + +static void MEM_STORE_ADDR_IMM_B(x86seg *seg, uint32_t addr, int host_reg) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_STORE_ADDR_EA_B(seg, host_reg); +} +static void MEM_STORE_ADDR_IMM_W(x86seg *seg, uint32_t addr, int host_reg) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_STORE_ADDR_EA_W(seg, host_reg); +} +static void MEM_STORE_ADDR_IMM_L(x86seg *seg, uint32_t addr, int host_reg) +{ + addbyte(0xb8); /*MOV EAX, addr*/ + addlong(addr); + MEM_STORE_ADDR_EA_L(seg, host_reg); +} + +static void STORE_HOST_REG_ADDR_BL(uintptr_t addr, int host_reg) +{ + if (host_reg & 0x10) + { + if (host_reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVZX EBX, host_reg*/ + addbyte(0xb7); + addbyte(0xc0 | (REG_ECX << 3) | (host_reg & 7)); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xe8 | REG_ECX); + addbyte(8); + } + else + { + if (host_reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVZX EBX, host_reg*/ + addbyte(0xb6); + addbyte(0xc0 | (REG_ECX << 3) | (host_reg & 7)); + } + addbyte(0x89); /*MOV addr, EBX*/ + addbyte(0x04 | (REG_ECX << 3)); + addbyte(0x25); + addlong(addr); +} +static void STORE_HOST_REG_ADDR_WL(uintptr_t addr, int host_reg) +{ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVZX EBX, host_reg*/ + addbyte(0xb7); + addbyte(0xc0 | (REG_ECX << 3) | (host_reg & 7)); + addbyte(0x89); /*MOV addr, EBX*/ + addbyte(0x04 | (REG_ECX << 3)); + addbyte(0x25); + addlong(addr); +} +static void STORE_HOST_REG_ADDR_W(uintptr_t addr, int host_reg) +{ + addbyte(0x66); + if (host_reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOVL addr,host_reg*/ + addbyte(0x04 | ((host_reg & 7) << 3)); + addbyte(0x25); + addlong(addr); +} +static void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg) +{ + if (host_reg & 8) + addbyte(0x44); + addbyte(0x89); /*MOVL addr,host_reg*/ + addbyte(0x04 | ((host_reg & 7) << 3)); + addbyte(0x25); + addlong(addr); +} + +static void AND_HOST_REG_B(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) + { + if (dst_reg & 0x10) + { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + if (!(src_reg & 0x10)) + { + addbyte(0x66); /*SHL AX, 8*/ + addbyte(0xc1); + addbyte(0xe0); + addbyte(8); + } + addbyte(0x66); /*OR AX, 0x00ff*/ + addbyte(0x0d); + addword(0xff); + addbyte(0x66); /*ANDW dst_reg, AX*/ + addbyte(0x41); + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7)); + } + else if (src_reg & 0x10) + { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + addbyte(0x66); /*SHR AX, 8*/ + addbyte(0xc1); + addbyte(0xe8); + addbyte(8); + addbyte(0x41); /*ANDB dst_reg, AL*/ + addbyte(0x20); + addbyte(0xc0 | (dst_reg & 7)); + } + else + { + addbyte(0x45); /*ANDB dst_reg, src_reg*/ + addbyte(0x20); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } + else if (dst_reg & 8) + { + if (dst_reg & 0x10) + { + addbyte(0x66); /*SHL src_reg, 8*/ + addbyte(0xc1); + addbyte(0xe0 | src_reg); + addbyte(0x08); + addbyte(0x66); /*OR src_reg, 0xff*/ + addbyte(0x81); + addbyte(0xc8 | src_reg); + addword(0xff); + addbyte(0x66); /*ANDW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + { + addbyte(0x41); /*ANDB dst_reg, src_reg*/ + addbyte(0x20); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } + else if (src_reg & 8) + { + if (dst_reg & 0x10) + { + addbyte(0xc1); /*SHR dst_reg, 8*/ + addbyte(0xe8 | (dst_reg & 7)); + addbyte(8); + } + if (src_reg & 0x10) + { + addbyte(0x41); /*MOVZX EBX, src_reg*/ + addbyte(0x0f); + addbyte(0xb7); + addbyte(0xd8 | (src_reg & 7)); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0x20); /*ANDB dst_reg, EBX*/ + addbyte(0xd8 | (dst_reg & 7)); + } + else + { + addbyte(0x44); /*ANDB dst_reg, src_reg*/ + addbyte(0x20); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } + else + { + if (dst_reg & 0x10) + { + addbyte(0xc1); /*SHR dst_reg, 8*/ + addbyte(0xe8 | (dst_reg & 7)); + addbyte(8); + } + if (src_reg & 0x10) + { + addbyte(0x0f); /*MOVZX EBX, src_reg*/ + addbyte(0xb7); + addbyte(0xd8 | (src_reg & 7)); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0x20); /*ANDB dst_reg, EBX*/ + addbyte(0xd8 | (dst_reg & 7)); + } + else + { + addbyte(0x20); /*ANDB dst_reg, src_reg*/ + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } +#if 0 + else if (dst_reg & 8) + { + if (dst_reg & 0x10) + { + if (src_reg & 0x10) + { + addbyte(0x66); /*SHL src_reg, 8*/ + addbyte(0xc1); + addbyte(0xe0 | src_reg); + addbyte(0x08); + addbyte(0x66); /*OR src_reg, 0xff*/ + addbyte(0x81); + addbyte(0xc8 | src_reg); + addword(0xff); + } + addbyte(0x66); /*ANDW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + { + addbyte(0x41); /*ANDB dst_reg, src_reg*/ + addbyte(0x20); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } + else if (src_reg & 8) + { + if (src_reg & 0x10) + { + addbyte(0x66); /*OR src_reg, 0xff*/ + addbyte(0x81); + addbyte(0xc8 | src_reg); + addword(0xff); + } + if (src_reg & 0x10) + { + addbyte(0x66); /*SHL src_reg, 8*/ + addbyte(0xc1); + addbyte(0xe0 | src_reg); + addbyte(0x08); + addbyte(0x66); /*OR src_reg, 0xff*/ + addbyte(0x81); + addbyte(0xc8 | src_reg); + addword(0xff); + } + addbyte(0x66); /*ANDW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + { + addbyte(0x41); /*ANDB dst_reg, src_reg*/ + addbyte(0x20); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } + else + fatal("!(dst_reg & src_reg & 8) b %i %i\n", dst_reg, src_reg); +#endif +} +static void AND_HOST_REG_W(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) + { + addbyte(0x66); /*ANDW dst_reg, src_reg*/ + addbyte(0x45); + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else if (dst_reg & 8) + { + addbyte(0x66); /*ANDW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else if (src_reg & 8) + { + addbyte(0x66); /*ANDW dst_reg, src_reg*/ + addbyte(0x44); + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + { + addbyte(0x66); /*ANDW dst_reg, src_reg*/ + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } +} +static void AND_HOST_REG_L(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) + { + addbyte(0x45); /*ANDL dst_reg, src_reg*/ + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else if (dst_reg & 8) + { + addbyte(0x41); /*ANDL dst_reg, src_reg*/ + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else if (src_reg & 8) + { + addbyte(0x44); /*ANDL dst_reg, src_reg*/ + addbyte(0x21); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + { + addbyte(0x21); /*ANDL dst_reg, src_reg*/ + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } +} +static void AND_HOST_REG_IMM(int host_reg, uint32_t imm) +{ + if (host_reg & 0x10) + { + addbyte(0x66); /*ANDW host_reg, imm<<8*/ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x81); + addbyte(0xe0 | (host_reg & 7)); + addword((imm << 8) | 0xff); + } + else + { + if (host_reg & 8) + addbyte(0x41); + addbyte(0x81); /*ANDL host_reg, imm*/ + addbyte(0xe0 | (host_reg & 7)); + addlong(imm); + } +} + +static int TEST_HOST_REG_B(int dst_reg, int src_reg) +{ + if (dst_reg & 8) + { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); + + dst_reg = (dst_reg & 0x10) | REG_EDX; + } + + AND_HOST_REG_B(dst_reg, src_reg); + + return dst_reg & ~0x10; +} +static int TEST_HOST_REG_W(int dst_reg, int src_reg) +{ + if (dst_reg & 8) + { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); + + dst_reg = REG_EDX; + } + + AND_HOST_REG_W(dst_reg, src_reg); + + return dst_reg; +} +static int TEST_HOST_REG_L(int dst_reg, int src_reg) +{ + if (dst_reg & 8) + { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); + + dst_reg = REG_EDX; + } + + AND_HOST_REG_L(dst_reg, src_reg); + + return dst_reg; +} +static int TEST_HOST_REG_IMM(int host_reg, uint32_t imm) +{ + if (host_reg & 8) + { + addbyte(0x44); /*MOV EDX, host_reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EDX | ((host_reg & 7) << 3)); + host_reg = REG_EDX | (host_reg & 0x10); + } + if (host_reg & 0x10) + { + addbyte(0x66); /*ANDW host_reg, imm<<8*/ + addbyte(0x81); + addbyte(0xe0 | (host_reg & 7)); + addword((imm << 8) | 0xff); + } + else + { + addbyte(0x81); /*ANDL host_reg, imm*/ + addbyte(0xe0 | (host_reg & 7)); + addlong(imm); + } + + return host_reg; +} + +static void OR_HOST_REG_B(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) + { + if (dst_reg & 0x10) + { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + if (!(src_reg & 0x10)) + { + addbyte(0x66); /*SHL AX, 8*/ + addbyte(0xc1); + addbyte(0xe0); + addbyte(8); + } + else + { + addbyte(0x66); /*AND AX, 0xff00*/ + addbyte(0x25); + addword(0xff00); + } + addbyte(0x66); /*ORW dst_reg, AX*/ + addbyte(0x41); + addbyte(0x09); + addbyte(0xc0 | (dst_reg & 7)); + } + else if (src_reg & 0x10) + { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + addbyte(0x66); /*SHR AX, 8*/ + addbyte(0xc1); + addbyte(0xe8); + addbyte(8); + addbyte(0x41); /*ORB dst_reg, AL*/ + addbyte(0x08); + addbyte(0xc0 | (dst_reg & 7)); + } + else + { + addbyte(0x45); /*ORB dst_reg, src_reg*/ + addbyte(0x08); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } + else if (dst_reg & 8) + { + if (dst_reg & 0x10) + { + addbyte(0x66); /*SHL src_reg, 8*/ + addbyte(0xc1); + addbyte(0xe0 | src_reg); + addbyte(0x08); + addbyte(0x66); /*ORW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x09); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + { + addbyte(0x41); /*ORB dst_reg, src_reg*/ + addbyte(0x08); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } + else + fatal("!(dst_reg & src_reg & 8)\n"); +} +static void OR_HOST_REG_W(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) + { + addbyte(0x66); /*ORW dst_reg, src_reg*/ + addbyte(0x45); + addbyte(0x09); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else if (dst_reg & 8) + { + addbyte(0x66); /*ORW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x09); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + fatal("!(dst_reg & src_reg & 8)\n"); +} +static void OR_HOST_REG_L(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) + { + addbyte(0x45); /*ORL dst_reg, src_reg*/ + addbyte(0x09); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else if (dst_reg & 8) + { + addbyte(0x41); /*ORL dst_reg, src_reg*/ + addbyte(0x09); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + fatal("!(dst_reg & src_reg & 8)\n"); +} +static void OR_HOST_REG_IMM(int host_reg, uint32_t imm) +{ + if (host_reg & 0x10) + { + addbyte(0x66); /*ORW host_reg, imm<<8*/ + addbyte(0x41); + addbyte(0x81); + addbyte(0xc8 | (host_reg & 7)); + addword(imm << 8); + } + else if (host_reg & 8) + { + addbyte(0x41); /*ORL host_reg, imm*/ + addbyte(0x81); + addbyte(0xc8 | (host_reg & 7)); + addlong(imm); + } + else + fatal("OR to bad register\n"); +} + +static void XOR_HOST_REG_B(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) + { + if (dst_reg & 0x10) + { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + if (!(src_reg & 0x10)) + { + addbyte(0x66); /*SHL AX, 8*/ + addbyte(0xc1); + addbyte(0xe0); + addbyte(8); + } + else + { + addbyte(0x66); /*AND AX, 0xff00*/ + addbyte(0x25); + addword(0xff00); + } + addbyte(0x66); /*XORW dst_reg, AX*/ + addbyte(0x41); + addbyte(0x31); + addbyte(0xc0 | (dst_reg & 7)); + } + else if (src_reg & 0x10) + { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + addbyte(0x66); /*SHR AX, 8*/ + addbyte(0xc1); + addbyte(0xe8); + addbyte(8); + addbyte(0x41); /*XORB dst_reg, AL*/ + addbyte(0x30); + addbyte(0xc0 | (dst_reg & 7)); + } + else + { + addbyte(0x45); /*XORB dst_reg, src_reg*/ + addbyte(0x30); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } + else if (dst_reg & 8) + { + if (dst_reg & 0x10) + { + addbyte(0x66); /*SHL src_reg, 8*/ + addbyte(0xc1); + addbyte(0xe0 | src_reg); + addbyte(0x08); + addbyte(0x66); /*XORW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x31); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + { + addbyte(0x41); /*XORB dst_reg, src_reg*/ + addbyte(0x30); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } + else + fatal("!(dst_reg & src_reg & 8)\n"); +} +static void XOR_HOST_REG_W(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) + { + addbyte(0x66); /*XORW dst_reg, src_reg*/ + addbyte(0x45); + addbyte(0x31); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else if (dst_reg & 8) + { + addbyte(0x66); /*XORW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x31); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + fatal("!(dst_reg & src_reg & 8)\n"); +} +static void XOR_HOST_REG_L(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) + { + addbyte(0x45); /*XORL dst_reg, src_reg*/ + addbyte(0x31); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else if (dst_reg & 8) + { + addbyte(0x41); /*XORL dst_reg, src_reg*/ + addbyte(0x31); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + fatal("!(dst_reg & src_reg & 8)\n"); +} +static void XOR_HOST_REG_IMM(int host_reg, uint32_t imm) +{ + if (host_reg & 0x10) + { + addbyte(0x66); /*ORW host_reg, imm<<8*/ + addbyte(0x41); + addbyte(0x81); + addbyte(0xf0 | (host_reg & 7)); + addword(imm << 8); + } + else if (host_reg & 8) + { + addbyte(0x41); /*ORL host_reg, imm*/ + addbyte(0x81); + addbyte(0xf0 | (host_reg & 7)); + addlong(imm); + } + else + fatal("XOR to bad register\n"); +} + +static void ADD_HOST_REG_B(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) + { + if (dst_reg & 0x10) + { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + if (!(src_reg & 0x10)) + { + addbyte(0x66); /*SHL AX, 8*/ + addbyte(0xc1); + addbyte(0xe0); + addbyte(8); + } + else + { + addbyte(0x66); /*AND AX, 0xff00*/ + addbyte(0x25); + addword(0xff00); + } + addbyte(0x66); /*ADDW dst_reg, AX*/ + addbyte(0x41); + addbyte(0x01); + addbyte(0xc0 | (dst_reg & 7)); + } + else if (src_reg & 0x10) + { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + addbyte(0x66); /*SHR AX, 8*/ + addbyte(0xc1); + addbyte(0xe8); + addbyte(8); + addbyte(0x41); /*ADDB dst_reg, AL*/ + addbyte(0x00); + addbyte(0xc0 | (dst_reg & 7)); + } + else + { + addbyte(0x45); /*ADDB dst_reg, src_reg*/ + addbyte(0x00); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } + else if (dst_reg & 8) + { + if (dst_reg & 0x10) + { + addbyte(0x66); /*SHL src_reg, 8*/ + addbyte(0xc1); + addbyte(0xe0 | src_reg); + addbyte(0x08); + addbyte(0x66); /*ADDW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x01); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + { + addbyte(0x41); /*ADDB dst_reg, src_reg*/ + addbyte(0x00); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } + else + fatal("!(dst_reg & src_reg & 8)\n"); +} +static void ADD_HOST_REG_W(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) + { + addbyte(0x66); /*ADDW dst_reg, src_reg*/ + addbyte(0x45); + addbyte(0x01); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else if (dst_reg & 8) + { + addbyte(0x66); /*ADDW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x01); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + fatal("!(dst_reg & src_reg & 8)\n"); +} +static void ADD_HOST_REG_L(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) + { + addbyte(0x45); /*ADDL dst_reg, src_reg*/ + addbyte(0x01); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else if (dst_reg & 8) + { + addbyte(0x41); /*ADDL dst_reg, src_reg*/ + addbyte(0x01); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + fatal("!(dst_reg & src_reg & 8)\n"); +} + +static void SUB_HOST_REG_B(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) + { + if (dst_reg & 0x10) + { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + if (!(src_reg & 0x10)) + { + addbyte(0x66); /*SHL AX, 8*/ + addbyte(0xc1); + addbyte(0xe0); + addbyte(8); + } + else + { + addbyte(0x66); /*AND AX, 0xff00*/ + addbyte(0x25); + addword(0xff00); + } + addbyte(0x66); /*SUBW dst_reg, AX*/ + addbyte(0x41); + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7)); + } + else if (src_reg & 0x10) + { + addbyte(0x66); /*MOVW AX, src_reg*/ + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | ((src_reg & 7) << 3)); + addbyte(0x66); /*SHR AX, 8*/ + addbyte(0xc1); + addbyte(0xe8); + addbyte(8); + addbyte(0x41); /*SUBB dst_reg, AL*/ + addbyte(0x28); + addbyte(0xc0 | (dst_reg & 7)); + } + else + { + addbyte(0x45); /*SUBB dst_reg, src_reg*/ + addbyte(0x28); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } + else if (dst_reg & 8) + { + if (dst_reg & 0x10) + { + addbyte(0x66); /*SHL src_reg, 8*/ + addbyte(0xc1); + addbyte(0xe0 | src_reg); + addbyte(0x08); + addbyte(0x66); /*SUBW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + { + addbyte(0x41); /*SUBB dst_reg, src_reg*/ + addbyte(0x28); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } + else if (src_reg & 8) + { + if (dst_reg & 0x10) + { + addbyte(0xc1); /*SHR dst_reg, 8*/ + addbyte(0xe8 | (dst_reg & 7)); + addbyte(8); + } + if (src_reg & 0x10) + { + addbyte(0x41); /*MOVZX EBX, src_reg*/ + addbyte(0x0f); + addbyte(0xb7); + addbyte(0xd8 | (src_reg & 7)); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0x28); /*SUBB dst_reg, EBX*/ + addbyte(0xd8 | (dst_reg & 7)); + } + else + { + addbyte(0x44); /*SUBB dst_reg, src_reg*/ + addbyte(0x28); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } + else + { + if (dst_reg & 0x10) + { + addbyte(0xc1); /*SHR dst_reg, 8*/ + addbyte(0xe8 | (dst_reg & 7)); + addbyte(8); + } + if (src_reg & 0x10) + { + addbyte(0x0f); /*MOVZX EBX, src_reg*/ + addbyte(0xb7); + addbyte(0xd8 | (src_reg & 7)); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0x28); /*SUBB dst_reg, EBX*/ + addbyte(0xd8 | (dst_reg & 7)); + } + else + { + addbyte(0x28); /*SUBB dst_reg, src_reg*/ + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + } + +// fatal("!(dst_reg & src_reg & 8) subb %i %i\n", dst_reg, src_reg); +} +static void SUB_HOST_REG_W(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) + { + addbyte(0x66); /*SUBW dst_reg, src_reg*/ + addbyte(0x45); + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else if (dst_reg & 8) + { + addbyte(0x66); /*SUBW dst_reg, src_reg*/ + addbyte(0x41); + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else if (src_reg & 8) + { + addbyte(0x66); /*SUBW dst_reg, src_reg*/ + addbyte(0x44); + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + { + addbyte(0x66); /*SUBW dst_reg, src_reg*/ + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } +} +static void SUB_HOST_REG_L(int dst_reg, int src_reg) +{ + if (dst_reg & src_reg & 8) + { + addbyte(0x45); /*SUBL dst_reg, src_reg*/ + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else if (dst_reg & 8) + { + addbyte(0x41); /*SUBL dst_reg, src_reg*/ + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else if (src_reg & 8) + { + addbyte(0x44); /*SUBL dst_reg, src_reg*/ + addbyte(0x29); + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } + else + { + addbyte(0x29); /*SUBL dst_reg, src_reg*/ + addbyte(0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3)); + } +} + +static int CMP_HOST_REG_B(int dst_reg, int src_reg) +{ + if (dst_reg & 8) + { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); + + dst_reg = (dst_reg & 0x10) | REG_EDX; + } + + SUB_HOST_REG_B(dst_reg, src_reg); + + return dst_reg & ~0x10; +} +static int CMP_HOST_REG_W(int dst_reg, int src_reg) +{ + if (dst_reg & 8) + { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); + + dst_reg = REG_EDX; + } + + SUB_HOST_REG_W(dst_reg, src_reg); + + return dst_reg; +} +static int CMP_HOST_REG_L(int dst_reg, int src_reg) +{ + if (dst_reg & 8) + { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((dst_reg & 7) << 3) | REG_EDX); + + dst_reg = REG_EDX; + } + + SUB_HOST_REG_L(dst_reg, src_reg); + + return dst_reg; +} + +static void ADD_HOST_REG_IMM_B(int host_reg, uint8_t imm) +{ + if (host_reg & 0x10) + { + addbyte(0x66); /*ADDW host_reg, imm*/ + addbyte(0x41); + addbyte(0x81); + addbyte(0xC0 | (host_reg & 7)); + addword(imm << 8); + } + else + { + addbyte(0x41); /*ADDB host_reg, imm*/ + addbyte(0x80); + addbyte(0xC0 | (host_reg & 7)); + addbyte(imm); + } +} +static void ADD_HOST_REG_IMM_W(int host_reg, uint16_t imm) +{ + addbyte(0x66); /*ADDW host_reg, imm*/ + addbyte(0x41); + addbyte(0x81); + addbyte(0xC0 | (host_reg & 7)); + addword(imm); +} +static void ADD_HOST_REG_IMM(int host_reg, uint32_t imm) +{ + addbyte(0x41); /*ADDL host_reg, imm*/ + addbyte(0x81); + addbyte(0xC0 | (host_reg & 7)); + addlong(imm); +} + +static void SUB_HOST_REG_IMM_B(int host_reg, uint8_t imm) +{ + if (host_reg & 0x10) + { + addbyte(0x66); /*SUBW host_reg, imm*/ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x81); + addbyte(0xE8 | (host_reg & 7)); + addword(imm << 8); + } + else + { + if (host_reg & 8) + addbyte(0x41); + addbyte(0x80); /*SUBB host_reg, imm*/ + addbyte(0xE8 | (host_reg & 7)); + addbyte(imm); + } +} +static void SUB_HOST_REG_IMM_W(int host_reg, uint16_t imm) +{ + addbyte(0x66); /*SUBW host_reg, imm*/ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x81); + addbyte(0xE8 | (host_reg & 7)); + addword(imm); +} +static void SUB_HOST_REG_IMM(int host_reg, uint32_t imm) +{ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x81); /*SUBL host_reg, imm*/ + addbyte(0xE8 | (host_reg & 7)); + addlong(imm); +} + +static int CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) +{ + if (host_reg & 8) + { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); + + host_reg = (host_reg & 0x10) | REG_EDX; + } + + SUB_HOST_REG_IMM_B(host_reg, imm); + + return host_reg;// & ~0x10; +} +static int CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) +{ + if (host_reg & 8) + { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); + + host_reg = REG_EDX; + } + + SUB_HOST_REG_IMM_W(host_reg, imm); + + return host_reg; +} +static int CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) +{ + if (host_reg & 8) + { + addbyte(0x44); /*MOV EDX, dst_reg*/ + addbyte(0x89); + addbyte(0xc0 | ((host_reg & 7) << 3) | REG_EDX); + + host_reg = REG_EDX; + } + + SUB_HOST_REG_IMM(host_reg, imm); + + return host_reg; +} + +static void LOAD_STACK_TO_EA(int off) +{ + if (stack32) + { + addbyte(0x8b); /*MOVL EAX,[ESP]*/ + addbyte(0x45 | (REG_EAX << 3)); + addbyte((uint32_t)&ESP - (uint32_t)&EAX); + if (off) + { + addbyte(0x83); /*ADD EAX, off*/ + addbyte(0xc0 | (0 << 3) | REG_EAX); + addbyte(off); + } + } + else + { + addbyte(0x0f); /*MOVZX EAX,W[ESP]*/ + addbyte(0xb7); + addbyte(0x45 | (REG_EAX << 3)); + addbyte((uint32_t)&ESP - (uint32_t)&EAX); + if (off) + { + addbyte(0x66); /*ADD AX, off*/ + addbyte(0x05); + addword(off); + } + } +} +static void LOAD_EBP_TO_EA(int off) +{ + if (stack32) + { + addbyte(0x8b); /*MOVL EAX,[EBP]*/ + addbyte(0x45 | (REG_EAX << 3)); + addbyte((uint32_t)&EBP - (uint32_t)&EAX); + if (off) + { + addbyte(0x83); /*ADD EAX, off*/ + addbyte(0xc0 | (0 << 3) | REG_EAX); + addbyte(off); + } + } + else + { + addbyte(0x0f); /*MOVZX EAX,W[EBP]*/ + addbyte(0xb7); + addbyte(0x45 | (REG_EAX << 3)); + addbyte((uint32_t)&EBP - (uint32_t)&EAX); + if (off) + { + addbyte(0x66); /*ADD AX, off*/ + addbyte(0x05); + addword(off); + } + } +} + +static void SP_MODIFY(int off) +{ + if (stack32) + { + if (off < 0x80) + { + addbyte(0x83); /*ADD [ESP], off*/ + addbyte(0x45); + addbyte((uint32_t)&ESP - (uint32_t)&EAX); + addbyte(off); + } + else + { + addbyte(0x81); /*ADD [ESP], off*/ + addbyte(0x45); + addbyte((uint32_t)&ESP - (uint32_t)&EAX); + addlong(off); + } + } + else + { + if (off < 0x80) + { + addbyte(0x66); /*ADD [SP], off*/ + addbyte(0x83); + addbyte(0x45); + addbyte((uint32_t)&SP - (uint32_t)&EAX); + addbyte(off); + } + else + { + addbyte(0x66); /*ADD [SP], off*/ + addbyte(0x81); + addbyte(0x45); + addbyte((uint32_t)&SP - (uint32_t)&EAX); + addword(off); + } + } +} + +static void TEST_ZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) +{ + addbyte(0x66); /*CMPW host_reg, 0*/ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x83); + addbyte(0xc0 | 0x38 | (host_reg & 7)); + addbyte(0); + addbyte(0x75); /*JNZ +*/ + addbyte(11+5+(taken_cycles ? 8 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&pc); + addlong(new_pc); + if (taken_cycles) + { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x2c); + addbyte(0x25); + addlong((uintptr_t)&cycles); + addbyte(taken_cycles); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} +static void TEST_ZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) +{ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x83); /*CMPW host_reg, 0*/ + addbyte(0xc0 | 0x38 | (host_reg & 7)); + addbyte(0); + addbyte(0x75); /*JNZ +*/ + addbyte(11+5+(taken_cycles ? 8 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&pc); + addlong(new_pc); + if (taken_cycles) + { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x2c); + addbyte(0x25); + addlong((uintptr_t)&cycles); + addbyte(taken_cycles); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} + +static void TEST_NONZERO_JUMP_W(int host_reg, uint32_t new_pc, int taken_cycles) +{ + addbyte(0x66); /*CMPW host_reg, 0*/ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x83); + addbyte(0xc0 | 0x38 | (host_reg & 7)); + addbyte(0); + addbyte(0x74); /*JZ +*/ + addbyte(11+5+(taken_cycles ? 8 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&pc); + addlong(new_pc); + if (taken_cycles) + { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x2c); + addbyte(0x25); + addlong((uintptr_t)&cycles); + addbyte(taken_cycles); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} +static void TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) +{ + if (host_reg & 8) + addbyte(0x41); + addbyte(0x83); /*CMPW host_reg, 0*/ + addbyte(0xc0 | 0x38 | (host_reg & 7)); + addbyte(0); + addbyte(0x74); /*JZ +*/ + addbyte(11+5+(taken_cycles ? 8 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&pc); + addlong(new_pc); + if (taken_cycles) + { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x2c); + addbyte(0x25); + addlong((uintptr_t)&cycles); + addbyte(taken_cycles); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} + +static int BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +{ + if (codegen_flags_changed && flags_op != FLAGS_UNKNOWN) + { + addbyte(0x83); /*CMP flags_res, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uintptr_t)&flags_res); + addbyte(0); + addbyte(0x74); /*JZ +*/ + } + else + { + CALL_FUNC(ZF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x75); /*JNZ +*/ + } + if (not) + addbyte(12+2+2+11+5+(timing_bt ? 8 : 0)); + else + addbyte(12+2+2); + CALL_FUNC(CF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + if (not) + addbyte(0x75); /*JNZ +*/ + else + addbyte(0x74); /*JZ +*/ + addbyte(11+5+(timing_bt ? 8 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&pc); + addlong(op_pc+pc_offset+offset); + if (timing_bt) + { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x2c); + addbyte(0x25); + addlong((uintptr_t)&cycles); + addbyte(timing_bt); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} + +static int BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +{ + CALL_FUNC(NF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*SETNE BL*/ + addbyte(0x95); + addbyte(0xc3); + CALL_FUNC(VF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*SETNE AL*/ + addbyte(0x95); + addbyte(0xc0); + addbyte(0x38); /*CMP AL, BL*/ + addbyte(0xd8); + if (not) + addbyte(0x75); /*JNZ +*/ + else + addbyte(0x74); /*JZ +*/ + addbyte(11+5+(timing_bt ? 8 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&pc); + addlong(op_pc+pc_offset+offset); + if (timing_bt) + { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x2c); + addbyte(0x25); + addlong((uintptr_t)&cycles); + addbyte(timing_bt); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} + +static int BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) +{ + if (codegen_flags_changed && flags_op != FLAGS_UNKNOWN) + { + addbyte(0x83); /*CMP flags_res, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uintptr_t)&flags_res); + addbyte(0); + addbyte(0x74); /*JZ +*/ + } + else + { + CALL_FUNC(ZF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x75); /*JNZ +*/ + } + if (not) + addbyte(12+2+3+12+2+3+2+2+11+5+(timing_bt ? 8 : 0)); + else + addbyte(12+2+3+12+2+3+2+2); + + CALL_FUNC(NF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*SETNE BL*/ + addbyte(0x95); + addbyte(0xc3); + CALL_FUNC(VF_SET); + addbyte(0x85); /*TEST EAX,EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*SETNE AL*/ + addbyte(0x95); + addbyte(0xc0); + addbyte(0x38); /*CMP AL, BL*/ + addbyte(0xd8); + if (not) + addbyte(0x75); /*JNZ +*/ + else + addbyte(0x74); /*JZ +*/ + addbyte(11+5+(timing_bt ? 8 : 0)); + addbyte(0xC7); /*MOVL [pc], new_pc*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&pc); + addlong(op_pc+pc_offset+offset); + if (timing_bt) + { + addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x2c); + addbyte(0x25); + addlong((uintptr_t)&cycles); + addbyte(timing_bt); + } + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); +} + +static int LOAD_VAR_W(uintptr_t addr) +{ + int host_reg = REG_EBX; + + addbyte(0x0f); /*MOVZX host_reg,[reg]*/ + addbyte(0xb7); + addbyte(0x04 | (host_reg << 3)); + addbyte(0x25); + addlong((uint32_t)addr); + + return host_reg; +} +static int LOAD_VAR_L(uintptr_t addr) +{ + int host_reg = REG_EBX; + + addbyte(0x8b); /*MOVL host_reg,[reg]*/ + addbyte(0x04 | (host_reg << 3)); + addbyte(0x25); + addlong((uint32_t)addr); + + return host_reg; +} + +static int COPY_REG(int src_reg) +{ + if (src_reg & 8) + addbyte(0x44); + addbyte(0x89); + addbyte(0xc0 | REG_ECX | ((src_reg & 7) << 3)); + + return REG_ECX | (src_reg & 0x10); +} + +static int ZERO_EXTEND_W_B(int reg) +{ + if (reg & 0x10) + { + addbyte(0x44); /*MOV EAX, reg*/ + addbyte(0x89); + addbyte(0xc0 | (reg << 3)); + addbyte(0x0f); /*MOVZX EAX, AH*/ + addbyte(0xb6); + addbyte(0xc4); + + return REG_EAX; + } + + if (reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVZX regl, regb*/ + addbyte(0xb6); + addbyte(0xc0 | (reg & 7)); + + return REG_EAX; +} +static int ZERO_EXTEND_L_B(int reg) +{ + if (reg & 0x10) + { + addbyte(0x44); /*MOV EAX, reg*/ + addbyte(0x89); + addbyte(0xc0 | (reg << 3)); + addbyte(0x0f); /*MOVZX EAX, AH*/ + addbyte(0xb6); + addbyte(0xc4); + + return REG_EAX; + } + + if (reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVZX regl, regb*/ + addbyte(0xb6); + addbyte(0xc0 | (reg & 7)); + + return REG_EAX; +} +static int ZERO_EXTEND_L_W(int reg) +{ + if (reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVZX regl, regw*/ + addbyte(0xb7); + addbyte(0xc0 | (reg & 7)); + + return REG_EAX; +} + +static int SIGN_EXTEND_W_B(int reg) +{ + if (reg & 0x10) + { + addbyte(0x44); /*MOV EAX, reg*/ + addbyte(0x89); + addbyte(0xc0 | (reg << 3)); + addbyte(0x0f); /*MOVSX EAX, AH*/ + addbyte(0xbe); + addbyte(0xc4); + + return REG_EAX; + } + + if (reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVSX regl, regb*/ + addbyte(0xbe); + addbyte(0xc0 | (reg & 7)); + + return REG_EAX; +} +static int SIGN_EXTEND_L_B(int reg) +{ + if (reg & 0x10) + { + addbyte(0x44); /*MOV EAX, reg*/ + addbyte(0x89); + addbyte(0xc0 | (reg << 3)); + addbyte(0x0f); /*MOVSX EAX, AH*/ + addbyte(0xbe); + addbyte(0xc4); + + return REG_EAX; + } + + if (reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVSX regl, regb*/ + addbyte(0xbe); + addbyte(0xc0 | (reg & 7)); + + return REG_EAX; +} +static int SIGN_EXTEND_L_W(int reg) +{ + if (reg & 8) + addbyte(0x41); + addbyte(0x0f); /*MOVSX regl, regw*/ + addbyte(0xbf); + addbyte(0xc0 | (reg & 7)); + + return REG_EAX; +} + +static void SHL_B_IMM(int reg, int count) +{ + if (reg & 0x10) + { + addbyte(0x44); /*MOV EAX, reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EAX | ((reg & 7) << 3)); + addbyte(0xc0); /*SHL AH, count*/ + addbyte(0xe0 | REG_AH); + addbyte(count); + addbyte(0x41); /*MOV reg, EAX*/ + addbyte(0x89); + addbyte(0xc0 | (REG_EAX << 3) | (reg & 7)); + } + else + { + if (reg & 8) + addbyte(0x41); + addbyte(0xc0); /*SHL reg, count*/ + addbyte(0xc0 | (reg & 7) | 0x20); + addbyte(count); + } +} +static void SHL_W_IMM(int reg, int count) +{ + addbyte(0x66); /*SHL reg, count*/ + if (reg & 8) + addbyte(0x41); + addbyte(0xc1); + addbyte(0xc0 | (reg & 7) | 0x20); + addbyte(count); +} +static void SHL_L_IMM(int reg, int count) +{ + if (reg & 8) + addbyte(0x41); + addbyte(0xc1); /*SHL reg, count*/ + addbyte(0xc0 | (reg & 7) | 0x20); + addbyte(count); +} +static void SHR_B_IMM(int reg, int count) +{ + if (reg & 0x10) + { + addbyte(0x44); /*MOV EAX, reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EAX | ((reg & 7) << 3)); + addbyte(0xc0); /*SHR AH, count*/ + addbyte(0xe8 | REG_AH); + addbyte(count); + addbyte(0x41); /*MOV reg, EAX*/ + addbyte(0x89); + addbyte(0xc0 | (REG_EAX << 3) | (reg & 7)); + } + else + { + if (reg & 8) + addbyte(0x41); + addbyte(0xc0); /*SHR reg, count*/ + addbyte(0xc0 | (reg & 7) | 0x28); + addbyte(count); + } +} +static void SHR_W_IMM(int reg, int count) +{ + addbyte(0x66); /*SHR reg, count*/ + if (reg & 8) + addbyte(0x41); + addbyte(0xc1); + addbyte(0xc0 | (reg & 7) | 0x28); + addbyte(count); +} +static void SHR_L_IMM(int reg, int count) +{ + if (reg & 8) + addbyte(0x41); + addbyte(0xc1); /*SHR reg, count*/ + addbyte(0xc0 | (reg & 7) | 0x28); + addbyte(count); +} +static void SAR_B_IMM(int reg, int count) +{ + if (reg & 0x10) + { + addbyte(0x44); /*MOV EAX, reg*/ + addbyte(0x89); + addbyte(0xc0 | REG_EAX | ((reg & 7) << 3)); + addbyte(0xc0); /*SAR AH, count*/ + addbyte(0xf8 | REG_AH); + addbyte(count); + addbyte(0x41); /*MOV reg, EAX*/ + addbyte(0x89); + addbyte(0xc0 | (REG_EAX << 3) | (reg & 7)); + } + else + { + if (reg & 8) + addbyte(0x41); + addbyte(0xc0); /*SAR reg, count*/ + addbyte(0xc0 | (reg & 7) | 0x38); + addbyte(count); + } +} +static void SAR_W_IMM(int reg, int count) +{ + addbyte(0x66); /*SAR reg, count*/ + if (reg & 8) + addbyte(0x41); + addbyte(0xc1); + addbyte(0xc0 | (reg & 7) | 0x38); + addbyte(count); +} +static void SAR_L_IMM(int reg, int count) +{ + if (reg & 8) + addbyte(0x41); + addbyte(0xc1); /*SAR reg, count*/ + addbyte(0xc0 | (reg & 7) | 0x38); + addbyte(count); +} + +static void FP_ENTER() +{ + if (codegen_fpu_entered) + return; + + addbyte(0xf6); /*TEST cr0, 0xc*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&cr0); + addbyte(0xc); + addbyte(0x74); /*JZ +*/ + addbyte(11+5+12+5); + addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&oldpc); + addlong(op_old_pc); + load_param_1_32(&codeblock[block_current], 7); + CALL_FUNC(x86_int); + addbyte(0xe9); /*JMP end*/ + addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + + codegen_fpu_entered = 1; +} + +static void FP_FXCH(int reg) +{ + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x48); /*MOV RSI, ST*/ + addbyte(0xbe); + addquad((uint64_t)ST); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); + + addbyte(0x48); /*MOV RDX, [RSI + RBX*8]*/ + addbyte(0x8b); + addbyte(0x14); + addbyte(0xde); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(0x07); + addbyte(0x48); /*MOV RCX, [RSI + RAX*8]*/ + addbyte(0x8b); + addbyte(0x0c); + addbyte(0xc6); + addbyte(0x48); /*MOV [RSI + RAX*8], RDX*/ + addbyte(0x89); + addbyte(0x14); + addbyte(0xc6); + addbyte(0x48); /*MOV [RSI + RBX*8], RCX*/ + addbyte(0x89); + addbyte(0x0c); + addbyte(0xde); + + addbyte(0x48); /*MOVL ESI, tag*/ + addbyte(0xbe); + addquad((uintptr_t)tag); + addbyte(0x8a); /*MOV CL, tag[EAX]*/ + addbyte(0x14); + addbyte(0x1e); + addbyte(0x8a); /*MOV DL, tag[EBX]*/ + addbyte(0x0c); + addbyte(0x06); + addbyte(0x88); /*MOV tag[EBX], CL*/ + addbyte(0x14); + addbyte(0x06); + addbyte(0x88); /*MOV tag[EAX], DL*/ + addbyte(0x0c); + addbyte(0x1e); + + addbyte(0x48); /*MOV RSI, ST_i64*/ + addbyte(0xbe); + addquad((uint64_t)ST_i64); + addbyte(0x48); /*MOV RDX, [RSI + RBX*8]*/ + addbyte(0x8b); + addbyte(0x14); + addbyte(0xde); + addbyte(0x48); /*MOV RCX, [RSI + RAX*8]*/ + addbyte(0x8b); + addbyte(0x0c); + addbyte(0xc6); + addbyte(0x48); /*MOV [RSI + RAX*8], RDX*/ + addbyte(0x89); + addbyte(0x14); + addbyte(0xc6); + addbyte(0x48); /*MOV [RSI + RBX*8], RCX*/ + addbyte(0x89); + addbyte(0x0c); + addbyte(0xde); + reg = reg; +} + + + +static void FP_FLD(int reg) +{ + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + if (reg) + { + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(0x07); + } + else + { + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + } + + addbyte(0x48); /*MOV RCX, ST[EAX*8]*/ + addbyte(0x8b); + addbyte(0x0c); + addbyte(0xc5); + addlong((uintptr_t)ST); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(0x07); + addbyte(0x48); /*MOV RDX, ST_i64[EAX*8]*/ + addbyte(0x8b); + addbyte(0x14); + addbyte(0xc5); + addlong((uintptr_t)ST_i64); + addbyte(0x8a); /*MOV AL, [tag+EAX]*/ + addbyte(0x80); + addlong((uintptr_t)tag); + addbyte(0x48); /*MOV ST[EBX*8], RCX*/ + addbyte(0x89); + addbyte(0x0c); + addbyte(0xdd); + addlong((uintptr_t)ST); + addbyte(0x48); /*MOV ST_i64[EBX*8], RDX*/ + addbyte(0x89); + addbyte(0x14); + addbyte(0xdd); + addlong((uintptr_t)ST_i64); + addbyte(0x88); /*MOV [tag+EBX], AL*/ + addbyte(0x83); + addlong((uintptr_t)tag); + + addbyte(0x89); /*MOV [TOP], EBX*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uintptr_t)&TOP); +} + +static void FP_FST(int reg) +{ + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x48); /*MOV RCX, ST[EAX*8]*/ + addbyte(0x8b); + addbyte(0x0c); + addbyte(0xc5); + addlong((uintptr_t)ST); + addbyte(0x8a); /*MOV BL, [tag+EAX]*/ + addbyte(0x98); + addlong((uintptr_t)tag); + + if (reg) + { + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(0x07); + } + + addbyte(0x48); /*MOV ST[EAX*8], RCX*/ + addbyte(0x89); + addbyte(0x0c); + addbyte(0xc5); + addlong((uintptr_t)ST); + addbyte(0x88); /*MOV [tag+EAX], BL*/ + addbyte(0x98); + addlong((uintptr_t)tag); +} + +static void FP_POP() +{ + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0xc6); /*MOVB tag[EAX], 3*/ + addbyte(0x80); + addlong((uintptr_t)tag); + addbyte(3); + addbyte(0x83); /*ADD AL, 1*/ + addbyte(0xc0); + addbyte(1); + addbyte(0x83); /*AND AL, 7*/ + addbyte(0xe0); + addbyte(7); + addbyte(0x89); /*MOV [TOP], EAX*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&TOP); +} + +static void FP_LOAD_S() +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0xf3); /*CVTSS2SD XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x5a); + addbyte(0xc0); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x04); + addbyte(0xdd); + addlong((uintptr_t)ST); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x83); + addlong((uintptr_t)tag); +} +static void FP_LOAD_D() +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x48); /*TEST RAX, RAX*/ + addbyte(0x85); + addbyte(0xc0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x48); /*MOVQ [ST+EBX*8], RAX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0xdd); + addlong((uintptr_t)ST); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x83); + addlong((uintptr_t)tag); +} + +static void FP_LOAD_IW() +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x0f); /*MOVSX EAX, AX*/ + addbyte(0xbf); + addbyte(0xc0); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0xf2); /*CVTSI2SD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x2a); + addbyte(0xc0); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x04); + addbyte(0xdd); + addlong((uintptr_t)ST); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x83); + addlong((uintptr_t)tag); +} +static void FP_LOAD_IL() +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0xf2); /*CVTSI2SD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x2a); + addbyte(0xc0); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x04); + addbyte(0xdd); + addlong((uintptr_t)ST); + addbyte(0x0f); /*SETE [tag+EBX]*/ + addbyte(0x94); + addbyte(0x83); + addlong((uintptr_t)tag); +} +static void FP_LOAD_IQ() +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x83); /*SUB EBX, 1*/ + addbyte(0xeb); + addbyte(0x01); + addbyte(0xf2); /*CVTSI2SDQ XMM0, RAX*/ + addbyte(0x48); + addbyte(0x0f); + addbyte(0x2a); + addbyte(0xc0); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe3); + addbyte(7); + addbyte(0x48); /*TEST RAX, RAX*/ + addbyte(0x85); + addbyte(0xc0); + addbyte(0x48); /*MOV [ST_i64+EBX*8], RAX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0xdd); + addlong((uintptr_t)ST_i64); + addbyte(0x89); /*MOV TOP, EBX*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x0f); /*SETE AL*/ + addbyte(0x94); + addbyte(0xc0); + addbyte(0x66); /*MOVQ [ST+EBX*8], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x04); + addbyte(0xdd); + addlong((uintptr_t)ST); + addbyte(0x0c); /*OR AL, TAG_UINT64*/ + addbyte(TAG_UINT64); + addbyte(0x88); /*MOV [tag+EBX], AL*/ + addbyte(0x83); + addlong((uintptr_t)tag); +} + +static int FP_LOAD_REG(int reg) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uintptr_t)&TOP); + if (reg) + { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc0 | REG_EBX); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe0 | REG_EBX); + addbyte(0x07); + } + addbyte(0xf3); /*MOVQ XMM0, ST[EBX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x04); + addbyte(0xdd); + addlong((uintptr_t)ST); + addbyte(0xf2); /*CVTSD2SS XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x5a); + addbyte(0xc0); + addbyte(0x66); /*MOVD EBX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0 | REG_EBX); + + return REG_EBX; +} +static void FP_LOAD_REG_D(int reg, int *host_reg1, int *host_reg2) +{ + addbyte(0x8b); /*MOV EBX, TOP*/ + addbyte(0x1c); + addbyte(0x25); + addlong((uintptr_t)&TOP); + if (reg) + { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc0 | REG_EBX); + addbyte(reg); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe0 | REG_EBX); + addbyte(0x07); + } + addbyte(0x48); /*MOV RBX, ST[EBX*8]*/ + addbyte(0x8b); + addbyte(0x1c); + addbyte(0xdd); + addlong((uintptr_t)ST); + + *host_reg1 = REG_EBX; +} +static int64_t x87_fround(double b) +{ + switch ((npxc>>10)&3) + { + case 0: /*Nearest*/ + return (int64_t)(b+0.5); + case 1: /*Down*/ + return (int64_t)floor(b); + case 2: /*Up*/ + return (int64_t)ceil(b); + case 3: /*Chop*/ + return (int64_t)b; + } +} +static int FP_LOAD_REG_INT_W(int reg) +{ + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&TOP); + if (reg) + { + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(7); + } + addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x04); + addbyte(0xc5); + addlong((uintptr_t)ST); + + CALL_FUNC(x87_fround); + + addbyte(0x93); /*XCHG EBX, EAX*/ + + return REG_EBX; +} +static int FP_LOAD_REG_INT(int reg) +{ + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&TOP); + if (reg) + { + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(7); + } + addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x04); + addbyte(0xc5); + addlong((uintptr_t)ST); + + CALL_FUNC(x87_fround); + + addbyte(0x93); /*XCHG EBX, EAX*/ + + return REG_EBX; +} +static void FP_LOAD_REG_INT_Q(int reg, int *host_reg1, int *host_reg2) +{ + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&TOP); + if (reg) + { + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(reg); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(7); + } + + if (codegen_fpu_loaded_iq[TOP] && (tag[TOP] & TAG_UINT64)) + { + /*If we know the register was loaded with FILDq in this block and + has not been modified, then we can skip most of the conversion + and just load the 64-bit integer representation directly */ + addbyte(0x48); /*MOV RAX, [ST_i64+EAX*8]*/ + addbyte(0x8b); + addbyte(0x04); + addbyte(0xc5); + addlong((uint32_t)ST_i64); + + addbyte(0x48); /*XCHG RBX, RAX*/ + addbyte(0x93); + + *host_reg1 = REG_EBX; + + return; + } + + addbyte(0xf6); /*TEST TAG[EBX], TAG_UINT64*/ + addbyte(0x80); + addlong((uintptr_t)tag); + addbyte(TAG_UINT64); + + addbyte(0x74); /*JZ +*/ + addbyte(8+2); + + addbyte(0x48); /*MOV RAX, [ST_i64+EAX*8]*/ + addbyte(0x8b); + addbyte(0x04); + addbyte(0xc5); + addlong((uint32_t)ST_i64); + + addbyte(0xeb); /*JMP done*/ + addbyte(9+12); + + addbyte(0xf3); /*MOVQ XMM0, ST[EAX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x04); + addbyte(0xc5); + addlong((uintptr_t)ST); + + CALL_FUNC(x87_fround); + + addbyte(0x48); /*XCHG RBX, RAX*/ + addbyte(0x93); + + *host_reg1 = REG_EBX; +} + +#define FPU_ADD 0 +#define FPU_DIV 4 +#define FPU_DIVR 5 +#define FPU_MUL 1 +#define FPU_SUB 2 +#define FPU_SUBR 3 + +static void FP_OP_REG(int op, int dst, int src) +{ + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x48); /*MOV RSI, ST*/ + addbyte(0xbe); + addquad((uint64_t)ST); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + if (dst) + { + addbyte(0x83); /*ADD EAX, reg*/ + addbyte(0xc0); + addbyte(dst); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(0x07); + } + if (src) + { + addbyte(0x83); /*ADD EBX, reg*/ + addbyte(0xc0 | REG_EBX); + addbyte(src); + addbyte(0x83); /*AND EBX, 7*/ + addbyte(0xe0 | REG_EBX); + addbyte(0x07); + } + if (op == FPU_DIVR || op == FPU_SUBR) + { + addbyte(0xf3); /*MOVQ XMM0, [RSI+RBX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x04); + addbyte(0xde); + } + else + { + addbyte(0xf3); /*MOVQ XMM0, [RSI+RAX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x04); + addbyte(0xc6); + } + switch (op) + { + case FPU_ADD: + addbyte(0xf2); /*ADDSD XMM0, [RSI+RBX*8]*/ + addbyte(0x0f); + addbyte(0x58); + addbyte(0x04); + addbyte(0xde); + break; + case FPU_DIV: + addbyte(0xf2); /*DIVSD XMM0, [RSI+RBX*8]*/ + addbyte(0x0f); + addbyte(0x5e); + addbyte(0x04); + addbyte(0xde); + break; + case FPU_DIVR: + addbyte(0xf2); /*DIVSD XMM0, [RSI+RAX*8]*/ + addbyte(0x0f); + addbyte(0x5e); + addbyte(0x04); + addbyte(0xc6); + break; + case FPU_MUL: + addbyte(0xf2); /*MULSD XMM0, [RSI+RBX*8]*/ + addbyte(0x0f); + addbyte(0x59); + addbyte(0x04); + addbyte(0xde); + break; + case FPU_SUB: + addbyte(0xf2); /*SUBSD XMM0, [RSI+RBX*8]*/ + addbyte(0x0f); + addbyte(0x5c); + addbyte(0x04); + addbyte(0xde); + break; + case FPU_SUBR: + addbyte(0xf2); /*SUBSD XMM0, [RSI+RAX*8]*/ + addbyte(0x0f); + addbyte(0x5c); + addbyte(0x04); + addbyte(0xc6); + break; + } + addbyte(0x66); /*MOVQ [RSI+RAX*8], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x04); + addbyte(0xc6); +} + +static void FP_OP_MEM(int op) +{ + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x48); /*MOV RSI, ST*/ + addbyte(0xbe); + addquad((uint64_t)ST); + addbyte(0xf3); /*MOVQ XMM0, [RSI+RAX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x04); + addbyte(0xc6); + addbyte(0x80); /*AND tag[EAX], ~TAG_UINT64*/ + addbyte(0xa0 | REG_EAX); + addlong((uintptr_t)tag); + addbyte(~TAG_UINT64); + + switch (op) + { + case FPU_ADD: + addbyte(0xf2); /*ADDSD XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0x58); + addbyte(0xc1); + break; + case FPU_DIV: + addbyte(0xf2); /*DIVSD XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0x5e); + addbyte(0xc1); + break; + case FPU_DIVR: + addbyte(0xf2); /*DIVSD XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0x5e); + addbyte(0xc8); + break; + case FPU_MUL: + addbyte(0xf2); /*MULSD XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0x59); + addbyte(0xc1); + break; + case FPU_SUB: + addbyte(0xf2); /*SUBSD XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0x5c); + addbyte(0xc1); + break; + case FPU_SUBR: + addbyte(0xf2); /*SUBSD XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0x5c); + addbyte(0xc8); + break; + } + if (op == FPU_DIVR || op == FPU_SUBR) + { + addbyte(0x66); /*MOVQ [RSI+RAX*8], XMM1*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x0c); + addbyte(0xc6); + } + else + { + addbyte(0x66); /*MOVQ [RSI+RAX*8], XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x04); + addbyte(0xc6); + } +} + +static void FP_OP_S(int op) +{ + addbyte(0x66); /*MOVD XMM1, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc8); + addbyte(0xf3); /*CVTSS2SD XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x5a); + addbyte(0xc9); + FP_OP_MEM(op); +} +static void FP_OP_D(int op) +{ + addbyte(0x66); /*MOVQ XMM1, RAX*/ + addbyte(0x48); + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc8); + FP_OP_MEM(op); +} +static void FP_OP_IW(int op) +{ + addbyte(0x0f); /*MOVSX EAX, AX*/ + addbyte(0xbf); + addbyte(0xc0); + addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ + addbyte(0x0f); + addbyte(0x2a); + addbyte(0xc8); + FP_OP_MEM(op); +} +static void FP_OP_IL(int op) +{ + addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ + addbyte(0x0f); + addbyte(0x2a); + addbyte(0xc8); + FP_OP_MEM(op); +} + +#define C0 (1<<8) +#define C1 (1<<9) +#define C2 (1<<10) +#define C3 (1<<14) + +static void FP_COMPARE_REG(int dst, int src) +{ + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x48); /*MOV RSI, ST*/ + addbyte(0xbe); + addquad((uint64_t)ST); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + if (src || dst) + { + addbyte(0x83); /*ADD EAX, 1*/ + addbyte(0xc0); + addbyte(src ? src : dst); + addbyte(0x83); /*AND EAX, 7*/ + addbyte(0xe0); + addbyte(7); + } + + addbyte(0x8a); /*MOV CL, [npxs+1]*/ + addbyte(0x0c); + addbyte(0x25); + addlong(((uintptr_t)&npxs) + 1); +// addbyte(0xdb); /*FCLEX*/ +// addbyte(0xe2); + addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ + addbyte(0xe1); + addbyte((~(C0|C2|C3)) >> 8); + + if (src) + { + addbyte(0xf3); /*MOVQ XMM0, [RSI+RBX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x04); + addbyte(0xde); + addbyte(0x66); /*COMISD XMM0, [RSI+RAX*8]*/ + addbyte(0x0f); + addbyte(0x2f); + addbyte(0x04); + addbyte(0xc6); + } + else + { + addbyte(0xf3); /*MOVQ XMM0, [RSI+RAX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x04); + addbyte(0xc6); + addbyte(0x66); /*COMISD XMM0, [RSI+RBX*8]*/ + addbyte(0x0f); + addbyte(0x2f); + addbyte(0x04); + addbyte(0xde); + } + + addbyte(0x9f); /*LAHF*/ + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0|C2|C3) >> 8); + addbyte(0x08); /*OR CL, AH*/ + addbyte(0xe1); + addbyte(0x88); /*MOV [npxs+1], CL*/ + addbyte(0x0c); + addbyte(0x25); + addlong(((uintptr_t)&npxs) + 1); +} + +static void FP_COMPARE_MEM() +{ + addbyte(0x8b); /*MOV EAX, [TOP]*/ + addbyte(0x04); + addbyte(0x25); + addlong((uintptr_t)&TOP); + addbyte(0x48); /*MOV RSI, ST*/ + addbyte(0xbe); + addquad((uint64_t)ST); + + addbyte(0x8a); /*MOV CL, [npxs+1]*/ + addbyte(0x0c); + addbyte(0x25); + addlong(((uintptr_t)&npxs) + 1); +// addbyte(0xdb); /*FCLEX*/ +// addbyte(0xe2); + addbyte(0xf3); /*MOVQ XMM0, [RSI+RAX*8]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x04); + addbyte(0xc6); + addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ + addbyte(0xe1); + addbyte((~(C0|C2|C3)) >> 8); + addbyte(0x66); /*COMISD XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0x2f); + addbyte(0xc1); + addbyte(0x9f); /*LAHF*/ + addbyte(0x80); /*AND AH, (C0|C2|C3)*/ + addbyte(0xe4); + addbyte((C0|C2|C3) >> 8); + addbyte(0x08); /*OR CL, AH*/ + addbyte(0xe1); + addbyte(0x88); /*MOV [npxs+1], CL*/ + addbyte(0x0c); + addbyte(0x25); + addlong(((uintptr_t)&npxs) + 1); +} +static void FP_COMPARE_S() +{ + addbyte(0x66); /*MOVD XMM1, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc8); + addbyte(0xf3); /*CVTSS2SD XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x5a); + addbyte(0xc9); + FP_COMPARE_MEM(); +} +static void FP_COMPARE_D() +{ + addbyte(0x66); /*MOVQ XMM1, RAX*/ + addbyte(0x48); + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc8); + FP_COMPARE_MEM(); +} +static void FP_COMPARE_IW() +{ + addbyte(0x0f); /*MOVSX EAX, AX*/ + addbyte(0xbf); + addbyte(0xc0); + addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ + addbyte(0x0f); + addbyte(0x2a); + addbyte(0xc8); + FP_COMPARE_MEM(); +} +static void FP_COMPARE_IL() +{ + addbyte(0xf2); /*CVTSI2SD XMM1, EAX*/ + addbyte(0x0f); + addbyte(0x2a); + addbyte(0xc8); + FP_COMPARE_MEM(); +} diff --git a/src/codegen_ops_x86.h b/src/codegen_ops_x86.h index 9580648..f1fc95f 100644 --- a/src/codegen_ops_x86.h +++ b/src/codegen_ops_x86.h @@ -214,6 +214,8 @@ static void STORE_HOST_REG_ADDR(uintptr_t addr, int host_reg) addbyte(0x05 | (host_reg << 3)); addlong(addr); } +#define STORE_HOST_REG_ADDR_BL STORE_HOST_REG_ADDR +#define STORE_HOST_REG_ADDR_WL STORE_HOST_REG_ADDR static void ADD_HOST_REG_B(int dst_reg, int src_reg) { @@ -292,6 +294,30 @@ static void AND_HOST_REG_IMM(int host_reg, uint32_t imm) addlong(imm); } } +static int TEST_HOST_REG_B(int dst_reg, int src_reg) +{ + AND_HOST_REG_B(dst_reg, src_reg); + + return dst_reg; +} +static int TEST_HOST_REG_W(int dst_reg, int src_reg) +{ + AND_HOST_REG_W(dst_reg, src_reg); + + return dst_reg; +} +static int TEST_HOST_REG_L(int dst_reg, int src_reg) +{ + AND_HOST_REG_L(dst_reg, src_reg); + + return dst_reg; +} +static int TEST_HOST_REG_IMM(int host_reg, uint32_t imm) +{ + AND_HOST_REG_IMM(host_reg, imm); + + return host_reg; +} #define OR_HOST_REG_B OR_HOST_REG_L #define OR_HOST_REG_W OR_HOST_REG_L @@ -372,6 +398,43 @@ static void SUB_HOST_REG_IMM(int host_reg, uint32_t imm) } } +static int CMP_HOST_REG_B(int dst_reg, int src_reg) +{ + SUB_HOST_REG_B(dst_reg, src_reg); + + return dst_reg; +} +static int CMP_HOST_REG_W(int dst_reg, int src_reg) +{ + SUB_HOST_REG_W(dst_reg, src_reg); + + return dst_reg; +} +static int CMP_HOST_REG_L(int dst_reg, int src_reg) +{ + SUB_HOST_REG_L(dst_reg, src_reg); + + return dst_reg; +} +static int CMP_HOST_REG_IMM_B(int host_reg, uint8_t imm) +{ + SUB_HOST_REG_IMM_B(host_reg, imm); + + return host_reg; +} +static int CMP_HOST_REG_IMM_W(int host_reg, uint16_t imm) +{ + SUB_HOST_REG_IMM_W(host_reg, imm); + + return host_reg; +} +static int CMP_HOST_REG_IMM_L(int host_reg, uint32_t imm) +{ + SUB_HOST_REG_IMM(host_reg, imm); + + return host_reg; +} + #define XOR_HOST_REG_B XOR_HOST_REG_L #define XOR_HOST_REG_W XOR_HOST_REG_L static void XOR_HOST_REG_L(int dst_reg, int src_reg) @@ -2647,40 +2710,51 @@ static void FP_COMPARE_REG(int dst, int src) addlong(((uintptr_t)&npxs) + 1); } -static void ZERO_EXTEND_W_B(int reg) +static int ZERO_EXTEND_W_B(int reg) { addbyte(0x0f); /*MOVZX regl, regb*/ addbyte(0xb6); addbyte(0xc0 | reg | (reg << 3)); + return reg; } -static void ZERO_EXTEND_L_B(int reg) +static int ZERO_EXTEND_L_B(int reg) { addbyte(0x0f); /*MOVZX regl, regb*/ addbyte(0xb6); addbyte(0xc0 | reg | (reg << 3)); + return reg; } -static void ZERO_EXTEND_L_W(int reg) +static int ZERO_EXTEND_L_W(int reg) { addbyte(0x0f); /*MOVZX regl, regw*/ addbyte(0xb7); addbyte(0xc0 | reg | (reg << 3)); + return reg; } -static void SIGN_EXTEND_W_B(int reg) +static int SIGN_EXTEND_W_B(int reg) { addbyte(0x0f); /*MOVSX regl, regb*/ addbyte(0xbe); addbyte(0xc0 | reg | (reg << 3)); + return reg; } -static void SIGN_EXTEND_L_B(int reg) +static int SIGN_EXTEND_L_B(int reg) { addbyte(0x0f); /*MOVSX regl, regb*/ addbyte(0xbe); addbyte(0xc0 | reg | (reg << 3)); + return reg; } -static void SIGN_EXTEND_L_W(int reg) +static int SIGN_EXTEND_L_W(int reg) { addbyte(0x0f); /*MOVSX regl, regw*/ addbyte(0xbf); addbyte(0xc0 | reg | (reg << 3)); + return reg; +} + +static int COPY_REG(int src_reg) +{ + return src_reg; } diff --git a/src/codegen_ops_xchg.h b/src/codegen_ops_xchg.h index 9dc2dcf..7762266 100644 --- a/src/codegen_ops_xchg.h +++ b/src/codegen_ops_xchg.h @@ -1,12 +1,13 @@ #define OP_XCHG_AX_(reg) \ static uint32_t ropXCHG_AX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ { \ - int ax_reg, host_reg; \ + int ax_reg, host_reg, temp_reg; \ \ ax_reg = LOAD_REG_W(REG_AX); \ host_reg = LOAD_REG_W(REG_ ## reg); \ + temp_reg = COPY_REG(host_reg); \ STORE_REG_TARGET_W_RELEASE(ax_reg, REG_ ## reg); \ - STORE_REG_TARGET_W_RELEASE(host_reg, REG_AX); \ + STORE_REG_TARGET_W_RELEASE(temp_reg, REG_AX); \ \ return op_pc; \ } @@ -22,12 +23,13 @@ OP_XCHG_AX_(BP) #define OP_XCHG_EAX_(reg) \ static uint32_t ropXCHG_EAX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \ { \ - int eax_reg, host_reg; \ + int eax_reg, host_reg, temp_reg; \ \ eax_reg = LOAD_REG_L(REG_EAX); \ host_reg = LOAD_REG_L(REG_ ## reg); \ + temp_reg = COPY_REG(host_reg); \ STORE_REG_TARGET_L_RELEASE(eax_reg, REG_ ## reg); \ - STORE_REG_TARGET_L_RELEASE(host_reg, REG_EAX); \ + STORE_REG_TARGET_L_RELEASE(temp_reg, REG_EAX); \ \ return op_pc; \ } @@ -42,43 +44,46 @@ OP_XCHG_EAX_(EBP) static uint32_t ropXCHG_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + int src_reg, dst_reg, temp_reg; if ((fetchdat & 0xc0) != 0xc0) return 0; dst_reg = LOAD_REG_B(fetchdat & 7); src_reg = LOAD_REG_B((fetchdat >> 3) & 7); + temp_reg = COPY_REG(src_reg); STORE_REG_TARGET_B_RELEASE(dst_reg, (fetchdat >> 3) & 7); - STORE_REG_TARGET_B_RELEASE(src_reg, fetchdat & 7); + STORE_REG_TARGET_B_RELEASE(temp_reg, fetchdat & 7); return op_pc + 1; } static uint32_t ropXCHG_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + int src_reg, dst_reg, temp_reg; if ((fetchdat & 0xc0) != 0xc0) return 0; dst_reg = LOAD_REG_W(fetchdat & 7); src_reg = LOAD_REG_W((fetchdat >> 3) & 7); + temp_reg = COPY_REG(src_reg); STORE_REG_TARGET_W_RELEASE(dst_reg, (fetchdat >> 3) & 7); - STORE_REG_TARGET_W_RELEASE(src_reg, fetchdat & 7); + STORE_REG_TARGET_W_RELEASE(temp_reg, fetchdat & 7); return op_pc + 1; } static uint32_t ropXCHG_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) { - int src_reg, dst_reg; + int src_reg, dst_reg, temp_reg; if ((fetchdat & 0xc0) != 0xc0) return 0; dst_reg = LOAD_REG_L(fetchdat & 7); src_reg = LOAD_REG_L((fetchdat >> 3) & 7); + temp_reg = COPY_REG(src_reg); STORE_REG_TARGET_L_RELEASE(dst_reg, (fetchdat >> 3) & 7); - STORE_REG_TARGET_L_RELEASE(src_reg, fetchdat & 7); + STORE_REG_TARGET_L_RELEASE(temp_reg, fetchdat & 7); return op_pc + 1; } diff --git a/src/codegen_x86-64.c b/src/codegen_x86-64.c index e5e33d9..0b48fe4 100644 --- a/src/codegen_x86-64.c +++ b/src/codegen_x86-64.c @@ -24,64 +24,6 @@ #include #endif -static void load_param_1_32(codeblock_t *block, uint32_t param) -{ -#if WIN64 - addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ -#else - addbyte(0xbf); /*MOVL $fetchdat,%edi*/ -#endif - addlong(param); -} -static void load_param_1_64(codeblock_t *block, uint64_t param) -{ - addbyte(0x48); -#if WIN64 - addbyte(0xb9); /*MOVL $fetchdat,%ecx*/ -#else - addbyte(0xbf); /*MOVL $fetchdat,%edi*/ -#endif - addquad(param); -} - -static void load_param_2_32(codeblock_t *block, uint32_t param) -{ -#if WIN64 - addbyte(0xba); /*MOVL $fetchdat,%edx*/ -#else - addbyte(0xbe); /*MOVL $fetchdat,%esi*/ -#endif - addlong(param); -} -static void load_param_2_64(codeblock_t *block, uint64_t param) -{ - addbyte(0x48); -#if WIN64 - addbyte(0xba); /*MOVL $fetchdat,%edx*/ -#else - addbyte(0xbe); /*MOVL $fetchdat,%esi*/ -#endif - addquad(param); -} - -static void call(codeblock_t *block, uintptr_t func) -{ - uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5]; - - if (diff >= -0x80000000 && diff < 0x7fffffff) - { - addbyte(0xE8); /*CALL*/ - addlong((uint32_t)diff); - } - else - { - addbyte(0x48); /*MOV RAX, func*/ - addbyte(0xb8); - addquad(func); - addbyte(0xff); /*CALL RAX*/ - addbyte(0xd0); - } -} int codegen_flags_changed = 0; int codegen_fpu_entered = 0; @@ -1142,7 +1084,6 @@ generate_call: } #endif } -#if 0 if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) { uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block); @@ -1159,7 +1100,7 @@ generate_call: return; } } -#endif + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; // if (output) // pclog("Generate call at %08X %02X %08X %02X %08X %08X %08X %08X %08X %02X %02X %02X %02X\n", &codeblock[block_current][block_pos], opcode, new_pc, ram[old_pc], EAX, EBX, ECX, EDX, ESI, ram[0x7bd2+6],ram[0x7bd2+7],ram[0x7bd2+8],ram[0x7bd2+9]);