Reviewed-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/loongarch64/tcg-target.c.inc | 223 +++++++++++++++++++------------
1 file changed, 137 insertions(+), 86 deletions(-)
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index ab1b67e028..dff966c395 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1833,76 +1833,125 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
const int const_args[TCG_MAX_OP_ARGS])
{
TCGType type = vecl + TCG_TYPE_V64;
+ bool lasx = type == TCG_TYPE_V256;
TCGArg a0, a1, a2, a3;
-
- static const LoongArchInsn cmp_vec_insn[16][4] = {
- [TCG_COND_EQ] = {OPC_VSEQ_B, OPC_VSEQ_H, OPC_VSEQ_W, OPC_VSEQ_D},
- [TCG_COND_LE] = {OPC_VSLE_B, OPC_VSLE_H, OPC_VSLE_W, OPC_VSLE_D},
- [TCG_COND_LEU] = {OPC_VSLE_BU, OPC_VSLE_HU, OPC_VSLE_WU, OPC_VSLE_DU},
- [TCG_COND_LT] = {OPC_VSLT_B, OPC_VSLT_H, OPC_VSLT_W, OPC_VSLT_D},
- [TCG_COND_LTU] = {OPC_VSLT_BU, OPC_VSLT_HU, OPC_VSLT_WU, OPC_VSLT_DU},
- };
- static const LoongArchInsn cmp_vec_imm_insn[16][4] = {
- [TCG_COND_EQ] = {OPC_VSEQI_B, OPC_VSEQI_H, OPC_VSEQI_W, OPC_VSEQI_D},
- [TCG_COND_LE] = {OPC_VSLEI_B, OPC_VSLEI_H, OPC_VSLEI_W, OPC_VSLEI_D},
- [TCG_COND_LEU] = {OPC_VSLEI_BU, OPC_VSLEI_HU, OPC_VSLEI_WU, OPC_VSLEI_DU},
- [TCG_COND_LT] = {OPC_VSLTI_B, OPC_VSLTI_H, OPC_VSLTI_W, OPC_VSLTI_D},
- [TCG_COND_LTU] = {OPC_VSLTI_BU, OPC_VSLTI_HU, OPC_VSLTI_WU, OPC_VSLTI_DU},
- };
LoongArchInsn insn;
- static const LoongArchInsn neg_vec_insn[4] = {
- OPC_VNEG_B, OPC_VNEG_H, OPC_VNEG_W, OPC_VNEG_D
+
+ static const LoongArchInsn cmp_vec_insn[16][2][4] = {
+ [TCG_COND_EQ] = {
+ { OPC_VSEQ_B, OPC_VSEQ_H, OPC_VSEQ_W, OPC_VSEQ_D },
+ { OPC_XVSEQ_B, OPC_XVSEQ_H, OPC_XVSEQ_W, OPC_XVSEQ_D },
+ },
+ [TCG_COND_LE] = {
+ { OPC_VSLE_B, OPC_VSLE_H, OPC_VSLE_W, OPC_VSLE_D },
+ { OPC_XVSLE_B, OPC_XVSLE_H, OPC_XVSLE_W, OPC_XVSLE_D },
+ },
+ [TCG_COND_LEU] = {
+ { OPC_VSLE_BU, OPC_VSLE_HU, OPC_VSLE_WU, OPC_VSLE_DU },
+ { OPC_XVSLE_BU, OPC_XVSLE_HU, OPC_XVSLE_WU, OPC_XVSLE_DU },
+ },
+ [TCG_COND_LT] = {
+ { OPC_VSLT_B, OPC_VSLT_H, OPC_VSLT_W, OPC_VSLT_D },
+ { OPC_XVSLT_B, OPC_XVSLT_H, OPC_XVSLT_W, OPC_XVSLT_D },
+ },
+ [TCG_COND_LTU] = {
+ { OPC_VSLT_BU, OPC_VSLT_HU, OPC_VSLT_WU, OPC_VSLT_DU },
+ { OPC_XVSLT_BU, OPC_XVSLT_HU, OPC_XVSLT_WU, OPC_XVSLT_DU },
+ }
};
- static const LoongArchInsn mul_vec_insn[4] = {
- OPC_VMUL_B, OPC_VMUL_H, OPC_VMUL_W, OPC_VMUL_D
+ static const LoongArchInsn cmp_vec_imm_insn[16][2][4] = {
+ [TCG_COND_EQ] = {
+ { OPC_VSEQI_B, OPC_VSEQI_H, OPC_VSEQI_W, OPC_VSEQI_D },
+ { OPC_XVSEQI_B, OPC_XVSEQI_H, OPC_XVSEQI_W, OPC_XVSEQI_D },
+ },
+ [TCG_COND_LE] = {
+ { OPC_VSLEI_B, OPC_VSLEI_H, OPC_VSLEI_W, OPC_VSLEI_D },
+ { OPC_XVSLEI_B, OPC_XVSLEI_H, OPC_XVSLEI_W, OPC_XVSLEI_D },
+ },
+ [TCG_COND_LEU] = {
+ { OPC_VSLEI_BU, OPC_VSLEI_HU, OPC_VSLEI_WU, OPC_VSLEI_DU },
+ { OPC_XVSLEI_BU, OPC_XVSLEI_HU, OPC_XVSLEI_WU, OPC_XVSLEI_DU },
+ },
+ [TCG_COND_LT] = {
+ { OPC_VSLTI_B, OPC_VSLTI_H, OPC_VSLTI_W, OPC_VSLTI_D },
+ { OPC_XVSLTI_B, OPC_XVSLTI_H, OPC_XVSLTI_W, OPC_XVSLTI_D },
+ },
+ [TCG_COND_LTU] = {
+ { OPC_VSLTI_BU, OPC_VSLTI_HU, OPC_VSLTI_WU, OPC_VSLTI_DU },
+ { OPC_XVSLTI_BU, OPC_XVSLTI_HU, OPC_XVSLTI_WU, OPC_XVSLTI_DU },
+ }
};
- static const LoongArchInsn smin_vec_insn[4] = {
- OPC_VMIN_B, OPC_VMIN_H, OPC_VMIN_W, OPC_VMIN_D
+ static const LoongArchInsn neg_vec_insn[2][4] = {
+ { OPC_VNEG_B, OPC_VNEG_H, OPC_VNEG_W, OPC_VNEG_D },
+ { OPC_XVNEG_B, OPC_XVNEG_H, OPC_XVNEG_W, OPC_XVNEG_D },
};
- static const LoongArchInsn umin_vec_insn[4] = {
- OPC_VMIN_BU, OPC_VMIN_HU, OPC_VMIN_WU, OPC_VMIN_DU
+ static const LoongArchInsn mul_vec_insn[2][4] = {
+ { OPC_VMUL_B, OPC_VMUL_H, OPC_VMUL_W, OPC_VMUL_D },
+ { OPC_XVMUL_B, OPC_XVMUL_H, OPC_XVMUL_W, OPC_XVMUL_D },
};
- static const LoongArchInsn smax_vec_insn[4] = {
- OPC_VMAX_B, OPC_VMAX_H, OPC_VMAX_W, OPC_VMAX_D
+ static const LoongArchInsn smin_vec_insn[2][4] = {
+ { OPC_VMIN_B, OPC_VMIN_H, OPC_VMIN_W, OPC_VMIN_D },
+ { OPC_XVMIN_B, OPC_XVMIN_H, OPC_XVMIN_W, OPC_XVMIN_D },
};
- static const LoongArchInsn umax_vec_insn[4] = {
- OPC_VMAX_BU, OPC_VMAX_HU, OPC_VMAX_WU, OPC_VMAX_DU
+ static const LoongArchInsn umin_vec_insn[2][4] = {
+ { OPC_VMIN_BU, OPC_VMIN_HU, OPC_VMIN_WU, OPC_VMIN_DU },
+ { OPC_XVMIN_BU, OPC_XVMIN_HU, OPC_XVMIN_WU, OPC_XVMIN_DU },
};
- static const LoongArchInsn ssadd_vec_insn[4] = {
- OPC_VSADD_B, OPC_VSADD_H, OPC_VSADD_W, OPC_VSADD_D
+ static const LoongArchInsn smax_vec_insn[2][4] = {
+ { OPC_VMAX_B, OPC_VMAX_H, OPC_VMAX_W, OPC_VMAX_D },
+ { OPC_XVMAX_B, OPC_XVMAX_H, OPC_XVMAX_W, OPC_XVMAX_D },
};
- static const LoongArchInsn usadd_vec_insn[4] = {
- OPC_VSADD_BU, OPC_VSADD_HU, OPC_VSADD_WU, OPC_VSADD_DU
+ static const LoongArchInsn umax_vec_insn[2][4] = {
+ { OPC_VMAX_BU, OPC_VMAX_HU, OPC_VMAX_WU, OPC_VMAX_DU },
+ { OPC_XVMAX_BU, OPC_XVMAX_HU, OPC_XVMAX_WU, OPC_XVMAX_DU },
};
- static const LoongArchInsn sssub_vec_insn[4] = {
- OPC_VSSUB_B, OPC_VSSUB_H, OPC_VSSUB_W, OPC_VSSUB_D
+ static const LoongArchInsn ssadd_vec_insn[2][4] = {
+ { OPC_VSADD_B, OPC_VSADD_H, OPC_VSADD_W, OPC_VSADD_D },
+ { OPC_XVSADD_B, OPC_XVSADD_H, OPC_XVSADD_W, OPC_XVSADD_D },
};
- static const LoongArchInsn ussub_vec_insn[4] = {
- OPC_VSSUB_BU, OPC_VSSUB_HU, OPC_VSSUB_WU, OPC_VSSUB_DU
+ static const LoongArchInsn usadd_vec_insn[2][4] = {
+ { OPC_VSADD_BU, OPC_VSADD_HU, OPC_VSADD_WU, OPC_VSADD_DU },
+ { OPC_XVSADD_BU, OPC_XVSADD_HU, OPC_XVSADD_WU, OPC_XVSADD_DU },
};
- static const LoongArchInsn shlv_vec_insn[4] = {
- OPC_VSLL_B, OPC_VSLL_H, OPC_VSLL_W, OPC_VSLL_D
+ static const LoongArchInsn sssub_vec_insn[2][4] = {
+ { OPC_VSSUB_B, OPC_VSSUB_H, OPC_VSSUB_W, OPC_VSSUB_D },
+ { OPC_XVSSUB_B, OPC_XVSSUB_H, OPC_XVSSUB_W, OPC_XVSSUB_D },
};
- static const LoongArchInsn shrv_vec_insn[4] = {
- OPC_VSRL_B, OPC_VSRL_H, OPC_VSRL_W, OPC_VSRL_D
+ static const LoongArchInsn ussub_vec_insn[2][4] = {
+ { OPC_VSSUB_BU, OPC_VSSUB_HU, OPC_VSSUB_WU, OPC_VSSUB_DU },
+ { OPC_XVSSUB_BU, OPC_XVSSUB_HU, OPC_XVSSUB_WU, OPC_XVSSUB_DU },
};
- static const LoongArchInsn sarv_vec_insn[4] = {
- OPC_VSRA_B, OPC_VSRA_H, OPC_VSRA_W, OPC_VSRA_D
+ static const LoongArchInsn shlv_vec_insn[2][4] = {
+ { OPC_VSLL_B, OPC_VSLL_H, OPC_VSLL_W, OPC_VSLL_D },
+ { OPC_XVSLL_B, OPC_XVSLL_H, OPC_XVSLL_W, OPC_XVSLL_D },
};
- static const LoongArchInsn shli_vec_insn[4] = {
- OPC_VSLLI_B, OPC_VSLLI_H, OPC_VSLLI_W, OPC_VSLLI_D
+ static const LoongArchInsn shrv_vec_insn[2][4] = {
+ { OPC_VSRL_B, OPC_VSRL_H, OPC_VSRL_W, OPC_VSRL_D },
+ { OPC_XVSRL_B, OPC_XVSRL_H, OPC_XVSRL_W, OPC_XVSRL_D },
};
- static const LoongArchInsn shri_vec_insn[4] = {
- OPC_VSRLI_B, OPC_VSRLI_H, OPC_VSRLI_W, OPC_VSRLI_D
+ static const LoongArchInsn sarv_vec_insn[2][4] = {
+ { OPC_VSRA_B, OPC_VSRA_H, OPC_VSRA_W, OPC_VSRA_D },
+ { OPC_XVSRA_B, OPC_XVSRA_H, OPC_XVSRA_W, OPC_XVSRA_D },
};
- static const LoongArchInsn sari_vec_insn[4] = {
- OPC_VSRAI_B, OPC_VSRAI_H, OPC_VSRAI_W, OPC_VSRAI_D
+ static const LoongArchInsn shli_vec_insn[2][4] = {
+ { OPC_VSLLI_B, OPC_VSLLI_H, OPC_VSLLI_W, OPC_VSLLI_D },
+ { OPC_XVSLLI_B, OPC_XVSLLI_H, OPC_XVSLLI_W, OPC_XVSLLI_D },
};
- static const LoongArchInsn rotrv_vec_insn[4] = {
- OPC_VROTR_B, OPC_VROTR_H, OPC_VROTR_W, OPC_VROTR_D
+ static const LoongArchInsn shri_vec_insn[2][4] = {
+ { OPC_VSRLI_B, OPC_VSRLI_H, OPC_VSRLI_W, OPC_VSRLI_D },
+ { OPC_XVSRLI_B, OPC_XVSRLI_H, OPC_XVSRLI_W, OPC_XVSRLI_D },
};
- static const LoongArchInsn rotri_vec_insn[4] = {
- OPC_VROTRI_B, OPC_VROTRI_H, OPC_VROTRI_W, OPC_VROTRI_D
+ static const LoongArchInsn sari_vec_insn[2][4] = {
+ { OPC_VSRAI_B, OPC_VSRAI_H, OPC_VSRAI_W, OPC_VSRAI_D },
+ { OPC_XVSRAI_B, OPC_XVSRAI_H, OPC_XVSRAI_W, OPC_XVSRAI_D },
+ };
+ static const LoongArchInsn rotrv_vec_insn[2][4] = {
+ { OPC_VROTR_B, OPC_VROTR_H, OPC_VROTR_W, OPC_VROTR_D },
+ { OPC_XVROTR_B, OPC_XVROTR_H, OPC_XVROTR_W, OPC_XVROTR_D },
+ };
+ static const LoongArchInsn rotri_vec_insn[2][4] = {
+ { OPC_VROTRI_B, OPC_VROTRI_H, OPC_VROTRI_W, OPC_VROTRI_D },
+ { OPC_XVROTRI_B, OPC_XVROTRI_H, OPC_XVROTRI_W, OPC_XVROTRI_D },
};
a0 = args[0];
@@ -1910,9 +1959,6 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
a2 = args[2];
a3 = args[3];
- /* Currently only supports V64 & V128 */
- tcg_debug_assert(type == TCG_TYPE_V64 || type == TCG_TYPE_V128);
-
switch (opc) {
case INDEX_op_st_vec:
tcg_out_st(s, type, a0, a1, a2);
@@ -1921,7 +1967,7 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
tcg_out_ld(s, type, a0, a1, a2);
break;
case INDEX_op_and_vec:
- insn = OPC_VAND_V;
+ insn = lasx ? OPC_XVAND_V : OPC_VAND_V;
goto vdvjvk;
case INDEX_op_andc_vec:
/*
@@ -1931,22 +1977,22 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
*/
a1 = a2;
a2 = args[1];
- insn = OPC_VANDN_V;
+ insn = lasx ? OPC_XVANDN_V : OPC_VANDN_V;
goto vdvjvk;
case INDEX_op_or_vec:
- insn = OPC_VOR_V;
+ insn = lasx ? OPC_XVOR_V : OPC_VOR_V;
goto vdvjvk;
case INDEX_op_orc_vec:
- insn = OPC_VORN_V;
+ insn = lasx ? OPC_XVORN_V : OPC_VORN_V;
goto vdvjvk;
case INDEX_op_xor_vec:
- insn = OPC_VXOR_V;
+ insn = lasx ? OPC_XVXOR_V : OPC_VXOR_V;
goto vdvjvk;
case INDEX_op_not_vec:
a2 = a1;
/* fall through */
case INDEX_op_nor_vec:
- insn = OPC_VNOR_V;
+ insn = lasx ? OPC_XVNOR_V : OPC_VNOR_V;
goto vdvjvk;
case INDEX_op_cmp_vec:
{
@@ -1962,13 +2008,13 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
cond == TCG_COND_LE ||
cond == TCG_COND_LT) &&
(-0x10 <= value && value <= 0x0f)) {
- insn = cmp_vec_imm_insn[cond][vece];
+ insn = cmp_vec_imm_insn[cond][lasx][vece];
tcg_out32(s, encode_vdvjsk5_insn(insn, a0, a1, value));
break;
} else if ((cond == TCG_COND_LEU ||
cond == TCG_COND_LTU) &&
(0x00 <= value && value <= 0x1f)) {
- insn = cmp_vec_imm_insn[cond][vece];
+ insn = cmp_vec_imm_insn[cond][lasx][vece];
tcg_out32(s, encode_vdvjuk5_insn(insn, a0, a1, value));
break;
}
@@ -1982,86 +2028,91 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
a2 = TCG_VEC_TMP0;
}
- insn = cmp_vec_insn[cond][vece];
+ insn = cmp_vec_insn[cond][lasx][vece];
if (insn == 0) {
TCGArg t;
t = a1, a1 = a2, a2 = t;
cond = tcg_swap_cond(cond);
- insn = cmp_vec_insn[cond][vece];
+ insn = cmp_vec_insn[cond][lasx][vece];
tcg_debug_assert(insn != 0);
}
}
goto vdvjvk;
case INDEX_op_add_vec:
- tcg_out_addsub_vec(s, false, vece, a0, a1, a2, const_args[2], true);
+ tcg_out_addsub_vec(s, lasx, vece, a0, a1, a2, const_args[2], true);
break;
case INDEX_op_sub_vec:
- tcg_out_addsub_vec(s, false, vece, a0, a1, a2, const_args[2], false);
+ tcg_out_addsub_vec(s, lasx, vece, a0, a1, a2, const_args[2], false);
break;
case INDEX_op_neg_vec:
- tcg_out32(s, encode_vdvj_insn(neg_vec_insn[vece], a0, a1));
+ tcg_out32(s, encode_vdvj_insn(neg_vec_insn[lasx][vece], a0, a1));
break;
case INDEX_op_mul_vec:
- insn = mul_vec_insn[vece];
+ insn = mul_vec_insn[lasx][vece];
goto vdvjvk;
case INDEX_op_smin_vec:
- insn = smin_vec_insn[vece];
+ insn = smin_vec_insn[lasx][vece];
goto vdvjvk;
case INDEX_op_smax_vec:
- insn = smax_vec_insn[vece];
+ insn = smax_vec_insn[lasx][vece];
goto vdvjvk;
case INDEX_op_umin_vec:
- insn = umin_vec_insn[vece];
+ insn = umin_vec_insn[lasx][vece];
goto vdvjvk;
case INDEX_op_umax_vec:
- insn = umax_vec_insn[vece];
+ insn = umax_vec_insn[lasx][vece];
goto vdvjvk;
case INDEX_op_ssadd_vec:
- insn = ssadd_vec_insn[vece];
+ insn = ssadd_vec_insn[lasx][vece];
goto vdvjvk;
case INDEX_op_usadd_vec:
- insn = usadd_vec_insn[vece];
+ insn = usadd_vec_insn[lasx][vece];
goto vdvjvk;
case INDEX_op_sssub_vec:
- insn = sssub_vec_insn[vece];
+ insn = sssub_vec_insn[lasx][vece];
goto vdvjvk;
case INDEX_op_ussub_vec:
- insn = ussub_vec_insn[vece];
+ insn = ussub_vec_insn[lasx][vece];
goto vdvjvk;
case INDEX_op_shlv_vec:
- insn = shlv_vec_insn[vece];
+ insn = shlv_vec_insn[lasx][vece];
goto vdvjvk;
case INDEX_op_shrv_vec:
- insn = shrv_vec_insn[vece];
+ insn = shrv_vec_insn[lasx][vece];
goto vdvjvk;
case INDEX_op_sarv_vec:
- insn = sarv_vec_insn[vece];
+ insn = sarv_vec_insn[lasx][vece];
goto vdvjvk;
case INDEX_op_rotlv_vec:
/* rotlv_vec a1, a2 = rotrv_vec a1, -a2 */
- tcg_out32(s, encode_vdvj_insn(neg_vec_insn[vece], TCG_VEC_TMP0, a2));
+ tcg_out32(s, encode_vdvj_insn(neg_vec_insn[lasx][vece],
+ TCG_VEC_TMP0, a2));
a2 = TCG_VEC_TMP0;
/* fall through */
case INDEX_op_rotrv_vec:
- insn = rotrv_vec_insn[vece];
+ insn = rotrv_vec_insn[lasx][vece];
goto vdvjvk;
case INDEX_op_shli_vec:
- insn = shli_vec_insn[vece];
+ insn = shli_vec_insn[lasx][vece];
goto vdvjukN;
case INDEX_op_shri_vec:
- insn = shri_vec_insn[vece];
+ insn = shri_vec_insn[lasx][vece];
goto vdvjukN;
case INDEX_op_sari_vec:
- insn = sari_vec_insn[vece];
+ insn = sari_vec_insn[lasx][vece];
goto vdvjukN;
case INDEX_op_rotli_vec:
/* rotli_vec a1, a2 = rotri_vec a1, -a2 */
a2 = extract32(-a2, 0, 3 + vece);
- insn = rotri_vec_insn[vece];
+ insn = rotri_vec_insn[lasx][vece];
goto vdvjukN;
case INDEX_op_bitsel_vec:
/* vbitsel vd, vj, vk, va = bitsel_vec vd, va, vk, vj */
- tcg_out_opc_vbitsel_v(s, a0, a3, a2, a1);
+ if (lasx) {
+ tcg_out_opc_xvbitsel_v(s, a0, a3, a2, a1);
+ } else {
+ tcg_out_opc_vbitsel_v(s, a0, a3, a2, a1);
+ }
break;
case INDEX_op_dupm_vec:
tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
--
2.34.1