Added code generation for MMX instructions
This commit is contained in:
parent
88256eff59
commit
4011a246ff
9 changed files with 1020 additions and 8 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue