target-alpha: Convert most ieee insns to source/sink

This one fixes a bug, previously noted as supressing exceptions
in the (unlikely) case the destination register was $f31.

Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Richard Henderson 2014-03-19 12:32:05 -07:00
parent 8b0190bbde
commit e20b8c04a3
1 changed files with 17 additions and 52 deletions

View File

@ -807,18 +807,12 @@ static void gen_ieee_arith2(DisasContext *ctx,
{ {
TCGv vb; TCGv vb;
/* ??? This is wrong: the instruction is not a nop, it still may
raise exceptions. */
if (unlikely(rc == 31)) {
return;
}
gen_qual_roundmode(ctx, fn11); gen_qual_roundmode(ctx, fn11);
gen_qual_flushzero(ctx, fn11); gen_qual_flushzero(ctx, fn11);
gen_fp_exc_clear(); gen_fp_exc_clear();
vb = gen_ieee_input(ctx, rb, fn11, 0); vb = gen_ieee_input(ctx, rb, fn11, 0);
helper(cpu_fir[rc], cpu_env, vb); helper(dest_fpr(ctx, rc), cpu_env, vb);
gen_fp_exc_raise(rc, fn11); gen_fp_exc_raise(rc, fn11);
} }
@ -836,35 +830,30 @@ IEEE_ARITH2(cvtts)
static void gen_fcvttq(DisasContext *ctx, int rb, int rc, int fn11) static void gen_fcvttq(DisasContext *ctx, int rb, int rc, int fn11)
{ {
TCGv vb; TCGv vb, vc;
int ignore = 0; int ignore = 0;
/* ??? This is wrong: the instruction is not a nop, it still may
raise exceptions. */
if (unlikely(rc == 31)) {
return;
}
/* No need to set flushzero, since we have an integer output. */ /* No need to set flushzero, since we have an integer output. */
gen_fp_exc_clear(); gen_fp_exc_clear();
vb = gen_ieee_input(ctx, rb, fn11, 0); vb = gen_ieee_input(ctx, rb, fn11, 0);
vc = dest_fpr(ctx, rc);
/* Almost all integer conversions use cropped rounding, and most /* Almost all integer conversions use cropped rounding, and most
also do not have integer overflow enabled. Special case that. */ also do not have integer overflow enabled. Special case that. */
switch (fn11) { switch (fn11) {
case QUAL_RM_C: case QUAL_RM_C:
gen_helper_cvttq_c(cpu_fir[rc], cpu_env, vb); gen_helper_cvttq_c(vc, cpu_env, vb);
break; break;
case QUAL_V | QUAL_RM_C: case QUAL_V | QUAL_RM_C:
case QUAL_S | QUAL_V | QUAL_RM_C: case QUAL_S | QUAL_V | QUAL_RM_C:
ignore = float_flag_inexact; ignore = float_flag_inexact;
/* FALLTHRU */ /* FALLTHRU */
case QUAL_S | QUAL_V | QUAL_I | QUAL_RM_C: case QUAL_S | QUAL_V | QUAL_I | QUAL_RM_C:
gen_helper_cvttq_svic(cpu_fir[rc], cpu_env, vb); gen_helper_cvttq_svic(vc, cpu_env, vb);
break; break;
default: default:
gen_qual_roundmode(ctx, fn11); gen_qual_roundmode(ctx, fn11);
gen_helper_cvttq(cpu_fir[rc], cpu_env, vb); gen_helper_cvttq(vc, cpu_env, vb);
ignore |= (fn11 & QUAL_V ? 0 : float_flag_overflow); ignore |= (fn11 & QUAL_V ? 0 : float_flag_overflow);
ignore |= (fn11 & QUAL_I ? 0 : float_flag_inexact); ignore |= (fn11 & QUAL_I ? 0 : float_flag_inexact);
break; break;
@ -877,35 +866,21 @@ static void gen_ieee_intcvt(DisasContext *ctx,
void (*helper)(TCGv, TCGv_ptr, TCGv), void (*helper)(TCGv, TCGv_ptr, TCGv),
int rb, int rc, int fn11) int rb, int rc, int fn11)
{ {
TCGv vb; TCGv vb, vc;
/* ??? This is wrong: the instruction is not a nop, it still may
raise exceptions. */
if (unlikely(rc == 31)) {
return;
}
gen_qual_roundmode(ctx, fn11); gen_qual_roundmode(ctx, fn11);
vb = load_fpr(ctx, rb);
if (rb == 31) { vc = dest_fpr(ctx, rc);
vb = tcg_const_i64(0);
} else {
vb = cpu_fir[rb];
}
/* The only exception that can be raised by integer conversion /* The only exception that can be raised by integer conversion
is inexact. Thus we only need to worry about exceptions when is inexact. Thus we only need to worry about exceptions when
inexact handling is requested. */ inexact handling is requested. */
if (fn11 & QUAL_I) { if (fn11 & QUAL_I) {
gen_fp_exc_clear(); gen_fp_exc_clear();
helper(cpu_fir[rc], cpu_env, vb); helper(vc, cpu_env, vb);
gen_fp_exc_raise(rc, fn11); gen_fp_exc_raise(rc, fn11);
} else { } else {
helper(cpu_fir[rc], cpu_env, vb); helper(vc, cpu_env, vb);
}
if (rb == 31) {
tcg_temp_free(vb);
} }
} }
@ -997,13 +972,7 @@ static void gen_ieee_arith3(DisasContext *ctx,
void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv), void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
int ra, int rb, int rc, int fn11) int ra, int rb, int rc, int fn11)
{ {
TCGv va, vb; TCGv va, vb, vc;
/* ??? This is wrong: the instruction is not a nop, it still may
raise exceptions. */
if (unlikely(rc == 31)) {
return;
}
gen_qual_roundmode(ctx, fn11); gen_qual_roundmode(ctx, fn11);
gen_qual_flushzero(ctx, fn11); gen_qual_flushzero(ctx, fn11);
@ -1011,7 +980,8 @@ static void gen_ieee_arith3(DisasContext *ctx,
va = gen_ieee_input(ctx, ra, fn11, 0); va = gen_ieee_input(ctx, ra, fn11, 0);
vb = gen_ieee_input(ctx, rb, fn11, 0); vb = gen_ieee_input(ctx, rb, fn11, 0);
helper(cpu_fir[rc], cpu_env, va, vb); vc = dest_fpr(ctx, rc);
helper(vc, cpu_env, va, vb);
gen_fp_exc_raise(rc, fn11); gen_fp_exc_raise(rc, fn11);
} }
@ -1035,19 +1005,14 @@ static void gen_ieee_compare(DisasContext *ctx,
void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv), void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv),
int ra, int rb, int rc, int fn11) int ra, int rb, int rc, int fn11)
{ {
TCGv va, vb; TCGv va, vb, vc;
/* ??? This is wrong: the instruction is not a nop, it still may
raise exceptions. */
if (unlikely(rc == 31)) {
return;
}
gen_fp_exc_clear(); gen_fp_exc_clear();
va = gen_ieee_input(ctx, ra, fn11, 1); va = gen_ieee_input(ctx, ra, fn11, 1);
vb = gen_ieee_input(ctx, rb, fn11, 1); vb = gen_ieee_input(ctx, rb, fn11, 1);
helper(cpu_fir[rc], cpu_env, va, vb); vc = dest_fpr(ctx, rc);
helper(vc, cpu_env, va, vb);
gen_fp_exc_raise(rc, fn11); gen_fp_exc_raise(rc, fn11);
} }