DEF_HELPER_FLAGS_2(hadd_ss, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(hadd_us, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(havg, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_3(hshladd, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32)
+DEF_HELPER_FLAGS_3(hshradd, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32)
DEF_HELPER_FLAGS_2(hsub_ss, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(hsub_us, TCG_CALL_NO_RWG_SE, i64, i64, i64)
&rrr t r1 r2
&rrr_cf t r1 r2 cf
&rrr_cf_d t r1 r2 cf d
+&rrr_sh t r1 r2 sh
&rrr_cf_d_sh t r1 r2 cf d sh
&rri t r i
&rri_cf t r i cf
@rrr ...... r2:5 r1:5 .... ....... t:5 &rrr
@rrr_cf ...... r2:5 r1:5 cf:4 ....... t:5 &rrr_cf
@rrr_cf_d ...... r2:5 r1:5 cf:4 ...... d:1 t:5 &rrr_cf_d
+@rrr_sh ...... r2:5 r1:5 ........ sh:2 . t:5 &rrr_sh
@rrr_cf_d_sh ...... r2:5 r1:5 cf:4 .... sh:2 d:1 t:5 &rrr_cf_d_sh
@rrr_cf_d_sh0 ...... r2:5 r1:5 cf:4 ...... d:1 t:5 &rrr_cf_d_sh sh=0
@rri_cf ...... r:5 t:5 cf:4 . ........... &rri_cf i=%lowsign_11
add 000010 ..... ..... .... 0110.. . ..... @rrr_cf_d_sh
add_l 000010 ..... ..... .... 1010.. . ..... @rrr_cf_d_sh
add_tsv 000010 ..... ..... .... 1110.. . ..... @rrr_cf_d_sh
-add_c 000010 ..... ..... .... 011100 . ..... @rrr_cf_d_sh0
+{
+ add_c 000010 ..... ..... .... 011100 . ..... @rrr_cf_d_sh0
+ hshladd 000010 ..... ..... 0000 0111.. 0 ..... @rrr_sh
+}
add_c_tsv 000010 ..... ..... .... 111100 . ..... @rrr_cf_d_sh0
sub 000010 ..... ..... .... 010000 . ..... @rrr_cf_d
sub_tsv 000010 ..... ..... .... 110000 . ..... @rrr_cf_d
sub_tc 000010 ..... ..... .... 010011 . ..... @rrr_cf_d
sub_tsv_tc 000010 ..... ..... .... 110011 . ..... @rrr_cf_d
-sub_b 000010 ..... ..... .... 010100 . ..... @rrr_cf_d
+{
+ sub_b 000010 ..... ..... .... 010100 . ..... @rrr_cf_d
+ hshradd 000010 ..... ..... 0000 0101.. 0 ..... @rrr_sh
+}
sub_b_tsv 000010 ..... ..... .... 110100 . ..... @rrr_cf_d
ldil 001000 t:5 ..................... i=%assemble_21
}
return ret;
}
+
+uint64_t HELPER(hshladd)(uint64_t r1, uint64_t r2, uint32_t sh)
+{
+ uint64_t ret = 0;
+
+ for (int i = 0; i < 64; i += 16) {
+ int f1 = sextract64(r1, i, 16);
+ int f2 = sextract64(r2, i, 16);
+ int fr = (f1 << sh) + f2;
+
+ fr = MIN(fr, INT16_MAX);
+ fr = MAX(fr, INT16_MIN);
+ ret = deposit64(ret, i, 16, fr);
+ }
+ return ret;
+}
+
+uint64_t HELPER(hshradd)(uint64_t r1, uint64_t r2, uint32_t sh)
+{
+ uint64_t ret = 0;
+
+ for (int i = 0; i < 64; i += 16) {
+ int f1 = sextract64(r1, i, 16);
+ int f2 = sextract64(r2, i, 16);
+ int fr = (f1 >> sh) + f2;
+
+ fr = MIN(fr, INT16_MAX);
+ fr = MAX(fr, INT16_MIN);
+ ret = deposit64(ret, i, 16, fr);
+ }
+ return ret;
+}
return nullify_end(ctx);
}
+static bool do_multimedia_shadd(DisasContext *ctx, arg_rrr_sh *a,
+ void (*fn)(TCGv_i64, TCGv_i64,
+ TCGv_i64, TCGv_i32))
+{
+ TCGv_i64 r1, r2, dest;
+
+ if (!ctx->is_pa20) {
+ return false;
+ }
+
+ nullify_over(ctx);
+
+ r1 = load_gpr(ctx, a->r1);
+ r2 = load_gpr(ctx, a->r2);
+ dest = dest_gpr(ctx, a->t);
+
+ fn(dest, r1, r2, tcg_constant_i32(a->sh));
+ save_gpr(ctx, a->t, dest);
+
+ return nullify_end(ctx);
+}
+
static bool trans_hadd(DisasContext *ctx, arg_rrr *a)
{
return do_multimedia(ctx, a, tcg_gen_vec_add16_i64);
return do_multimedia_sh(ctx, a, tcg_gen_vec_shr16i_i64);
}
+static bool trans_hshladd(DisasContext *ctx, arg_rrr_sh *a)
+{
+ return do_multimedia_shadd(ctx, a, gen_helper_hshladd);
+}
+
+static bool trans_hshradd(DisasContext *ctx, arg_rrr_sh *a)
+{
+ return do_multimedia_shadd(ctx, a, gen_helper_hshradd);
+}
+
static bool trans_hsub(DisasContext *ctx, arg_rrr *a)
{
return do_multimedia(ctx, a, tcg_gen_vec_sub16_i64);