Added code generation for :
- TEST immediate - register versions of NOT and NEG - fixed shift versions of SHL, SHR and SAR - MOVZX and MOVSX - LEA - CMP with memory destination - JL, JNL, JLE, JNLE, JBE, JNBE
This commit is contained in:
parent
6d95f00c36
commit
9061c5d2fc
8 changed files with 683 additions and 36 deletions
|
|
@ -1249,7 +1249,6 @@ void exec386(int cycs)
|
|||
}
|
||||
else
|
||||
{
|
||||
int dirty = 0;
|
||||
uint32_t phys_addr = get_phys(cs+pc);
|
||||
int hash = HASH(phys_addr);
|
||||
codeblock_t *block = codeblock_hash[hash];
|
||||
|
|
@ -1297,14 +1296,12 @@ void exec386(int cycs)
|
|||
}
|
||||
}
|
||||
|
||||
if (valid_block && !dirty)
|
||||
if (valid_block)
|
||||
{
|
||||
void (*code)() = (void *)&block->data[BLOCK_START];
|
||||
|
||||
// if (output) pclog("Run block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%08x %04x %08x %08x %016llx %08x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, get_phys(cs+pc), block->phys, block->page_mask, block->endpc);
|
||||
|
||||
oldcs = CS;
|
||||
oldcpl = CPL;
|
||||
inrecomp=1;
|
||||
code();
|
||||
inrecomp=0;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "codegen_ops_jump.h"
|
||||
#include "codegen_ops_logic.h"
|
||||
#include "codegen_ops_mov.h"
|
||||
#include "codegen_ops_shift.h"
|
||||
#include "codegen_ops_stack.h"
|
||||
#include "codegen_ops_xchg.h"
|
||||
|
||||
|
|
@ -31,17 +32,17 @@ RecompOpFn recomp_opcodes[512] =
|
|||
/*40*/ ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw,
|
||||
/*50*/ ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16,
|
||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_b16,NULL, NULL, NULL, NULL, NULL,
|
||||
/*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, NULL, NULL, ropJS, ropJNS, ropJP, ropJNP, NULL, NULL, NULL, NULL,
|
||||
/*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE,
|
||||
|
||||
/*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_b, ropXCHG_w, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, NULL, NULL, NULL, NULL,
|
||||
/*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_b, ropXCHG_w, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, NULL, ropLEA_w, NULL, NULL,
|
||||
/*90*/ NULL, ropXCHG_AX_CX, ropXCHG_AX_DX, ropXCHG_AX_BX, ropXCHG_AX_SP, ropXCHG_AX_BP, ropXCHG_AX_SI, ropXCHG_AX_DI, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*a0*/ ropMOV_AL_a, ropMOV_AX_a, ropMOV_a_AL, ropMOV_a_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm,
|
||||
|
||||
/*c0*/ NULL, NULL, ropRET_imm_16, ropRET_16, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, ropLEAVE_16, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, ropLEAVE_16, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*d0*/ ropD0, ropD1_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
||||
/*32-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
|
|
@ -53,17 +54,17 @@ RecompOpFn recomp_opcodes[512] =
|
|||
/*40*/ ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl,
|
||||
/*50*/ ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32,
|
||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_b32,NULL, NULL, NULL, NULL, NULL,
|
||||
/*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, NULL, NULL, ropJS, ropJNS, ropJP, ropJNP, NULL, NULL, NULL, NULL,
|
||||
/*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE,
|
||||
|
||||
/*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_b, ropXCHG_l, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, NULL, NULL, NULL, NULL,
|
||||
/*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_b, ropXCHG_l, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, NULL, ropLEA_l, NULL, NULL,
|
||||
/*90*/ NULL, ropXCHG_EAX_ECX,ropXCHG_EAX_EDX,ropXCHG_EAX_EBX,ropXCHG_EAX_ESP,ropXCHG_EAX_EBP,ropXCHG_EAX_ESI,ropXCHG_EAX_EDI,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*a0*/ ropMOV_AL_a, ropMOV_EAX_a, ropMOV_a_AL, ropMOV_a_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm,
|
||||
|
||||
/*c0*/ NULL, NULL, ropRET_imm_32, ropRET_32, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, ropLEAVE_32, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, ropLEAVE_32, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*d0*/ ropD0, ropD1_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
};
|
||||
|
||||
RecompOpFn recomp_opcodes_0f[512] =
|
||||
|
|
@ -80,10 +81,10 @@ RecompOpFn recomp_opcodes_0f[512] =
|
|||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
||||
/*80*/ ropJO_w, ropJNO_w, ropJB_w, ropJNB_w, ropJE_w, ropJNE_w, NULL, NULL, ropJS_w, ropJNS_w, ropJP_w, ropJNP_w, NULL, NULL, NULL, NULL,
|
||||
/*80*/ ropJO_w, ropJNO_w, ropJB_w, ropJNB_w, ropJE_w, ropJNE_w, ropJBE_w, ropJNBE_w, ropJS_w, ropJNS_w, ropJP_w, ropJNP_w, ropJL_w, ropJNL_w, ropJLE_w, ropJNLE_w,
|
||||
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_w_b, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_w_b, NULL,
|
||||
|
||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
|
@ -102,10 +103,10 @@ RecompOpFn recomp_opcodes_0f[512] =
|
|||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
||||
/*80*/ ropJO_l, ropJNO_l, ropJB_l, ropJNB_l, ropJE_l, ropJNE_l, NULL, NULL, ropJS_l, ropJNS_l, ropJP_l, ropJNP_l, NULL, NULL, NULL, NULL,
|
||||
/*80*/ ropJO_l, ropJNO_l, ropJB_l, ropJNB_l, ropJE_l, ropJNE_l, ropJBE_l, ropJNBE_l, ropJS_l, ropJNS_l, ropJP_l, ropJNP_l, ropJL_l, ropJNL_l, ropJLE_l, ropJNLE_l,
|
||||
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_l_b, ropMOVZX_l_w, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_l_b, ropMOVSX_l_w,
|
||||
|
||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin
|
|||
return op_pc;
|
||||
}
|
||||
|
||||
#define ROP_ARITH(name, op, writeback) \
|
||||
#define ROP_ARITH_RMW(name, op, writeback) \
|
||||
static uint32_t rop ## name ## _b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
|
|
@ -140,7 +140,9 @@ static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin
|
|||
\
|
||||
codegen_flags_changed = 1; \
|
||||
return op_pc + 1; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ROP_ARITH_RM(name, op, writeback) \
|
||||
static uint32_t rop ## name ## _b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
|
|
@ -229,9 +231,97 @@ static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin
|
|||
return op_pc + 1; \
|
||||
}
|
||||
|
||||
ROP_ARITH(ADD, ADD, 1)
|
||||
ROP_ARITH(SUB, SUB, 1)
|
||||
ROP_ARITH(CMP, SUB, 0)
|
||||
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_rmw(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)
|
||||
{
|
||||
dst_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);
|
||||
dst_reg = 0;
|
||||
}
|
||||
|
||||
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);
|
||||
RELEASE_REG(dst_reg);
|
||||
RELEASE_REG(src_reg);
|
||||
|
||||
codegen_flags_changed = 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropCMP_w_rmw(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)
|
||||
{
|
||||
dst_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);
|
||||
dst_reg = 0;
|
||||
} \
|
||||
|
||||
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);
|
||||
RELEASE_REG(dst_reg);
|
||||
RELEASE_REG(src_reg);
|
||||
|
||||
codegen_flags_changed = 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropCMP_l_rmw(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)
|
||||
{
|
||||
dst_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);
|
||||
dst_reg = 0;
|
||||
}
|
||||
|
||||
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);
|
||||
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 ropADD_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -252,13 +252,19 @@ static uint32_t rop ## name ## _l(uint8_t opcode, \
|
|||
return op_pc+4; \
|
||||
}
|
||||
|
||||
ropBRANCH(JB, BRANCH_COND_B, 0)
|
||||
ropBRANCH(JNB, BRANCH_COND_B, 1)
|
||||
ropBRANCH(JE, BRANCH_COND_E, 0)
|
||||
ropBRANCH(JNE, BRANCH_COND_E, 1)
|
||||
ropBRANCH(JO, BRANCH_COND_O, 0)
|
||||
ropBRANCH(JNO, BRANCH_COND_O, 1)
|
||||
ropBRANCH(JP, BRANCH_COND_P, 0)
|
||||
ropBRANCH(JNP, BRANCH_COND_P, 1)
|
||||
ropBRANCH(JS, BRANCH_COND_S, 0)
|
||||
ropBRANCH(JNS, BRANCH_COND_S, 1)
|
||||
ropBRANCH(JB, BRANCH_COND_B, 0)
|
||||
ropBRANCH(JNB, BRANCH_COND_B, 1)
|
||||
ropBRANCH(JE, BRANCH_COND_E, 0)
|
||||
ropBRANCH(JNE, BRANCH_COND_E, 1)
|
||||
ropBRANCH(JO, BRANCH_COND_O, 0)
|
||||
ropBRANCH(JNO, BRANCH_COND_O, 1)
|
||||
ropBRANCH(JP, BRANCH_COND_P, 0)
|
||||
ropBRANCH(JNP, BRANCH_COND_P, 1)
|
||||
ropBRANCH(JS, BRANCH_COND_S, 0)
|
||||
ropBRANCH(JNS, BRANCH_COND_S, 1)
|
||||
ropBRANCH(JL, BRANCH_COND_L, 0)
|
||||
ropBRANCH(JNL, BRANCH_COND_L, 1)
|
||||
ropBRANCH(JLE, BRANCH_COND_LE, 0)
|
||||
ropBRANCH(JNLE, BRANCH_COND_LE, 1)
|
||||
ropBRANCH(JBE, BRANCH_COND_BE, 0)
|
||||
ropBRANCH(JNBE, BRANCH_COND_BE, 1)
|
||||
|
|
|
|||
|
|
@ -277,3 +277,159 @@ static uint32_t ropXOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32
|
|||
return op_pc + 4;
|
||||
}
|
||||
|
||||
static uint32_t ropF6(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
int host_reg, imm_reg;
|
||||
uint8_t imm;
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x00: /*TEST b,#8*/
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
host_reg = LOAD_REG_B(fetchdat & 7);
|
||||
imm = (fetchdat >> 8) & 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
imm = fastreadb(cs + op_pc + 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||
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);
|
||||
RELEASE_REG(host_reg);
|
||||
return op_pc + 2;
|
||||
|
||||
case 0x10: /*NOT b*/
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
host_reg = LOAD_REG_B(fetchdat & 7);
|
||||
XOR_HOST_REG_IMM(host_reg, 0xff);
|
||||
STORE_REG_B_RELEASE(host_reg);
|
||||
return op_pc + 1;
|
||||
|
||||
case 0x18: /*NEG b*/
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
imm_reg = LOAD_REG_IMM(0);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB8);
|
||||
host_reg = LOAD_REG_B(fetchdat & 7);
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, imm_reg);
|
||||
SUB_HOST_REG_B(imm_reg, host_reg);
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op2, host_reg);
|
||||
STORE_REG_TARGET_B_RELEASE(imm_reg, fetchdat & 7);
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, imm_reg);
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static uint32_t ropF7_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
int host_reg, imm_reg;
|
||||
uint16_t imm;
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x00: /*TEST w,#*/
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
||||
imm = (fetchdat >> 8) & 0xffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
imm = fastreadw(cs + op_pc + 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||
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);
|
||||
RELEASE_REG(host_reg);
|
||||
return op_pc + 3;
|
||||
|
||||
case 0x10: /*NOT w*/
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
||||
XOR_HOST_REG_IMM(host_reg, 0xffff);
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
return op_pc + 1;
|
||||
|
||||
case 0x18: /*NEG w*/
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
imm_reg = LOAD_REG_IMM(0);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB16);
|
||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, imm_reg);
|
||||
SUB_HOST_REG_W(imm_reg, host_reg);
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op2, host_reg);
|
||||
STORE_REG_TARGET_W_RELEASE(imm_reg, fetchdat & 7);
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, imm_reg);
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static uint32_t ropF7_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
int host_reg, imm_reg;
|
||||
uint32_t imm;
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x00: /*TEST l,#*/
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
host_reg = LOAD_REG_L(fetchdat & 7);
|
||||
imm = fastreadl(cs + op_pc + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
imm = fastreadl(cs + op_pc + 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||
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);
|
||||
RELEASE_REG(host_reg);
|
||||
return op_pc + 5;
|
||||
|
||||
case 0x10: /*NOT l*/
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
host_reg = LOAD_REG_L(fetchdat & 7);
|
||||
XOR_HOST_REG_IMM(host_reg, 0xffffffff);
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
return op_pc + 1;
|
||||
|
||||
case 0x18: /*NEG l*/
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
imm_reg = LOAD_REG_IMM(0);
|
||||
STORE_IMM_ADDR_L((uint32_t)&flags_op, FLAGS_SUB32);
|
||||
host_reg = LOAD_REG_L(fetchdat & 7);
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, imm_reg);
|
||||
SUB_HOST_REG_L(imm_reg, host_reg);
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op2, host_reg);
|
||||
STORE_REG_TARGET_L_RELEASE(imm_reg, fetchdat & 7);
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_res, imm_reg);
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -337,3 +337,170 @@ static uint32_t ropMOV_a_EAX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32,
|
|||
|
||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||
}
|
||||
|
||||
static uint32_t ropLEA_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
return 0;
|
||||
|
||||
FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
STORE_REG_TARGET_W_RELEASE(0, dest_reg);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropLEA_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
return 0;
|
||||
|
||||
FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
STORE_REG_TARGET_L_RELEASE(0, dest_reg);
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t ropMOVZX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int host_reg = LOAD_REG_B(fetchdat & 7);
|
||||
ZERO_EXTEND_W_B(host_reg);
|
||||
STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 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);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
|
||||
MEM_LOAD_ADDR_EA_B(target_seg);
|
||||
ZERO_EXTEND_W_B(0);
|
||||
STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropMOVZX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int host_reg = LOAD_REG_B(fetchdat & 7);
|
||||
ZERO_EXTEND_L_B(host_reg);
|
||||
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 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);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
|
||||
MEM_LOAD_ADDR_EA_B(target_seg);
|
||||
ZERO_EXTEND_L_B(0);
|
||||
STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropMOVZX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int host_reg = LOAD_REG_W(fetchdat & 7);
|
||||
ZERO_EXTEND_L_W(host_reg);
|
||||
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 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);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
|
||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
||||
ZERO_EXTEND_L_W(0);
|
||||
STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t ropMOVSX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int host_reg = LOAD_REG_B(fetchdat & 7);
|
||||
SIGN_EXTEND_W_B(host_reg);
|
||||
STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 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);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
|
||||
MEM_LOAD_ADDR_EA_B(target_seg);
|
||||
SIGN_EXTEND_W_B(0);
|
||||
STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropMOVSX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int host_reg = LOAD_REG_B(fetchdat & 7);
|
||||
SIGN_EXTEND_L_B(host_reg);
|
||||
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 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);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
|
||||
MEM_LOAD_ADDR_EA_B(target_seg);
|
||||
SIGN_EXTEND_L_B(0);
|
||||
STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropMOVSX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int host_reg = LOAD_REG_W(fetchdat & 7);
|
||||
SIGN_EXTEND_L_W(host_reg);
|
||||
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 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);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
|
||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
||||
SIGN_EXTEND_L_W(0);
|
||||
STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -394,7 +394,63 @@ static void CALL_FUNC(void *dest)
|
|||
addlong(((uint8_t *)dest - (uint8_t *)(&codeblock[block_current].data[block_pos + 4])));
|
||||
}
|
||||
|
||||
|
||||
static void SHL_B_IMM(int reg, int count)
|
||||
{
|
||||
addbyte(0xc0); /*SHL reg, count*/
|
||||
addbyte(0xc0 | reg | 0x20);
|
||||
addbyte(count);
|
||||
}
|
||||
static void SHL_W_IMM(int reg, int count)
|
||||
{
|
||||
addbyte(0x66); /*SHL reg, count*/
|
||||
addbyte(0xc1);
|
||||
addbyte(0xc0 | reg | 0x20);
|
||||
addbyte(count);
|
||||
}
|
||||
static void SHL_L_IMM(int reg, int count)
|
||||
{
|
||||
addbyte(0xc1); /*SHL reg, count*/
|
||||
addbyte(0xc0 | reg | 0x20);
|
||||
addbyte(count);
|
||||
}
|
||||
static void SHR_B_IMM(int reg, int count)
|
||||
{
|
||||
addbyte(0xc0); /*SHR reg, count*/
|
||||
addbyte(0xc0 | reg | 0x28);
|
||||
addbyte(count);
|
||||
}
|
||||
static void SHR_W_IMM(int reg, int count)
|
||||
{
|
||||
addbyte(0x66); /*SHR reg, count*/
|
||||
addbyte(0xc1);
|
||||
addbyte(0xc0 | reg | 0x28);
|
||||
addbyte(count);
|
||||
}
|
||||
static void SHR_L_IMM(int reg, int count)
|
||||
{
|
||||
addbyte(0xc1); /*SHR reg, count*/
|
||||
addbyte(0xc0 | reg | 0x28);
|
||||
addbyte(count);
|
||||
}
|
||||
static void SAR_B_IMM(int reg, int count)
|
||||
{
|
||||
addbyte(0xc0); /*SAR reg, count*/
|
||||
addbyte(0xc0 | reg | 0x38);
|
||||
addbyte(count);
|
||||
}
|
||||
static void SAR_W_IMM(int reg, int count)
|
||||
{
|
||||
addbyte(0x66); /*SAR reg, count*/
|
||||
addbyte(0xc1);
|
||||
addbyte(0xc0 | reg | 0x38);
|
||||
addbyte(count);
|
||||
}
|
||||
static void SAR_L_IMM(int reg, int count)
|
||||
{
|
||||
addbyte(0xc1); /*SAR reg, count*/
|
||||
addbyte(0xc0 | reg | 0x38);
|
||||
addbyte(count);
|
||||
}
|
||||
|
||||
|
||||
static void CHECK_SEG_READ(x86seg *seg)
|
||||
|
|
@ -1215,6 +1271,142 @@ static void TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles)
|
|||
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(0x05 | 0x38);
|
||||
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(5+2+2+10+5+(timing_bt ? 7 : 0));
|
||||
else
|
||||
addbyte(5+2+2);
|
||||
CALL_FUNC(CF_SET);
|
||||
addbyte(0x85); /*TEST EAX,EAX*/
|
||||
addbyte(0xc0);
|
||||
if (not)
|
||||
addbyte(0x75); /*JNZ +*/
|
||||
else
|
||||
addbyte(0x74); /*JZ +*/
|
||||
addbyte(10+5+(timing_bt ? 7 : 0));
|
||||
addbyte(0xC7); /*MOVL [pc], new_pc*/
|
||||
addbyte(0x05);
|
||||
addlong((uintptr_t)&pc);
|
||||
addlong(op_pc+pc_offset+offset);
|
||||
if (timing_bt)
|
||||
{
|
||||
addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/
|
||||
addbyte(0x2d);
|
||||
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(10+5+(timing_bt ? 7 : 0));
|
||||
addbyte(0xC7); /*MOVL [pc], new_pc*/
|
||||
addbyte(0x05);
|
||||
addlong((uintptr_t)&pc);
|
||||
addlong(op_pc+pc_offset+offset);
|
||||
if (timing_bt)
|
||||
{
|
||||
addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/
|
||||
addbyte(0x2d);
|
||||
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(0x05 | 0x38);
|
||||
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(5+2+3+5+2+3+2+2+10+5+(timing_bt ? 7 : 0));
|
||||
else
|
||||
addbyte(5+2+3+5+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(10+5+(timing_bt ? 7 : 0));
|
||||
addbyte(0xC7); /*MOVL [pc], new_pc*/
|
||||
addbyte(0x05);
|
||||
addlong((uintptr_t)&pc);
|
||||
addlong(op_pc+pc_offset+offset);
|
||||
if (timing_bt)
|
||||
{
|
||||
addbyte(0x83); /*SUB $codegen_block_cycles, cyclcs*/
|
||||
addbyte(0x2d);
|
||||
addlong((uintptr_t)&cycles);
|
||||
addbyte(timing_bt);
|
||||
}
|
||||
addbyte(0xe9); /*JMP end*/
|
||||
addlong(BLOCK_EXIT_OFFSET - (block_pos + 4));
|
||||
}
|
||||
|
||||
|
||||
static void FP_ENTER()
|
||||
{
|
||||
|
|
@ -1758,3 +1950,41 @@ static void FP_OP_REG(int op, int dst, int src)
|
|||
addbyte(0xc6);
|
||||
}
|
||||
}
|
||||
|
||||
static void ZERO_EXTEND_W_B(int reg)
|
||||
{
|
||||
addbyte(0x0f); /*MOVZX regl, regb*/
|
||||
addbyte(0xb6);
|
||||
addbyte(0xc0 | reg | (reg << 3));
|
||||
}
|
||||
static void ZERO_EXTEND_L_B(int reg)
|
||||
{
|
||||
addbyte(0x0f); /*MOVZX regl, regb*/
|
||||
addbyte(0xb6);
|
||||
addbyte(0xc0 | reg | (reg << 3));
|
||||
}
|
||||
static void ZERO_EXTEND_L_W(int reg)
|
||||
{
|
||||
addbyte(0x0f); /*MOVZX regl, regw*/
|
||||
addbyte(0xb7);
|
||||
addbyte(0xc0 | reg | (reg << 3));
|
||||
}
|
||||
|
||||
static void SIGN_EXTEND_W_B(int reg)
|
||||
{
|
||||
addbyte(0x0f); /*MOVSX regl, regb*/
|
||||
addbyte(0xbe);
|
||||
addbyte(0xc0 | reg | (reg << 3));
|
||||
}
|
||||
static void SIGN_EXTEND_L_B(int reg)
|
||||
{
|
||||
addbyte(0x0f); /*MOVSX regl, regb*/
|
||||
addbyte(0xbe);
|
||||
addbyte(0xc0 | reg | (reg << 3));
|
||||
}
|
||||
static void SIGN_EXTEND_L_W(int reg)
|
||||
{
|
||||
addbyte(0x0f); /*MOVSX regl, regw*/
|
||||
addbyte(0xbf);
|
||||
addbyte(0xc0 | reg | (reg << 3));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -238,6 +238,8 @@ void codegen_block_init(uint32_t phys_addr)
|
|||
addbyte(0x83); /*SUBL $16,%esp*/
|
||||
addbyte(0xEC);
|
||||
addbyte(0x10);
|
||||
addbyte(0xBD); /*MOVL EBP, &EAX*/
|
||||
addlong((uint32_t)&EAX);
|
||||
|
||||
// pclog("New block %i for %08X %03x\n", block_current, cs+pc, block_num);
|
||||
|
||||
|
|
@ -872,8 +874,6 @@ generate_call:
|
|||
#endif
|
||||
}
|
||||
|
||||
addbyte(0xBD); /*MOVL EBP, &EAX*/
|
||||
addlong((uint32_t)&EAX);
|
||||
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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue