--- gcc/config/mips/loongson.md | 36 ++++++++++++++++++++++++++++++++ gcc/config/mips/mips-protos.h | 1 + gcc/config/mips/mips.c | 45 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 0 deletions(-)
diff --git a/gcc/config/mips/loongson.md b/gcc/config/mips/loongson.md index 325838d..8404bf0 100644 --- a/gcc/config/mips/loongson.md +++ b/gcc/config/mips/loongson.md @@ -643,6 +643,42 @@ FAIL; }) +(define_expand "vec_unpacks_lo_<mode>" + [(match_operand:<V_stretch_half> 0 "register_operand" "") + (match_operand:VHB 1 "register_operand" "")] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" +{ + mips_expand_vec_unpack (operands, false, false); + DONE; +}) + +(define_expand "vec_unpacks_hi_<mode>" + [(match_operand:<V_stretch_half> 0 "register_operand" "") + (match_operand:VHB 1 "register_operand" "")] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" +{ + mips_expand_vec_unpack (operands, false, true); + DONE; +}) + +(define_expand "vec_unpacku_lo_<mode>" + [(match_operand:<V_stretch_half> 0 "register_operand" "") + (match_operand:VHB 1 "register_operand" "")] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" +{ + mips_expand_vec_unpack (operands, true, false); + DONE; +}) + +(define_expand "vec_unpacku_hi_<mode>" + [(match_operand:<V_stretch_half> 0 "register_operand" "") + (match_operand:VHB 1 "register_operand" "")] + "TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS" +{ + mips_expand_vec_unpack (operands, true, true); + DONE; +}) + ;; Integer division and modulus. For integer multiplication, see mips.md. (define_insn "<u>div<mode>3" diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 37c958d..82c8c33 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -329,6 +329,7 @@ extern void mips_expand_atomic_qihi (union mips_gen_fn_ptrs, extern void mips_expand_vector_init (rtx, rtx); extern bool mips_expand_vec_perm_const (rtx op[4]); +extern void mips_expand_vec_unpack (rtx op[2], bool, bool); extern bool mips_eh_uses (unsigned int); extern bool mips_epilogue_uses (unsigned int); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 0ac1096..b3a3ad0 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -16611,6 +16611,51 @@ mips_vectorize_vec_perm_const_ok (enum machine_mode vmode, return ret; } + +/* Expand an integral vector unpack operation. */ + +void +mips_expand_vec_unpack (rtx operands[2], bool unsigned_p, bool high_p) +{ + enum machine_mode imode = GET_MODE (operands[1]); + rtx (*unpack) (rtx, rtx, rtx); + rtx (*cmpgt) (rtx, rtx, rtx); + rtx tmp, dest, zero; + + switch (imode) + { + case V8QImode: + if (high_p) + unpack = gen_loongson_punpckhbh; + else + unpack = gen_loongson_punpcklbh; + cmpgt = gen_loongson_pcmpgtb; + break; + case V4HImode: + if (high_p) + unpack = gen_loongson_punpckhhw; + else + unpack = gen_loongson_punpcklhw; + cmpgt = gen_loongson_pcmpgth; + break; + default: + gcc_unreachable (); + } + + zero = force_reg (imode, CONST0_RTX (imode)); + if (unsigned_p) + tmp = zero; + else + { + tmp = gen_reg_rtx (imode); + emit_insn (cmpgt (tmp, zero, operands[1])); + } + + dest = gen_reg_rtx (imode); + emit_insn (unpack (dest, operands[1], tmp)); + + emit_move_insn (operands[0], gen_lowpart (GET_MODE (operands[0]), dest)); +} /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP -- 1.7.7.4