From 6341caf318289e7753360c04081dc988ed417616 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 24 Nov 2018 20:35:33 +0000 Subject: [PATCH] ARM MMX fixes --- src/codegen_backend_arm_defs.h | 2 + src/codegen_backend_arm_ops.c | 68 +++++++++++++++------ src/codegen_backend_arm_ops.h | 8 +++ src/codegen_backend_arm_uops.c | 106 +++++++++++++++++++++------------ 4 files changed, 129 insertions(+), 55 deletions(-) diff --git a/src/codegen_backend_arm_defs.h b/src/codegen_backend_arm_defs.h index 7deb72f..def8970 100644 --- a/src/codegen_backend_arm_defs.h +++ b/src/codegen_backend_arm_defs.h @@ -43,6 +43,8 @@ #define REG_D15 15 #define REG_D_TEMP REG_D0 +#define REG_Q_TEMP REG_D0 +#define REG_Q_TEMP_2 REG_D2 #define REG_MASK_R0 (1 << REG_R0) #define REG_MASK_R1 (1 << REG_R1) diff --git a/src/codegen_backend_arm_ops.c b/src/codegen_backend_arm_ops.c index c0a5a6a..b6692a7 100644 --- a/src/codegen_backend_arm_ops.c +++ b/src/codegen_backend_arm_ops.c @@ -113,13 +113,17 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VMOV_D_64 0xec400b10 #define OPCODE_VMOV_S_32 0xee000a10 #define OPCODE_VMOV_D_D 0xeeb00b40 +#define OPCODE_VMOVN_I32 0xf3b60200 +#define OPCODE_VMOVN_I64 0xf3ba0200 #define OPCODE_VMRS_APSR 0xeef1fa10 #define OPCODE_VMSR_FPSCR 0xeee10a10 #define OPCODE_VMUL 0xee200b00 -#define OPCODE_VMUL_S16 0xf2100510 +#define OPCODE_VMUL_S16 0xf2100910 #define OPCODE_VMULL_S16 0xf2900c00 #define OPCODE_VORR_D 0xf2200110 #define OPCODE_VPADDL_S16 0xf3b40200 +#define OPCODE_VPADDL_S32 0xf3b80200 +#define OPCODE_VPADDL_Q_S32 0xf3b80240 #define OPCODE_VQADD_S8 0xf2000010 #define OPCODE_VQADD_S16 0xf2100010 #define OPCODE_VQADD_U8 0xf3000010 @@ -140,14 +144,16 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define OPCODE_VSHR_D_U16 0xf3900010 #define OPCODE_VSHR_D_U32 0xf3a00010 #define OPCODE_VSHR_D_U64 0xf3800090 +#define OPCODE_VSHRN 0xf2800810 #define OPCODE_VSTR_D 0xed800b00 #define OPCODE_VSTR_S 0xed800a00 #define OPCODE_VSUB 0xee300b40 #define OPCODE_VSUB_I8 0xf3000800 #define OPCODE_VSUB_I16 0xf3100800 #define OPCODE_VSUB_I32 0xf3200800 +#define OPCODE_VZIP_D8 0xf3b20180 #define OPCODE_VZIP_D16 0xf3b60180 -#define OPCODE_VZIP_D32 0xf3ba0180 +#define OPCODE_VZIP_D32 0xf3ba0080 #define B_OFFSET(x) (((x) >> 2) & 0xffffff) @@ -182,6 +188,8 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val) #define VSHIFT_IMM(shift) ((shift) << 16) +#define VSHIFT_IMM_32(shift) (((16 - (shift)) | 0x10) << 16) + static inline uint32_t arm_data_offset(int offset) { if (offset < -0xffc || offset > 0xffc) @@ -902,6 +910,14 @@ void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VMOV_D_D | Vd(dest_reg) | Vm(src_reg)); } +void host_arm_VMOVN_I32(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_VMOVN_I32 | Vd(dest_reg) | Vm(src_reg)); +} +void host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_VMOVN_I64 | Vd(dest_reg) | Vm(src_reg)); +} void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg) { codegen_addlong(block, COND_AL | OPCODE_VMSR_FPSCR | Rd(src_reg)); @@ -933,6 +949,14 @@ void host_arm_VPADDL_S16(codeblock_t *block, int dst_reg, int src_reg) { codegen_addlong(block, OPCODE_VPADDL_S16 | Vd(dst_reg) | Vm(src_reg)); } +void host_arm_VPADDL_S32(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_VPADDL_S32 | Vd(dst_reg) | Vm(src_reg)); +} +void host_arm_VPADDL_Q_S32(codeblock_t *block, int dst_reg, int src_reg) +{ + codegen_addlong(block, OPCODE_VPADDL_Q_S32 | Vd(dst_reg) | Vm(src_reg)); +} void host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m) { @@ -980,59 +1004,65 @@ void host_arm_VQMOVN_U16(codeblock_t *block, int dst_reg, int src_reg) codegen_addlong(block, OPCODE_VQMOVN_U16 | Vd(dst_reg) | Vm(src_reg)); } -void host_arm_VSHL_D_IMM_16(codeblock_t *block, int dest_reg, int src_reg, int shift) +void host_arm_VSHL_D_IMM_16(codeblock_t *block, int dst_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) +void host_arm_VSHL_D_IMM_32(codeblock_t *block, int dst_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) +void host_arm_VSHL_D_IMM_64(codeblock_t *block, int dst_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) +void host_arm_VSHR_D_S16(codeblock_t *block, int dst_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)); + codegen_addlong(block, OPCODE_VSHR_D_S16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(16-shift)); } -void host_arm_VSHR_SD_32(codeblock_t *block, int dest_reg, int src_reg, int shift) +void host_arm_VSHR_D_S32(codeblock_t *block, int dst_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)); + codegen_addlong(block, OPCODE_VSHR_D_S32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(32-shift)); } -void host_arm_VSHR_SD_64(codeblock_t *block, int dest_reg, int src_reg, int shift) +void host_arm_VSHR_D_S64(codeblock_t *block, int dst_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)); + codegen_addlong(block, OPCODE_VSHR_D_S64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(64-shift)); } -void host_arm_VSHR_UD_16(codeblock_t *block, int dest_reg, int src_reg, int shift) +void host_arm_VSHR_D_U16(codeblock_t *block, int dst_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)); + codegen_addlong(block, OPCODE_VSHR_D_U16 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(16-shift)); } -void host_arm_VSHR_UD_32(codeblock_t *block, int dest_reg, int src_reg, int shift) +void host_arm_VSHR_D_U32(codeblock_t *block, int dst_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)); + codegen_addlong(block, OPCODE_VSHR_D_U32 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(32-shift)); } -void host_arm_VSHR_UD_64(codeblock_t *block, int dest_reg, int src_reg, int shift) +void host_arm_VSHR_D_U64(codeblock_t *block, int dst_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)); + codegen_addlong(block, OPCODE_VSHR_D_U64 | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM(64-shift)); +} +void host_arm_VSHRN_32(codeblock_t *block, int dst_reg, int src_reg, int shift) +{ + if (shift > 16) + fatal("host_arm_VSHRN_32 : shift > 16\n"); + codegen_addlong(block, OPCODE_VSHRN | Vd(dst_reg) | Vm(src_reg) | VSHIFT_IMM_32(16-shift)); } void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset) @@ -1064,6 +1094,10 @@ void host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_r codegen_addlong(block, OPCODE_VSUB_I32 | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m)); } +void host_arm_VZIP_D8(codeblock_t *block, int d_reg, int m_reg) +{ + codegen_addlong(block, OPCODE_VZIP_D8 | Vd(d_reg) | Vm(m_reg)); +} void host_arm_VZIP_D16(codeblock_t *block, int d_reg, int m_reg) { codegen_addlong(block, OPCODE_VZIP_D16 | Vd(d_reg) | Vm(m_reg)); diff --git a/src/codegen_backend_arm_ops.h b/src/codegen_backend_arm_ops.h index 946d7d5..edfbbc1 100644 --- a/src/codegen_backend_arm_ops.h +++ b/src/codegen_backend_arm_ops.h @@ -163,11 +163,15 @@ void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg void host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset); void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset); + void host_arm_VMOV_32_S(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VMOV_64_D(codeblock_t *block, int dest_reg_low, int dest_reg_high, int src_reg); void host_arm_VMOV_D_64(codeblock_t *block, int dest_reg, int src_reg_low, int src_reg_high); void host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg); void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg); +void host_arm_VMOVN_I32(codeblock_t *block, int dest_reg, int src_reg); +void host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg); + void host_arm_VMRS_APSR(codeblock_t *block); void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg); @@ -178,6 +182,8 @@ void host_arm_VMULL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VPADDL_S16(codeblock_t *block, int dst_reg, int src_reg); +void host_arm_VPADDL_S32(codeblock_t *block, int dst_reg, int src_reg); +void host_arm_VPADDL_Q_S32(codeblock_t *block, int dst_reg, int src_reg); void host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VQADD_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); @@ -201,6 +207,7 @@ void host_arm_VSHR_D_S64(codeblock_t *block, int dest_reg, int src_reg, int shif 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_VSHRN_32(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); @@ -209,5 +216,6 @@ void host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_re void host_arm_VSUB_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); void host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m); +void host_arm_VZIP_D8(codeblock_t *block, int d_reg, int m_reg); void host_arm_VZIP_D16(codeblock_t *block, int d_reg, int m_reg); void host_arm_VZIP_D32(codeblock_t *block, int d_reg, int m_reg); diff --git a/src/codegen_backend_arm_uops.c b/src/codegen_backend_arm_uops.c index 11e9f8f..c63a370 100644 --- a/src/codegen_backend_arm_uops.c +++ b/src/codegen_backend_arm_uops.c @@ -1290,7 +1290,7 @@ static int codegen_MOVZX(codeblock_t *block, uop_t *uop) } else if (REG_IS_L(dest_size) && REG_IS_Q(src_size)) { - host_arm_VMOV_32_S(block, dest_reg, src_reg, REG_TEMP); + host_arm_VMOV_32_S(block, dest_reg, src_reg); } else if (REG_IS_L(dest_size) && REG_IS_B(src_size)) { @@ -1511,8 +1511,10 @@ static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_VQMOVN_S16(block, dest_reg, dest_reg); - host_arm_VQMOVN_S16(block, REG_D_TEMP, src_reg_b); + host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); + host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); + host_arm_VQMOVN_S16(block, dest_reg, REG_Q_TEMP); + host_arm_VQMOVN_S16(block, REG_D_TEMP, REG_Q_TEMP_2); host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); } else @@ -1522,13 +1524,15 @@ static int codegen_PACKSSWB(codeblock_t *block, uop_t *uop) } static int codegen_PACKSSDW(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); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_VQMOVN_S32(block, dest_reg, dest_reg); - host_arm_VQMOVN_S32(block, REG_D_TEMP, src_reg_b); + host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); + host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); + host_arm_VQMOVN_S32(block, dest_reg, REG_Q_TEMP); + host_arm_VQMOVN_S32(block, REG_D_TEMP, REG_Q_TEMP_2); host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); } else @@ -1538,13 +1542,15 @@ static int codegen_PACKSSDW(codeblock_t *block, uop_t *uop) } static int codegen_PACKUSWB(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); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_VQMOVN_U16(block, dest_reg, dest_reg); - host_arm_VQMOVN_U16(block, REG_D_TEMP, src_reg_b); + host_arm_VMOV_D_D(block, REG_Q_TEMP, src_reg_a); + host_arm_VMOV_D_D(block, REG_Q_TEMP_2, src_reg_b); + host_arm_VQMOVN_U16(block, dest_reg, REG_Q_TEMP); + host_arm_VQMOVN_U16(block, REG_D_TEMP, REG_Q_TEMP_2); host_arm_VZIP_D32(block, dest_reg, REG_D_TEMP); } else @@ -1739,13 +1745,14 @@ static int codegen_PCMPGTD(codeblock_t *block, uop_t *uop) static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) { - int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); - int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_VMUL_S16(block, dest_reg, src_reg_a, src_reg_b); - host_arm_VPADDL_S16(block, dest_reg, dest_reg); + host_arm_VMULL_S16(block, REG_Q_TEMP, src_reg_a, src_reg_b); + host_arm_VPADDL_Q_S32(block, REG_Q_TEMP, REG_Q_TEMP); + host_arm_VMOVN_I64(block, dest_reg, REG_Q_TEMP); } else fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1754,13 +1761,13 @@ static int codegen_PMADDWD(codeblock_t *block, uop_t *uop) } static int codegen_PMULHW(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); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { - host_arm_VMULL_S16(block, dest_reg, src_reg_a, src_reg_b); - host_arm_VSHRN_16(block, dest_reg, dest_reg, 16); + host_arm_VMULL_S16(block, REG_Q_TEMP, src_reg_a, src_reg_b); + host_arm_VSHRN_32(block, dest_reg, REG_Q_TEMP, 16); } else fatal("PMULHW %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -1769,10 +1776,10 @@ static int codegen_PMULHW(codeblock_t *block, uop_t *uop) } static int codegen_PMULLW(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); + int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real); + int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real); - if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_b) && uop->dest_reg_a_real == uop->src_reg_a_real) + if (REG_IS_Q(dest_size) && REG_IS_Q(src_size_a) && REG_IS_Q(src_size_b)) { host_arm_VMUL_S16(block, dest_reg, src_reg_a, src_reg_b); } @@ -1789,7 +1796,9 @@ static int codegen_PSLLW_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 15) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else 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); @@ -1806,7 +1815,9 @@ static int codegen_PSLLD_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 31) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else 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); @@ -1823,7 +1834,9 @@ static int codegen_PSLLQ_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 63) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else 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); @@ -1840,7 +1853,9 @@ static int codegen_PSRAW_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 15) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else 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); @@ -1857,7 +1872,9 @@ static int codegen_PSRAD_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 31) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else 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); @@ -1874,7 +1891,9 @@ static int codegen_PSRAQ_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 63) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else 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); @@ -1891,7 +1910,9 @@ static int codegen_PSRLW_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 15) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else 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); @@ -1908,7 +1929,9 @@ static int codegen_PSRLD_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 31) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else 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); @@ -1925,7 +1948,9 @@ static int codegen_PSRLQ_IMM(codeblock_t *block, uop_t *uop) if (REG_IS_Q(dest_size) && REG_IS_Q(src_size)) { - if (uop->imm_data > 63) + if (uop->imm_data == 0) + host_arm_VMOV_D_D(block, dest_reg, src_reg); + else 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); @@ -1966,9 +1991,6 @@ static int codegen_PSUBW(codeblock_t *block, uop_t *uop) } static int codegen_PSUBD(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); - 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); @@ -2851,6 +2873,10 @@ void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_of else fatal("codegen_direct_read_32 - not in range\n"); } +void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset) +{ + host_arm_VLDR_D(block, host_reg, REG_HOST_SP, stack_offset); +} void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset) { host_arm_VLDR_D(block, host_reg, REG_HOST_SP, stack_offset); @@ -2863,6 +2889,10 @@ void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int hos else fatal("codegen_direct_write_32 - not in range\n"); } +void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg) +{ + host_arm_VSTR_D(block, host_reg, REG_HOST_SP, stack_offset); +} void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg) { host_arm_VSTR_D(block, host_reg, REG_HOST_SP, stack_offset);