diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 06d431e..576b12f 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -112,6 +112,12 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_BIC_V (0x0e601c00) #define OPCODE_BLR (0xd63f0000) #define OPCODE_BR (0xd61f0000) +#define OPCODE_CMEQ_V8B (0x2e208c00) +#define OPCODE_CMEQ_V4H (0x2e608c00) +#define OPCODE_CMEQ_V2S (0x2ea08c00) +#define OPCODE_CMGT_V8B (0x0e203400) +#define OPCODE_CMGT_V4H (0x0e603400) +#define OPCODE_CMGT_V2S (0x0ea03400) #define OPCODE_EOR_V (0x2e201c00) #define OPCODE_FADD_D (0x1e602800) #define OPCODE_FCMP_D (0x1e602000) @@ -518,6 +524,31 @@ void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest) codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg)); } +void host_arm64_CMEQ_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_CMEQ_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_CMEQ_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_CMEQ_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_CMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_CMEQ_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_CMGT_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_CMGT_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_CMGT_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_CMGT_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} +void host_arm64_CMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) +{ + codegen_addlong(block, OPCODE_CMGT_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data) { if ((int32_t)imm_data < 0 && imm_data != (1ull << 31)) diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index 699988d..4dba688 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -48,6 +48,13 @@ void host_arm64_BIC_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest); +void host_arm64_CMEQ_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_CMEQ_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_CMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_CMGT_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_CMGT_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_CMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); + void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data); void host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index f19d6b8..4600f21 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1483,6 +1483,91 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PCMPEQB(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_arm64_CMEQ_V8B(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQW(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_CMEQ_V4H(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQD(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_CMEQ_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTB(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_CMGT_V8B(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTW(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_CMGT_V4H(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTD(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_CMGT_V2S(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -2269,6 +2354,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, + [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, + [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, + [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, + [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, + [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 17c29f9..b604f7e 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -92,6 +92,12 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VADD_I32 0xf2200800 #define OPCODE_VAND_D 0xf2000110 #define OPCODE_VBIC_D 0xf2100110 +#define OPCODE_VCEQ_I8 0xf3000810 +#define OPCODE_VCEQ_I16 0xf3100810 +#define OPCODE_VCEQ_I32 0xf3200810 +#define OPCODE_VCGT_S8 0xf2000300 +#define OPCODE_VCGT_S16 0xf2100300 +#define OPCODE_VCGT_S32 0xf2200300 #define OPCODE_VCMP_D 0xeeb40b40 #define OPCODE_VCVT_D_IS 0xeeb80bc0 #define OPCODE_VCVT_D_S 0xeeb70ac0 @@ -802,6 +808,32 @@ 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_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)); +} +void host_arm_VCEQ_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VCEQ_I16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VCEQ_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VCEQ_I32 | 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)); +} +void host_arm_VCGT_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VCGT_S16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} +void host_arm_VCGT_S32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) +{ + codegen_addlong(block, OPCODE_VCGT_S32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); +} + void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VCVT_D_IS | Vd(dest_reg) | Vm(src_reg)); diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 5a1f792..6c7081a 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -146,6 +146,14 @@ void host_arm_VADD_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_r 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_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_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); + 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); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 75d01b0..9f57130 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1603,6 +1603,91 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PCMPEQB(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_VCEQ_I8(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQW(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_VCEQ_I16(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQD(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_VCEQ_I32(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTB(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_VCGT_S8(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTW(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_VCGT_S16(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTD(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_VCGT_S32(block, dest_reg, src_reg_a, src_reg_b); + } + else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real); @@ -2389,6 +2474,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, + [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, + [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, + [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, + [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, + [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index 97bab1f..83a24fd 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -1270,6 +1270,35 @@ void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ } +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ +} + +void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ +} +void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ +} +void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ +} +void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ +} +void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ +} +void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ +} void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { @@ -1346,11 +1375,6 @@ void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ } -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ -} - void host_x86_POP(codeblock_t *block, int dst_reg) { if (dst_reg & 8) diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 119f854..ba2c0a5 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -164,6 +164,14 @@ void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); @@ -183,8 +191,6 @@ void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_POP(codeblock_t *block, int src_reg); void host_x86_PUSH(codeblock_t *block, int src_reg); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 331a12f..4bd8b0e 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -1369,6 +1369,91 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PCMPEQB(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_PCMPEQB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQW(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_PCMPEQW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQD(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_PCMPEQD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTB(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_PCMPGTB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTW(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_PCMPGTW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTD(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_PCMPGTD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); @@ -2040,6 +2125,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, + [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, + [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, + [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, + [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, + [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 1dbee0b..a3e63b7 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -1128,6 +1128,35 @@ void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/ } +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ +} + +void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/ +} +void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/ +} +void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/ +} +void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/ +} +void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/ +} +void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/ +} void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) { @@ -1204,11 +1233,6 @@ void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/ } -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) -{ - codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/ -} - void host_x86_POP(codeblock_t *block, int src_reg) { codegen_addbyte(block, 0x58 | src_reg); /*POP reg*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index f7483c2..bf1e492 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -165,6 +165,14 @@ void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); + +void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); +void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); @@ -184,8 +192,6 @@ void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); -void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); - void host_x86_POP(codeblock_t *block, int src_reg); void host_x86_PUSH(codeblock_t *block, int src_reg); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index 7b5a8de..e8b11b9 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -1372,6 +1372,91 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PCMPEQB(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_PCMPEQB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPEQB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQW(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_PCMPEQW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPEQW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPEQD(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_PCMPEQD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPEQD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTB(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_PCMPGTB_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPGTB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTW(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_PCMPGTW_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPGTW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} +static int codegen_PCMPGTD(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_PCMPGTD_XREG_XREG(block, dest_reg, src_reg_b); + } + else + fatal("PCMPGTD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); + + return 0; +} + static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) { int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); @@ -2040,6 +2125,13 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PCMPEQB & UOP_MASK] = codegen_PCMPEQB, + [UOP_PCMPEQW & UOP_MASK] = codegen_PCMPEQW, + [UOP_PCMPEQD & UOP_MASK] = codegen_PCMPEQD, + [UOP_PCMPGTB & UOP_MASK] = codegen_PCMPGTB, + [UOP_PCMPGTW & UOP_MASK] = codegen_PCMPGTW, + [UOP_PCMPGTD & UOP_MASK] = codegen_PCMPGTD, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 1fdd3a8..694b585 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -230,6 +230,18 @@ #define UOP_PSRLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa6) /*UOP_PSRLQ_IMM - (packed quad) dest_reg = src_reg_a >> immediate*/ #define UOP_PSRLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa7) +/*UOP_PCMPEQB - (packed byte) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/ +#define UOP_PCMPEQB (UOP_TYPE_PARAMS_REGS | 0xa8) +/*UOP_PCMPEQW - (packed word) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/ +#define UOP_PCMPEQW (UOP_TYPE_PARAMS_REGS | 0xa9) +/*UOP_PCMPEQD - (packed long) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/ +#define UOP_PCMPEQD (UOP_TYPE_PARAMS_REGS | 0xaa) +/*UOP_PCMPGTB - (packed signed byte) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ +#define UOP_PCMPGTB (UOP_TYPE_PARAMS_REGS | 0xab) +/*UOP_PCMPGTW - (packed signed word) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ +#define UOP_PCMPGTW (UOP_TYPE_PARAMS_REGS | 0xac) +/*UOP_PCMPGTD - (packed signed long) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/ +#define UOP_PCMPGTD (UOP_TYPE_PARAMS_REGS | 0xad) #define UOP_MAX 0xb0 @@ -579,6 +591,13 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, #define uop_PADDUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSB, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PADDUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPEQB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQB, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPEQW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQW, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPEQD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQD, ir, dst_reg, src_reg_a, src_reg_b) +#define uop_PCMPGTB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTB, ir, dst_reg, src_reg_a, src_reg_b) +#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_PSLLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLW_IMM, ir, dst_reg, src_reg, imm) #define uop_PSLLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLD_IMM, ir, dst_reg, src_reg, imm) #define uop_PSLLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLQ_IMM, ir, dst_reg, src_reg, imm) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index fa7f769..0ec4059 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -12,6 +12,7 @@ #include "codegen_ops_logic.h" #include "codegen_ops_misc.h" #include "codegen_ops_mmx_arith.h" +#include "codegen_ops_mmx_cmp.h" #include "codegen_ops_mmx_loadstore.h" #include "codegen_ops_mmx_logic.h" #include "codegen_ops_mmx_shift.h" @@ -78,8 +79,8 @@ RecompOpFn recomp_opcodes_0f[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, -/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, +/*60*/ NULL, NULL, NULL, NULL, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, +/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, /*80*/ ropJO_16, ropJNO_16, ropJB_16, ropJNB_16, ropJE_16, ropJNE_16, ropJBE_16, ropJNBE_16, ropJS_16, ropJNS_16, ropJP_16, ropJNP_16, ropJL_16, ropJNL_16, ropJLE_16, ropJNLE_16, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -100,8 +101,8 @@ RecompOpFn recomp_opcodes_0f[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, -/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, +/*60*/ NULL, NULL, NULL, NULL, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, +/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, /*80*/ ropJO_32, ropJNO_32, ropJB_32, ropJNB_32, ropJE_32, ropJNE_32, ropJBE_32, ropJNBE_32, ropJS_32, ropJNS_32, ropJP_32, ropJNP_32, ropJL_32, ropJNL_32, ropJLE_32, ropJNLE_32, /*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/codegen_ops_mmx_cmp.c b/src/codegen_ops_mmx_cmp.c new file mode 100644 index 0000000..f56f413 --- /dev/null +++ b/src/codegen_ops_mmx_cmp.c @@ -0,0 +1,43 @@ +#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_mmx_cmp.h" +#include "codegen_ops_helpers.h" + +#define ropPcmp(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 + 1; \ +} + +ropPcmp(PCMPEQB) +ropPcmp(PCMPEQW) +ropPcmp(PCMPEQD) +ropPcmp(PCMPGTB) +ropPcmp(PCMPGTW) +ropPcmp(PCMPGTD) diff --git a/src/codegen_ops_mmx_cmp.h b/src/codegen_ops_mmx_cmp.h new file mode 100644 index 0000000..6069ad1 --- /dev/null +++ b/src/codegen_ops_mmx_cmp.h @@ -0,0 +1,6 @@ +uint32_t ropPCMPEQB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPCMPEQW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPCMPEQD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPCMPGTB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPCMPGTW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPCMPGTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);