diff options
Diffstat (limited to 'tcg/ppc/tcg-target.c.inc')
-rw-r--r-- | tcg/ppc/tcg-target.c.inc | 90 |
1 files changed, 51 insertions, 39 deletions
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc index 19a4a12f15..cf64892295 100644 --- a/tcg/ppc/tcg-target.c.inc +++ b/tcg/ppc/tcg-target.c.inc @@ -912,31 +912,41 @@ static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret, } } -static void tcg_out_dupi_vec(TCGContext *s, TCGType type, TCGReg ret, - tcg_target_long val) +static void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece, + TCGReg ret, int64_t val) { uint32_t load_insn; int rel, low; intptr_t add; - low = (int8_t)val; - if (low >= -16 && low < 16) { - if (val == (tcg_target_long)dup_const(MO_8, low)) { + switch (vece) { + case MO_8: + low = (int8_t)val; + if (low >= -16 && low < 16) { tcg_out32(s, VSPLTISB | VRT(ret) | ((val & 31) << 16)); return; } - if (val == (tcg_target_long)dup_const(MO_16, low)) { + if (have_isa_3_00) { + tcg_out32(s, XXSPLTIB | VRT(ret) | ((val & 0xff) << 11)); + return; + } + break; + + case MO_16: + low = (int16_t)val; + if (low >= -16 && low < 16) { tcg_out32(s, VSPLTISH | VRT(ret) | ((val & 31) << 16)); return; } - if (val == (tcg_target_long)dup_const(MO_32, low)) { + break; + + case MO_32: + low = (int32_t)val; + if (low >= -16 && low < 16) { tcg_out32(s, VSPLTISW | VRT(ret) | ((val & 31) << 16)); return; } - } - if (have_isa_3_00 && val == (tcg_target_long)dup_const(MO_8, val)) { - tcg_out32(s, XXSPLTIB | VRT(ret) | ((val & 0xff) << 11)); - return; + break; } /* @@ -956,14 +966,15 @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type, TCGReg ret, if (TCG_TARGET_REG_BITS == 64) { new_pool_label(s, val, rel, s->code_ptr, add); } else { - new_pool_l2(s, rel, s->code_ptr, add, val, val); + new_pool_l2(s, rel, s->code_ptr, add, val >> 32, val); } } else { load_insn = LVX | VRT(ret) | RB(TCG_REG_TMP1); if (TCG_TARGET_REG_BITS == 64) { new_pool_l2(s, rel, s->code_ptr, add, val, val); } else { - new_pool_l4(s, rel, s->code_ptr, add, val, val, val, val); + new_pool_l4(s, rel, s->code_ptr, add, + val >> 32, val, val >> 32, val); } } @@ -987,12 +998,6 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg ret, tcg_out_movi_int(s, type, ret, arg, false); break; - case TCG_TYPE_V64: - case TCG_TYPE_V128: - tcg_debug_assert(ret >= TCG_REG_V0); - tcg_out_dupi_vec(s, type, ret, arg); - break; - default: g_assert_not_reached(); } @@ -2972,8 +2977,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ case INDEX_op_mov_i64: - case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */ - case INDEX_op_movi_i64: case INDEX_op_call: /* Always emitted via tcg_out_call. */ default: tcg_abort(); @@ -3321,7 +3324,6 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, return; case INDEX_op_mov_vec: /* Always emitted via tcg_out_mov. */ - case INDEX_op_dupi_vec: /* Always emitted via tcg_out_movi. */ case INDEX_op_dup_vec: /* Always emitted via tcg_out_dup_vec. */ default: g_assert_not_reached(); @@ -3334,13 +3336,22 @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc, static void expand_vec_shi(TCGType type, unsigned vece, TCGv_vec v0, TCGv_vec v1, TCGArg imm, TCGOpcode opci) { - TCGv_vec t1 = tcg_temp_new_vec(type); + TCGv_vec t1; - /* Splat w/bytes for xxspltib. */ - tcg_gen_dupi_vec(MO_8, t1, imm & ((8 << vece) - 1)); + if (vece == MO_32) { + /* + * Only 5 bits are significant, and VSPLTISB can represent -16..15. + * So using negative numbers gets us the 4th bit easily. + */ + imm = sextract32(imm, 0, 5); + } else { + imm &= (8 << vece) - 1; + } + + /* Splat w/bytes for xxspltib when 2.07 allows MO_64. */ + t1 = tcg_constant_vec(type, MO_8, imm); vec_gen_3(opci, type, vece, tcgv_vec_arg(v0), tcgv_vec_arg(v1), tcgv_vec_arg(t1)); - tcg_temp_free_vec(t1); } static void expand_vec_cmp(TCGType type, unsigned vece, TCGv_vec v0, @@ -3398,7 +3409,7 @@ static void expand_vec_mul(TCGType type, unsigned vece, TCGv_vec v0, { TCGv_vec t1 = tcg_temp_new_vec(type); TCGv_vec t2 = tcg_temp_new_vec(type); - TCGv_vec t3, t4; + TCGv_vec c0, c16; switch (vece) { case MO_8: @@ -3417,21 +3428,22 @@ static void expand_vec_mul(TCGType type, unsigned vece, TCGv_vec v0, case MO_32: tcg_debug_assert(!have_isa_2_07); - t3 = tcg_temp_new_vec(type); - t4 = tcg_temp_new_vec(type); - tcg_gen_dupi_vec(MO_8, t4, -16); + /* + * Only 5 bits are significant, and VSPLTISB can represent -16..15. + * So using -16 is a quick way to represent 16. + */ + c16 = tcg_constant_vec(type, MO_8, -16); + c0 = tcg_constant_vec(type, MO_8, 0); + vec_gen_3(INDEX_op_rotlv_vec, type, MO_32, tcgv_vec_arg(t1), - tcgv_vec_arg(v2), tcgv_vec_arg(t4)); + tcgv_vec_arg(v2), tcgv_vec_arg(c16)); vec_gen_3(INDEX_op_ppc_mulou_vec, type, MO_16, tcgv_vec_arg(t2), tcgv_vec_arg(v1), tcgv_vec_arg(v2)); - tcg_gen_dupi_vec(MO_8, t3, 0); - vec_gen_4(INDEX_op_ppc_msum_vec, type, MO_16, tcgv_vec_arg(t3), - tcgv_vec_arg(v1), tcgv_vec_arg(t1), tcgv_vec_arg(t3)); - vec_gen_3(INDEX_op_shlv_vec, type, MO_32, tcgv_vec_arg(t3), - tcgv_vec_arg(t3), tcgv_vec_arg(t4)); - tcg_gen_add_vec(MO_32, v0, t2, t3); - tcg_temp_free_vec(t3); - tcg_temp_free_vec(t4); + vec_gen_4(INDEX_op_ppc_msum_vec, type, MO_16, tcgv_vec_arg(t1), + tcgv_vec_arg(v1), tcgv_vec_arg(t1), tcgv_vec_arg(c0)); + vec_gen_3(INDEX_op_shlv_vec, type, MO_32, tcgv_vec_arg(t1), + tcgv_vec_arg(t1), tcgv_vec_arg(c16)); + tcg_gen_add_vec(MO_32, v0, t1, t2); break; default: |