278 lines
10 KiB
C
278 lines
10 KiB
C
static uint32_t ropMOVQ_q_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
{
|
|
int host_reg1, host_reg2;
|
|
|
|
MMX_ENTER();
|
|
|
|
LOAD_MMX_Q((fetchdat >> 3) & 7, &host_reg1, &host_reg2);
|
|
|
|
if ((fetchdat & 0xc0) == 0xc0)
|
|
{
|
|
STORE_MMX_Q(fetchdat & 7, host_reg1, host_reg2);
|
|
}
|
|
else
|
|
{
|
|
x86seg *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_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 ropMOVQ_mm_q(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
{
|
|
MMX_ENTER();
|
|
|
|
if ((fetchdat & 0xc0) == 0xc0)
|
|
{
|
|
int host_reg1, host_reg2;
|
|
|
|
LOAD_MMX_Q(fetchdat & 7, &host_reg1, &host_reg2);
|
|
STORE_MMX_Q((fetchdat >> 3) & 7, host_reg1, host_reg2);
|
|
}
|
|
else
|
|
{
|
|
x86seg *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);
|
|
STORE_MMX_Q((fetchdat >> 3) & 7, LOAD_Q_REG_1, LOAD_Q_REG_2);
|
|
}
|
|
|
|
return op_pc + 1;
|
|
}
|
|
|
|
static uint32_t ropMOVD_l_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
{
|
|
int host_reg;
|
|
|
|
MMX_ENTER();
|
|
|
|
host_reg = LOAD_MMX_D((fetchdat >> 3) & 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)&cpu_state.oldpc, op_old_pc);
|
|
|
|
CHECK_SEG_WRITE(target_seg);
|
|
CHECK_SEG_LIMITS(target_seg, 3);
|
|
|
|
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
|
|
}
|
|
|
|
return op_pc + 1;
|
|
}
|
|
static uint32_t ropMOVD_mm_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
{
|
|
MMX_ENTER();
|
|
|
|
if ((fetchdat & 0xc0) == 0xc0)
|
|
{
|
|
int host_reg = LOAD_REG_L(fetchdat & 7);
|
|
STORE_MMX_LQ((fetchdat >> 3) & 7, host_reg);
|
|
}
|
|
else
|
|
{
|
|
x86seg *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);
|
|
STORE_MMX_LQ((fetchdat >> 3) & 7, 0);
|
|
}
|
|
|
|
return op_pc + 1;
|
|
}
|
|
|
|
#define MMX_OP(name, func) \
|
|
static uint32_t name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
|
{ \
|
|
int src_reg1, src_reg2; \
|
|
int xmm_src, xmm_dst; \
|
|
\
|
|
MMX_ENTER(); \
|
|
\
|
|
if ((fetchdat & 0xc0) == 0xc0) \
|
|
{ \
|
|
xmm_src = LOAD_MMX_Q_MMX(fetchdat & 7); \
|
|
} \
|
|
else \
|
|
{ \
|
|
x86seg *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); \
|
|
src_reg1 = LOAD_Q_REG_1; \
|
|
src_reg2 = LOAD_Q_REG_2; \
|
|
xmm_src = LOAD_INT_TO_MMX(src_reg1, src_reg2); \
|
|
} \
|
|
xmm_dst = LOAD_MMX_Q_MMX((fetchdat >> 3) & 7); \
|
|
func(xmm_dst, xmm_src); \
|
|
STORE_MMX_Q_MMX((fetchdat >> 3) & 7, xmm_dst); \
|
|
\
|
|
return op_pc + 1; \
|
|
}
|
|
|
|
MMX_OP(ropPAND, MMX_AND)
|
|
MMX_OP(ropPANDN, MMX_ANDN)
|
|
MMX_OP(ropPOR, MMX_OR)
|
|
MMX_OP(ropPXOR, MMX_XOR)
|
|
|
|
MMX_OP(ropPADDB, MMX_ADDB)
|
|
MMX_OP(ropPADDW, MMX_ADDW)
|
|
MMX_OP(ropPADDD, MMX_ADDD)
|
|
MMX_OP(ropPADDSB, MMX_ADDSB)
|
|
MMX_OP(ropPADDSW, MMX_ADDSW)
|
|
MMX_OP(ropPADDUSB, MMX_ADDUSB)
|
|
MMX_OP(ropPADDUSW, MMX_ADDUSW)
|
|
|
|
MMX_OP(ropPSUBB, MMX_SUBB)
|
|
MMX_OP(ropPSUBW, MMX_SUBW)
|
|
MMX_OP(ropPSUBD, MMX_SUBD)
|
|
MMX_OP(ropPSUBSB, MMX_SUBSB)
|
|
MMX_OP(ropPSUBSW, MMX_SUBSW)
|
|
MMX_OP(ropPSUBUSB, MMX_SUBUSB)
|
|
MMX_OP(ropPSUBUSW, MMX_SUBUSW)
|
|
|
|
MMX_OP(ropPUNPCKLBW, MMX_PUNPCKLBW);
|
|
MMX_OP(ropPUNPCKLWD, MMX_PUNPCKLWD);
|
|
MMX_OP(ropPUNPCKLDQ, MMX_PUNPCKLDQ);
|
|
MMX_OP(ropPACKSSWB, MMX_PACKSSWB);
|
|
MMX_OP(ropPCMPGTB, MMX_PCMPGTB);
|
|
MMX_OP(ropPCMPGTW, MMX_PCMPGTW);
|
|
MMX_OP(ropPCMPGTD, MMX_PCMPGTD);
|
|
MMX_OP(ropPACKUSWB, MMX_PACKUSWB);
|
|
MMX_OP(ropPUNPCKHBW, MMX_PUNPCKHBW);
|
|
MMX_OP(ropPUNPCKHWD, MMX_PUNPCKHWD);
|
|
MMX_OP(ropPUNPCKHDQ, MMX_PUNPCKHDQ);
|
|
MMX_OP(ropPACKSSDW, MMX_PACKSSDW);
|
|
|
|
MMX_OP(ropPCMPEQB, MMX_PCMPEQB);
|
|
MMX_OP(ropPCMPEQW, MMX_PCMPEQW);
|
|
MMX_OP(ropPCMPEQD, MMX_PCMPEQD);
|
|
|
|
MMX_OP(ropPSRLW, MMX_PSRLW)
|
|
MMX_OP(ropPSRLD, MMX_PSRLD)
|
|
MMX_OP(ropPSRLQ, MMX_PSRLQ)
|
|
MMX_OP(ropPSRAW, MMX_PSRAW)
|
|
MMX_OP(ropPSRAD, MMX_PSRAD)
|
|
MMX_OP(ropPSLLW, MMX_PSLLW)
|
|
MMX_OP(ropPSLLD, MMX_PSLLD)
|
|
MMX_OP(ropPSLLQ, MMX_PSLLQ)
|
|
|
|
MMX_OP(ropPMULLW, MMX_PMULLW);
|
|
MMX_OP(ropPMULHW, MMX_PMULHW);
|
|
MMX_OP(ropPMADDWD, MMX_PMADDWD);
|
|
|
|
static uint32_t ropPSxxW_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
{
|
|
int xmm_dst;
|
|
|
|
if ((fetchdat & 0xc0) != 0xc0)
|
|
return 0;
|
|
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
|
|
return 0;
|
|
|
|
MMX_ENTER();
|
|
|
|
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
|
|
switch (fetchdat & 0x38)
|
|
{
|
|
case 0x10: /*PSRLW*/
|
|
MMX_PSRLW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
|
break;
|
|
case 0x20: /*PSRAW*/
|
|
MMX_PSRAW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
|
break;
|
|
case 0x30: /*PSLLW*/
|
|
MMX_PSLLW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
|
break;
|
|
}
|
|
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
|
|
|
|
return op_pc + 2;
|
|
}
|
|
static uint32_t ropPSxxD_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
{
|
|
int xmm_dst;
|
|
|
|
if ((fetchdat & 0xc0) != 0xc0)
|
|
return 0;
|
|
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
|
|
return 0;
|
|
|
|
MMX_ENTER();
|
|
|
|
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
|
|
switch (fetchdat & 0x38)
|
|
{
|
|
case 0x10: /*PSRLD*/
|
|
MMX_PSRLD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
|
break;
|
|
case 0x20: /*PSRAD*/
|
|
MMX_PSRAD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
|
break;
|
|
case 0x30: /*PSLLD*/
|
|
MMX_PSLLD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
|
break;
|
|
}
|
|
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
|
|
|
|
return op_pc + 2;
|
|
}
|
|
static uint32_t ropPSxxQ_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
{
|
|
int xmm_dst;
|
|
|
|
if ((fetchdat & 0xc0) != 0xc0)
|
|
return 0;
|
|
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
|
|
return 0;
|
|
|
|
MMX_ENTER();
|
|
|
|
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
|
|
switch (fetchdat & 0x38)
|
|
{
|
|
case 0x10: /*PSRLQ*/
|
|
MMX_PSRLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
|
break;
|
|
case 0x20: /*PSRAQ*/
|
|
MMX_PSRAQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
|
break;
|
|
case 0x30: /*PSLLQ*/
|
|
MMX_PSLLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
|
break;
|
|
}
|
|
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
|
|
|
|
return op_pc + 2;
|
|
}
|
|
|
|
static uint32_t ropEMMS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
|
{
|
|
codegen_mmx_entered = 0;
|
|
|
|
return 0;
|
|
}
|