Added code generation for memory versions of MOV, and memory source versions of ADD, SUB, AND, OR, XOR and CMP.
This commit is contained in:
parent
7a7f586cd3
commit
ba715706b6
11 changed files with 997 additions and 85 deletions
|
|
@ -21,8 +21,8 @@ int cpu_reps, cpu_reps_latched;
|
|||
int cpu_notreps, cpu_notreps_latched;
|
||||
|
||||
int inrecomp = 0;
|
||||
int cpu_recomp_blocks, cpu_recomp_ins, cpu_new_blocks;
|
||||
int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_new_blocks_latched;
|
||||
int cpu_recomp_blocks, cpu_recomp_ins, cpu_recomp_full_ins, cpu_new_blocks;
|
||||
int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_recomp_full_ins_latched, cpu_new_blocks_latched;
|
||||
|
||||
int cpu_block_end = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr)
|
|||
|
||||
extern int cpu_block_end;
|
||||
|
||||
extern int cpu_recomp_blocks, cpu_recomp_ins, cpu_new_blocks;
|
||||
extern int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_new_blocks_latched;
|
||||
extern int cpu_recomp_blocks, cpu_recomp_ins, cpu_recomp_full_ins, cpu_new_blocks;
|
||||
extern int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_recomp_full_ins_latched, cpu_new_blocks_latched;
|
||||
extern int cpu_recomp_flushes, cpu_recomp_flushes_latched;
|
||||
extern int cpu_recomp_evicted, cpu_recomp_evicted_latched;
|
||||
extern int cpu_recomp_reuse, cpu_recomp_reuse_latched;
|
||||
|
|
@ -111,7 +111,7 @@ extern int block_pos;
|
|||
static inline void addbyte(uint8_t val)
|
||||
{
|
||||
codeblock[block_current].data[block_pos++] = val;
|
||||
if (block_pos >= 1850)
|
||||
if (block_pos >= 1800)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@ static inline void addword(uint16_t val)
|
|||
{
|
||||
*(uint16_t *)&codeblock[block_current].data[block_pos] = val;
|
||||
block_pos += 2;
|
||||
if (block_pos >= 1850)
|
||||
if (block_pos >= 1800)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
|
|
@ -131,7 +131,7 @@ static inline void addlong(uint32_t val)
|
|||
{
|
||||
*(uint32_t *)&codeblock[block_current].data[block_pos] = val;
|
||||
block_pos += 4;
|
||||
if (block_pos >= 1850)
|
||||
if (block_pos >= 1800)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
|
|
@ -139,4 +139,8 @@ static inline void addlong(uint32_t val)
|
|||
|
||||
/*Current physical page of block being recompiled. -1 if no recompilation taking place */
|
||||
extern uint32_t recomp_page;
|
||||
|
||||
extern x86seg *op_ea_seg;
|
||||
extern int op_ssegs;
|
||||
extern uint32_t op_old_pc;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ RecompOpFn recomp_opcodes[512] =
|
|||
|
||||
/*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,
|
||||
/*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*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, 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, NULL, NULL, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
|
@ -52,7 +52,7 @@ RecompOpFn recomp_opcodes[512] =
|
|||
|
||||
/*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,
|
||||
/*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*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,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, NULL, NULL, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
|
|
|||
|
|
@ -134,12 +134,19 @@ static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin
|
|||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
\
|
||||
if ((fetchdat & 0xc0) != 0xc0) \
|
||||
return 0; \
|
||||
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); \
|
||||
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_ ## op ## 8); \
|
||||
src_reg = LOAD_REG_B(fetchdat & 7); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); \
|
||||
op ## _HOST_REG_B(dst_reg, src_reg); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); \
|
||||
|
|
@ -154,12 +161,19 @@ static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin
|
|||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
\
|
||||
if ((fetchdat & 0xc0) != 0xc0) \
|
||||
return 0; \
|
||||
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); \
|
||||
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_ ## op ## 16); \
|
||||
src_reg = LOAD_REG_W(fetchdat & 7); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op1, dst_reg); \
|
||||
op ## _HOST_REG_W(dst_reg, src_reg); \
|
||||
STORE_HOST_REG_ADDR((uint32_t)&flags_op2, src_reg); \
|
||||
|
|
@ -174,12 +188,19 @@ static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uin
|
|||
{ \
|
||||
int src_reg, dst_reg; \
|
||||
\
|
||||
if ((fetchdat & 0xc0) != 0xc0) \
|
||||
return 0; \
|
||||
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); \
|
||||
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_ ## op ## 32); \
|
||||
src_reg = LOAD_REG_L(fetchdat & 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); \
|
||||
|
|
|
|||
|
|
@ -22,109 +22,318 @@ static uint32_t ropMOV_rl_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32,
|
|||
|
||||
static uint32_t ropMOV_b_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
int host_reg = LOAD_REG_B((fetchdat >> 3) & 7);
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
host_reg = LOAD_REG_B((fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_B_RELEASE(host_reg, fetchdat & 7);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
STORE_REG_TARGET_B_RELEASE(host_reg, 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);
|
||||
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
CHECK_SEG_LIMITS(target_seg, 0);
|
||||
|
||||
MEM_STORE_ADDR_EA_B(target_seg, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropMOV_w_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
int host_reg = LOAD_REG_W((fetchdat >> 3) & 7);
|
||||
|
||||
host_reg = LOAD_REG_W((fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
STORE_REG_TARGET_W_RELEASE(host_reg, 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);
|
||||
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
CHECK_SEG_LIMITS(target_seg, 1);
|
||||
|
||||
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t ropMOV_l_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
host_reg = LOAD_REG_L((fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7);
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
STORE_REG_TARGET_L_RELEASE(host_reg, 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);
|
||||
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
CHECK_SEG_LIMITS(target_seg, 3);
|
||||
|
||||
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t ropMOV_r_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int host_reg = LOAD_REG_B(fetchdat & 7);
|
||||
STORE_REG_TARGET_B_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
host_reg = LOAD_REG_B(fetchdat & 7);
|
||||
STORE_REG_TARGET_B_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
|
||||
MEM_LOAD_ADDR_EA_B(target_seg);
|
||||
STORE_REG_TARGET_B_RELEASE(0, (fetchdat >> 3) & 7);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropMOV_r_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int host_reg = LOAD_REG_W(fetchdat & 7);
|
||||
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);
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
||||
STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
|
||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
||||
STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropMOV_r_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
host_reg = LOAD_REG_L(fetchdat & 7);
|
||||
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int host_reg = LOAD_REG_L(fetchdat & 7);
|
||||
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_L(target_seg);
|
||||
STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t ropMOV_b_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
STORE_IMM_REG_B(fetchdat & 7, (fetchdat >> 8) & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
// return 0;
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
uint32_t imm = fastreadb(cs + op_pc + 1);
|
||||
int host_reg = LOAD_REG_IMM(imm);
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
|
||||
MEM_STORE_ADDR_EA_B(target_seg, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
}
|
||||
|
||||
STORE_IMM_REG_B(fetchdat & 7, (fetchdat >> 8) & 0xff);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t ropMOV_w_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
STORE_IMM_REG_W(fetchdat & 7, (fetchdat >> 8) & 0xffff);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if ((cs+pc) <= 0xbff70000 || (cs+pc) > 0xbff80000)
|
||||
// return 0;
|
||||
// {
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
uint32_t imm = fastreadw(cs + op_pc + 1);
|
||||
int host_reg = LOAD_REG_IMM(imm);
|
||||
//pclog("MOV imm %04x(%08x):%08x %08x %04x\n", CS, cs, pc, op_pc, imm);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
// }
|
||||
}
|
||||
|
||||
STORE_IMM_REG_W(fetchdat & 7, (fetchdat >> 8) & 0xffff);
|
||||
|
||||
return op_pc + 3;
|
||||
}
|
||||
static uint32_t ropMOV_l_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t imm = fastreadl(cs + op_pc + 1);
|
||||
int host_reg;
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
uint32_t imm = fastreadl(cs + op_pc + 1);
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
STORE_IMM_REG_L(fetchdat & 7, imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
// return 0;
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
uint32_t imm = fastreadl(cs + op_pc + 1);
|
||||
int host_reg = LOAD_REG_IMM(imm);
|
||||
|
||||
STORE_IMM_REG_L(fetchdat & 7, imm);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
|
||||
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
}
|
||||
|
||||
return op_pc + 5;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t ropMOV_AL_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t addr;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
addr = fastreadl(cs + op_pc);
|
||||
else
|
||||
addr = fastreadw(cs + op_pc);
|
||||
|
||||
CHECK_SEG_READ(op_ea_seg);
|
||||
|
||||
MEM_LOAD_ADDR_IMM_B(op_ea_seg, addr);
|
||||
STORE_REG_TARGET_B_RELEASE(0, REG_AL);
|
||||
|
||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||
}
|
||||
static uint32_t ropMOV_AX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t addr;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
addr = fastreadl(cs + op_pc);
|
||||
else
|
||||
addr = fastreadw(cs + op_pc);
|
||||
|
||||
CHECK_SEG_READ(op_ea_seg);
|
||||
|
||||
MEM_LOAD_ADDR_IMM_W(op_ea_seg, addr);
|
||||
STORE_REG_TARGET_W_RELEASE(0, REG_AX);
|
||||
|
||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||
}
|
||||
static uint32_t ropMOV_EAX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t addr;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
addr = fastreadl(cs + op_pc);
|
||||
else
|
||||
addr = fastreadw(cs + op_pc);
|
||||
|
||||
CHECK_SEG_READ(op_ea_seg);
|
||||
|
||||
MEM_LOAD_ADDR_IMM_L(op_ea_seg, addr);
|
||||
STORE_REG_TARGET_L_RELEASE(0, REG_EAX);
|
||||
|
||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||
}
|
||||
|
||||
static uint32_t ropMOV_a_AL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t addr;
|
||||
int host_reg;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
addr = fastreadl(cs + op_pc);
|
||||
else
|
||||
addr = fastreadw(cs + op_pc);
|
||||
|
||||
CHECK_SEG_WRITE(op_ea_seg);
|
||||
|
||||
host_reg = LOAD_REG_B(REG_AL);
|
||||
|
||||
MEM_STORE_ADDR_IMM_B(op_ea_seg, addr, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||
}
|
||||
static uint32_t ropMOV_a_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t addr;
|
||||
int host_reg;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
addr = fastreadl(cs + op_pc);
|
||||
else
|
||||
addr = fastreadw(cs + op_pc);
|
||||
|
||||
CHECK_SEG_WRITE(op_ea_seg);
|
||||
|
||||
host_reg = LOAD_REG_W(REG_AX);
|
||||
|
||||
MEM_STORE_ADDR_IMM_W(op_ea_seg, addr, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||
}
|
||||
static uint32_t ropMOV_a_EAX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t addr;
|
||||
int host_reg;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
addr = fastreadl(cs + op_pc);
|
||||
else
|
||||
addr = fastreadw(cs + op_pc);
|
||||
|
||||
CHECK_SEG_WRITE(op_ea_seg);
|
||||
|
||||
host_reg = LOAD_REG_L(REG_EAX);
|
||||
|
||||
MEM_STORE_ADDR_IMM_L(op_ea_seg, addr, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
/*Register allocation :
|
||||
EBX, ECX, EDX - emulated registers
|
||||
EAX - work register, EA storage
|
||||
ESI, EDI - work registers
|
||||
*/
|
||||
#define HOST_REG_START 1
|
||||
#define HOST_REG_END 4
|
||||
static inline int find_host_reg()
|
||||
{
|
||||
int c;
|
||||
for (c = 0; c < NR_HOST_REGS; c++)
|
||||
for (c = HOST_REG_START; c < HOST_REG_END; c++)
|
||||
{
|
||||
if (host_reg_mapping[c] == -1)
|
||||
break;
|
||||
|
|
@ -100,6 +107,18 @@ static int LOAD_REG_L(int reg)
|
|||
return host_reg;
|
||||
}
|
||||
|
||||
static int LOAD_REG_IMM(uint32_t imm)
|
||||
{
|
||||
int host_reg = find_host_reg();
|
||||
host_reg_mapping[host_reg] = reg;
|
||||
|
||||
addbyte(0xc7); /*MOVL host_reg, imm*/
|
||||
addbyte(0xc0 | host_reg);
|
||||
addlong(imm);
|
||||
|
||||
return host_reg;
|
||||
}
|
||||
|
||||
static void STORE_REG_B_RELEASE(int host_reg)
|
||||
{
|
||||
addbyte(0x88); /*MOVB [reg],host_reg*/
|
||||
|
|
@ -284,3 +303,615 @@ static void CALL_FUNC(void *dest)
|
|||
addbyte(0xE8); /*CALL*/
|
||||
addlong(((uint8_t *)dest - (uint8_t *)(&codeblock[block_current].data[block_pos + 4])));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void CHECK_SEG_READ(x86seg *seg)
|
||||
{
|
||||
addbyte(0x83); /*CMP seg->base, -1*/
|
||||
addbyte(0x05|0x38);
|
||||
addlong((uint32_t)&seg->base);
|
||||
addbyte(-1);
|
||||
addbyte(0x0f);
|
||||
addbyte(0x84); /*JE end*/
|
||||
addlong(BLOCK_EXIT_OFFSET - (block_pos + 4));
|
||||
}
|
||||
static void CHECK_SEG_WRITE(x86seg *seg)
|
||||
{
|
||||
addbyte(0x83); /*CMP seg->base, -1*/
|
||||
addbyte(0x05|0x38);
|
||||
addlong((uint32_t)&seg->base);
|
||||
addbyte(-1);
|
||||
addbyte(0x0f);
|
||||
addbyte(0x84); /*JE end*/
|
||||
addlong(BLOCK_EXIT_OFFSET - (block_pos + 4));
|
||||
}
|
||||
static void CHECK_SEG_LIMITS(x86seg *seg, int end_offset)
|
||||
{
|
||||
addbyte(0x3b); /*CMP EAX, seg->limit_low*/
|
||||
addbyte(0x05);
|
||||
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(0x05);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void MEM_LOAD_ADDR_EA_B(x86seg *seg)
|
||||
{
|
||||
addbyte(0x8b); /*MOVL EDX, seg->base*/
|
||||
addbyte(0x05 | (REG_EDX << 3));
|
||||
addlong((uint32_t)&seg->base);
|
||||
addbyte(0x89); /*MOV ESI, EDX*/
|
||||
addbyte(0xd6);
|
||||
addbyte(0x01); /*ADDL EDX, EAX*/
|
||||
addbyte(0xc2);
|
||||
addbyte(0x89); /*MOV EDI, EDX*/
|
||||
addbyte(0xd7);
|
||||
addbyte(0xc1); /*SHR EDX, 12*/
|
||||
addbyte(0xea);
|
||||
addbyte(12);
|
||||
addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/
|
||||
addbyte(0x14);
|
||||
addbyte(0x95);
|
||||
addlong((uint32_t)readlookup2);
|
||||
addbyte(0x83); /*CMP EDX, -1*/
|
||||
addbyte(0xfa);
|
||||
addbyte(-1);
|
||||
addbyte(0x74); /*JE slowpath*/
|
||||
addbyte(3+2);
|
||||
addbyte(0x8a); /*MOV AL, [EDX+EDI]*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x3a);
|
||||
addbyte(0xeb); /*JMP done*/
|
||||
addbyte(4+3+5+7+6);
|
||||
addbyte(0x89); /*slowpath: MOV [ESP+4], EAX*/
|
||||
addbyte(0x44);
|
||||
addbyte(0x24);
|
||||
addbyte(0x04);
|
||||
addbyte(0x89); /*MOV [ESP], ESI*/
|
||||
addbyte(0x34);
|
||||
addbyte(0x24);
|
||||
addbyte(0xe8); /*CALL readmemb386l*/
|
||||
addlong((uint32_t)readmemb386l - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
|
||||
addbyte(0x83); /*CMP abrt, 0*/
|
||||
addbyte(0x3d);
|
||||
addlong((uint32_t)&abrt);
|
||||
addbyte(0);
|
||||
addbyte(0x0f); /*JNE end*/
|
||||
addbyte(0x85);
|
||||
addlong(BLOCK_EXIT_OFFSET - (block_pos + 4));
|
||||
/*done:*/
|
||||
addbyte(0x0f); /*MOVZX EAX, AL*/
|
||||
addbyte(0xb6);
|
||||
addbyte(0xc0);
|
||||
host_reg_mapping[0] = 8;
|
||||
}
|
||||
static void MEM_LOAD_ADDR_EA_W(x86seg *seg)
|
||||
{
|
||||
addbyte(0x8b); /*MOVL EDX, seg->base*/
|
||||
addbyte(0x05 | (REG_EDX << 3));
|
||||
addlong((uint32_t)&seg->base);
|
||||
addbyte(0x89); /*MOV ESI, EDX*/
|
||||
addbyte(0xd6);
|
||||
addbyte(0x01); /*ADDL EDX, EAX*/
|
||||
addbyte(0xc2);
|
||||
addbyte(0x89); /*MOV EDI, EDX*/
|
||||
addbyte(0xd7);
|
||||
addbyte(0x83); /*XOR EDI, -1*/
|
||||
addbyte(0xf7);
|
||||
addbyte(-1);
|
||||
addbyte(0xc1); /*SHR EDX, 12*/
|
||||
addbyte(0xea);
|
||||
addbyte(12);
|
||||
addbyte(0xf7); /*TEST EDI, 0xfff*/
|
||||
addbyte(0xc7);
|
||||
addlong(0xfff);
|
||||
addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/
|
||||
addbyte(0x14);
|
||||
addbyte(0x95);
|
||||
addlong((uint32_t)readlookup2);
|
||||
addbyte(0x74); /*JE slowpath*/
|
||||
addbyte(3+3+2+4+2);
|
||||
addbyte(0x83); /*XOR EDI, -1*/
|
||||
addbyte(0xf7);
|
||||
addbyte(-1);
|
||||
addbyte(0x83); /*CMP EDX, -1*/
|
||||
addbyte(0xfa);
|
||||
addbyte(-1);
|
||||
addbyte(0x74); /*JE slowpath*/
|
||||
addbyte(4+2);
|
||||
addbyte(0x66); /*MOV AX, [EDX+EDI]*/
|
||||
addbyte(0x8b);
|
||||
addbyte(0x04);
|
||||
addbyte(0x3a);
|
||||
addbyte(0xeb); /*JMP done*/
|
||||
addbyte(4+3+5+7+6);
|
||||
addbyte(0x89); /*slowpath: MOV [ESP+4], EAX*/
|
||||
addbyte(0x44);
|
||||
addbyte(0x24);
|
||||
addbyte(0x04);
|
||||
addbyte(0x89); /*MOV [ESP], ESI*/
|
||||
addbyte(0x34);
|
||||
addbyte(0x24);
|
||||
addbyte(0xe8); /*CALL readmemwl*/
|
||||
addlong((uint32_t)readmemwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
|
||||
addbyte(0x83); /*CMP abrt, 0*/
|
||||
addbyte(0x3d);
|
||||
addlong((uint32_t)&abrt);
|
||||
addbyte(0);
|
||||
addbyte(0x0f);
|
||||
addbyte(0x85); /*JNE end*/
|
||||
addlong(BLOCK_EXIT_OFFSET - (block_pos + 4));
|
||||
/*done:*/
|
||||
addbyte(0x0f); /*MOVZX EAX, AX*/
|
||||
addbyte(0xb7);
|
||||
addbyte(0xc0);
|
||||
host_reg_mapping[0] = 8;
|
||||
}
|
||||
static void MEM_LOAD_ADDR_EA_L(x86seg *seg)
|
||||
{
|
||||
addbyte(0x8b); /*MOVL EDX, seg->base*/
|
||||
addbyte(0x05 | (REG_EDX << 3));
|
||||
addlong((uint32_t)&seg->base);
|
||||
addbyte(0x89); /*MOV ESI, EDX*/
|
||||
addbyte(0xd6);
|
||||
addbyte(0x01); /*ADDL EDX, EAX*/
|
||||
addbyte(0xc2);
|
||||
addbyte(0x89); /*MOV EDI, EDX*/
|
||||
addbyte(0xd7);
|
||||
addbyte(0x83); /*XOR EDI, -1*/
|
||||
addbyte(0xf7);
|
||||
addbyte(-1);
|
||||
addbyte(0xc1); /*SHR EDX, 12*/
|
||||
addbyte(0xea);
|
||||
addbyte(12);
|
||||
addbyte(0xf7); /*TEST EDI, 0xffc*/
|
||||
addbyte(0xc7);
|
||||
addlong(0xffc);
|
||||
addbyte(0x8b); /*MOV EDX, readlookup2[EDX*4]*/
|
||||
addbyte(0x14);
|
||||
addbyte(0x95);
|
||||
addlong((uint32_t)readlookup2);
|
||||
addbyte(0x74); /*JE slowpath*/
|
||||
addbyte(3+3+2+3+2);
|
||||
addbyte(0x83); /*XOR EDI, -1*/
|
||||
addbyte(0xf7);
|
||||
addbyte(-1);
|
||||
addbyte(0x83); /*CMP EDX, -1*/
|
||||
addbyte(0xfa);
|
||||
addbyte(-1);
|
||||
addbyte(0x74); /*JE slowpath*/
|
||||
addbyte(3+2);
|
||||
addbyte(0x8b); /*MOV EAX, [EDX+EDI]*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x3a);
|
||||
addbyte(0xeb); /*JMP done*/
|
||||
addbyte(4+3+5+7+6);
|
||||
addbyte(0x89); /*slowpath: MOV [ESP+4], EAX*/
|
||||
addbyte(0x44);
|
||||
addbyte(0x24);
|
||||
addbyte(0x04);
|
||||
addbyte(0x89); /*MOV [ESP], ESI*/
|
||||
addbyte(0x34);
|
||||
addbyte(0x24);
|
||||
addbyte(0xe8); /*CALL readmemll*/
|
||||
addlong((uint32_t)readmemll - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
|
||||
addbyte(0x83); /*CMP abrt, 0*/
|
||||
addbyte(0x3d);
|
||||
addlong((uint32_t)&abrt);
|
||||
addbyte(0);
|
||||
addbyte(0x0f);
|
||||
addbyte(0x85); /*JNE end*/
|
||||
addlong(BLOCK_EXIT_OFFSET - (block_pos + 4));
|
||||
/*done:*/
|
||||
host_reg_mapping[0] = 8;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
addbyte(0x8b); /*MOVL ESI, seg->base*/
|
||||
addbyte(0x05 | (REG_ESI << 3));
|
||||
addlong((uint32_t)&seg->base);
|
||||
addbyte(0x01); /*ADDL ESI, EAX*/
|
||||
addbyte(0xc0 | (REG_EAX << 3) | REG_ESI);
|
||||
addbyte(0x89); /*MOV EDI, ESI*/
|
||||
addbyte(0xc0 | (REG_ESI << 3) | REG_EDI);
|
||||
addbyte(0xc1); /*SHR ESI, 12*/
|
||||
addbyte(0xe8 | REG_ESI);
|
||||
addbyte(12);
|
||||
addbyte(0xf7); /*TEST EDI, 0xfff*/
|
||||
addbyte(0xc7);
|
||||
addlong(0xfff);
|
||||
addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/
|
||||
addbyte(0x04 | (REG_ESI << 3));
|
||||
addbyte(0x85 | (REG_ESI << 3));
|
||||
addlong((uint32_t)writelookup2);
|
||||
addbyte(0x83); /*CMP ESI, -1*/
|
||||
addbyte(0xf8 | REG_ESI);
|
||||
addbyte(-1);
|
||||
addbyte(0x74); /*JE slowpath*/
|
||||
addbyte(3+2);
|
||||
addbyte(0x88); /*MOV [EDI+ESI],host_reg*/
|
||||
addbyte(0x04 | (host_reg << 3));
|
||||
addbyte(REG_EDI | (REG_ESI << 3));
|
||||
addbyte(0xeb); /*JMP done*/
|
||||
addbyte(4+5+4+3+5+7+6);
|
||||
addbyte(0x89); /*slowpath: MOV [ESP+4], EAX*/
|
||||
addbyte(0x44);
|
||||
addbyte(0x24);
|
||||
addbyte(0x04);
|
||||
addbyte(0xa1); /*MOV EAX, seg->base*/
|
||||
addlong((uint32_t)&seg->base);
|
||||
addbyte(0x89); /*MOV [ESP+8], host_reg*/
|
||||
addbyte(0x44 | (host_reg << 3));
|
||||
addbyte(0x24);
|
||||
addbyte(0x08);
|
||||
addbyte(0x89); /*MOV [ESP], EAX*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x24);
|
||||
addbyte(0xe8); /*CALL writememb386l*/
|
||||
addlong((uint32_t)writememb386l - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
|
||||
addbyte(0x83); /*CMP abrt, 0*/
|
||||
addbyte(0x3d);
|
||||
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 ESI, seg->base*/
|
||||
addbyte(0x05 | (REG_ESI << 3));
|
||||
addlong((uint32_t)&seg->base);
|
||||
addbyte(0x01); /*ADDL ESI, EAX*/
|
||||
addbyte(0xc0 | (REG_EAX << 3) | REG_ESI);
|
||||
addbyte(0x89); /*MOV EDI, ESI*/
|
||||
addbyte(0xc0 | (REG_ESI << 3) | REG_EDI);
|
||||
addbyte(0x83); /*XOR EDI, -1*/
|
||||
addbyte(0xf7);
|
||||
addbyte(-1);
|
||||
addbyte(0xc1); /*SHR ESI, 12*/
|
||||
addbyte(0xe8 | REG_ESI);
|
||||
addbyte(12);
|
||||
addbyte(0xf7); /*TEST EDI, 0xfff*/
|
||||
addbyte(0xc7);
|
||||
addlong(0xfff);
|
||||
addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/
|
||||
addbyte(0x04 | (REG_ESI << 3));
|
||||
addbyte(0x85 | (REG_ESI << 3));
|
||||
addlong((uint32_t)writelookup2);
|
||||
addbyte(0x74); /*JE slowpath*/
|
||||
addbyte(3+3+2+4+2);
|
||||
addbyte(0x83); /*XOR EDI, -1*/
|
||||
addbyte(0xf7);
|
||||
addbyte(-1);
|
||||
addbyte(0x83); /*CMP ESI, -1*/
|
||||
addbyte(0xf8 | REG_ESI);
|
||||
addbyte(-1);
|
||||
addbyte(0x74); /*JE slowpath*/
|
||||
addbyte(4+2);
|
||||
addbyte(0x66); /*MOV [EDI+ESI],host_reg*/
|
||||
addbyte(0x89);
|
||||
addbyte(0x04 | (host_reg << 3));
|
||||
addbyte(REG_EDI | (REG_ESI << 3));
|
||||
addbyte(0xeb); /*JMP done*/
|
||||
addbyte(4+5+4+3+5+7+6);
|
||||
addbyte(0x89); /*slowpath: MOV [ESP+4], EAX*/
|
||||
addbyte(0x44);
|
||||
addbyte(0x24);
|
||||
addbyte(0x04);
|
||||
addbyte(0xa1); /*MOV EAX, seg->base*/
|
||||
addlong((uint32_t)&seg->base);
|
||||
addbyte(0x89); /*MOV [ESP+8], host_reg*/
|
||||
addbyte(0x44 | (host_reg << 3));
|
||||
addbyte(0x24);
|
||||
addbyte(0x08);
|
||||
addbyte(0x89); /*MOV [ESP], EAX*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x24);
|
||||
addbyte(0xe8); /*CALL writememwl*/
|
||||
addlong((uint32_t)writememwl - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
|
||||
addbyte(0x83); /*CMP abrt, 0*/
|
||||
addbyte(0x3d);
|
||||
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 ESI, seg->base*/
|
||||
addbyte(0x05 | (REG_ESI << 3));
|
||||
addlong((uint32_t)&seg->base);
|
||||
addbyte(0x01); /*ADDL ESI, EAX*/
|
||||
addbyte(0xc0 | (REG_EAX << 3) | REG_ESI);
|
||||
addbyte(0x89); /*MOV EDI, ESI*/
|
||||
addbyte(0xc0 | (REG_ESI << 3) | REG_EDI);
|
||||
addbyte(0x83); /*XOR EDI, -1*/
|
||||
addbyte(0xf7);
|
||||
addbyte(-1);
|
||||
addbyte(0xc1); /*SHR ESI, 12*/
|
||||
addbyte(0xe8 | REG_ESI);
|
||||
addbyte(12);
|
||||
addbyte(0xf7); /*TEST EDI, 0xffc*/
|
||||
addbyte(0xc7);
|
||||
addlong(0xffc);
|
||||
addbyte(0x8b); /*MOV ESI, readlookup2[ESI*4]*/
|
||||
addbyte(0x04 | (REG_ESI << 3));
|
||||
addbyte(0x85 | (REG_ESI << 3));
|
||||
addlong((uint32_t)writelookup2);
|
||||
addbyte(0x74); /*JE slowpath*/
|
||||
addbyte(3+3+2+3+2);
|
||||
addbyte(0x83); /*XOR EDI, -1*/
|
||||
addbyte(0xf7);
|
||||
addbyte(-1);
|
||||
addbyte(0x83); /*CMP ESI, -1*/
|
||||
addbyte(0xf8 | REG_ESI);
|
||||
addbyte(-1);
|
||||
addbyte(0x74); /*JE slowpath*/
|
||||
addbyte(3+2);
|
||||
addbyte(0x89); /*MOV [EDI+ESI],host_reg*/
|
||||
addbyte(0x04 | (host_reg << 3));
|
||||
addbyte(REG_EDI | (REG_ESI << 3));
|
||||
addbyte(0xeb); /*JMP done*/
|
||||
addbyte(4+5+4+3+5+7+6);
|
||||
addbyte(0x89); /*slowpath: MOV [ESP+4], EAX*/
|
||||
addbyte(0x44);
|
||||
addbyte(0x24);
|
||||
addbyte(0x04);
|
||||
addbyte(0xa1); /*MOV EAX, seg->base*/
|
||||
addlong((uint32_t)&seg->base);
|
||||
addbyte(0x89); /*MOV [ESP+8], host_reg*/
|
||||
addbyte(0x44 | (host_reg << 3));
|
||||
addbyte(0x24);
|
||||
addbyte(0x08);
|
||||
addbyte(0x89); /*MOV [ESP], EAX*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x24);
|
||||
addbyte(0xe8); /*CALL writememll*/
|
||||
addlong((uint32_t)writememll - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
|
||||
addbyte(0x83); /*CMP abrt, 0*/
|
||||
addbyte(0x3d);
|
||||
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_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 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 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, imm16*/
|
||||
addlong((fetchdat >> 8) & 0xffff);
|
||||
(*op_pc) += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (mod)
|
||||
{
|
||||
case 0:
|
||||
addbyte(0xa1); /*MOVL EAX, *mod1add[0][rm]*/
|
||||
addlong((uint32_t)mod1add[0][rm]);
|
||||
addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t)mod1add[1][rm]);
|
||||
break;
|
||||
case 1:
|
||||
addbyte(0xb8); /*MOVL EAX, imm8*/
|
||||
addlong((uint32_t)(int8_t)(rmdat >> 8));// pc++;
|
||||
addbyte(0x03); /*ADDL EAX, *mod1add[0][rm]*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t)mod1add[0][rm]);
|
||||
addbyte(0x03); /*ADDL EAX, *mod1add[1][rm]*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t)mod1add[1][rm]);
|
||||
(*op_pc)++;
|
||||
break;
|
||||
case 2:
|
||||
addbyte(0xb8); /*MOVL EAX, imm16*/
|
||||
addlong((fetchdat >> 8) & 0xffff);// pc++;
|
||||
addbyte(0x03); /*EAX, ADDL *mod1add[0][rm]*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t)mod1add[0][rm]);
|
||||
addbyte(0x03); /*EAX, ADDL *mod1add[1][rm]*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t)mod1add[1][rm]);
|
||||
(*op_pc) += 2;
|
||||
break;
|
||||
}
|
||||
addbyte(0x25); /*ANDL EAX, 0xffff*/
|
||||
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)
|
||||
{
|
||||
uint32_t new_eaaddr;
|
||||
int mod = (fetchdat >> 6) & 3;
|
||||
int reg = (fetchdat >> 3) & 7;
|
||||
int rm = fetchdat & 7;
|
||||
|
||||
if (rm == 4)
|
||||
{
|
||||
uint8_t sib = fetchdat >> 8;
|
||||
(*op_pc)++;
|
||||
|
||||
switch (mod)
|
||||
{
|
||||
case 0:
|
||||
if ((sib & 7) == 5)
|
||||
{
|
||||
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
|
||||
addbyte(0xb8); /*MOVL EAX, imm32*/
|
||||
addlong(new_eaaddr);// pc++;
|
||||
(*op_pc) += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
addbyte(0xa1); /*MOVL EAX, regs[sib&7].l*/
|
||||
addlong((uint32_t)®s[sib & 7].l);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
new_eaaddr = (uint32_t)(int8_t)((fetchdat >> 16) & 0xff);
|
||||
addbyte(0xb8); /*MOVL EAX, imm8*/
|
||||
addlong(new_eaaddr);
|
||||
addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t)®s[sib & 7].l);
|
||||
(*op_pc)++;
|
||||
break;
|
||||
case 2:
|
||||
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
|
||||
addbyte(0xb8); /*MOVL EAX, new_eaaddr*/
|
||||
addlong(new_eaaddr);
|
||||
addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t)®s[sib & 7].l);
|
||||
(*op_pc) += 4;
|
||||
break;
|
||||
}
|
||||
if (stack_offset && (sib & 7) == 4 && (mod || (sib & 7) != 5)) /*ESP*/
|
||||
{
|
||||
addbyte(0x05); /*ADDL EAX, stack_offset*/
|
||||
addlong(stack_offset);
|
||||
}
|
||||
if (((sib & 7) == 4 || (mod && (sib & 7) == 5)) && !op_ssegs)
|
||||
op_ea_seg = &_ss;
|
||||
if (((sib >> 3) & 7) != 4)
|
||||
{
|
||||
switch (sib >> 6)
|
||||
{
|
||||
case 0:
|
||||
addbyte(0x03); /*ADDL EAX, regs[sib&7].l*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t)®s[(sib >> 3) & 7].l);
|
||||
break;
|
||||
case 1:
|
||||
addbyte(0x8B); addbyte(0x05 | (REG_EDI << 3)); addlong((uint32_t)®s[(sib >> 3) & 7].l); /*MOVL EDI, reg*/
|
||||
addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/
|
||||
addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/
|
||||
break;
|
||||
case 2:
|
||||
addbyte(0x8B); addbyte(0x05 | (REG_EDI << 3)); addlong((uint32_t)®s[(sib >> 3) & 7].l); /*MOVL EDI, reg*/
|
||||
addbyte(0xC1); addbyte(0xE0 | REG_EDI); addbyte(2); /*SHL EDI, 2*/
|
||||
addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/
|
||||
break;
|
||||
case 3:
|
||||
addbyte(0x8B); addbyte(0x05 | (REG_EDI << 3)); addlong((uint32_t)®s[(sib >> 3) & 7].l); /*MOVL EDI reg*/
|
||||
addbyte(0xC1); addbyte(0xE0 | REG_EDI); addbyte(3); /*SHL EDI, 3*/
|
||||
addbyte(0x01); addbyte(0xc0 | REG_EAX | (REG_EDI << 3)); /*ADDL EAX, EDI*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mod && rm == 5)
|
||||
{
|
||||
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
|
||||
addbyte(0xb8); /*MOVL EAX, imm32*/
|
||||
addlong(new_eaaddr);
|
||||
(*op_pc) += 4;
|
||||
return op_ea_seg;
|
||||
}
|
||||
addbyte(0xa1); /*MOVL EAX, regs[rm].l*/
|
||||
addlong((uint32_t)®s[rm].l);
|
||||
eaaddr = regs[rm].l;
|
||||
if (mod)
|
||||
{
|
||||
if (rm == 5 && !op_ssegs)
|
||||
op_ea_seg = &_ss;
|
||||
if (mod == 1)
|
||||
{
|
||||
addbyte(0x05); /*ADD EAX, imm8*/
|
||||
addlong((uint32_t)(int8_t)(fetchdat >> 8));
|
||||
(*op_pc)++;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
|
||||
addbyte(0x05); /*ADD EAX, imm32*/
|
||||
addlong(new_eaaddr);
|
||||
(*op_pc) += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,13 +10,15 @@
|
|||
#include "x87.h"
|
||||
#include "mem.h"
|
||||
|
||||
#include "386_common.h"
|
||||
|
||||
#include "codegen.h"
|
||||
#include "codegen_ops.h"
|
||||
#include "codegen_ops_x86.h"
|
||||
|
||||
#include "386_common.h"
|
||||
|
||||
#define BLOCK_EXIT_OFFSET 0x7f0
|
||||
x86seg *op_ea_seg;
|
||||
int op_ssegs;
|
||||
uint32_t op_old_pc;
|
||||
|
||||
uint32_t recomp_page = -1;
|
||||
|
||||
|
|
@ -38,6 +40,7 @@ static uint32_t codegen_endpc;
|
|||
|
||||
int codegen_block_cycles;
|
||||
static int codegen_block_ins;
|
||||
static int codegen_block_full_ins;
|
||||
|
||||
static uint32_t last_op32;
|
||||
static x86seg *last_ea_seg;
|
||||
|
|
@ -188,17 +191,28 @@ void codegen_block_init(uint32_t phys_addr)
|
|||
block->use32 = use32;
|
||||
block->next = block->prev = NULL;
|
||||
|
||||
block_pos = 0;
|
||||
block_pos = BLOCK_GPF_OFFSET;
|
||||
addbyte(0xc7); /*MOV [ESP],0*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x24);
|
||||
addlong(0);
|
||||
addbyte(0xc7); /*MOV [ESP+4],0*/
|
||||
addbyte(0x44);
|
||||
addbyte(0x24);
|
||||
addbyte(0x04);
|
||||
addlong(0);
|
||||
addbyte(0xe8); /*CALL x86gpf*/
|
||||
addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
|
||||
block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/
|
||||
addbyte(0x83); /*ADDL $8,%esp*/
|
||||
addbyte(0x83); /*ADDL $16,%esp*/
|
||||
addbyte(0xC4);
|
||||
addbyte(0x08);
|
||||
addbyte(0x10);
|
||||
addbyte(0xC3); /*RET*/
|
||||
cpu_block_end = 0;
|
||||
block_pos = 0; /*Entry code*/
|
||||
addbyte(0x83); /*SUBL $8,%esp*/
|
||||
addbyte(0x83); /*SUBL $16,%esp*/
|
||||
addbyte(0xEC);
|
||||
addbyte(0x08);
|
||||
addbyte(0x10);
|
||||
|
||||
// pclog("New block %i for %08X %03x\n", block_current, cs+pc, block_num);
|
||||
|
||||
|
|
@ -210,6 +224,7 @@ void codegen_block_init(uint32_t phys_addr)
|
|||
codegen_timing_block_start();
|
||||
|
||||
codegen_block_ins = 0;
|
||||
codegen_block_full_ins = 0;
|
||||
|
||||
recomp_page = phys_addr & ~0xfff;
|
||||
}
|
||||
|
|
@ -342,11 +357,22 @@ void codegen_block_end()
|
|||
addlong((uint32_t)&cpu_recomp_ins);
|
||||
addlong(codegen_block_ins);
|
||||
}
|
||||
|
||||
addbyte(0x83); /*ADDL $8,%esp*/
|
||||
#if 0
|
||||
if (codegen_block_full_ins)
|
||||
{
|
||||
addbyte(0x81); /*ADD $codegen_block_ins,ins*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t)&cpu_recomp_full_ins);
|
||||
addlong(codegen_block_full_ins);
|
||||
}
|
||||
#endif
|
||||
addbyte(0x83); /*ADDL $16,%esp*/
|
||||
addbyte(0xC4);
|
||||
addbyte(0x08);
|
||||
addbyte(0x10);
|
||||
addbyte(0xC3); /*RET*/
|
||||
|
||||
if (block_pos > BLOCK_GPF_OFFSET)
|
||||
fatal("Over limit!\n");
|
||||
// pclog("End block %i\n", block_num);
|
||||
|
||||
recomp_page = -1;
|
||||
|
|
@ -636,8 +662,6 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
|
|||
uint32_t op_32 = use32;
|
||||
uint32_t op_pc = new_pc;
|
||||
OpFn *op_table = x86_dynarec_opcodes;
|
||||
x86seg *op_ea_seg = &_ds;
|
||||
int op_ssegs = 0;
|
||||
int opcode_shift = 0;
|
||||
int opcode_mask = 0x3ff;
|
||||
int over = 0;
|
||||
|
|
@ -645,6 +669,10 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
|
|||
int test_modrm = 1;
|
||||
int c;
|
||||
|
||||
op_ea_seg = &_ds;
|
||||
op_ssegs = 0;
|
||||
op_old_pc = old_pc;
|
||||
|
||||
for (c = 0; c < NR_HOST_REGS; c++)
|
||||
host_reg_mapping[c] = -1;
|
||||
|
||||
|
|
@ -779,6 +807,7 @@ generate_call:
|
|||
|
||||
codegen_block_ins++;
|
||||
block->ins++;
|
||||
codegen_block_full_ins++;
|
||||
codegen_endpc = (cs + pc) + 8;
|
||||
|
||||
return;
|
||||
|
|
@ -899,6 +928,16 @@ generate_call:
|
|||
addlong(codegen_block_ins);
|
||||
codegen_block_ins = 0;
|
||||
}
|
||||
#if 0
|
||||
if (codegen_block_full_ins)
|
||||
{
|
||||
addbyte(0x81); /*ADD $codegen_block_ins,ins*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t)&cpu_recomp_full_ins);
|
||||
addlong(codegen_block_full_ins);
|
||||
codegen_block_full_ins = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
block->ins++;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@
|
|||
|
||||
#define HASH(l) ((l) & 0x1ffff)
|
||||
|
||||
#define BLOCK_EXIT_OFFSET 0x7f0
|
||||
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
|
||||
|
||||
enum
|
||||
{
|
||||
OP_RET = 0xc3
|
||||
|
|
|
|||
2
src/pc.c
2
src/pc.c
|
|
@ -372,6 +372,7 @@ void runpc()
|
|||
#if DYNAREC
|
||||
cpu_recomp_blocks_latched = cpu_recomp_blocks;
|
||||
cpu_recomp_ins_latched = cpu_recomp_ins;
|
||||
cpu_recomp_full_ins_latched = cpu_recomp_full_ins;
|
||||
cpu_new_blocks_latched = cpu_new_blocks;
|
||||
cpu_recomp_flushes_latched = cpu_recomp_flushes;
|
||||
cpu_recomp_evicted_latched = cpu_recomp_evicted;
|
||||
|
|
@ -382,6 +383,7 @@ void runpc()
|
|||
|
||||
cpu_recomp_blocks = 0;
|
||||
cpu_recomp_ins = 0;
|
||||
cpu_recomp_full_ins = 0;
|
||||
cpu_new_blocks = 0;
|
||||
cpu_recomp_flushes = 0;
|
||||
cpu_recomp_evicted = 0;
|
||||
|
|
|
|||
|
|
@ -48,7 +48,8 @@ static BOOL CALLBACK status_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
|
|||
"CPU time : %f%% (%f%%)\n"
|
||||
#ifdef DYNAREC
|
||||
"New blocks : %i\nOld blocks : %i\nRecompiled speed : %f MIPS\nAverage size : %f\n"
|
||||
"Flushes : %i\nEvicted : %i\nReused : %i\nRemoved : %i\nReal speed : %f MIPS\nREP : %i\nnot REP : %i\n"
|
||||
"Flushes : %i\nEvicted : %i\nReused : %i\nRemoved : %i\nReal speed : %f MIPS"
|
||||
// "\nFully recompiled ins %% : %f%%"
|
||||
#endif
|
||||
,mips,
|
||||
flops,
|
||||
|
|
@ -67,8 +68,9 @@ static BOOL CALLBACK status_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
|
|||
cpu_recomp_flushes_latched, cpu_recomp_evicted_latched,
|
||||
cpu_recomp_reuse_latched, cpu_recomp_removed_latched,
|
||||
|
||||
((double)cpu_recomp_ins_latched / 1000000.0) / ((double)main_time / timer_freq),
|
||||
cpu_reps_latched, cpu_notreps_latched
|
||||
((double)cpu_recomp_ins_latched / 1000000.0) / ((double)main_time / timer_freq)
|
||||
// ((double)cpu_recomp_full_ins_latched / (double)cpu_recomp_ins_latched) * 100.0
|
||||
// cpu_reps_latched, cpu_notreps_latched
|
||||
#endif
|
||||
);
|
||||
main_time = 0;
|
||||
|
|
|
|||
|
|
@ -101,3 +101,4 @@ extern int inscounts[256];
|
|||
void x86illegal();
|
||||
|
||||
void x86seg_reset();
|
||||
void x86gpf(char *s, uint16_t error);
|
||||
|
|
|
|||
Loading…
Reference in a new issue