3697
3698
static bool trans_WHILE_ptr(DisasContext *s, arg_WHILE_ptr *a)
3699
{
3700
- TCGv_i64 op0, op1, diff, t1, tmax;
3700
+ TCGv_i64 op0, op1, diff, t1;
3701
TCGv_i32 t2;
3702
TCGv_ptr ptr;
3703
unsigned vsz = vec_full_reg_size(s);
3713
op0 = read_cpu_reg(s, a->rn, 1);
3714
op1 = read_cpu_reg(s, a->rm, 1);
3715
3716
- tmax = tcg_constant_i64(vsz >> a->esz);
3716
diff = tcg_temp_new_i64();
3717
3718
if (a->rw) {
3722
tcg_gen_sub_i64(diff, op0, op1);
3723
tcg_gen_sub_i64(t1, op1, op0);
3724
tcg_gen_movcond_i64(TCG_COND_GEU, diff, op0, op1, diff, t1);
3726
- /* Divide, rounding down, by ESIZE. */
3727
- tcg_gen_shri_i64(diff, diff, a->esz);
3728
- /* If op1 == op0, diff == 0, and the condition is always true. */
3729
- tcg_gen_movcond_i64(TCG_COND_EQ, diff, op0, op1, tmax, diff);
3725
} else {
3726
/* WHILEWR */
3732
- tcg_gen_sub_i64(diff, op1, op0);
3733
- /* Divide, rounding down, by ESIZE. */
3734
- tcg_gen_shri_i64(diff, diff, a->esz);
3735
- /* If op0 >= op1, diff <= 0, the condition is always true. */
3736
- tcg_gen_movcond_i64(TCG_COND_GEU, diff, op0, op1, tmax, diff);
3727
+ /* Saturating subtraction maps diff <= 0 to diff == 0. */
3728
+ tcg_gen_ussub_i64(diff, op1, op0);
3729
}
3730
3739
- /* Bound to the maximum. */
3740
- tcg_gen_umin_i64(diff, diff, tmax);
3731
+ /* Divide, rounding down, by ESIZE. */
3732
+ tcg_gen_shri_i64(diff, diff, a->esz);
3733
3742
- /* Since we're bounded, pass as a 32-bit type. */
3734
+ /*
3735
+ * If diff == 0, the condition is always true. Also, bound to max.
3736
+ * Simplify
3737
+ * diff = diff ? diff : max;
3738
+ * diff = umin(diff, max);
3739
+ * via
3740
+ * diff -= 1;
3741
+ * diff = umin(diff, max - 1);
3742
+ * diff += 1;
3743
+ * via 0 - 1 == UINT64_MAX.
3744
+ */
3745
+ tcg_gen_addi_i64(diff, diff, -1);
3746
+ tcg_gen_umin_i64(diff, diff, tcg_constant_i64((vsz >> a->esz) - 1));
3747
+
3748
+ /*
3749
+ * Since we're bounded, pass as a 32-bit type.
3750
+ * Sink the diff += 1 from above into the 32-bit type.
3751
+ */
3752
t2 = tcg_temp_new_i32();
3753
tcg_gen_extrl_i64_i32(t2, diff);
3754
+ tcg_gen_addi_i32(t2, t2, 1);
3755
3756
desc = FIELD_DP32(desc, PREDDESC, OPRSZ, vsz / 8);
3757
desc = FIELD_DP32(desc, PREDDESC, ESZ, a->esz);