Added recompiled versions of 3DNow instructions - PF2ID, PFADD, PFCMPEQ, PFCMPGE, PFCMPGT, PFMAX, PFMIN, PFMUL, PFRCP, PFRCPIT1, PFRCPIT2, PFRSQRT, PFRSQIT1, PFSUB, PFSUBR and PI2FD.
This commit is contained in:
parent
cfd4ac3a4f
commit
e26abe7a1f
19 changed files with 1411 additions and 8 deletions
|
|
@ -306,10 +306,12 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
|
|||
RecompOpFn *recomp_op_table = recomp_opcodes;
|
||||
int opcode_shift = 0;
|
||||
int opcode_mask = 0x3ff;
|
||||
uint32_t recomp_opcode_mask = 0x1ff;
|
||||
uint32_t op_32 = use32;
|
||||
int over = 0;
|
||||
int test_modrm = 1;
|
||||
int pc_off = 0;
|
||||
uint32_t next_pc = 0;
|
||||
#ifdef DEBUG_EXTRA
|
||||
uint8_t last_prefix = 0;
|
||||
#endif
|
||||
|
|
@ -507,10 +509,68 @@ generate_call:
|
|||
(opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) ||
|
||||
(op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80)))
|
||||
codegen_accumulate_flush(ir);
|
||||
// pclog("%04x:%08x : %02x\n", CS, new_pc, opcode);
|
||||
if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff])
|
||||
|
||||
if (op_table == x86_dynarec_opcodes_0f && opcode == 0x0f)
|
||||
{
|
||||
uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](block, ir, opcode, fetchdat, op_32, op_pc);
|
||||
/*3DNow opcodes are stored after ModR/M, SIB and any offset*/
|
||||
uint8_t modrm = fetchdat & 0xff;
|
||||
uint8_t sib = (fetchdat >> 8) & 0xff;
|
||||
uint32_t opcode_pc = op_pc + 1;
|
||||
uint8_t opcode_3dnow;
|
||||
|
||||
if ((modrm & 0xc0) != 0xc0)
|
||||
{
|
||||
if (op_32 & 0x200)
|
||||
{
|
||||
if ((modrm & 7) == 4)
|
||||
{
|
||||
/* Has SIB*/
|
||||
opcode_pc++;
|
||||
if ((modrm & 0xc0) == 0x40)
|
||||
opcode_pc++;
|
||||
else if ((modrm & 0xc0) == 0x80)
|
||||
opcode_pc += 4;
|
||||
else if ((sib & 0x07) == 0x05)
|
||||
opcode_pc += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((modrm & 0xc0) == 0x40)
|
||||
opcode_pc++;
|
||||
else if ((modrm & 0xc0) == 0x80)
|
||||
opcode_pc += 4;
|
||||
else if ((modrm & 0xc7) == 0x05)
|
||||
opcode_pc += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((modrm & 0xc0) == 0x40)
|
||||
opcode_pc++;
|
||||
else if ((modrm & 0xc0) == 0x80)
|
||||
opcode_pc += 2;
|
||||
else if ((modrm & 0xc7) == 0x06)
|
||||
opcode_pc += 2;
|
||||
}
|
||||
}
|
||||
|
||||
opcode_3dnow = fastreadb(cs + opcode_pc);
|
||||
// pclog("recomp_opcodes_3DNOW[%02x]=%p\n", opcode, recomp_opcodes_3DNOW[opcode]);
|
||||
if (recomp_opcodes_3DNOW[opcode_3dnow])
|
||||
{
|
||||
next_pc = opcode_pc + 1;
|
||||
|
||||
op_table = x86_dynarec_opcodes_3DNOW;
|
||||
recomp_op_table = recomp_opcodes_3DNOW;
|
||||
opcode = opcode_3dnow;
|
||||
recomp_opcode_mask = 0xff;
|
||||
opcode_mask = 0xff;
|
||||
}
|
||||
}
|
||||
// pclog("%04x:%08x : %02x\n", CS, new_pc, opcode);
|
||||
if (recomp_op_table && recomp_op_table[(opcode | op_32) & recomp_opcode_mask])
|
||||
{
|
||||
uint32_t new_pc = recomp_op_table[(opcode | op_32) & recomp_opcode_mask](block, ir, opcode, fetchdat, op_32, op_pc);
|
||||
if (new_pc)
|
||||
{
|
||||
if (new_pc != -1)
|
||||
|
|
@ -532,7 +592,8 @@ generate_call:
|
|||
|
||||
if (!test_modrm ||
|
||||
(op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) ||
|
||||
(op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]))
|
||||
(op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]) ||
|
||||
(op_table == x86_dynarec_opcodes_3DNOW))
|
||||
{
|
||||
int stack_offset = 0;
|
||||
|
||||
|
|
@ -564,7 +625,10 @@ generate_call:
|
|||
uop_LOG_INSTR(ir, opcode | (last_prefix << 8));
|
||||
#endif
|
||||
|
||||
uop_MOV_IMM(ir, IREG_pc, op_pc+pc_off);
|
||||
if (op_table == x86_dynarec_opcodes_3DNOW)
|
||||
uop_MOV_IMM(ir, IREG_pc, next_pc);
|
||||
else
|
||||
uop_MOV_IMM(ir, IREG_pc, op_pc+pc_off);
|
||||
uop_MOV_IMM(ir, IREG_oldpc, old_pc);
|
||||
if (op_32 != last_op_32)
|
||||
uop_MOV_IMM(ir, IREG_op32, op_32);
|
||||
|
|
|
|||
|
|
@ -119,9 +119,14 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
#define OPCODE_CMGT_V8B (0x0e203400)
|
||||
#define OPCODE_CMGT_V4H (0x0e603400)
|
||||
#define OPCODE_CMGT_V2S (0x0ea03400)
|
||||
#define OPCODE_DUP_V2S (0x0e040400)
|
||||
#define OPCODE_EOR_V (0x2e201c00)
|
||||
#define OPCODE_FABS_D (0x1e60c000)
|
||||
#define OPCODE_FADD_D (0x1e602800)
|
||||
#define OPCODE_FADD_V2S (0x0e20d400)
|
||||
#define OPCODE_FCMEQ_V2S (0x0e20e400)
|
||||
#define OPCODE_FCMGE_V2S (0x2e20e400)
|
||||
#define OPCODE_FCMGT_V2S (0x2ea0e400)
|
||||
#define OPCODE_FCMP_D (0x1e602000)
|
||||
#define OPCODE_FCVT_D_S (0x1e22c000)
|
||||
#define OPCODE_FCVT_S_D (0x1e624000)
|
||||
|
|
@ -133,17 +138,25 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
#define OPCODE_FCVTPS_X_D (0x9e680000)
|
||||
#define OPCODE_FCVTZS_W_D (0x1e780000)
|
||||
#define OPCODE_FCVTZS_X_D (0x9e780000)
|
||||
#define OPCODE_FCVTZS_V2S (0x0ea1b800)
|
||||
#define OPCODE_FDIV_D (0x1e601800)
|
||||
#define OPCODE_FDIV_S (0x1e201800)
|
||||
#define OPCODE_FMAX_V2S (0x0e20f400)
|
||||
#define OPCODE_FMIN_V2S (0x0ea0f400)
|
||||
#define OPCODE_FMOV_D_D (0x1e604000)
|
||||
#define OPCODE_FMOV_D_Q (0x9e670000)
|
||||
#define OPCODE_FMOV_Q_D (0x9e660000)
|
||||
#define OPCODE_FMOV_S_W (0x1e270000)
|
||||
#define OPCODE_FMOV_W_S (0x1e260000)
|
||||
#define OPCODE_FMOV_S_ONE (0x1e2e1000)
|
||||
#define OPCODE_FMUL_D (0x1e600800)
|
||||
#define OPCODE_FMUL_V2S (0x2e20dc00)
|
||||
#define OPCODE_FNEG_D (0x1e614000)
|
||||
#define OPCODE_FRINTX_D (0x1e674000)
|
||||
#define OPCODE_FSQRT_D (0x1e61c000)
|
||||
#define OPCODE_FSQRT_S (0x1e21c000)
|
||||
#define OPCODE_FSUB_D (0x1e603800)
|
||||
#define OPCODE_FSUB_V2S (0x0ea0d400)
|
||||
#define OPCODE_LDR_REG (0xb8606800)
|
||||
#define OPCODE_LDRX_REG (0xf8606800)
|
||||
#define OPCODE_LDRB_REG (0x38606800)
|
||||
|
|
@ -227,6 +240,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
|
||||
#define SHRN_SHIFT_IMM_V4S(shift) (((shift) | 0x10) << 16)
|
||||
|
||||
#define DUP_ELEMENT(element) ((element) << 19)
|
||||
|
||||
static int literal_offset = 0;
|
||||
void codegen_reset_literal_pool(codeblock_t *block)
|
||||
{
|
||||
|
|
@ -662,6 +677,11 @@ void host_arm64_CSEL_VS(codeblock_t *block, int dst_reg, int src_n_reg, int src_
|
|||
codegen_addlong(block, OPCODE_CSEL | CSEL_COND(COND_VS) | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
||||
}
|
||||
|
||||
void host_arm64_DUP_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int element)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_DUP_V2S | Rd(dst_reg) | Rn(src_n_reg) | DUP_ELEMENT(element));
|
||||
}
|
||||
|
||||
void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
|
||||
{
|
||||
if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */
|
||||
|
|
@ -692,6 +712,22 @@ void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m
|
|||
{
|
||||
codegen_addlong(block, OPCODE_FADD_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
||||
}
|
||||
void host_arm64_FADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_FADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
||||
}
|
||||
void host_arm64_FCMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_FCMEQ_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
||||
}
|
||||
void host_arm64_FCMGE_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_FCMGE_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
||||
}
|
||||
void host_arm64_FCMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_FCMGT_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
||||
}
|
||||
|
||||
void host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg)
|
||||
{
|
||||
|
|
@ -739,21 +775,46 @@ void host_arm64_FCVTZS_X_D(codeblock_t *block, int dst_reg, int src_reg)
|
|||
{
|
||||
codegen_addlong(block, OPCODE_FCVTZS_X_D | Rd(dst_reg) | Rn(src_reg));
|
||||
}
|
||||
void host_arm64_FCVTZS_V2S(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_FCVTZS_V2S | Rd(dst_reg) | Rn(src_reg));
|
||||
}
|
||||
|
||||
void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_FDIV_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
||||
}
|
||||
void host_arm64_FDIV_S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_FDIV_S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
||||
}
|
||||
|
||||
void host_arm64_FMAX_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_FMAX_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
||||
}
|
||||
void host_arm64_FMIN_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_FMIN_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
||||
}
|
||||
|
||||
void host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_FMUL_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
||||
}
|
||||
void host_arm64_FMUL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_FMUL_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
||||
}
|
||||
|
||||
void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_FSUB_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
||||
}
|
||||
void host_arm64_FSUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_FSUB_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
||||
}
|
||||
|
||||
void host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
|
|
@ -775,6 +836,10 @@ void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg)
|
|||
{
|
||||
codegen_addlong(block, OPCODE_FMOV_W_S | Rd(dst_reg) | Rn(src_reg));
|
||||
}
|
||||
void host_arm64_FMOV_S_ONE(codeblock_t *block, int dst_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_FMOV_S_ONE | Rd(dst_reg));
|
||||
}
|
||||
|
||||
void host_arm64_FNEG_D(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
|
|
@ -790,6 +855,10 @@ void host_arm64_FSQRT_D(codeblock_t *block, int dst_reg, int src_reg)
|
|||
{
|
||||
codegen_addlong(block, OPCODE_FSQRT_D | Rd(dst_reg) | Rn(src_reg));
|
||||
}
|
||||
void host_arm64_FSQRT_S(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_FSQRT_S | Rd(dst_reg) | Rn(src_reg));
|
||||
}
|
||||
|
||||
void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ void host_arm64_CSEL_CC(codeblock_t *block, int dst_reg, int src_n_reg, int src_
|
|||
void host_arm64_CSEL_EQ(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
void host_arm64_CSEL_VS(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
|
||||
void host_arm64_DUP_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int element);
|
||||
|
||||
void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
||||
void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||
void host_arm64_EOR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
|
|
@ -78,10 +80,17 @@ void host_arm64_EOR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int sr
|
|||
void host_arm64_FABS_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
void host_arm64_FADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
void host_arm64_FCMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
void host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg);
|
||||
void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
void host_arm64_FDIV_S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
void host_arm64_FMAX_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
void host_arm64_FMIN_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
void host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
void host_arm64_FMUL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
void host_arm64_FSUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
|
||||
void host_arm64_FCVT_D_S(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
|
@ -94,16 +103,19 @@ void host_arm64_FCVTPS_W_D(codeblock_t *block, int dst_reg, int src_reg);
|
|||
void host_arm64_FCVTPS_X_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_arm64_FCVTZS_W_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_arm64_FCVTZS_X_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_arm64_FCVTZS_V2S(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_arm64_FMOV_D_Q(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_arm64_FMOV_Q_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_arm64_FMOV_S_W(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_arm64_FMOV_S_ONE(codeblock_t *block, int dst_reg);
|
||||
|
||||
void host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_arm64_FSQRT_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_arm64_FSQRT_S(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
|
||||
|
||||
|
|
|
|||
|
|
@ -1682,6 +1682,182 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_PF2ID(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
host_arm64_FCVTZS_V2S(block, dest_reg, src_reg_a);
|
||||
}
|
||||
else
|
||||
fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFADD(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_FADD_V2S(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_FCMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_FCMGE_V2S(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_FCMGT_V2S(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFMAX(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_FMAX_V2S(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFMIN(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_FMIN_V2S(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFMUL(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_FMUL_V2S(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFRCP(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
/*TODO: This could be improved (use VRECPE/VRECPS)*/
|
||||
host_arm_FMOV_S_ONE(block, REG_D_TEMP);
|
||||
host_arm_FDIV_S(block, dest_reg, REG_D_TEMP, src_reg_a);
|
||||
host_arm_DUP_V2S(block, dest_reg, dest_reg, 0);
|
||||
}
|
||||
else
|
||||
fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
/*TODO: This could be improved (use VRSQRTE/VRSQRTS)*/
|
||||
host_arm_FSQRT_S(block, REG_D_TEMP, src_reg_a);
|
||||
host_arm_FMOV_S_ONE(block, REG_D_TEMP);
|
||||
host_arm_FDIV_S(block, dest_reg, dest_reg, REG_D_TEMP);
|
||||
host_arm_DUP_V2S(block, dest_reg, dest_reg, 0);
|
||||
}
|
||||
else
|
||||
fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFSUB(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_FSUB_V2S(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PI2FD(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
host_arm64_SCVTF_V2S(block, dest_reg, src_reg_a);
|
||||
}
|
||||
else
|
||||
fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_PMADDWD(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
|
@ -2629,6 +2805,19 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW,
|
||||
[UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD,
|
||||
|
||||
[UOP_PF2ID & UOP_MASK] = codegen_PF2ID,
|
||||
[UOP_PFADD & UOP_MASK] = codegen_PFADD,
|
||||
[UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ,
|
||||
[UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE,
|
||||
[UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT,
|
||||
[UOP_PFMAX & UOP_MASK] = codegen_PFMAX,
|
||||
[UOP_PFMIN & UOP_MASK] = codegen_PFMIN,
|
||||
[UOP_PFMUL & UOP_MASK] = codegen_PFMUL,
|
||||
[UOP_PFRCP & UOP_MASK] = codegen_PFRCP,
|
||||
[UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT,
|
||||
[UOP_PFSUB & UOP_MASK] = codegen_PFSUB,
|
||||
[UOP_PI2FD & UOP_MASK] = codegen_PI2FD,
|
||||
|
||||
[UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD,
|
||||
[UOP_PMULHW & UOP_MASK] = codegen_PMULHW,
|
||||
[UOP_PMULLW & UOP_MASK] = codegen_PMULLW,
|
||||
|
|
|
|||
|
|
@ -91,11 +91,15 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
#define OPCODE_VADD_I8 0xf2000800
|
||||
#define OPCODE_VADD_I16 0xf2100800
|
||||
#define OPCODE_VADD_I32 0xf2200800
|
||||
#define OPCODE_VADD_F32 0xf2000d00
|
||||
#define OPCODE_VAND_D 0xf2000110
|
||||
#define OPCODE_VBIC_D 0xf2100110
|
||||
#define OPCODE_VCEQ_F32 0xf2000e00
|
||||
#define OPCODE_VCEQ_I8 0xf3000810
|
||||
#define OPCODE_VCEQ_I16 0xf3100810
|
||||
#define OPCODE_VCEQ_I32 0xf3200810
|
||||
#define OPCODE_VCGE_F32 0xf3000e00
|
||||
#define OPCODE_VCGT_F32 0xf3200e00
|
||||
#define OPCODE_VCGT_S8 0xf2000300
|
||||
#define OPCODE_VCGT_S16 0xf2100300
|
||||
#define OPCODE_VCGT_S32 0xf2200300
|
||||
|
|
@ -103,12 +107,17 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
#define OPCODE_VCVT_D_IS 0xeeb80bc0
|
||||
#define OPCODE_VCVT_D_S 0xeeb70ac0
|
||||
#define OPCODE_VCVT_IS_D 0xeebd0bc0
|
||||
#define OPCODE_VCVT_S32_F32 0xf3bb0680
|
||||
#define OPCODE_VCVT_S_D 0xeeb70bc0
|
||||
#define OPCODE_VCVTR_IS_D 0xeebd0b40
|
||||
#define OPCODE_VDIV 0xee800b00
|
||||
#define OPCODE_VDIV_S 0xee800a00
|
||||
#define OPCODE_VDUP_32 0xf3b40c00
|
||||
#define OPCODE_VEOR_D 0xf3000110
|
||||
#define OPCODE_VLDR_D 0xed900b00
|
||||
#define OPCODE_VLDR_S 0xed900a00
|
||||
#define OPCODE_VMAX_F32 0xf200f00
|
||||
#define OPCODE_VMIN_F32 0xf220f00
|
||||
#define OPCODE_VMOV_32_S 0xee100a10
|
||||
#define OPCODE_VMOV_64_D 0xec500b10
|
||||
#define OPCODE_VMOV_D_64 0xec400b10
|
||||
|
|
@ -116,9 +125,11 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
#define OPCODE_VMOV_D_D 0xeeb00b40
|
||||
#define OPCODE_VMOVN_I32 0xf3b60200
|
||||
#define OPCODE_VMOVN_I64 0xf3ba0200
|
||||
#define OPCODE_VMOV_F32_ONE 0xf2870f10
|
||||
#define OPCODE_VMRS_APSR 0xeef1fa10
|
||||
#define OPCODE_VMSR_FPSCR 0xeee10a10
|
||||
#define OPCODE_VMUL 0xee200b00
|
||||
#define OPCODE_VMUL_F32 0xf3000d10
|
||||
#define OPCODE_VMUL_S16 0xf2100910
|
||||
#define OPCODE_VMULL_S16 0xf2900c00
|
||||
#define OPCODE_VNEG_D 0xeeb10b40
|
||||
|
|
@ -148,6 +159,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
#define OPCODE_VSHR_D_U64 0xf3800090
|
||||
#define OPCODE_VSHRN 0xf2800810
|
||||
#define OPCODE_VSQRT_D 0xeeb10bc0
|
||||
#define OPCODE_VSQRT_S 0xeeb10ac0
|
||||
#define OPCODE_VSTR_D 0xed800b00
|
||||
#define OPCODE_VSTR_S 0xed800a00
|
||||
#define OPCODE_VSUB 0xee300b40
|
||||
|
|
@ -193,6 +205,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
|
||||
#define VSHIFT_IMM_32(shift) (((16 - (shift)) | 0x10) << 16)
|
||||
|
||||
#define VDUP_32_IMM(imm) ((imm) << 19)
|
||||
|
||||
static inline uint32_t arm_data_offset(int offset)
|
||||
{
|
||||
if (offset < -0xffc || offset > 0xffc)
|
||||
|
|
@ -808,6 +822,10 @@ void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg
|
|||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_VADD | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
}
|
||||
void host_arm_VADD_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_VADD_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
}
|
||||
void host_arm_VADD_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_VADD_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
|
|
@ -833,6 +851,10 @@ void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m)
|
|||
codegen_addlong(block, COND_AL | OPCODE_VCMP_D | Rd(src_reg_d) | Rm(src_reg_m));
|
||||
}
|
||||
|
||||
void host_arm_VCEQ_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_VCEQ_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
}
|
||||
void host_arm_VCEQ_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_VCEQ_I8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
|
|
@ -845,6 +867,14 @@ void host_arm_VCEQ_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_r
|
|||
{
|
||||
codegen_addlong(block, OPCODE_VCEQ_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
}
|
||||
void host_arm_VCGE_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_VCGE_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
}
|
||||
void host_arm_VCGT_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_VCGT_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
}
|
||||
void host_arm_VCGT_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_VCGT_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
|
|
@ -870,6 +900,10 @@ void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg)
|
|||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_VCVT_IS_D | Vd(dest_reg) | Vm(src_reg));
|
||||
}
|
||||
void host_arm_VCVT_S32_F32(codeblock_t *block, int dest_reg, int src_reg)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_VCVT_S32_F32 | Vd(dest_reg) | Vm(src_reg));
|
||||
}
|
||||
void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_VCVT_S_D | Vd(dest_reg) | Vm(src_reg));
|
||||
|
|
@ -882,6 +916,14 @@ void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg
|
|||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_VDIV | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
}
|
||||
void host_arm_VDIV_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_VDIV_S | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
}
|
||||
void host_arm_VDUP_32(codeblock_t *block, int dst_reg, int src_reg_m, int imm)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_VDUP_32 | Rd(dst_reg) | Rm(src_reg_m) | VDUP_32_IMM(imm));
|
||||
}
|
||||
void host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_VEOR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
|
|
@ -926,6 +968,10 @@ void host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg)
|
|||
{
|
||||
codegen_addlong(block, OPCODE_VMOVN_I64 | Vd(dest_reg) | Vm(src_reg));
|
||||
}
|
||||
void host_arm_VMOV_F32_ONE(codeblock_t *block, int dst_reg)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_VMOV_F32_ONE | Rd(src_reg));
|
||||
}
|
||||
void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_VMSR_FPSCR | Rd(src_reg));
|
||||
|
|
@ -935,10 +981,23 @@ void host_arm_VMRS_APSR(codeblock_t *block)
|
|||
codegen_addlong(block, COND_AL | OPCODE_VMRS_APSR);
|
||||
}
|
||||
|
||||
void host_arm_VMAX_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_VMAX_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
}
|
||||
void host_arm_VMIN_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_VMIN_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
}
|
||||
|
||||
void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_VMUL | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
}
|
||||
void host_arm_VMUL_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_VMUL_F32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
}
|
||||
void host_arm_VMUL_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_VMUL_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||
|
|
@ -1082,6 +1141,10 @@ void host_arm_VSQRT_D(codeblock_t *block, int dest_reg, int src_reg)
|
|||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_VSQRT_D | Vd(dest_reg) | Vm(src_reg));
|
||||
}
|
||||
void host_arm_VSQRT_S(codeblock_t *block, int dest_reg, int src_reg)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_VSQRT_S | Vd(dest_reg) | Vm(src_reg));
|
||||
}
|
||||
|
||||
void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -145,13 +145,17 @@ void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg
|
|||
void host_arm_VADD_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VADD_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VADD_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VADD_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VAND_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VBIC_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m);
|
||||
|
||||
void host_arm_VCEQ_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VCEQ_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VCEQ_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VCEQ_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VCGE_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VCGT_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VCGT_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VCGT_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VCGT_S32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
|
|
@ -161,9 +165,11 @@ void host_arm_VCHS_D(codeblock_t *block, int dest_reg, int src_reg);
|
|||
void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg);
|
||||
void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg);
|
||||
void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||
void host_arm_VCVT_S32_F32(codeblock_t *block, int dest_reg, int src_reg);
|
||||
void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||
void host_arm_VCVTR_IS_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||
void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VDIV_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||
void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||
|
|
@ -179,7 +185,13 @@ void host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg);
|
|||
void host_arm_VMRS_APSR(codeblock_t *block);
|
||||
void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg);
|
||||
|
||||
void host_arm_VMAX_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VMIN_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
|
||||
void host_arm_VMOV_F32_ONE(codeblock_t *block, int dst_reg);
|
||||
|
||||
void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VMUL_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VMUL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VMULL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src_reg_m);
|
||||
|
||||
|
|
@ -216,10 +228,12 @@ void host_arm_VSHR_D_U64(codeblock_t *block, int dest_reg, int src_reg, int shif
|
|||
void host_arm_VSHRN_32(codeblock_t *block, int dest_reg, int src_reg, int shift);
|
||||
|
||||
void host_arm_VSQRT_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||
void host_arm_VSQRT_S(codeblock_t *block, int dest_reg, int src_reg);
|
||||
|
||||
void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset);
|
||||
void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset);
|
||||
void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VSUB_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VSUB_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
void host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||
|
|
|
|||
|
|
@ -1806,6 +1806,182 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_PF2ID(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
host_arm_VCVT_S32_F32(block, dest_reg, src_reg_a);
|
||||
}
|
||||
else
|
||||
fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFADD(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_VADD_F32(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_VCEQ_F32(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_VCGE_F32(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_VCGT_F32(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFMAX(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_VMAX_F32(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFMIN(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_VMIN_F32(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFMUL(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_VMUL_F32(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFRCP(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
/*TODO: This could be improved (use VRECPE/VRECPS)*/
|
||||
host_arm_VMOV_F32_ONE(block, REG_D_TEMP);
|
||||
host_arm_VDIV_S(block, dest_reg, REG_D_TEMP, src_reg_a);
|
||||
host_arm_VDUP_32(block, dest_reg, dest_reg, 0);
|
||||
}
|
||||
else
|
||||
fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
/*TODO: This could be improved (use VRSQRTE/VRSQRTS)*/
|
||||
host_arm_VSQRT_S(block, REG_D_TEMP, src_reg_a);
|
||||
host_arm_VMOV_F32_ONE(block, REG_D_TEMP);
|
||||
host_arm_VDIV_S(block, dest_reg, dest_reg, REG_D_TEMP);
|
||||
host_arm_VDUP_32(block, dest_reg, dest_reg, 0);
|
||||
}
|
||||
else
|
||||
fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFSUB(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_arm_VSUB_F32(block, dest_reg, src_reg_a, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PI2FD(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
host_arm_VCVT_Q_F32_IS(block, dest_reg, src_reg_a);
|
||||
}
|
||||
else
|
||||
fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_PMADDWD(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
|
@ -2775,6 +2951,19 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW,
|
||||
[UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD,
|
||||
|
||||
[UOP_PF2ID & UOP_MASK] = codegen_PF2ID,
|
||||
[UOP_PFADD & UOP_MASK] = codegen_PFADD,
|
||||
[UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ,
|
||||
[UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE,
|
||||
[UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT,
|
||||
[UOP_PFMAX & UOP_MASK] = codegen_PFMAX,
|
||||
[UOP_PFMIN & UOP_MASK] = codegen_PFMIN,
|
||||
[UOP_PFMUL & UOP_MASK] = codegen_PFMUL,
|
||||
[UOP_PFRCP & UOP_MASK] = codegen_PFRCP,
|
||||
[UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT,
|
||||
[UOP_PFSUB & UOP_MASK] = codegen_PFSUB,
|
||||
[UOP_PI2FD & UOP_MASK] = codegen_PI2FD,
|
||||
|
||||
[UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD,
|
||||
[UOP_PMULHW & UOP_MASK] = codegen_PMULHW,
|
||||
[UOP_PMULLW & UOP_MASK] = codegen_PMULLW,
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
|||
host_x86_PUSH(block, REG_RAX);
|
||||
host_x86_PUSH(block, REG_RDX);
|
||||
#if WIN64
|
||||
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20);
|
||||
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x28);
|
||||
if (size == 4 && is_float)
|
||||
host_x86_MOVD_REG_XREG(block, REG_EDX, REG_XMM_TEMP); //data
|
||||
else if (size == 8)
|
||||
|
|
@ -227,7 +227,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
|||
else if (size == 8)
|
||||
host_x86_CALL(block, (void *)writememql);
|
||||
#if WIN64
|
||||
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20);
|
||||
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x28);
|
||||
#endif
|
||||
host_x86_POP(block, REG_RDX);
|
||||
host_x86_POP(block, REG_RAX);
|
||||
|
|
|
|||
|
|
@ -212,6 +212,10 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int
|
|||
codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3));
|
||||
|
|
@ -341,11 +345,25 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b)
|
|||
codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type)
|
||||
{
|
||||
codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/
|
||||
}
|
||||
|
||||
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3));
|
||||
}
|
||||
|
||||
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/
|
||||
}
|
||||
|
||||
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/
|
||||
|
|
@ -364,6 +382,10 @@ void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
|||
{
|
||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2a); /*CVTSI2SD dst_reg, src_reg*/
|
||||
|
|
@ -384,6 +406,10 @@ void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
|||
{
|
||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3));
|
||||
}
|
||||
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/
|
||||
}
|
||||
|
||||
void host_x86_JMP(codeblock_t *block, void *p)
|
||||
{
|
||||
|
|
@ -1216,6 +1242,19 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p)
|
|||
fatal("host_x86_MOVZX_REG_ABS_32_8 - bad offset %i\n", offset);
|
||||
}
|
||||
|
||||
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/
|
||||
}
|
||||
|
||||
void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3));
|
||||
|
|
@ -1635,6 +1674,10 @@ void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
|||
{
|
||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/
|
||||
}
|
||||
|
||||
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
|
|
@ -1714,6 +1757,10 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int
|
|||
codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3));
|
||||
|
|
@ -1751,6 +1798,11 @@ void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data)
|
|||
}
|
||||
}
|
||||
|
||||
void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3));
|
||||
}
|
||||
|
||||
void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s
|
|||
void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
|
|
@ -27,17 +28,27 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
|||
void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||
void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||
|
||||
#define CMPPS_EQ 0
|
||||
#define CMPPS_NLT 5
|
||||
#define CMPPS_NLE 6
|
||||
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type);
|
||||
|
||||
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||
|
||||
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_JMP(codeblock_t *block, void *p);
|
||||
|
||||
|
|
@ -146,7 +157,11 @@ void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
|
|||
|
||||
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p);
|
||||
|
||||
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_MULSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
|
||||
|
|
@ -240,6 +255,7 @@ void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift);
|
|||
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||
|
||||
void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
|
||||
|
|
@ -250,6 +266,7 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s
|
|||
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
|
||||
|
|
@ -257,6 +274,8 @@ void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg)
|
|||
void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg);
|
||||
void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||
|
||||
void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
|
||||
void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
|
||||
|
|
|
|||
|
|
@ -1569,6 +1569,191 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_PF2ID(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a);
|
||||
}
|
||||
else
|
||||
fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFADD(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_ADDPS_XREG_XREG(block, dest_reg, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_EQ);
|
||||
}
|
||||
else
|
||||
fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLT);
|
||||
}
|
||||
else
|
||||
fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLE);
|
||||
}
|
||||
else
|
||||
fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFMAX(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_MAXPS_XREG_XREG(block, dest_reg, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFMIN(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_MINPS_XREG_XREG(block, dest_reg, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFMUL(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_MULPS_XREG_XREG(block, dest_reg, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFRCP(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
/*TODO: This could be improved (use RCPSS + iteration)*/
|
||||
host_x86_MOV32_REG_IMM(block, REG_ECX, 1);
|
||||
host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a);
|
||||
host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX);
|
||||
host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP);
|
||||
host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg);
|
||||
}
|
||||
else
|
||||
fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
/*TODO: This could be improved (use RSQRTSS + iteration)*/
|
||||
host_x86_SQRTSS_XREG_XREG(block, REG_XMM_TEMP, src_reg_a);
|
||||
host_x86_MOV32_REG_IMM(block, REG_ECX, 1);
|
||||
host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX);
|
||||
host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP);
|
||||
host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg);
|
||||
}
|
||||
else
|
||||
fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFSUB(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_SUBPS_XREG_XREG(block, dest_reg, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a);
|
||||
host_x86_SUBPS_XREG_XREG(block, REG_XMM_TEMP, src_reg_b);
|
||||
host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP);
|
||||
}
|
||||
else
|
||||
fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PI2FD(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
host_x86_CVTDQ2PS_XREG_XREG(block, dest_reg, src_reg_a);
|
||||
}
|
||||
else
|
||||
fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_PMADDWD(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
|
@ -2384,6 +2569,19 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW,
|
||||
[UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD,
|
||||
|
||||
[UOP_PF2ID & UOP_MASK] = codegen_PF2ID,
|
||||
[UOP_PFADD & UOP_MASK] = codegen_PFADD,
|
||||
[UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ,
|
||||
[UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE,
|
||||
[UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT,
|
||||
[UOP_PFMAX & UOP_MASK] = codegen_PFMAX,
|
||||
[UOP_PFMIN & UOP_MASK] = codegen_PFMIN,
|
||||
[UOP_PFMUL & UOP_MASK] = codegen_PFMUL,
|
||||
[UOP_PFRCP & UOP_MASK] = codegen_PFRCP,
|
||||
[UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT,
|
||||
[UOP_PFSUB & UOP_MASK] = codegen_PFSUB,
|
||||
[UOP_PI2FD & UOP_MASK] = codegen_PI2FD,
|
||||
|
||||
[UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD,
|
||||
[UOP_PMULHW & UOP_MASK] = codegen_PMULHW,
|
||||
[UOP_PMULLW & UOP_MASK] = codegen_PMULLW,
|
||||
|
|
|
|||
|
|
@ -185,6 +185,10 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int
|
|||
codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3));
|
||||
|
|
@ -309,11 +313,25 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b)
|
|||
codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type)
|
||||
{
|
||||
codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/
|
||||
}
|
||||
|
||||
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3));
|
||||
}
|
||||
|
||||
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/
|
||||
}
|
||||
|
||||
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/
|
||||
|
|
@ -327,6 +345,10 @@ void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
|||
{
|
||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
|
||||
}
|
||||
|
||||
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
|
|
@ -340,7 +362,11 @@ void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base
|
|||
|
||||
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3));
|
||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSD dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/
|
||||
}
|
||||
|
||||
void host_x86_INC32_ABS(codeblock_t *block, void *p)
|
||||
|
|
@ -1024,6 +1050,19 @@ void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_r
|
|||
codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, W[base_reg + idx_reg]*/
|
||||
}
|
||||
|
||||
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/
|
||||
}
|
||||
|
||||
void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3));
|
||||
|
|
@ -1406,6 +1445,10 @@ void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
|||
{
|
||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/
|
||||
}
|
||||
|
||||
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
|
|
@ -1476,6 +1519,10 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int
|
|||
codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3));
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s
|
|||
void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
|
|
@ -27,17 +28,27 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
|||
void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||
void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||
|
||||
#define CMPPS_EQ 0
|
||||
#define CMPPS_NLT 5
|
||||
#define CMPPS_NLE 6
|
||||
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type);
|
||||
|
||||
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dest_reg, int src_reg);
|
||||
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dest_reg, int src_reg);
|
||||
void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||
|
||||
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_INC32_ABS(codeblock_t *block, void *p);
|
||||
|
||||
|
|
@ -148,6 +159,10 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p);
|
|||
void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||
void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||
|
||||
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
|
@ -242,6 +257,7 @@ void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift);
|
|||
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||
|
||||
void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
|
||||
|
|
@ -251,6 +267,7 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s
|
|||
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
|
||||
|
|
|
|||
|
|
@ -1572,6 +1572,191 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_PF2ID(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
host_x86_CVTPS2DQ_XREG_XREG(block, dest_reg, src_reg_a);
|
||||
}
|
||||
else
|
||||
fatal("PF2ID %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFADD(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_ADDPS_XREG_XREG(block, dest_reg, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFCMPEQ(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_EQ);
|
||||
}
|
||||
else
|
||||
fatal("PFCMPEQ %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFCMPGE(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLT);
|
||||
}
|
||||
else
|
||||
fatal("PFCMPGE %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFCMPGT(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_CMPPS_XREG_XREG(block, dest_reg, src_reg_b, CMPPS_NLE);
|
||||
}
|
||||
else
|
||||
fatal("PFCMPGT %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFMAX(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_MAXPS_XREG_XREG(block, dest_reg, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFMAX %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFMIN(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_MINPS_XREG_XREG(block, dest_reg, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFMIN %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFMUL(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_MULPS_XREG_XREG(block, dest_reg, src_reg_b);
|
||||
}
|
||||
else
|
||||
fatal("PFMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFRCP(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
/*TODO: This could be improved (use RCPSS + iteration)*/
|
||||
host_x86_MOV32_REG_IMM(block, REG_ECX, 1);
|
||||
host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a);
|
||||
host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX);
|
||||
host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP);
|
||||
host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg);
|
||||
}
|
||||
else
|
||||
fatal("PFRCP %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFRSQRT(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
/*TODO: This could be improved (use RSQRTSS + iteration)*/
|
||||
host_x86_SQRTSS_XREG_XREG(block, REG_XMM_TEMP, src_reg_a);
|
||||
host_x86_MOV32_REG_IMM(block, REG_ECX, 1);
|
||||
host_x86_CVTSI2SS_XREG_REG(block, dest_reg, REG_ECX);
|
||||
host_x86_DIVSS_XREG_XREG(block, dest_reg, REG_XMM_TEMP);
|
||||
host_x86_UNPCKLPS_XREG_XREG(block, dest_reg, dest_reg);
|
||||
}
|
||||
else
|
||||
fatal("PFRSQRT %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PFSUB(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real)
|
||||
{
|
||||
host_x86_SUBPS_XREG_XREG(block, dest_reg, src_reg_b);
|
||||
}
|
||||
else if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b))
|
||||
{
|
||||
host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg_a);
|
||||
host_x86_SUBPS_XREG_XREG(block, REG_XMM_TEMP, src_reg_b);
|
||||
host_x86_MOVQ_XREG_XREG(block, dest_reg, REG_XMM_TEMP);
|
||||
}
|
||||
else
|
||||
fatal("PFSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_PI2FD(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a))
|
||||
{
|
||||
host_x86_CVTDQ2PS_XREG_XREG(block, dest_reg, src_reg_a);
|
||||
}
|
||||
else
|
||||
fatal("PI2FD %02x %02x\n", uop->dest_reg_a_real);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_PMADDWD(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
|
@ -2394,6 +2579,19 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW,
|
||||
[UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD,
|
||||
|
||||
[UOP_PF2ID & UOP_MASK] = codegen_PF2ID,
|
||||
[UOP_PFADD & UOP_MASK] = codegen_PFADD,
|
||||
[UOP_PFCMPEQ & UOP_MASK] = codegen_PFCMPEQ,
|
||||
[UOP_PFCMPGE & UOP_MASK] = codegen_PFCMPGE,
|
||||
[UOP_PFCMPGT & UOP_MASK] = codegen_PFCMPGT,
|
||||
[UOP_PFMAX & UOP_MASK] = codegen_PFMAX,
|
||||
[UOP_PFMIN & UOP_MASK] = codegen_PFMIN,
|
||||
[UOP_PFMUL & UOP_MASK] = codegen_PFMUL,
|
||||
[UOP_PFRCP & UOP_MASK] = codegen_PFRCP,
|
||||
[UOP_PFRSQRT & UOP_MASK] = codegen_PFRSQRT,
|
||||
[UOP_PFSUB & UOP_MASK] = codegen_PFSUB,
|
||||
[UOP_PI2FD & UOP_MASK] = codegen_PI2FD,
|
||||
|
||||
[UOP_PMADDWD & UOP_MASK] = codegen_PMADDWD,
|
||||
[UOP_PMULHW & UOP_MASK] = codegen_PMULHW,
|
||||
[UOP_PMULLW & UOP_MASK] = codegen_PMULLW,
|
||||
|
|
|
|||
|
|
@ -281,7 +281,32 @@
|
|||
/*UOP_PMADDWD - (packed word) dest_reg = (src_reg_a * src_reg_b) >> 16*/
|
||||
#define UOP_PMADDWD (UOP_TYPE_PARAMS_REGS | 0xb9)
|
||||
|
||||
#define UOP_MAX 0xba
|
||||
/*UOP_PFADD - (packed float) dest_reg = src_reg_a + src_reg_b*/
|
||||
#define UOP_PFADD (UOP_TYPE_PARAMS_REGS | 0xba)
|
||||
/*UOP_PFSUB - (packed float) dest_reg = src_reg_a - src_reg_b*/
|
||||
#define UOP_PFSUB (UOP_TYPE_PARAMS_REGS | 0xbb)
|
||||
/*UOP_PFMUL - (packed float) dest_reg = src_reg_a * src_reg_b*/
|
||||
#define UOP_PFMUL (UOP_TYPE_PARAMS_REGS | 0xbc)
|
||||
/*UOP_PFMAX - (packed float) dest_reg = MAX(src_reg_a, src_reg_b)*/
|
||||
#define UOP_PFMAX (UOP_TYPE_PARAMS_REGS | 0xbd)
|
||||
/*UOP_PFMIN - (packed float) dest_reg = MIN(src_reg_a, src_reg_b)*/
|
||||
#define UOP_PFMIN (UOP_TYPE_PARAMS_REGS | 0xbe)
|
||||
/*UOP_PFCMPEQ - (packed float) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/
|
||||
#define UOP_PFCMPEQ (UOP_TYPE_PARAMS_REGS | 0xbf)
|
||||
/*UOP_PFCMPGE - (packed float) dest_reg = (src_reg_a >= src_reg_b) ? ~0 : 0*/
|
||||
#define UOP_PFCMPGE (UOP_TYPE_PARAMS_REGS | 0xc0)
|
||||
/*UOP_PFCMPGT - (packed float) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/
|
||||
#define UOP_PFCMPGT (UOP_TYPE_PARAMS_REGS | 0xc1)
|
||||
/*UOP_PF2ID - (packed long)dest_reg = (packed float)src_reg_a*/
|
||||
#define UOP_PF2ID (UOP_TYPE_PARAMS_REGS | 0xc2)
|
||||
/*UOP_PI2FD - (packed float)dest_reg = (packed long)src_reg_a*/
|
||||
#define UOP_PI2FD (UOP_TYPE_PARAMS_REGS | 0xc3)
|
||||
/*UOP_PFRCP - (packed float) dest_reg[0] = dest_reg[1] = 1.0 / src_reg[0]*/
|
||||
#define UOP_PFRCP (UOP_TYPE_PARAMS_REGS | 0xc4)
|
||||
/*UOP_PFRSQRT - (packed float) dest_reg[0] = dest_reg[1] = 1.0 / sqrt(src_reg[0])*/
|
||||
#define UOP_PFRSQRT (UOP_TYPE_PARAMS_REGS | 0xc5)
|
||||
|
||||
#define UOP_MAX 0xc6
|
||||
|
||||
#define UOP_MASK 0xffff
|
||||
|
||||
|
|
@ -645,6 +670,19 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir,
|
|||
#define uop_PCMPGTW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||
#define uop_PCMPGTD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTD, ir, dst_reg, src_reg_a, src_reg_b)
|
||||
|
||||
#define uop_PF2ID(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PF2ID, ir, dst_reg, src_reg)
|
||||
#define uop_PFADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFADD, ir, dst_reg, src_reg_a, src_reg_b)
|
||||
#define uop_PFCMPEQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPEQ, ir, dst_reg, src_reg_a, src_reg_b)
|
||||
#define uop_PFCMPGE(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGE, ir, dst_reg, src_reg_a, src_reg_b)
|
||||
#define uop_PFCMPGT(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGT, ir, dst_reg, src_reg_a, src_reg_b)
|
||||
#define uop_PFMAX(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMAX, ir, dst_reg, src_reg_a, src_reg_b)
|
||||
#define uop_PFMIN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMIN, ir, dst_reg, src_reg_a, src_reg_b)
|
||||
#define uop_PFMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMUL, ir, dst_reg, src_reg_a, src_reg_b)
|
||||
#define uop_PFRCP(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRCP, ir, dst_reg, src_reg)
|
||||
#define uop_PFRSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRSQRT, ir, dst_reg, src_reg)
|
||||
#define uop_PFSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFSUB, ir, dst_reg, src_reg_a, src_reg_b)
|
||||
#define uop_PI2FD(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PI2FD, ir, dst_reg, src_reg)
|
||||
|
||||
#define uop_PMADDWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMADDWD, ir, dst_reg, src_reg_a, src_reg_b)
|
||||
#define uop_PMULHW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULHW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||
#define uop_PMULLW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULLW, ir, dst_reg, src_reg_a, src_reg_b)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "codegen.h"
|
||||
#include "codegen_ir.h"
|
||||
#include "codegen_ops.h"
|
||||
#include "codegen_ops_3dnow.h"
|
||||
#include "codegen_ops_arith.h"
|
||||
#include "codegen_ops_branch.h"
|
||||
#include "codegen_ops_fpu_arith.h"
|
||||
|
|
@ -116,6 +117,30 @@ RecompOpFn recomp_opcodes_0f[512] =
|
|||
/*f0*/ NULL, NULL, NULL, NULL, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL,
|
||||
};
|
||||
|
||||
RecompOpFn recomp_opcodes_3DNOW[256] =
|
||||
{
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPI2FD, NULL, NULL,
|
||||
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPF2ID, NULL, NULL,
|
||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
||||
/*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,
|
||||
|
||||
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*90*/ ropPFCMPGE, NULL, NULL, NULL, ropPFMIN, NULL, ropPFRCP, ropPFRSQRT, NULL, NULL, ropPFSUB, NULL, NULL, NULL, ropPFADD, NULL,
|
||||
/*a0*/ ropPFCMPGT, NULL, NULL, NULL, ropPFMAX, NULL, ropPFRCPIT, ropPFRSQIT1, NULL, NULL, ropPFSUBR, NULL, NULL, NULL, NULL, NULL,
|
||||
/*b0*/ ropPFCMPEQ, NULL, NULL, NULL, ropPFMUL, NULL, ropPFRCPIT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
||||
/*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,
|
||||
};
|
||||
|
||||
RecompOpFn recomp_opcodes_d8[512] =
|
||||
{
|
||||
/*16-bit data*/
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ typedef uint32_t (*RecompOpFn)(codeblock_t *block, struct ir_data_t *ir, uint8_t
|
|||
|
||||
extern RecompOpFn recomp_opcodes[512];
|
||||
extern RecompOpFn recomp_opcodes_0f[512];
|
||||
extern RecompOpFn recomp_opcodes_3DNOW[256];
|
||||
extern RecompOpFn recomp_opcodes_d8[512];
|
||||
extern RecompOpFn recomp_opcodes_d9[512];
|
||||
extern RecompOpFn recomp_opcodes_da[512];
|
||||
|
|
|
|||
193
src/codegen_ops_3dnow.c
Normal file
193
src/codegen_ops_3dnow.c
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
#include "ibm.h"
|
||||
|
||||
#include "x86.h"
|
||||
#include "x86_flags.h"
|
||||
#include "386_common.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_accumulate.h"
|
||||
#include "codegen_ir.h"
|
||||
#include "codegen_ops.h"
|
||||
#include "codegen_ops_3dnow.h"
|
||||
#include "codegen_ops_helpers.h"
|
||||
|
||||
#define ropParith(func) \
|
||||
uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
|
||||
{ \
|
||||
int dest_reg = (fetchdat >> 3) & 7; \
|
||||
\
|
||||
uop_MMX_ENTER(ir); \
|
||||
if ((fetchdat & 0xc0) == 0xc0) \
|
||||
{ \
|
||||
int src_reg = fetchdat & 7; \
|
||||
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
x86seg *target_seg; \
|
||||
\
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||
codegen_check_seg_read(block, ir, target_seg); \
|
||||
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
|
||||
} \
|
||||
\
|
||||
return op_pc + 2; \
|
||||
}
|
||||
|
||||
ropParith(PFADD)
|
||||
ropParith(PFCMPEQ)
|
||||
ropParith(PFCMPGE)
|
||||
ropParith(PFCMPGT)
|
||||
ropParith(PFMAX)
|
||||
ropParith(PFMIN)
|
||||
ropParith(PFMUL)
|
||||
ropParith(PFSUB)
|
||||
|
||||
uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
uop_PF2ID(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||
}
|
||||
else
|
||||
{
|
||||
x86seg *target_seg;
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||
codegen_check_seg_read(block, ir, target_seg);
|
||||
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||
uop_PF2ID(ir, IREG_MM(dest_reg), IREG_temp0_Q);
|
||||
}
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
|
||||
uint32_t ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
uop_PFSUB(ir, IREG_MM(dest_reg), IREG_MM(src_reg), IREG_MM(dest_reg));
|
||||
}
|
||||
else
|
||||
{
|
||||
x86seg *target_seg;
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||
codegen_check_seg_read(block, ir, target_seg);
|
||||
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||
uop_PFSUB(ir, IREG_MM(dest_reg), IREG_temp0_Q, IREG_MM(dest_reg));
|
||||
}
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
|
||||
uint32_t ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
uop_PI2FD(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||
}
|
||||
else
|
||||
{
|
||||
x86seg *target_seg;
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||
codegen_check_seg_read(block, ir, target_seg);
|
||||
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||
uop_PI2FD(ir, IREG_MM(dest_reg), IREG_temp0_Q);
|
||||
}
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
|
||||
uint32_t ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||
}
|
||||
else
|
||||
{
|
||||
x86seg *target_seg;
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||
codegen_check_seg_read(block, ir, target_seg);
|
||||
uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
|
||||
}
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
uop_PFRCP(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||
}
|
||||
else
|
||||
{
|
||||
x86seg *target_seg;
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||
codegen_check_seg_read(block, ir, target_seg);
|
||||
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||
uop_PFRCP(ir, IREG_MM(dest_reg), IREG_temp0_Q);
|
||||
}
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
int dest_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
uop_MMX_ENTER(ir);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = fetchdat & 7;
|
||||
uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
|
||||
}
|
||||
else
|
||||
{
|
||||
x86seg *target_seg;
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||
codegen_check_seg_read(block, ir, target_seg);
|
||||
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
|
||||
uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_temp0_Q);
|
||||
}
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
|
||||
uint32_t ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
uop_MMX_ENTER(ir);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
15
src/codegen_ops_3dnow.h
Normal file
15
src/codegen_ops_3dnow.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropPFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropPFCMPEQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropPFCMPGE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropPFCMPGT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropPFMAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropPFMIN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropPFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropPFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
Loading…
Reference in a new issue