Files
86Box-fork/src/codegen_ops_jump.h

271 lines
9.9 KiB
C

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)&cpu_state.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)&cpu_state.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)&cpu_state.pc, op_pc+4+offset);
return -1;
}
static uint32_t ropJCXZ(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;
if (op_32 & 0x200)
{
int host_reg = LOAD_REG_L(REG_ECX);
TEST_ZERO_JUMP_L(host_reg, op_pc+1+offset, 0);
}
else
{
int host_reg = LOAD_REG_W(REG_CX);
TEST_ZERO_JUMP_W(host_reg, op_pc+1+offset, 0);
}
return op_pc+1;
}
static uint32_t ropLOOP(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;
if (op_32 & 0x200)
{
int host_reg = LOAD_REG_L(REG_ECX);
SUB_HOST_REG_IMM(host_reg, 1);
STORE_REG_L_RELEASE(host_reg);
TEST_NONZERO_JUMP_L(host_reg, op_pc+1+offset, 0);
}
else
{
int host_reg = LOAD_REG_W(REG_CX);
SUB_HOST_REG_IMM(host_reg, 1);
STORE_REG_W_RELEASE(host_reg);
TEST_NONZERO_JUMP_W(host_reg, op_pc+1+offset, 0);
}
return op_pc+1;
}
static int BRANCH_COND_B(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
CALL_FUNC(CF_SET);
if (not)
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
}
static int BRANCH_COND_E(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
int host_reg;
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
case FLAGS_ADD8:
case FLAGS_ADD16:
case FLAGS_ADD32:
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
case FLAGS_SHL8:
case FLAGS_SHL16:
case FLAGS_SHL32:
case FLAGS_SHR8:
case FLAGS_SHR16:
case FLAGS_SHR32:
case FLAGS_SAR8:
case FLAGS_SAR16:
case FLAGS_SAR32:
case FLAGS_INC8:
case FLAGS_INC16:
case FLAGS_INC32:
case FLAGS_DEC8:
case FLAGS_DEC16:
case FLAGS_DEC32:
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
if (not)
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
else
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
break;
case FLAGS_UNKNOWN:
CALL_FUNC(ZF_SET);
if (not)
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
break;
}
}
static int BRANCH_COND_O(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
CALL_FUNC(VF_SET);
if (not)
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
}
static int BRANCH_COND_P(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
CALL_FUNC(PF_SET);
if (not)
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
}
static int BRANCH_COND_S(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
int host_reg;
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
{
case FLAGS_ZN8:
case FLAGS_ADD8:
case FLAGS_SUB8:
case FLAGS_SHL8:
case FLAGS_SHR8:
case FLAGS_SAR8:
case FLAGS_INC8:
case FLAGS_DEC8:
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
AND_HOST_REG_IMM(host_reg, 0x80);
if (not)
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
break;
case FLAGS_ZN16:
case FLAGS_ADD16:
case FLAGS_SUB16:
case FLAGS_SHL16:
case FLAGS_SHR16:
case FLAGS_SAR16:
case FLAGS_INC16:
case FLAGS_DEC16:
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
AND_HOST_REG_IMM(host_reg, 0x8000);
if (not)
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
break;
case FLAGS_ZN32:
case FLAGS_ADD32:
case FLAGS_SUB32:
case FLAGS_SHL32:
case FLAGS_SHR32:
case FLAGS_SAR32:
case FLAGS_INC32:
case FLAGS_DEC32:
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
AND_HOST_REG_IMM(host_reg, 0x80000000);
if (not)
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
break;
case FLAGS_UNKNOWN:
CALL_FUNC(NF_SET);
if (not)
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
break;
}
}
#define ropBRANCH(name, func, not) \
static uint32_t rop ## name(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; \
\
func(1, op_pc, offset, not); \
\
return op_pc+1; \
} \
static uint32_t rop ## name ## _w(uint8_t opcode, \
uint32_t fetchdat, uint32_t op_32, \
uint32_t op_pc, codeblock_t *block) \
{ \
uint32_t offset = fetchdat & 0xffff; \
\
if (offset & 0x8000) \
offset |= 0xffff0000; \
\
func(2, op_pc, offset, not); \
\
return op_pc+2; \
} \
static uint32_t rop ## name ## _l(uint8_t opcode, \
uint32_t fetchdat, uint32_t op_32, \
uint32_t op_pc, codeblock_t *block) \
{ \
uint32_t offset = fastreadl(cs + op_pc); \
\
func(4, op_pc, offset, not); \
\
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(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)