From e43a2a6be04d2fa15f53742af44a4d8837c20182 Mon Sep 17 00:00:00 2001 From: SarahW Date: Thu, 22 Nov 2018 18:43:36 +0000 Subject: [PATCH] Added recompiled versions of PSLL*, PSLR* and PSAR* with immediate shifts. --- src/codegen_backend_arm64_ops.c | 105 ++++++++++++++----- src/codegen_backend_arm64_ops.h | 32 ++++-- src/codegen_backend_arm64_uops.c | 164 ++++++++++++++++++++++++++++++ src/codegen_backend_arm_ops.c | 67 ++++++++++++ src/codegen_backend_arm_ops.h | 11 ++ src/codegen_backend_arm_uops.c | 164 ++++++++++++++++++++++++++++++ src/codegen_backend_x86-64_ops.c | 49 +++++++++ src/codegen_backend_x86-64_ops.h | 13 +++ src/codegen_backend_x86-64_uops.c | 137 +++++++++++++++++++++++++ src/codegen_backend_x86_ops.c | 49 +++++++++ src/codegen_backend_x86_ops.h | 13 +++ src/codegen_backend_x86_uops.c | 137 +++++++++++++++++++++++++ src/codegen_ir_defs.h | 30 +++++- src/codegen_ops.c | 5 +- src/codegen_ops_mmx_shift.c | 87 ++++++++++++++++ src/codegen_ops_mmx_shift.h | 7 ++ 16 files changed, 1029 insertions(+), 41 deletions(-) create mode 100644 src/codegen_ops_mmx_shift.c create mode 100644 src/codegen_ops_mmx_shift.h diff --git a/src/codegen_backend_arm64_ops.c b/src/codegen_backend_arm64_ops.c index 8a372f0..06d431e 100644 --- a/src/codegen_backend_arm64_ops.c +++ b/src/codegen_backend_arm64_ops.c @@ -154,6 +154,10 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_SQADD_V4H (0x0e600c00) #define OPCODE_SQSUB_V8B (0x0e202c00) #define OPCODE_SQSUB_V4H (0x0e602c00) +#define OPCODE_SHL_VD (0x0e005400) +#define OPCODE_SHL_VQ (0x4e005400) +#define OPCODE_SSHR_VD (0x0e004400) +#define OPCODE_SSHR_VQ (0x4e004400) #define OPCODE_STR_REG (0xb8206800) #define OPCODE_STRB_REG (0x38206800) #define OPCODE_STRH_REG (0x78206800) @@ -167,6 +171,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_UQADD_V4H (0x2e600c00) #define OPCODE_UQSUB_V8B (0x2e202c00) #define OPCODE_UQSUB_V4H (0x2e602c00) +#define OPCODE_USHR_VD (0x2e004400) +#define OPCODE_USHR_VQ (0x6e004400) #define DATPROC_SHIFT(sh) (sh << 10) #define DATPROC_IMM_SHIFT(sh) (sh << 22) @@ -191,6 +197,10 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OFFSET12_W(offset) ((offset >> 2) << 10) #define OFFSET12_Q(offset) ((offset >> 3) << 10) +#define SHIFT_IMM_V4H(shift) (((shift) | 0x10) << 16) +#define SHIFT_IMM_V2S(shift) (((shift) | 0x20) << 16) +#define SHIFT_IMM_V2D(shift) (((shift) | 0x40) << 16) + static int literal_offset = 0; void codegen_reset_literal_pool(codeblock_t *block) { @@ -291,17 +301,17 @@ void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int { codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_ADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_ADD_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset) @@ -907,21 +917,47 @@ void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg) codegen_addlong(block, OPCODE_SCVTF_D_W | Rd(dst_reg) | Rn(src_reg)); } -void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + +void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_SHL_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); +} +void host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_SHL_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(shift)); +} +void host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_SHL_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(shift)); +} + +void host_arm64_SSHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); +} +void host_arm64_SSHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_SSHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(shift)); +} +void host_arm64_SSHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_SSHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(shift)); } void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset) @@ -1021,17 +1057,17 @@ void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int { codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); } -void host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_SUB_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_SUB_V2S | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit) @@ -1045,21 +1081,34 @@ void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int codegen_addlong(block, OPCODE_UBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31)); } -void host_arm64_UQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_UQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_UQADD_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_UQADD_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_UQSUB_V8B | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); } -void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift) +void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg) { - codegen_addlong(block, OPCODE_UQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift)); + codegen_addlong(block, OPCODE_UQSUB_V4H | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg)); +} + +void host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V4H(shift)); +} +void host_arm64_USHR_V2S(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_USHR_VD | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2S(shift)); +} +void host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_n_reg, shift) +{ + codegen_addlong(block, OPCODE_USHR_VQ | Rd(dst_reg) | Rn(src_n_reg) | SHIFT_IMM_V2D(shift)); } void host_arm64_call(codeblock_t *block, void *dst_addr) diff --git a/src/codegen_backend_arm64_ops.h b/src/codegen_backend_arm64_ops.h index a1a1910..699988d 100644 --- a/src/codegen_backend_arm64_ops.h +++ b/src/codegen_backend_arm64_ops.h @@ -1,9 +1,9 @@ void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset); @@ -140,10 +140,18 @@ void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg); void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg); -void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); + +void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift); + +void host_arm64_SSHR_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm64_SSHR_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm64_SSHR_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift); void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset); @@ -165,9 +173,9 @@ void host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offs void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data); void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); -void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); +void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg); uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit); @@ -180,6 +188,10 @@ void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int sr void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift); +void host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm64_USHR_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift); +void host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift); + void host_arm64_call(codeblock_t *block, void *dst_addr); void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr); void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data); diff --git a/src/codegen_backend_arm64_uops.c b/src/codegen_backend_arm64_uops.c index ae5dc5a..f19d6b8 100644 --- a/src/codegen_backend_arm64_uops.c +++ b/src/codegen_backend_arm64_uops.c @@ -1483,6 +1483,160 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) 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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 15) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); + else + host_arm64_SHL_V4H(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLD_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 31) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); + else + host_arm64_SHL_V2S(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLQ_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 63) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); + else + host_arm64_SHL_V2D(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAW_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 15) + host_arm64_SSHR_V4H(block, dest_reg, src_reg, 15); + else + host_arm64_SSHR_V4H(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAD_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 31) + host_arm64_SSHR_V2S(block, dest_reg, src_reg, 31); + else + host_arm64_SSHR_V2S(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAQ_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 63) + host_arm64_SSHR_V2D(block, dest_reg, src_reg, 63); + else + host_arm64_SSHR_V2D(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLW_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 15) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); + else + host_arm64_USHR_V4H(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLD_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 31) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); + else + host_arm64_USHR_V2S(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLQ_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 63) + host_arm64_EOR_REG_V(block, dest_reg, dest_reg, dest_reg); + else + host_arm64_USHR_V2D(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_PSUBB(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); @@ -2115,6 +2269,16 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, + [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index 2818e55..17c29f9 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -119,6 +119,15 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VQSUB_S16 0xf2100210 #define OPCODE_VQSUB_U8 0xf3000210 #define OPCODE_VQSUB_U16 0xf3100210 +#define OPCODE_VSHL_D_IMM_16 0xf2900510 +#define OPCODE_VSHL_D_IMM_32 0xf2a00510 +#define OPCODE_VSHL_D_IMM_64 0xf2800590 +#define OPCODE_VSHR_D_S16 0xf2900010 +#define OPCODE_VSHR_D_S32 0xf2a00010 +#define OPCODE_VSHR_D_S64 0xf2800090 +#define OPCODE_VSHR_D_U16 0xf3900010 +#define OPCODE_VSHR_D_U32 0xf3a00010 +#define OPCODE_VSHR_D_U64 0xf3800090 #define OPCODE_VSTR_D 0xed800b00 #define OPCODE_VSTR_S 0xed800a00 #define OPCODE_VSUB 0xee300b40 @@ -157,6 +166,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define LDRH_IMM(imm) (((imm) & 0xf) | (((imm) & 0xf0) << 4)) #define STRH_IMM(imm) LDRH_IMM(imm) +#define VSHIFT_IMM(shift) ((shift) << 16) static inline uint32_t arm_data_offset(int offset) { @@ -868,6 +878,7 @@ void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg { codegen_addlong(block, OPCODE_VORR_D | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } + void host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { codegen_addlong(block, OPCODE_VQADD_S8 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); @@ -900,6 +911,62 @@ void host_arm_VQSUB_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_ { codegen_addlong(block, OPCODE_VQSUB_U16 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } + +void host_arm_VSHL_D_IMM_16(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 15) + fatal("host_arm_VSHL_D_IMM_16 : shift > 15\n"); + codegen_addlong(block, OPCODE_VSHL_D_IMM_16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHL_D_IMM_32(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 31) + fatal("host_arm_VSHL_D_IMM_32 : shift > 31\n"); + codegen_addlong(block, OPCODE_VSHL_D_IMM_32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHL_D_IMM_64(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 63) + fatal("host_arm_VSHL_D_IMM_64 : shift > 63\n"); + codegen_addlong(block, OPCODE_VSHL_D_IMM_64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHR_SD_16(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 15) + fatal("host_arm_VSHR_SD_IMM_16 : shift > 15\n"); + codegen_addlong(block, OPCODE_VSHR_SD_16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHR_SD_32(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 31) + fatal("host_arm_VSHR_SD_IMM_32 : shift > 31\n"); + codegen_addlong(block, OPCODE_VSHR_SD_32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHR_SD_64(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 63) + fatal("host_arm_VSHR_SD_IMM_64 : shift > 63\n"); + codegen_addlong(block, OPCODE_VSHR_SD_64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHR_UD_16(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 15) + fatal("host_arm_VSHR_UD_IMM_16 : shift > 15\n"); + codegen_addlong(block, OPCODE_VSHR_UD_16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHR_UD_32(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 31) + fatal("host_arm_VSHR_UD_IMM_32 : shift > 31\n"); + codegen_addlong(block, OPCODE_VSHR_UD_32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} +void host_arm_VSHR_UD_64(codeblock_t *block, int dest_reg, int src_reg, int shift) +{ + if (shift > 63) + fatal("host_arm_VSHR_UD_IMM_64 : shift > 63\n"); + codegen_addlong(block, OPCODE_VSHR_UD_64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(shift)); +} + void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset) { if ((offset > 1020) || (offset & 3)) diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 166656c..5a1f792 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -172,6 +172,17 @@ void host_arm_VQSUB_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_r void host_arm_VQSUB_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VQSUB_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VQSUB_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); + +void host_arm_VSHL_D_IMM_16(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHL_D_IMM_32(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHL_D_IMM_64(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHR_D_S16(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHR_D_S32(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHR_D_S64(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHR_D_U16(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHR_D_U32(codeblock_t *block, int dest_reg, int src_reg, int shift); +void host_arm_VSHR_D_U64(codeblock_t *block, int dest_reg, int src_reg, int shift); + 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); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 329459e..75d01b0 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1603,6 +1603,160 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) 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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 15) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); + else + host_arm_VSHL_D_IMM_16(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLD_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 31) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); + else + host_arm_VSHL_D_IMM_32(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLQ_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 63) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); + else + host_arm_VSHL_D_IMM_64(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAW_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 15) + host_arm_VSHR_D_S16(block, dest_reg, src_reg, 15); + else + host_arm_VSHR_D_S16(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAD_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 31) + host_arm_VSHR_D_S32(block, dest_reg, src_reg, 31); + else + host_arm_VSHR_D_S32(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAQ_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 63) + host_arm_VSHR_D_S64(block, dest_reg, src_reg, 63); + else + host_arm_VSHR_D_S64(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLW_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 15) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); + else + host_arm_VSHR_D_U16(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLD_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 31) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); + else + host_arm_VSHR_D_U32(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLQ_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); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real); + + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) + { + if (uop->imm_data > 63) + host_arm_VEOR_D(block, dest_reg, dest_reg, dest_reg); + else + host_arm_VSHR_D_U64(block, dest_reg, src_reg, uop->imm_data); + } + else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_PSUBB(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); @@ -2235,6 +2389,16 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, + [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, diff --git a/src/codegen_backend_x86-64_ops.c b/src/codegen_backend_x86-64_ops.c index efc7e3d..97bab1f 100644 --- a/src/codegen_backend_x86-64_ops.c +++ b/src/codegen_backend_x86-64_ops.c @@ -1257,6 +1257,7 @@ void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ } + void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ @@ -1269,6 +1270,53 @@ 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_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} + void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ @@ -1297,6 +1345,7 @@ 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*/ diff --git a/src/codegen_backend_x86-64_ops.h b/src/codegen_backend_x86-64_ops.h index 5f16760..119f854 100644 --- a/src/codegen_backend_x86-64_ops.h +++ b/src/codegen_backend_x86-64_ops.h @@ -160,9 +160,21 @@ void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); 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_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); +void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); + void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); @@ -170,6 +182,7 @@ void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); 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); diff --git a/src/codegen_backend_x86-64_uops.c b/src/codegen_backend_x86-64_uops.c index 0eddc13..331a12f 100644 --- a/src/codegen_backend_x86-64_uops.c +++ b/src/codegen_backend_x86-64_uops.c @@ -1369,6 +1369,133 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSLLW_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSLLD_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSLLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRAW_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRAD_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRAQ_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRLW_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRLD_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_PSUBB(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); @@ -1913,6 +2040,16 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, + [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, diff --git a/src/codegen_backend_x86_ops.c b/src/codegen_backend_x86_ops.c index 2d4fb79..1dbee0b 100644 --- a/src/codegen_backend_x86_ops.c +++ b/src/codegen_backend_x86_ops.c @@ -1115,6 +1115,7 @@ void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/ } + void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/ @@ -1127,6 +1128,53 @@ 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_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} +void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift) +{ + codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/ + codegen_addbyte(block, shift); +} + void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg) { codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/ @@ -1155,6 +1203,7 @@ 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*/ diff --git a/src/codegen_backend_x86_ops.h b/src/codegen_backend_x86_ops.h index ca5f3ff..f7483c2 100644 --- a/src/codegen_backend_x86_ops.h +++ b/src/codegen_backend_x86_ops.h @@ -161,9 +161,21 @@ void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); 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_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); +void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift); +void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift); + void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); @@ -171,6 +183,7 @@ void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg); 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); diff --git a/src/codegen_backend_x86_uops.c b/src/codegen_backend_x86_uops.c index d84c0c2..7b5a8de 100644 --- a/src/codegen_backend_x86_uops.c +++ b/src/codegen_backend_x86_uops.c @@ -1372,6 +1372,133 @@ static int codegen_PADDUSW(codeblock_t *block, uop_t *uop) return 0; } +static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSLLW_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSLLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSLLD_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSLLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSLLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSLLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRAW_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRAW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRAD_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRAD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRAQ_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRAQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRLW_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRLW_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRLD_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRLD_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} +static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) +{ + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real); + + if (REG_IS_Q(dest_size) && uop->dest_reg_a_real == uop->src_reg_a_real) + { + host_x86_PSRLQ_XREG_IMM(block, dest_reg, uop->imm_data); + } + else + fatal("PSRLQ_IMM %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real); + + return 0; +} + static int codegen_PSUBB(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); @@ -1913,6 +2040,16 @@ const uOpFn uop_handlers[UOP_MAX] = [UOP_PADDUSB & UOP_MASK] = codegen_PADDUSB, [UOP_PADDUSW & UOP_MASK] = codegen_PADDUSW, + [UOP_PSLLW_IMM & UOP_MASK] = codegen_PSLLW_IMM, + [UOP_PSLLD_IMM & UOP_MASK] = codegen_PSLLD_IMM, + [UOP_PSLLQ_IMM & UOP_MASK] = codegen_PSLLQ_IMM, + [UOP_PSRAW_IMM & UOP_MASK] = codegen_PSRAW_IMM, + [UOP_PSRAD_IMM & UOP_MASK] = codegen_PSRAD_IMM, + [UOP_PSRAQ_IMM & UOP_MASK] = codegen_PSRAQ_IMM, + [UOP_PSRLW_IMM & UOP_MASK] = codegen_PSRLW_IMM, + [UOP_PSRLD_IMM & UOP_MASK] = codegen_PSRLD_IMM, + [UOP_PSRLQ_IMM & UOP_MASK] = codegen_PSRLQ_IMM, + [UOP_PSUBB & UOP_MASK] = codegen_PSUBB, [UOP_PSUBW & UOP_MASK] = codegen_PSUBW, [UOP_PSUBD & UOP_MASK] = codegen_PSUBD, diff --git a/src/codegen_ir_defs.h b/src/codegen_ir_defs.h index 7c7bb39..1fdd3a8 100644 --- a/src/codegen_ir_defs.h +++ b/src/codegen_ir_defs.h @@ -212,8 +212,26 @@ #define UOP_PSUBUSB (UOP_TYPE_PARAMS_REGS | 0x9d) /*UOP_PSUBUSW - (packed word with unsigned saturation) dest_reg = src_reg_a - src_reg_b*/ #define UOP_PSUBUSW (UOP_TYPE_PARAMS_REGS | 0x9e) +/*UOP_PSLLW_IMM - (packed word) dest_reg = src_reg_a << immediate*/ +#define UOP_PSLLW_IMM (UOP_TYPE_PARAMS_REGS | 0x9f) +/*UOP_PSLLD_IMM - (packed long) dest_reg = src_reg_a << immediate*/ +#define UOP_PSLLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa0) +/*UOP_PSLLQ_IMM - (packed quad) dest_reg = src_reg_a << immediate*/ +#define UOP_PSLLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa1) +/*UOP_PSRAW_IMM - (packed word) dest_reg = src_reg_a >> immediate*/ +#define UOP_PSRAW_IMM (UOP_TYPE_PARAMS_REGS | 0xa2) +/*UOP_PSRAD_IMM - (packed long) dest_reg = src_reg_a >> immediate*/ +#define UOP_PSRAD_IMM (UOP_TYPE_PARAMS_REGS | 0xa3) +/*UOP_PSRAQ_IMM - (packed quad) dest_reg = src_reg_a >> immediate*/ +#define UOP_PSRAQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa4) +/*UOP_PSRLW_IMM - (packed word) dest_reg = src_reg_a >> immediate*/ +#define UOP_PSRLW_IMM (UOP_TYPE_PARAMS_REGS | 0xa5) +/*UOP_PSRLD_IMM - (packed long) dest_reg = src_reg_a >> immediate*/ +#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) -#define UOP_MAX 0x9f +#define UOP_MAX 0xb0 #define UOP_MASK 0xffff @@ -561,6 +579,16 @@ 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_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) +#define uop_PSRAW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAW_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRAD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAD_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRAQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAQ_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLW_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLD_IMM, ir, dst_reg, src_reg, imm) +#define uop_PSRLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLQ_IMM, ir, dst_reg, src_reg, imm) + #define uop_PSUBB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBB, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PSUBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBW, ir, dst_reg, src_reg_a, src_reg_b) #define uop_PSUBD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBD, ir, dst_reg, src_reg_a, src_reg_b) diff --git a/src/codegen_ops.c b/src/codegen_ops.c index 4b17b81..fa7f769 100644 --- a/src/codegen_ops.c +++ b/src/codegen_ops.c @@ -14,6 +14,7 @@ #include "codegen_ops_mmx_arith.h" #include "codegen_ops_mmx_loadstore.h" #include "codegen_ops_mmx_logic.h" +#include "codegen_ops_mmx_shift.h" #include "codegen_ops_mov.h" #include "codegen_ops_shift.h" #include "codegen_ops_stack.h" @@ -78,7 +79,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, +/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, NULL, NULL, NULL, 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,7 +101,7 @@ RecompOpFn recomp_opcodes_0f[512] = /*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q, -/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r, +/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, NULL, NULL, NULL, 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_shift.c b/src/codegen_ops_mmx_shift.c new file mode 100644 index 0000000..ad0f597 --- /dev/null +++ b/src/codegen_ops_mmx_shift.c @@ -0,0 +1,87 @@ +#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_shift.h" +#include "codegen_ops_helpers.h" + +uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + int shift = fastreadb(cs + op_pc + 1); + + uop_MMX_ENTER(ir); + switch (op) + { + case 0x10: /*PSRLW*/ + uop_PSRLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x20: /*PSRAW*/ + uop_PSRAW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x30: /*PSLLW*/ + uop_PSLLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + default: + return 0; + + } + + return op_pc + 2; +} +uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + int shift = fastreadb(cs + op_pc + 1); + + uop_MMX_ENTER(ir); + switch (op) + { + case 0x10: /*PSRLD*/ + uop_PSRLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x20: /*PSRAD*/ + uop_PSRAD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x30: /*PSLLD*/ + uop_PSLLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + default: + return 0; + + } + + return op_pc + 2; +} +uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) +{ + int reg = fetchdat & 7; + int op = fetchdat & 0x38; + int shift = fastreadb(cs + op_pc + 1); + + uop_MMX_ENTER(ir); + switch (op) + { + case 0x10: /*PSRLQ*/ + uop_PSRLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x20: /*PSRAQ*/ + uop_PSRAQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + case 0x30: /*PSLLQ*/ + uop_PSLLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift); + break; + default: + return 0; + + } + + return op_pc + 2; +} diff --git a/src/codegen_ops_mmx_shift.h b/src/codegen_ops_mmx_shift.h new file mode 100644 index 0000000..3a3b712 --- /dev/null +++ b/src/codegen_ops_mmx_shift.h @@ -0,0 +1,7 @@ +uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); + +uint32_t ropPSLLW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPSLLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc); +uint32_t ropPSLLQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);