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:
TomW 2015-05-30 17:08:54 +01:00
commit 9061c5d2fc
8 changed files with 683 additions and 36 deletions

View file

@ -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;

View file

@ -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,

View file

@ -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)
{

View file

@ -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)

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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));
}

View file

@ -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);