Added code generation for register and immediate PUSH/POP, RET, relative CALL and JMP instructions.
This commit is contained in:
parent
42155b4c6a
commit
a97e89e857
8 changed files with 371 additions and 17 deletions
|
|
@ -1191,7 +1191,7 @@ void exec386(int cycs)
|
||||||
|
|
||||||
cycdiff=0;
|
cycdiff=0;
|
||||||
oldcyc=cycles;
|
oldcyc=cycles;
|
||||||
// if (output && CACHE_ON()) pclog("Block %04x:%04x %04x:%08x %i\n", CS, pc, SS,ESP, codeblock_page_dirty[0x1de]);
|
// if (output && CACHE_ON()) pclog("Block %04x:%04x %04x:%08x\n", CS, pc, SS,ESP);
|
||||||
if (!CACHE_ON()) /*Interpret block*/
|
if (!CACHE_ON()) /*Interpret block*/
|
||||||
{
|
{
|
||||||
cpu_block_end = 0;
|
cpu_block_end = 0;
|
||||||
|
|
@ -1265,7 +1265,7 @@ void exec386(int cycs)
|
||||||
and physical address. The physical address check will
|
and physical address. The physical address check will
|
||||||
also catch any page faults at this stage*/
|
also catch any page faults at this stage*/
|
||||||
valid_block = (block->pc == cs + pc) && (block->_cs == cs) &&
|
valid_block = (block->pc == cs + pc) && (block->_cs == cs) &&
|
||||||
(block->use32 == use32) && (block->phys == phys_addr);
|
(block->use32 == use32) && (block->phys == phys_addr) && (block->stack32 == stack32);
|
||||||
|
|
||||||
if (valid_block && (block->page_mask & page->dirty_mask))
|
if (valid_block && (block->page_mask & page->dirty_mask))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ typedef struct codeblock_t
|
||||||
uint32_t endpc;
|
uint32_t endpc;
|
||||||
uint32_t phys, phys_2;
|
uint32_t phys, phys_2;
|
||||||
uint32_t use32;
|
uint32_t use32;
|
||||||
|
int stack32;
|
||||||
int pnt;
|
int pnt;
|
||||||
int ins;
|
int ins;
|
||||||
uint64_t page_mask, page_mask2;
|
uint64_t page_mask, page_mask2;
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,10 @@
|
||||||
#include "codegen_ops_x86.h"
|
#include "codegen_ops_x86.h"
|
||||||
|
|
||||||
#include "codegen_ops_arith.h"
|
#include "codegen_ops_arith.h"
|
||||||
|
#include "codegen_ops_jump.h"
|
||||||
#include "codegen_ops_logic.h"
|
#include "codegen_ops_logic.h"
|
||||||
#include "codegen_ops_mov.h"
|
#include "codegen_ops_mov.h"
|
||||||
|
#include "codegen_ops_stack.h"
|
||||||
#include "codegen_ops_xchg.h"
|
#include "codegen_ops_xchg.h"
|
||||||
|
|
||||||
RecompOpFn recomp_opcodes[512] =
|
RecompOpFn recomp_opcodes[512] =
|
||||||
|
|
@ -24,8 +26,8 @@ RecompOpFn recomp_opcodes[512] =
|
||||||
/*30*/ ropXOR_b_rmw, ropXOR_w_rmw, ropXOR_b_rm, ropXOR_w_rm, ropXOR_AL_imm, ropXOR_AX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_w_rmw, ropCMP_b_rm, ropCMP_w_rm, ropCMP_AL_imm, ropCMP_AX_imm, NULL, NULL,
|
/*30*/ ropXOR_b_rmw, ropXOR_w_rmw, ropXOR_b_rm, ropXOR_w_rm, ropXOR_AL_imm, ropXOR_AX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_w_rmw, ropCMP_b_rm, ropCMP_w_rm, ropCMP_AL_imm, ropCMP_AX_imm, NULL, NULL,
|
||||||
|
|
||||||
/*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,
|
/*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*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*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, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_b16,NULL, NULL, NULL, NULL, NULL,
|
||||||
/*70*/ 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*/ 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, NULL, NULL, NULL,
|
||||||
|
|
@ -33,9 +35,9 @@ RecompOpFn recomp_opcodes[512] =
|
||||||
/*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,
|
/*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,
|
/*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,
|
/*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,
|
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*e0*/ NULL, NULL, NULL, NULL, 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, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
||||||
/*32-bit data*/
|
/*32-bit data*/
|
||||||
|
|
@ -46,8 +48,8 @@ RecompOpFn recomp_opcodes[512] =
|
||||||
/*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL,
|
/*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL,
|
||||||
|
|
||||||
/*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,
|
/*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*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*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, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_b32,NULL, NULL, NULL, NULL, NULL,
|
||||||
/*70*/ 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*/ 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, NULL, NULL, NULL,
|
||||||
|
|
@ -55,9 +57,9 @@ RecompOpFn recomp_opcodes[512] =
|
||||||
/*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,
|
/*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,
|
/*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,
|
/*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,
|
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*e0*/ NULL, NULL, NULL, NULL, 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, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
29
src/codegen_ops_jump.h
Normal file
29
src/codegen_ops_jump.h
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
static uint32_t ropJMP_r8(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint32_t offset = fetchdat & 0xff;
|
||||||
|
|
||||||
|
if (offset & 0x80)
|
||||||
|
offset |= 0xffffff00;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&pc, op_pc+1+offset);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ropJMP_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint16_t offset = fetchdat & 0xffff;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&pc, (op_pc+2+offset) & 0xffff);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ropJMP_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint32_t offset = fastreadl(cs + op_pc);
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&pc, op_pc+4+offset);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
219
src/codegen_ops_stack.h
Normal file
219
src/codegen_ops_stack.h
Normal file
|
|
@ -0,0 +1,219 @@
|
||||||
|
static uint32_t ropPUSH_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_STACK_TO_EA(-2);
|
||||||
|
host_reg = LOAD_REG_W(opcode & 7);
|
||||||
|
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
|
||||||
|
SP_MODIFY(-2);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
static uint32_t ropPUSH_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_STACK_TO_EA(-4);
|
||||||
|
host_reg = LOAD_REG_L(opcode & 7);
|
||||||
|
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
|
||||||
|
SP_MODIFY(-4);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ropPUSH_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint16_t imm = fetchdat & 0xffff;
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_STACK_TO_EA(-2);
|
||||||
|
host_reg = LOAD_REG_IMM(imm);
|
||||||
|
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
|
||||||
|
SP_MODIFY(-2);
|
||||||
|
|
||||||
|
return op_pc+2;
|
||||||
|
}
|
||||||
|
static uint32_t ropPUSH_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint32_t imm = fastreadl(cs + op_pc);
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_STACK_TO_EA(-4);
|
||||||
|
host_reg = LOAD_REG_IMM(imm);
|
||||||
|
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
|
||||||
|
SP_MODIFY(-4);
|
||||||
|
|
||||||
|
return op_pc+4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ropPUSH_imm_b16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint16_t imm = fetchdat & 0xff;
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
if (imm & 0x80)
|
||||||
|
imm |= 0xff00;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_STACK_TO_EA(-2);
|
||||||
|
host_reg = LOAD_REG_IMM(imm);
|
||||||
|
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
|
||||||
|
SP_MODIFY(-2);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
static uint32_t ropPUSH_imm_b32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint32_t imm = fetchdat & 0xff;
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
if (imm & 0x80)
|
||||||
|
imm |= 0xffffff00;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_STACK_TO_EA(-4);
|
||||||
|
host_reg = LOAD_REG_IMM(imm);
|
||||||
|
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
|
||||||
|
SP_MODIFY(-4);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ropPOP_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_STACK_TO_EA(0);
|
||||||
|
MEM_LOAD_ADDR_EA_W(&_ss);
|
||||||
|
SP_MODIFY(2);
|
||||||
|
STORE_REG_TARGET_W_RELEASE(0, opcode & 7);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
static uint32_t ropPOP_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_STACK_TO_EA(0);
|
||||||
|
MEM_LOAD_ADDR_EA_L(&_ss);
|
||||||
|
SP_MODIFY(4);
|
||||||
|
STORE_REG_TARGET_L_RELEASE(0, opcode & 7);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ropRET_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_STACK_TO_EA(0);
|
||||||
|
MEM_LOAD_ADDR_EA_W(&_ss);
|
||||||
|
STORE_HOST_REG_ADDR(&pc, 0);
|
||||||
|
SP_MODIFY(2);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
static uint32_t ropRET_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_STACK_TO_EA(0);
|
||||||
|
MEM_LOAD_ADDR_EA_L(&_ss);
|
||||||
|
STORE_HOST_REG_ADDR(&pc, 0);
|
||||||
|
SP_MODIFY(4);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ropRET_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint16_t offset = fetchdat & 0xffff;
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_STACK_TO_EA(0);
|
||||||
|
MEM_LOAD_ADDR_EA_W(&_ss);
|
||||||
|
STORE_HOST_REG_ADDR(&pc, 0);
|
||||||
|
SP_MODIFY(2+offset);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
static uint32_t ropRET_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint16_t offset = fetchdat & 0xffff;
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_STACK_TO_EA(0);
|
||||||
|
MEM_LOAD_ADDR_EA_L(&_ss);
|
||||||
|
STORE_HOST_REG_ADDR(&pc, 0);
|
||||||
|
SP_MODIFY(4+offset);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ropCALL_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint16_t offset = fetchdat & 0xffff;
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_STACK_TO_EA(-2);
|
||||||
|
host_reg = LOAD_REG_IMM(op_pc+2);
|
||||||
|
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
|
||||||
|
SP_MODIFY(-2);
|
||||||
|
STORE_IMM_ADDR_L(&pc, (op_pc+2+offset) & 0xffff);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
static uint32_t ropCALL_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint32_t offset = fastreadl(cs + op_pc);
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_STACK_TO_EA(-4);
|
||||||
|
host_reg = LOAD_REG_IMM(op_pc+4);
|
||||||
|
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
|
||||||
|
SP_MODIFY(-4);
|
||||||
|
STORE_IMM_ADDR_L(&pc, op_pc+4+offset);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t ropLEAVE_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_EBP_TO_EA(0);
|
||||||
|
MEM_LOAD_ADDR_EA_W(&_ss);
|
||||||
|
host_reg = LOAD_REG_W(REG_BP); /*SP = BP + 2*/
|
||||||
|
STORE_REG_TARGET_W_RELEASE(0, REG_BP); /*BP = POP_W()*/
|
||||||
|
ADD_HOST_REG_IMM_W(host_reg, 2);
|
||||||
|
STORE_REG_TARGET_W_RELEASE(host_reg, REG_SP);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
static uint32_t ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||||
|
{
|
||||||
|
int host_reg;
|
||||||
|
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
|
||||||
|
LOAD_EBP_TO_EA(0);
|
||||||
|
MEM_LOAD_ADDR_EA_L(&_ss);
|
||||||
|
host_reg = LOAD_REG_L(REG_EBP); /*ESP = EBP + 4*/
|
||||||
|
STORE_REG_TARGET_L_RELEASE(0, REG_EBP); /*EBP = POP_L()*/
|
||||||
|
ADD_HOST_REG_IMM(host_reg, 4);
|
||||||
|
STORE_REG_TARGET_L_RELEASE(host_reg, REG_ESP);
|
||||||
|
|
||||||
|
return op_pc;
|
||||||
|
}
|
||||||
|
|
@ -915,3 +915,102 @@ static x86seg *FETCH_EA(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint
|
||||||
return FETCH_EA_32(op_ea_seg, fetchdat, op_ssegs, op_pc, 0);
|
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);
|
return FETCH_EA_16(op_ea_seg, fetchdat, op_ssegs, op_pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void LOAD_STACK_TO_EA(int off)
|
||||||
|
{
|
||||||
|
if (stack32)
|
||||||
|
{
|
||||||
|
addbyte(0x8b); /*MOVL EAX,[ESP]*/
|
||||||
|
addbyte(0x05 | (REG_EAX << 3));
|
||||||
|
addlong((uint32_t)&ESP);
|
||||||
|
if (off)
|
||||||
|
{
|
||||||
|
addbyte(0x83); /*ADD EAX, off*/
|
||||||
|
addbyte(0xc0 | (0 << 3) | REG_EAX);
|
||||||
|
addbyte(off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addbyte(0x0f); /*MOVZX EAX,W[ESP]*/
|
||||||
|
addbyte(0xb7);
|
||||||
|
addbyte(0x05 | (REG_EAX << 3));
|
||||||
|
addlong((uint32_t)&ESP);
|
||||||
|
if (off)
|
||||||
|
{
|
||||||
|
addbyte(0x66); /*ADD AX, off*/
|
||||||
|
addbyte(0x05);
|
||||||
|
addword(off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LOAD_EBP_TO_EA(int off)
|
||||||
|
{
|
||||||
|
if (stack32)
|
||||||
|
{
|
||||||
|
addbyte(0x8b); /*MOVL EAX,[EBP]*/
|
||||||
|
addbyte(0x05 | (REG_EAX << 3));
|
||||||
|
addlong((uint32_t)&EBP);
|
||||||
|
if (off)
|
||||||
|
{
|
||||||
|
addbyte(0x83); /*ADD EAX, off*/
|
||||||
|
addbyte(0xc0 | (0 << 3) | REG_EAX);
|
||||||
|
addbyte(off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addbyte(0x0f); /*MOVZX EAX,W[EBP]*/
|
||||||
|
addbyte(0xb7);
|
||||||
|
addbyte(0x05 | (REG_EAX << 3));
|
||||||
|
addlong((uint32_t)&EBP);
|
||||||
|
if (off)
|
||||||
|
{
|
||||||
|
addbyte(0x66); /*ADD AX, off*/
|
||||||
|
addbyte(0x05);
|
||||||
|
addword(off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SP_MODIFY(int off)
|
||||||
|
{
|
||||||
|
if (stack32)
|
||||||
|
{
|
||||||
|
if (off < 0x80)
|
||||||
|
{
|
||||||
|
addbyte(0x83); /*ADD [ESP], off*/
|
||||||
|
addbyte(0x05);
|
||||||
|
addlong((uint32_t)&ESP);
|
||||||
|
addbyte(off);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addbyte(0x81); /*ADD [ESP], off*/
|
||||||
|
addbyte(0x05);
|
||||||
|
addlong((uint32_t)&ESP);
|
||||||
|
addlong(off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (off < 0x80)
|
||||||
|
{
|
||||||
|
addbyte(0x66); /*ADD [SP], off*/
|
||||||
|
addbyte(0x83);
|
||||||
|
addbyte(0x05);
|
||||||
|
addlong((uint32_t)&SP);
|
||||||
|
addbyte(off);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addbyte(0x66); /*ADD [SP], off*/
|
||||||
|
addbyte(0x81);
|
||||||
|
addbyte(0x05);
|
||||||
|
addlong((uint32_t)&SP);
|
||||||
|
addword(off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,7 @@ void codegen_block_init(uint32_t phys_addr)
|
||||||
block->pnt = block_current;
|
block->pnt = block_current;
|
||||||
block->phys = phys_addr;
|
block->phys = phys_addr;
|
||||||
block->use32 = use32;
|
block->use32 = use32;
|
||||||
|
block->stack32 = stack32;
|
||||||
block->next = block->prev = NULL;
|
block->next = block->prev = NULL;
|
||||||
|
|
||||||
block_pos = BLOCK_GPF_OFFSET;
|
block_pos = BLOCK_GPF_OFFSET;
|
||||||
|
|
@ -803,7 +804,8 @@ generate_call:
|
||||||
uint32_t new_pc = recomp_opcodes[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block);
|
uint32_t new_pc = recomp_opcodes[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block);
|
||||||
if (new_pc)
|
if (new_pc)
|
||||||
{
|
{
|
||||||
STORE_IMM_ADDR_L((uintptr_t)&pc, new_pc);
|
if (new_pc != -1)
|
||||||
|
STORE_IMM_ADDR_L((uintptr_t)&pc, new_pc);
|
||||||
|
|
||||||
codegen_block_ins++;
|
codegen_block_ins++;
|
||||||
block->ins++;
|
block->ins++;
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,8 @@ static int opMOV_seg_w_a16(uint32_t fetchdat)
|
||||||
fetchdat = fastreadl(cs + pc);
|
fetchdat = fastreadl(cs + pc);
|
||||||
pc++;
|
pc++;
|
||||||
if (abrt) return 1;
|
if (abrt) return 1;
|
||||||
return x86_opcodes[(fetchdat & 0xff) | op32](fetchdat >> 8);
|
x86_opcodes[(fetchdat & 0xff) | op32](fetchdat >> 8);
|
||||||
|
return 1;
|
||||||
case 0x20: /*FS*/
|
case 0x20: /*FS*/
|
||||||
loadseg(new_seg, &_fs);
|
loadseg(new_seg, &_fs);
|
||||||
break;
|
break;
|
||||||
|
|
@ -192,7 +193,8 @@ static int opMOV_seg_w_a32(uint32_t fetchdat)
|
||||||
fetchdat = fastreadl(cs + pc);
|
fetchdat = fastreadl(cs + pc);
|
||||||
pc++;
|
pc++;
|
||||||
if (abrt) return 1;
|
if (abrt) return 1;
|
||||||
return x86_opcodes[(fetchdat & 0xff) | op32](fetchdat >> 8);
|
x86_opcodes[(fetchdat & 0xff) | op32](fetchdat >> 8);
|
||||||
|
return 1;
|
||||||
case 0x20: /*FS*/
|
case 0x20: /*FS*/
|
||||||
loadseg(new_seg, &_fs);
|
loadseg(new_seg, &_fs);
|
||||||
break;
|
break;
|
||||||
|
|
@ -277,7 +279,7 @@ static int opLSS_w_a16(uint32_t fetchdat)
|
||||||
regs[reg].w = addr;
|
regs[reg].w = addr;
|
||||||
|
|
||||||
CLOCK_CYCLES(7);
|
CLOCK_CYCLES(7);
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
static int opLSS_w_a32(uint32_t fetchdat)
|
static int opLSS_w_a32(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
|
|
@ -291,7 +293,7 @@ static int opLSS_w_a32(uint32_t fetchdat)
|
||||||
regs[reg].w = addr;
|
regs[reg].w = addr;
|
||||||
|
|
||||||
CLOCK_CYCLES(7);
|
CLOCK_CYCLES(7);
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
static int opLSS_l_a16(uint32_t fetchdat)
|
static int opLSS_l_a16(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
|
|
@ -306,7 +308,7 @@ static int opLSS_l_a16(uint32_t fetchdat)
|
||||||
regs[reg].l = addr;
|
regs[reg].l = addr;
|
||||||
|
|
||||||
CLOCK_CYCLES(7);
|
CLOCK_CYCLES(7);
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
static int opLSS_l_a32(uint32_t fetchdat)
|
static int opLSS_l_a32(uint32_t fetchdat)
|
||||||
{
|
{
|
||||||
|
|
@ -321,7 +323,7 @@ static int opLSS_l_a32(uint32_t fetchdat)
|
||||||
regs[reg].l = addr;
|
regs[reg].l = addr;
|
||||||
|
|
||||||
CLOCK_CYCLES(7);
|
CLOCK_CYCLES(7);
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define opLsel(name, sel) \
|
#define opLsel(name, sel) \
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue