diff --git a/src/codegen.h b/src/codegen.h index fc0132a..bab424b 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -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]; diff --git a/src/codegen_ops.c b/src/codegen_ops.c index af46820..97358fd 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -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, }; diff --git a/src/codegen_ops_mmx.h b/src/codegen_ops_mmx.h new file mode 100644 index 0000000..dfb694d --- /dev/null +++ b/src/codegen_ops_mmx.h @@ -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; +} diff --git a/src/codegen_ops_x86-64.h b/src/codegen_ops_x86-64.h index bbc7cd7..418a4b1 100644 --- a/src/codegen_ops_x86-64.h +++ b/src/codegen_ops_x86-64.h @@ -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); +} diff --git a/src/codegen_ops_x86.h b/src/codegen_ops_x86.h index 5b630b0..235c058 100644 --- a/src/codegen_ops_x86.h +++ b/src/codegen_ops_x86.h @@ -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); +} diff --git a/src/codegen_x86-64.c b/src/codegen_x86-64.c index e97d1c9..7181fda 100644 --- a/src/codegen_x86-64.c +++ b/src/codegen_x86-64.c @@ -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(); diff --git a/src/codegen_x86-64.h b/src/codegen_x86-64.h index 8567979..2a41fda 100644 --- a/src/codegen_x86-64.h +++ b/src/codegen_x86-64.h @@ -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]; diff --git a/src/codegen_x86.c b/src/codegen_x86.c index 0944099..8a0af7e 100644 --- a/src/codegen_x86.c +++ b/src/codegen_x86.c @@ -23,8 +23,10 @@ #include #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(); diff --git a/src/codegen_x86.h b/src/codegen_x86.h index 8567979..2a41fda 100644 --- a/src/codegen_x86.h +++ b/src/codegen_x86.h @@ -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];