Added code generation for MMX instructions
This commit is contained in:
parent
88256eff59
commit
4011a246ff
9 changed files with 1020 additions and 8 deletions
|
|
@ -160,6 +160,7 @@ extern uint32_t op_old_pc;
|
|||
extern int codegen_flags_changed;
|
||||
|
||||
extern int codegen_fpu_entered;
|
||||
extern int codegen_mmx_entered;
|
||||
|
||||
extern int codegen_fpu_loaded_iq[8];
|
||||
extern int codegen_reg_loaded[8];
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include "codegen_ops_jump.h"
|
||||
#include "codegen_ops_logic.h"
|
||||
#include "codegen_ops_misc.h"
|
||||
#include "codegen_ops_mmx.h"
|
||||
#include "codegen_ops_mov.h"
|
||||
#include "codegen_ops_shift.h"
|
||||
#include "codegen_ops_stack.h"
|
||||
|
|
@ -83,7 +84,7 @@ RecompOpFn recomp_opcodes_0f[512] =
|
|||
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*50*/ 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, 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,
|
||||
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropEMMS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
||||
/*80*/ ropJO_w, ropJNO_w, ropJB_w, ropJNB_w, ropJE_w, ropJNE_w, ropJBE_w, ropJNBE_w, ropJS_w, ropJNS_w, ropJP_w, ropJNP_w, ropJL_w, ropJNL_w, ropJLE_w, ropJNLE_w,
|
||||
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
|
@ -104,8 +105,8 @@ RecompOpFn recomp_opcodes_0f[512] =
|
|||
|
||||
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*50*/ 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, 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,
|
||||
/*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_mm_l, ropMOVQ_mm_q,
|
||||
/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, ropEMMS, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_l_mm, ropMOVQ_q_mm,
|
||||
|
||||
/*80*/ ropJO_l, ropJNO_l, ropJB_l, ropJNB_l, ropJE_l, ropJNE_l, ropJBE_l, ropJNBE_l, ropJS_l, ropJNS_l, ropJP_l, ropJNP_l, ropJL_l, ropJNL_l, ropJLE_l, ropJNLE_l,
|
||||
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
|
@ -113,9 +114,9 @@ RecompOpFn recomp_opcodes_0f[512] =
|
|||
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_l_b, ropMOVZX_l_w, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_l_b, ropMOVSX_l_w,
|
||||
|
||||
/*c0*/ 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,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*d0*/ NULL, ropPSRLW, ropPSRLD, ropPSRLQ, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN,
|
||||
/*e0*/ NULL, ropPSRAW, ropPSRAD, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR,
|
||||
/*f0*/ NULL, ropPSLLW, ropPSLLD, ropPSLLQ, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
277
src/codegen_ops_mmx.h
Normal file
277
src/codegen_ops_mmx.h
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
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)&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)&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)&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)&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)&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;
|
||||
}
|
||||
|
|
@ -2,6 +2,21 @@
|
|||
R8-R15 - emulated registers
|
||||
*/
|
||||
|
||||
#define HOST_REG_XMM_START 0
|
||||
#define HOST_REG_XMM_END 7
|
||||
static inline int find_host_xmm_reg()
|
||||
{
|
||||
int c;
|
||||
for (c = HOST_REG_XMM_START; c < HOST_REG_XMM_END; c++)
|
||||
{
|
||||
if (host_reg_xmm_mapping[c] == -1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == HOST_REG_XMM_END)
|
||||
fatal("Out of host XMM regs!\n");
|
||||
return c;
|
||||
}
|
||||
static void call(codeblock_t *block, uintptr_t func)
|
||||
{
|
||||
uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5];
|
||||
|
|
@ -4347,3 +4362,349 @@ static void CLEAR_BITS(uintptr_t addr, uint32_t val)
|
|||
addbyte(~val);
|
||||
}
|
||||
}
|
||||
|
||||
#define LOAD_Q_REG_1 REG_EAX
|
||||
#define LOAD_Q_REG_2 REG_EDX
|
||||
|
||||
static void MMX_ENTER()
|
||||
{
|
||||
if (codegen_mmx_entered)
|
||||
return;
|
||||
|
||||
addbyte(0xf6); /*TEST cr0, 0xc*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x25);
|
||||
addlong((uintptr_t)&cr0);
|
||||
addbyte(0xc);
|
||||
addbyte(0x74); /*JZ +*/
|
||||
addbyte(11+5+12+5);
|
||||
addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x25);
|
||||
addlong((uintptr_t)&oldpc);
|
||||
addlong(op_old_pc);
|
||||
load_param_1_32(&codeblock[block_current], 7);
|
||||
CALL_FUNC(x86_int);
|
||||
addbyte(0xe9); /*JMP end*/
|
||||
addlong(BLOCK_EXIT_OFFSET - (block_pos + 4));
|
||||
|
||||
|
||||
addbyte(0x31); /*XOR EAX, EAX*/
|
||||
addbyte(0xc0);
|
||||
addbyte(0xc7); /*MOV ISMMX, 1*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t)&ismmx);
|
||||
addlong(1);
|
||||
addbyte(0x89); /*MOV TOP, EAX*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t)&TOP);
|
||||
addbyte(0x89); /*MOV tag, EAX*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t)&tag[0]);
|
||||
addbyte(0x89); /*MOV tag+4, EAX*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t)&tag[4]);
|
||||
|
||||
codegen_mmx_entered = 1;
|
||||
}
|
||||
|
||||
extern int mmx_ebx_ecx_loaded;
|
||||
|
||||
static int LOAD_MMX_D(int guest_reg)
|
||||
{
|
||||
int host_reg = REG_EBX;
|
||||
|
||||
addbyte(0x8b); /*MOV EBX, reg*/
|
||||
addbyte(0x04 | (host_reg << 3));
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t)&MM[guest_reg].l[0]);
|
||||
|
||||
return host_reg;
|
||||
}
|
||||
static void LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2)
|
||||
{
|
||||
int host_reg = REG_EBX;
|
||||
|
||||
if (host_reg & 8)
|
||||
addbyte(0x4c);
|
||||
else
|
||||
addbyte(0x48);
|
||||
addbyte(0x8b); /*MOV RBX, reg*/
|
||||
addbyte(0x04 | ((host_reg & 7) << 3));
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t)&MM[guest_reg].q);
|
||||
|
||||
*host_reg1 = host_reg;
|
||||
}
|
||||
static int LOAD_MMX_Q_MMX(int guest_reg)
|
||||
{
|
||||
int dst_reg = find_host_xmm_reg();
|
||||
host_reg_xmm_mapping[dst_reg] = 100;
|
||||
|
||||
addbyte(0xf3); /*MOV XMMx, reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x7e);
|
||||
addbyte(0x04 | ((dst_reg & 7) << 3));
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t)&MM[guest_reg].q);
|
||||
|
||||
return dst_reg;
|
||||
}
|
||||
|
||||
static int LOAD_INT_TO_MMX(int src_reg1, int src_reg2)
|
||||
{
|
||||
int dst_reg = find_host_xmm_reg();
|
||||
host_reg_xmm_mapping[dst_reg] = 100;
|
||||
|
||||
addbyte(0x66); /*MOVQ host_reg, src_reg1*/
|
||||
if (src_reg1 & 8)
|
||||
addbyte(0x49);
|
||||
else
|
||||
addbyte(0x48);
|
||||
addbyte(0x0f);
|
||||
addbyte(0x6e);
|
||||
addbyte(0xc0 | (dst_reg << 3) | (src_reg1 & 7));
|
||||
|
||||
return dst_reg;
|
||||
}
|
||||
|
||||
static void STORE_MMX_LQ(int guest_reg, int host_reg1)
|
||||
{
|
||||
addbyte(0xC7); /*MOVL [reg],0*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t)&MM[guest_reg].l[1]);
|
||||
addlong(0);
|
||||
if (host_reg1 & 8)
|
||||
addbyte(0x44);
|
||||
addbyte(0x89); /*MOVL [reg],host_reg*/
|
||||
addbyte(0x04 | ((host_reg1 & 7) << 3));
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t)&MM[guest_reg].l[0]);
|
||||
}
|
||||
static void STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2)
|
||||
{
|
||||
if (host_reg1 & 8)
|
||||
addbyte(0x4c);
|
||||
else
|
||||
addbyte(0x48);
|
||||
addbyte(0x89); /*MOV [reg],host_reg*/
|
||||
addbyte(0x04 | ((host_reg1 & 7) << 3));
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t)&MM[guest_reg].l[0]);
|
||||
}
|
||||
static void STORE_MMX_Q_MMX(int guest_reg, int host_reg)
|
||||
{
|
||||
addbyte(0x66); /*MOVQ [guest_reg],host_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0xd6);
|
||||
addbyte(0x04 | (host_reg << 3));
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t)&MM[guest_reg].q);
|
||||
}
|
||||
|
||||
#define MMX_x86_OP(name, opcode) \
|
||||
static void MMX_ ## name(int dst_reg, int src_reg) \
|
||||
{ \
|
||||
addbyte(0x66); /*op dst_reg, src_reg*/ \
|
||||
addbyte(0x0f); \
|
||||
addbyte(opcode); \
|
||||
addbyte(0xc0 | (dst_reg << 3) | src_reg); \
|
||||
}
|
||||
|
||||
MMX_x86_OP(AND, 0xdb)
|
||||
MMX_x86_OP(ANDN, 0xdf)
|
||||
MMX_x86_OP(OR, 0xeb)
|
||||
MMX_x86_OP(XOR, 0xef)
|
||||
|
||||
MMX_x86_OP(ADDB, 0xfc)
|
||||
MMX_x86_OP(ADDW, 0xfd)
|
||||
MMX_x86_OP(ADDD, 0xfe)
|
||||
MMX_x86_OP(ADDSB, 0xec)
|
||||
MMX_x86_OP(ADDSW, 0xed)
|
||||
MMX_x86_OP(ADDUSB, 0xdc)
|
||||
MMX_x86_OP(ADDUSW, 0xdd)
|
||||
|
||||
MMX_x86_OP(SUBB, 0xf8)
|
||||
MMX_x86_OP(SUBW, 0xf9)
|
||||
MMX_x86_OP(SUBD, 0xfa)
|
||||
MMX_x86_OP(SUBSB, 0xe8)
|
||||
MMX_x86_OP(SUBSW, 0xe9)
|
||||
MMX_x86_OP(SUBUSB, 0xd8)
|
||||
MMX_x86_OP(SUBUSW, 0xd9)
|
||||
|
||||
MMX_x86_OP(PUNPCKLBW, 0x60);
|
||||
MMX_x86_OP(PUNPCKLWD, 0x61);
|
||||
MMX_x86_OP(PUNPCKLDQ, 0x62);
|
||||
MMX_x86_OP(PCMPGTB, 0x64);
|
||||
MMX_x86_OP(PCMPGTW, 0x65);
|
||||
MMX_x86_OP(PCMPGTD, 0x66);
|
||||
|
||||
MMX_x86_OP(PCMPEQB, 0x74);
|
||||
MMX_x86_OP(PCMPEQW, 0x75);
|
||||
MMX_x86_OP(PCMPEQD, 0x76);
|
||||
|
||||
MMX_x86_OP(PSRLW, 0xd1);
|
||||
MMX_x86_OP(PSRLD, 0xd2);
|
||||
MMX_x86_OP(PSRLQ, 0xd3);
|
||||
MMX_x86_OP(PSRAW, 0xe1);
|
||||
MMX_x86_OP(PSRAD, 0xe2);
|
||||
MMX_x86_OP(PSLLW, 0xf1);
|
||||
MMX_x86_OP(PSLLD, 0xf2);
|
||||
MMX_x86_OP(PSLLQ, 0xf3);
|
||||
|
||||
MMX_x86_OP(PMULLW, 0xd5);
|
||||
MMX_x86_OP(PMULHW, 0xe5);
|
||||
MMX_x86_OP(PMADDWD, 0xf5);
|
||||
|
||||
static void MMX_PACKSSWB(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x66); /*PACKSSWB dst_reg, src_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x63);
|
||||
addbyte(0xc0 | (dst_reg << 3) | src_reg);
|
||||
addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x70);
|
||||
addbyte(0xc0 | (dst_reg << 3) | dst_reg);
|
||||
addbyte(0x08);
|
||||
}
|
||||
static void MMX_PACKUSWB(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x66); /*PACKUSWB dst_reg, src_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x67);
|
||||
addbyte(0xc0 | (dst_reg << 3) | src_reg);
|
||||
addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x70);
|
||||
addbyte(0xc0 | (dst_reg << 3) | dst_reg);
|
||||
addbyte(0x08);
|
||||
}
|
||||
static void MMX_PACKSSDW(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x66); /*PACKSSDW dst_reg, src_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x6b);
|
||||
addbyte(0xc0 | (dst_reg << 3) | src_reg);
|
||||
addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x70);
|
||||
addbyte(0xc0 | (dst_reg << 3) | dst_reg);
|
||||
addbyte(0x08);
|
||||
}
|
||||
static void MMX_PUNPCKHBW(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x66); /*PUNPCKLBW dst_reg, src_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x60);
|
||||
addbyte(0xc0 | (dst_reg << 3) | src_reg);
|
||||
addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x70);
|
||||
addbyte(0xc0 | (dst_reg << 3) | dst_reg);
|
||||
addbyte(0x0e);
|
||||
}
|
||||
static void MMX_PUNPCKHWD(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x66); /*PUNPCKLWD dst_reg, src_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x61);
|
||||
addbyte(0xc0 | (dst_reg << 3) | src_reg);
|
||||
addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x70);
|
||||
addbyte(0xc0 | (dst_reg << 3) | dst_reg);
|
||||
addbyte(0x0e);
|
||||
}
|
||||
static void MMX_PUNPCKHDQ(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x66); /*PUNPCKLDQ dst_reg, src_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x62);
|
||||
addbyte(0xc0 | (dst_reg << 3) | src_reg);
|
||||
addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x70);
|
||||
addbyte(0xc0 | (dst_reg << 3) | dst_reg);
|
||||
addbyte(0x0e);
|
||||
}
|
||||
|
||||
static void MMX_PSRLW_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSRLW dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x71);
|
||||
addbyte(0xc0 | dst_reg | 0x10);
|
||||
addbyte(amount);
|
||||
}
|
||||
static void MMX_PSRAW_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSRAW dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x71);
|
||||
addbyte(0xc0 | dst_reg | 0x20);
|
||||
addbyte(amount);
|
||||
}
|
||||
static void MMX_PSLLW_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSLLW dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x71);
|
||||
addbyte(0xc0 | dst_reg | 0x30);
|
||||
addbyte(amount);
|
||||
}
|
||||
|
||||
static void MMX_PSRLD_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSRLD dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x72);
|
||||
addbyte(0xc0 | dst_reg | 0x10);
|
||||
addbyte(amount);
|
||||
}
|
||||
static void MMX_PSRAD_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSRAD dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x72);
|
||||
addbyte(0xc0 | dst_reg | 0x20);
|
||||
addbyte(amount);
|
||||
}
|
||||
static void MMX_PSLLD_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSLLD dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x72);
|
||||
addbyte(0xc0 | dst_reg | 0x30);
|
||||
addbyte(amount);
|
||||
}
|
||||
|
||||
static void MMX_PSRLQ_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSRLQ dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x73);
|
||||
addbyte(0xc0 | dst_reg | 0x10);
|
||||
addbyte(amount);
|
||||
}
|
||||
static void MMX_PSRAQ_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSRAQ dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x73);
|
||||
addbyte(0xc0 | dst_reg | 0x20);
|
||||
addbyte(amount);
|
||||
}
|
||||
static void MMX_PSLLQ_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSLLQ dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x73);
|
||||
addbyte(0xc0 | dst_reg | 0x30);
|
||||
addbyte(amount);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
#define HOST_REG_START 1
|
||||
#define HOST_REG_END 4
|
||||
#define HOST_REG_XMM_START 0
|
||||
#define HOST_REG_XMM_END 7
|
||||
static inline int find_host_reg()
|
||||
{
|
||||
int c;
|
||||
|
|
@ -19,6 +21,19 @@ static inline int find_host_reg()
|
|||
fatal("Out of host regs!\n");
|
||||
return c;
|
||||
}
|
||||
static inline int find_host_xmm_reg()
|
||||
{
|
||||
int c;
|
||||
for (c = HOST_REG_XMM_START; c < HOST_REG_XMM_END; c++)
|
||||
{
|
||||
if (host_reg_xmm_mapping[c] == -1)
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == HOST_REG_XMM_END)
|
||||
fatal("Out of host XMM regs!\n");
|
||||
return c;
|
||||
}
|
||||
|
||||
static void STORE_IMM_ADDR_B(uintptr_t addr, uint8_t val)
|
||||
{
|
||||
|
|
@ -2996,3 +3011,345 @@ static void CLEAR_BITS(uintptr_t addr, uint32_t val)
|
|||
addbyte(~val);
|
||||
}
|
||||
}
|
||||
|
||||
#define LOAD_Q_REG_1 REG_EAX
|
||||
#define LOAD_Q_REG_2 REG_EDX
|
||||
|
||||
static void MMX_ENTER()
|
||||
{
|
||||
if (codegen_mmx_entered)
|
||||
return;
|
||||
|
||||
addbyte(0xf6); /*TEST cr0, 0xc*/
|
||||
addbyte(0x05);
|
||||
addlong((uintptr_t)&cr0);
|
||||
addbyte(0xc);
|
||||
addbyte(0x74); /*JZ +*/
|
||||
addbyte(10+7+5+5);
|
||||
addbyte(0xC7); /*MOVL [oldpc],op_old_pc*/
|
||||
addbyte(0x05);
|
||||
addlong((uintptr_t)&oldpc);
|
||||
addlong(op_old_pc);
|
||||
addbyte(0xc7); /*MOV [ESP], 7*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x24);
|
||||
addlong(7);
|
||||
addbyte(0xe8); /*CALL x86_int*/
|
||||
addlong((uint32_t)x86_int - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
|
||||
addbyte(0xe9); /*JMP end*/
|
||||
addlong(BLOCK_EXIT_OFFSET - (block_pos + 4));
|
||||
|
||||
addbyte(0x31); /*XOR EAX, EAX*/
|
||||
addbyte(0xc0);
|
||||
addbyte(0xc7); /*MOV ISMMX, 1*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t)&ismmx);
|
||||
addlong(1);
|
||||
addbyte(0xa3); /*MOV TOP, EAX*/
|
||||
addlong((uint32_t)&TOP);
|
||||
addbyte(0xa3); /*MOV tag, EAX*/
|
||||
addlong((uint32_t)&tag[0]);
|
||||
addbyte(0xa3); /*MOV tag+4, EAX*/
|
||||
addlong((uint32_t)&tag[4]);
|
||||
|
||||
codegen_mmx_entered = 1;
|
||||
}
|
||||
|
||||
extern int mmx_ebx_ecx_loaded;
|
||||
|
||||
static int LOAD_MMX_D(int guest_reg)
|
||||
{
|
||||
int host_reg = find_host_reg();
|
||||
host_reg_mapping[host_reg] = 100;
|
||||
|
||||
addbyte(0x8b); /*MOV EBX, reg*/
|
||||
addbyte(0x05 | (host_reg << 3));
|
||||
addlong((uint32_t)&MM[guest_reg].l[0]);
|
||||
|
||||
return host_reg;
|
||||
}
|
||||
static int LOAD_MMX_Q(int guest_reg, int *host_reg1, int *host_reg2)
|
||||
{
|
||||
if (!mmx_ebx_ecx_loaded)
|
||||
{
|
||||
*host_reg1 = REG_EBX;
|
||||
*host_reg2 = REG_ECX;
|
||||
mmx_ebx_ecx_loaded = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*host_reg1 = REG_EAX;
|
||||
*host_reg2 = REG_EDX;
|
||||
}
|
||||
|
||||
addbyte(0x8b); /*MOV EBX, reg*/
|
||||
addbyte(0x05 | ((*host_reg1) << 3));
|
||||
addlong((uint32_t)&MM[guest_reg].l[0]);
|
||||
addbyte(0x8b); /*MOV ECX, reg+4*/
|
||||
addbyte(0x05 | ((*host_reg2) << 3));
|
||||
addlong((uint32_t)&MM[guest_reg].l[1]);
|
||||
}
|
||||
static int LOAD_MMX_Q_MMX(int guest_reg)
|
||||
{
|
||||
int dst_reg = find_host_xmm_reg();
|
||||
host_reg_xmm_mapping[dst_reg] = guest_reg;
|
||||
|
||||
addbyte(0xf3); /*MOVQ dst_reg,[reg]*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x7e);
|
||||
addbyte(0x05 | (dst_reg << 3));
|
||||
addlong((uint32_t)&MM[guest_reg].q);
|
||||
|
||||
return dst_reg;
|
||||
}
|
||||
|
||||
static int LOAD_INT_TO_MMX(int src_reg1, int src_reg2)
|
||||
{
|
||||
int dst_reg = find_host_xmm_reg();
|
||||
host_reg_xmm_mapping[dst_reg] = 100;
|
||||
|
||||
addbyte(0x66); /*MOVD dst_reg, src_reg1*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x6e);
|
||||
addbyte(0xc0 | (dst_reg << 3) | src_reg1);
|
||||
addbyte(0x66); /*MOVD XMM7, src_reg2*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x6e);
|
||||
addbyte(0xc0 | (7 << 3) | src_reg2);
|
||||
addbyte(0x66); /*PUNPCKLDQ dst_reg, XMM7*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x62);
|
||||
addbyte(0xc0 | 7 | (dst_reg << 3));
|
||||
|
||||
return dst_reg;
|
||||
}
|
||||
|
||||
static void STORE_MMX_LQ(int guest_reg, int host_reg1)
|
||||
{
|
||||
addbyte(0xC7); /*MOVL [reg],0*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t)&MM[guest_reg].l[1]);
|
||||
addlong(0);
|
||||
addbyte(0x89); /*MOVL [reg],host_reg*/
|
||||
addbyte(0x05 | (host_reg1 << 3));
|
||||
addlong((uint32_t)&MM[guest_reg].l[0]);
|
||||
}
|
||||
static void STORE_MMX_Q(int guest_reg, int host_reg1, int host_reg2)
|
||||
{
|
||||
addbyte(0x89); /*MOVL [reg],host_reg*/
|
||||
addbyte(0x05 | (host_reg1 << 3));
|
||||
addlong((uint32_t)&MM[guest_reg].l[0]);
|
||||
addbyte(0x89); /*MOVL [reg],host_reg*/
|
||||
addbyte(0x05 | (host_reg2 << 3));
|
||||
addlong((uint32_t)&MM[guest_reg].l[1]);
|
||||
}
|
||||
static void STORE_MMX_Q_MMX(int guest_reg, int host_reg)
|
||||
{
|
||||
addbyte(0x66); /*MOVQ [guest_reg],host_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0xd6);
|
||||
addbyte(0x05 | (host_reg << 3));
|
||||
addlong((uint32_t)&MM[guest_reg].q);
|
||||
}
|
||||
|
||||
#define MMX_x86_OP(name, opcode) \
|
||||
static void MMX_ ## name(int dst_reg, int src_reg) \
|
||||
{ \
|
||||
addbyte(0x66); /*op dst_reg, src_reg*/ \
|
||||
addbyte(0x0f); \
|
||||
addbyte(opcode); \
|
||||
addbyte(0xc0 | (dst_reg << 3) | src_reg); \
|
||||
}
|
||||
|
||||
MMX_x86_OP(AND, 0xdb)
|
||||
MMX_x86_OP(ANDN, 0xdf)
|
||||
MMX_x86_OP(OR, 0xeb)
|
||||
MMX_x86_OP(XOR, 0xef)
|
||||
|
||||
MMX_x86_OP(ADDB, 0xfc)
|
||||
MMX_x86_OP(ADDW, 0xfd)
|
||||
MMX_x86_OP(ADDD, 0xfe)
|
||||
MMX_x86_OP(ADDSB, 0xec)
|
||||
MMX_x86_OP(ADDSW, 0xed)
|
||||
MMX_x86_OP(ADDUSB, 0xdc)
|
||||
MMX_x86_OP(ADDUSW, 0xdd)
|
||||
|
||||
MMX_x86_OP(SUBB, 0xf8)
|
||||
MMX_x86_OP(SUBW, 0xf9)
|
||||
MMX_x86_OP(SUBD, 0xfa)
|
||||
MMX_x86_OP(SUBSB, 0xe8)
|
||||
MMX_x86_OP(SUBSW, 0xe9)
|
||||
MMX_x86_OP(SUBUSB, 0xd8)
|
||||
MMX_x86_OP(SUBUSW, 0xd9)
|
||||
|
||||
MMX_x86_OP(PUNPCKLBW, 0x60);
|
||||
MMX_x86_OP(PUNPCKLWD, 0x61);
|
||||
MMX_x86_OP(PUNPCKLDQ, 0x62);
|
||||
MMX_x86_OP(PCMPGTB, 0x64);
|
||||
MMX_x86_OP(PCMPGTW, 0x65);
|
||||
MMX_x86_OP(PCMPGTD, 0x66);
|
||||
|
||||
MMX_x86_OP(PCMPEQB, 0x74);
|
||||
MMX_x86_OP(PCMPEQW, 0x75);
|
||||
MMX_x86_OP(PCMPEQD, 0x76);
|
||||
|
||||
MMX_x86_OP(PSRLW, 0xd1);
|
||||
MMX_x86_OP(PSRLD, 0xd2);
|
||||
MMX_x86_OP(PSRLQ, 0xd3);
|
||||
MMX_x86_OP(PSRAW, 0xe1);
|
||||
MMX_x86_OP(PSRAD, 0xe2);
|
||||
MMX_x86_OP(PSLLW, 0xf1);
|
||||
MMX_x86_OP(PSLLD, 0xf2);
|
||||
MMX_x86_OP(PSLLQ, 0xf3);
|
||||
|
||||
MMX_x86_OP(PMULLW, 0xd5);
|
||||
MMX_x86_OP(PMULHW, 0xe5);
|
||||
MMX_x86_OP(PMADDWD, 0xf5);
|
||||
|
||||
static void MMX_PACKSSWB(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x66); /*PACKSSWB dst_reg, src_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x63);
|
||||
addbyte(0xc0 | (dst_reg << 3) | src_reg);
|
||||
addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x70);
|
||||
addbyte(0xc0 | (dst_reg << 3) | dst_reg);
|
||||
addbyte(0x08);
|
||||
}
|
||||
static void MMX_PACKUSWB(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x66); /*PACKUSWB dst_reg, src_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x67);
|
||||
addbyte(0xc0 | (dst_reg << 3) | src_reg);
|
||||
addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x70);
|
||||
addbyte(0xc0 | (dst_reg << 3) | dst_reg);
|
||||
addbyte(0x08);
|
||||
}
|
||||
static void MMX_PACKSSDW(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x66); /*PACKSSDW dst_reg, src_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x6b);
|
||||
addbyte(0xc0 | (dst_reg << 3) | src_reg);
|
||||
addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x70);
|
||||
addbyte(0xc0 | (dst_reg << 3) | dst_reg);
|
||||
addbyte(0x08);
|
||||
}
|
||||
static void MMX_PUNPCKHBW(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x66); /*PUNPCKLBW dst_reg, src_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x60);
|
||||
addbyte(0xc0 | (dst_reg << 3) | src_reg);
|
||||
addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x70);
|
||||
addbyte(0xc0 | (dst_reg << 3) | dst_reg);
|
||||
addbyte(0x0e);
|
||||
}
|
||||
static void MMX_PUNPCKHWD(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x66); /*PUNPCKLWD dst_reg, src_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x61);
|
||||
addbyte(0xc0 | (dst_reg << 3) | src_reg);
|
||||
addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x70);
|
||||
addbyte(0xc0 | (dst_reg << 3) | dst_reg);
|
||||
addbyte(0x0e);
|
||||
}
|
||||
static void MMX_PUNPCKHDQ(int dst_reg, int src_reg)
|
||||
{
|
||||
addbyte(0x66); /*PUNPCKLDQ dst_reg, src_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x62);
|
||||
addbyte(0xc0 | (dst_reg << 3) | src_reg);
|
||||
addbyte(0x66); /*PSHUFD dst_reg, dst_reg*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x70);
|
||||
addbyte(0xc0 | (dst_reg << 3) | dst_reg);
|
||||
addbyte(0x0e);
|
||||
}
|
||||
|
||||
static void MMX_PSRLW_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSRLW dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x71);
|
||||
addbyte(0xc0 | dst_reg | 0x10);
|
||||
addbyte(amount);
|
||||
}
|
||||
static void MMX_PSRAW_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSRAW dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x71);
|
||||
addbyte(0xc0 | dst_reg | 0x20);
|
||||
addbyte(amount);
|
||||
}
|
||||
static void MMX_PSLLW_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSLLW dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x71);
|
||||
addbyte(0xc0 | dst_reg | 0x30);
|
||||
addbyte(amount);
|
||||
}
|
||||
|
||||
static void MMX_PSRLD_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSRLD dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x72);
|
||||
addbyte(0xc0 | dst_reg | 0x10);
|
||||
addbyte(amount);
|
||||
}
|
||||
static void MMX_PSRAD_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSRAD dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x72);
|
||||
addbyte(0xc0 | dst_reg | 0x20);
|
||||
addbyte(amount);
|
||||
}
|
||||
static void MMX_PSLLD_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSLLD dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x72);
|
||||
addbyte(0xc0 | dst_reg | 0x30);
|
||||
addbyte(amount);
|
||||
}
|
||||
|
||||
static void MMX_PSRLQ_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSRLQ dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x73);
|
||||
addbyte(0xc0 | dst_reg | 0x10);
|
||||
addbyte(amount);
|
||||
}
|
||||
static void MMX_PSRAQ_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSRAQ dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x73);
|
||||
addbyte(0xc0 | dst_reg | 0x20);
|
||||
addbyte(amount);
|
||||
}
|
||||
static void MMX_PSLLQ_imm(int dst_reg, int amount)
|
||||
{
|
||||
addbyte(0x66); /*PSLLQ dst_reg, amount*/
|
||||
addbyte(0x0f);
|
||||
addbyte(0x73);
|
||||
addbyte(0xc0 | dst_reg | 0x30);
|
||||
addbyte(amount);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,9 +35,10 @@ uint32_t op_old_pc;
|
|||
uint32_t recomp_page = -1;
|
||||
|
||||
int host_reg_mapping[NR_HOST_REGS];
|
||||
int host_reg_xmm_mapping[NR_HOST_XMM_REGS];
|
||||
codeblock_t *codeblock;
|
||||
codeblock_t **codeblock_hash;
|
||||
|
||||
int codegen_mmx_entered = 0;
|
||||
|
||||
int block_current = 0;
|
||||
static int block_num;
|
||||
|
|
@ -292,7 +293,8 @@ void codegen_block_init(uint32_t phys_addr)
|
|||
|
||||
codegen_flags_changed = 0;
|
||||
codegen_fpu_entered = 0;
|
||||
|
||||
codegen_mmx_entered = 0;
|
||||
|
||||
codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] =
|
||||
codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0;
|
||||
|
||||
|
|
@ -920,6 +922,8 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
|
|||
|
||||
for (c = 0; c < NR_HOST_REGS; c++)
|
||||
host_reg_mapping[c] = -1;
|
||||
for (c = 0; c < NR_HOST_XMM_REGS; c++)
|
||||
host_reg_xmm_mapping[c] = -1;
|
||||
|
||||
codegen_timing_start();
|
||||
|
||||
|
|
|
|||
|
|
@ -17,3 +17,5 @@ enum
|
|||
|
||||
#define NR_HOST_REGS 3
|
||||
extern int host_reg_mapping[NR_HOST_REGS];
|
||||
#define NR_HOST_XMM_REGS 7
|
||||
extern int host_reg_xmm_mapping[NR_HOST_XMM_REGS];
|
||||
|
|
|
|||
|
|
@ -23,8 +23,10 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
int mmx_ebx_ecx_loaded;
|
||||
int codegen_flags_changed = 0;
|
||||
int codegen_fpu_entered = 0;
|
||||
int codegen_mmx_entered = 0;
|
||||
int codegen_fpu_loaded_iq[8];
|
||||
x86seg *op_ea_seg;
|
||||
int op_ssegs;
|
||||
|
|
@ -33,6 +35,7 @@ uint32_t op_old_pc;
|
|||
uint32_t recomp_page = -1;
|
||||
|
||||
int host_reg_mapping[NR_HOST_REGS];
|
||||
int host_reg_xmm_mapping[NR_HOST_XMM_REGS];
|
||||
codeblock_t *codeblock;
|
||||
codeblock_t **codeblock_hash;
|
||||
|
||||
|
|
@ -266,6 +269,7 @@ void codegen_block_init(uint32_t phys_addr)
|
|||
|
||||
codegen_flags_changed = 0;
|
||||
codegen_fpu_entered = 0;
|
||||
codegen_mmx_entered = 0;
|
||||
|
||||
codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] =
|
||||
codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0;
|
||||
|
|
@ -721,6 +725,9 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
|
|||
|
||||
for (c = 0; c < NR_HOST_REGS; c++)
|
||||
host_reg_mapping[c] = -1;
|
||||
mmx_ebx_ecx_loaded = 0;
|
||||
for (c = 0; c < NR_HOST_XMM_REGS; c++)
|
||||
host_reg_xmm_mapping[c] = -1;
|
||||
|
||||
codegen_timing_start();
|
||||
|
||||
|
|
|
|||
|
|
@ -17,3 +17,5 @@ enum
|
|||
|
||||
#define NR_HOST_REGS 3
|
||||
extern int host_reg_mapping[NR_HOST_REGS];
|
||||
#define NR_HOST_XMM_REGS 7
|
||||
extern int host_reg_xmm_mapping[NR_HOST_XMM_REGS];
|
||||
|
|
|
|||
Loading…
Reference in a new issue