2020-06-13 10:53:11 +02:00
|
|
|
static uint32_t ropFXCH(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
|
|
|
|
|
FP_FXCH(opcode & 7);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
|
|
|
|
|
FP_FLD(opcode & 7);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFST(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
|
|
|
|
|
FP_FST(opcode & 7);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFSTP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
|
|
|
|
|
FP_FST(opcode & 7);
|
|
|
|
|
FP_POP();
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFLDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
x86seg *target_seg;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_READ(target_seg);
|
|
|
|
|
MEM_LOAD_ADDR_EA_L(target_seg);
|
|
|
|
|
|
|
|
|
|
FP_LOAD_S();
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFLDd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
x86seg *target_seg;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_READ(target_seg);
|
|
|
|
|
MEM_LOAD_ADDR_EA_Q(target_seg);
|
|
|
|
|
|
|
|
|
|
FP_LOAD_D();
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFILDw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
x86seg *target_seg;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_READ(target_seg);
|
|
|
|
|
MEM_LOAD_ADDR_EA_W(target_seg);
|
|
|
|
|
|
|
|
|
|
FP_LOAD_IW();
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFILDl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
x86seg *target_seg;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_READ(target_seg);
|
|
|
|
|
MEM_LOAD_ADDR_EA_L(target_seg);
|
|
|
|
|
|
|
|
|
|
FP_LOAD_IL();
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFILDq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
x86seg *target_seg;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_READ(target_seg);
|
|
|
|
|
MEM_LOAD_ADDR_EA_Q(target_seg);
|
|
|
|
|
|
|
|
|
|
FP_LOAD_IQ();
|
|
|
|
|
|
|
|
|
|
codegen_fpu_loaded_iq[(cpu_state.TOP - 1) & 7] = 1;
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFSTs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
x86seg *target_seg;
|
|
|
|
|
int host_reg;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
host_reg = FP_LOAD_REG(0);
|
|
|
|
|
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_WRITE(target_seg);
|
|
|
|
|
|
|
|
|
|
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFSTd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
x86seg *target_seg;
|
2020-12-12 16:11:06 +01:00
|
|
|
int host_reg1, host_reg2 = 0;
|
2020-06-13 10:53:11 +02:00
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
FP_LOAD_REG_D(0, &host_reg1, &host_reg2);
|
|
|
|
|
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_WRITE(target_seg);
|
|
|
|
|
CHECK_SEG_LIMITS(target_seg, 7);
|
|
|
|
|
|
|
|
|
|
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFSTPs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
uint32_t new_pc = ropFSTs(opcode, fetchdat, op_32, op_pc, block);
|
|
|
|
|
|
|
|
|
|
FP_POP();
|
|
|
|
|
|
|
|
|
|
return new_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFSTPd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
uint32_t new_pc = ropFSTd(opcode, fetchdat, op_32, op_pc, block);
|
|
|
|
|
|
|
|
|
|
FP_POP();
|
|
|
|
|
|
|
|
|
|
return new_pc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define ropFarith(name, size, load, op) \
|
|
|
|
|
static uint32_t ropF ## name ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
|
|
|
{ \
|
|
|
|
|
x86seg *target_seg; \
|
|
|
|
|
\
|
|
|
|
|
FP_ENTER(); \
|
|
|
|
|
op_pc--; \
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
|
|
|
|
\
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
|
|
|
|
\
|
|
|
|
|
CHECK_SEG_READ(target_seg); \
|
|
|
|
|
load(target_seg); \
|
|
|
|
|
\
|
|
|
|
|
op(FPU_ ## name); \
|
|
|
|
|
\
|
|
|
|
|
return op_pc + 1; \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ropFarith(ADD, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
|
|
|
|
ropFarith(DIV, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
|
|
|
|
ropFarith(DIVR, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
|
|
|
|
ropFarith(MUL, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
|
|
|
|
ropFarith(SUB, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
|
|
|
|
ropFarith(SUBR, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
|
|
|
|
ropFarith(ADD, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
|
|
|
|
ropFarith(DIV, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
|
|
|
|
ropFarith(DIVR, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
|
|
|
|
ropFarith(MUL, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
|
|
|
|
ropFarith(SUB, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
|
|
|
|
ropFarith(SUBR, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
|
|
|
|
ropFarith(ADD, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
|
|
|
|
ropFarith(DIV, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
|
|
|
|
ropFarith(DIVR, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
|
|
|
|
ropFarith(MUL, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
|
|
|
|
ropFarith(SUB, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
|
|
|
|
ropFarith(SUBR, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
|
|
|
|
ropFarith(ADD, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
|
|
|
|
ropFarith(DIV, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
|
|
|
|
ropFarith(DIVR, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
|
|
|
|
ropFarith(MUL, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
|
|
|
|
ropFarith(SUB, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
|
|
|
|
ropFarith(SUBR, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
|
|
|
|
|
|
|
|
|
#define ropFcompare(name, size, load, op) \
|
|
|
|
|
static uint32_t ropF ## name ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
|
|
|
{ \
|
|
|
|
|
x86seg *target_seg; \
|
|
|
|
|
\
|
|
|
|
|
FP_ENTER(); \
|
|
|
|
|
op_pc--; \
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
|
|
|
|
\
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
|
|
|
|
\
|
|
|
|
|
CHECK_SEG_READ(target_seg); \
|
|
|
|
|
load(target_seg); \
|
|
|
|
|
\
|
|
|
|
|
op(); \
|
|
|
|
|
\
|
|
|
|
|
return op_pc + 1; \
|
|
|
|
|
} \
|
|
|
|
|
static uint32_t ropF ## name ## P ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
|
|
|
{ \
|
|
|
|
|
uint32_t new_pc = ropF ## name ## size(opcode, fetchdat, op_32, op_pc, block); \
|
|
|
|
|
\
|
|
|
|
|
FP_POP(); \
|
|
|
|
|
\
|
|
|
|
|
return new_pc; \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ropFcompare(COM, s, MEM_LOAD_ADDR_EA_L, FP_COMPARE_S);
|
|
|
|
|
ropFcompare(COM, d, MEM_LOAD_ADDR_EA_Q, FP_COMPARE_D);
|
|
|
|
|
ropFcompare(COM, iw, MEM_LOAD_ADDR_EA_W, FP_COMPARE_IW);
|
|
|
|
|
ropFcompare(COM, il, MEM_LOAD_ADDR_EA_L, FP_COMPARE_IL);
|
|
|
|
|
|
|
|
|
|
/*static uint32_t ropFADDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
x86seg *target_seg;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_READ(target_seg);
|
|
|
|
|
MEM_LOAD_ADDR_EA_L(target_seg);
|
|
|
|
|
|
|
|
|
|
FP_OP_S(FPU_ADD);
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFDIVs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
x86seg *target_seg;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_READ(target_seg);
|
|
|
|
|
MEM_LOAD_ADDR_EA_L(target_seg);
|
|
|
|
|
|
|
|
|
|
FP_OP_S(FPU_DIV);
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFMULs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
x86seg *target_seg;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_READ(target_seg);
|
|
|
|
|
MEM_LOAD_ADDR_EA_L(target_seg);
|
|
|
|
|
|
|
|
|
|
FP_OP_S(FPU_MUL);
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFSUBs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
x86seg *target_seg;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_READ(target_seg);
|
|
|
|
|
MEM_LOAD_ADDR_EA_L(target_seg);
|
|
|
|
|
|
|
|
|
|
FP_OP_S(FPU_SUB);
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFADD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_ADD, 0, opcode & 7);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFCOM(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_COMPARE_REG(0, opcode & 7);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFDIV(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_DIV, 0, opcode & 7);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFDIVR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_DIVR, 0, opcode & 7);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFMUL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_MUL, 0, opcode & 7);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFSUB(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_SUB, 0, opcode & 7);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFSUBR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_SUBR, 0, opcode & 7);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFADDr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_ADD, opcode & 7, 0);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFDIVr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_DIV, opcode & 7, 0);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFDIVRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_DIVR, opcode & 7, 0);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFMULr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_MUL, opcode & 7, 0);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFSUBr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_SUB, opcode & 7, 0);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFSUBRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_SUBR, opcode & 7, 0);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFADDP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_ADD, opcode & 7, 0);
|
|
|
|
|
FP_POP();
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFCOMP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_COMPARE_REG(0, opcode & 7);
|
|
|
|
|
FP_POP();
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFDIVP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_DIV, opcode & 7, 0);
|
|
|
|
|
FP_POP();
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFDIVRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_DIVR, opcode & 7, 0);
|
|
|
|
|
FP_POP();
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFMULP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_MUL, opcode & 7, 0);
|
|
|
|
|
FP_POP();
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFSUBP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_SUB, opcode & 7, 0);
|
|
|
|
|
FP_POP();
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFSUBRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_OP_REG(FPU_SUBR, opcode & 7, 0);
|
|
|
|
|
FP_POP();
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFCOMPP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_COMPARE_REG(0, 1);
|
|
|
|
|
FP_POP2();
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
int host_reg;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxs);
|
|
|
|
|
STORE_REG_TARGET_W_RELEASE(host_reg, REG_AX);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFISTw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
x86seg *target_seg;
|
|
|
|
|
int host_reg;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
host_reg = FP_LOAD_REG_INT_W(0);
|
|
|
|
|
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_WRITE(target_seg);
|
|
|
|
|
|
|
|
|
|
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFISTl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
x86seg *target_seg;
|
|
|
|
|
int host_reg;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
host_reg = FP_LOAD_REG_INT(0);
|
|
|
|
|
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_WRITE(target_seg);
|
|
|
|
|
|
|
|
|
|
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFISTPw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
uint32_t new_pc = ropFISTw(opcode, fetchdat, op_32, op_pc, block);
|
|
|
|
|
|
|
|
|
|
FP_POP();
|
|
|
|
|
|
|
|
|
|
return new_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFISTPl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
uint32_t new_pc = ropFISTl(opcode, fetchdat, op_32, op_pc, block);
|
|
|
|
|
|
|
|
|
|
FP_POP();
|
|
|
|
|
|
|
|
|
|
return new_pc;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFISTPq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
x86seg *target_seg;
|
|
|
|
|
int host_reg1, host_reg2;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
FP_LOAD_REG_INT_Q(0, &host_reg1, &host_reg2);
|
|
|
|
|
|
|
|
|
|
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_WRITE(target_seg);
|
|
|
|
|
|
|
|
|
|
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
|
|
|
|
|
|
|
|
|
|
FP_POP();
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFLDCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
x86seg *target_seg;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_READ(target_seg);
|
|
|
|
|
|
|
|
|
|
MEM_LOAD_ADDR_EA_W(target_seg);
|
|
|
|
|
STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.npxc, 0);
|
|
|
|
|
UPDATE_NPXC(0);
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}
|
|
|
|
|
static uint32_t ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
int host_reg;
|
|
|
|
|
x86seg *target_seg;
|
|
|
|
|
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
op_pc--;
|
|
|
|
|
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
|
|
|
|
|
|
|
|
|
CHECK_SEG_WRITE(target_seg);
|
|
|
|
|
|
|
|
|
|
host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxc);
|
|
|
|
|
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
|
|
|
|
|
|
|
|
|
|
return op_pc + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_FCHS();
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define opFLDimm(name, v) \
|
|
|
|
|
static uint32_t ropFLD ## name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
|
|
|
{ \
|
|
|
|
|
static double fp_imm = v; \
|
|
|
|
|
\
|
|
|
|
|
FP_ENTER(); \
|
|
|
|
|
FP_LOAD_IMM_Q(*(uint64_t *)&fp_imm); \
|
|
|
|
|
\
|
|
|
|
|
return op_pc; \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
opFLDimm(1, 1.0)
|
|
|
|
|
opFLDimm(L2T, 3.3219280948873623)
|
|
|
|
|
opFLDimm(L2E, 1.4426950408889634);
|
|
|
|
|
opFLDimm(PI, 3.141592653589793);
|
|
|
|
|
opFLDimm(EG2, 0.3010299956639812);
|
|
|
|
|
opFLDimm(Z, 0.0)
|
|
|
|
|
|
|
|
|
|
static uint32_t ropFLDLN2(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
|
|
|
{
|
|
|
|
|
FP_ENTER();
|
|
|
|
|
FP_LOAD_IMM_Q(0x3fe62e42fefa39f0ull);
|
|
|
|
|
|
|
|
|
|
return op_pc;
|
|
|
|
|
}
|