Skip to content

Commit

Permalink
target/sparc: Split fcc out of env->fsr
Browse files Browse the repository at this point in the history
Represent each fcc field separately from the rest of fsr.
This vastly simplifies floating-point comparisons.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Acked-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Message-Id: <20231103173841.33651-22-richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed Feb 2, 2024
1 parent d8dc88b commit 581628e
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 522 deletions.
20 changes: 9 additions & 11 deletions target/sparc/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@

#if !defined(TARGET_SPARC64)
#define TARGET_DPREGS 16
#define TARGET_FCCREGS 1
#else
#define TARGET_DPREGS 32
#define TARGET_FCCREGS 4
#endif

/*#define EXCP_INTERRUPT 0x100*/
Expand Down Expand Up @@ -203,24 +205,19 @@ enum {
#ifdef TARGET_SPARC64
#define FSR_FTT_NMASK 0xfffffffffffe3fffULL
#define FSR_FTT_CEXC_NMASK 0xfffffffffffe3fe0ULL
#define FSR_LDFSR_OLDMASK 0x0000003f000fc000ULL
#define FSR_LDXFSR_MASK 0x0000003fcfc00fffULL
#define FSR_LDXFSR_OLDMASK 0x00000000000fc000ULL
#else
#define FSR_FTT_NMASK 0xfffe3fffULL
#define FSR_FTT_CEXC_NMASK 0xfffe3fe0ULL
#define FSR_LDFSR_OLDMASK 0x000fc000ULL
#endif
#define FSR_LDFSR_MASK 0xcfc00fffULL
#define FSR_FTT_IEEE_EXCP (1ULL << 14)
#define FSR_FTT_UNIMPFPOP (3ULL << 14)
#define FSR_FTT_SEQ_ERROR (4ULL << 14)
#define FSR_FTT_INVAL_FPR (6ULL << 14)

#define FSR_FCC1_SHIFT 11
#define FSR_FCC1 (1ULL << FSR_FCC1_SHIFT)
#define FSR_FCC0_SHIFT 10
#define FSR_FCC0 (1ULL << FSR_FCC0_SHIFT)
#define FSR_FCC0_SHIFT 10
#define FSR_FCC1_SHIFT 32
#define FSR_FCC2_SHIFT 34
#define FSR_FCC3_SHIFT 36

/* MMU */
#define MMU_E (1<<0)
Expand Down Expand Up @@ -467,8 +464,9 @@ struct CPUArchState {
temporary register when possible) */

/* FPU State Register, in parts */
target_ulong fsr; /* rm, tem, aexc, fcc* */
uint32_t fsr_cexc_ftt; /* cexc, ftt */
uint32_t fsr; /* rm, tem, aexc */
uint32_t fsr_cexc_ftt; /* cexc, ftt */
uint32_t fcc[TARGET_FCCREGS]; /* fcc* */

CPU_DoubleU fpr[TARGET_DPREGS]; /* floating point registers */
uint32_t cwp; /* index of current register window (extracted
Expand Down
169 changes: 72 additions & 97 deletions target/sparc/fop_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,113 +343,80 @@ Int128 helper_fsqrtq(CPUSPARCState *env, Int128 src)
return f128_ret(ret);
}

#define GEN_FCMP(name, size, FS, E) \
void glue(helper_, name)(CPUSPARCState *env, Int128 src1, Int128 src2) \
{ \
float128 reg1 = f128_in(src1); \
float128 reg2 = f128_in(src2); \
FloatRelation ret; \
target_ulong fsr; \
if (E) { \
ret = glue(size, _compare)(reg1, reg2, &env->fp_status); \
} else { \
ret = glue(size, _compare_quiet)(reg1, reg2, \
&env->fp_status); \
} \
check_ieee_exceptions(env, GETPC()); \
fsr = env->fsr; \
switch (ret) { \
case float_relation_unordered: \
fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
fsr |= FSR_NVA; \
break; \
case float_relation_less: \
fsr &= ~(FSR_FCC1) << FS; \
fsr |= FSR_FCC0 << FS; \
break; \
case float_relation_greater: \
fsr &= ~(FSR_FCC0) << FS; \
fsr |= FSR_FCC1 << FS; \
break; \
default: \
fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
break; \
} \
env->fsr = fsr; \
static uint32_t finish_fcmp(CPUSPARCState *env, FloatRelation r, uintptr_t ra)
{
check_ieee_exceptions(env, ra);

/*
* FCC values:
* 0 =
* 1 <
* 2 >
* 3 unordered
*/
switch (r) {
case float_relation_equal:
return 0;
case float_relation_less:
return 1;
case float_relation_greater:
return 2;
case float_relation_unordered:
env->fsr |= FSR_NVA;
return 3;
}
#define GEN_FCMP_T(name, size, FS, E) \
void glue(helper_, name)(CPUSPARCState *env, size src1, size src2) \
{ \
FloatRelation ret; \
target_ulong fsr; \
if (E) { \
ret = glue(size, _compare)(src1, src2, &env->fp_status); \
} else { \
ret = glue(size, _compare_quiet)(src1, src2, \
&env->fp_status); \
} \
check_ieee_exceptions(env, GETPC()); \
fsr = env->fsr; \
switch (ret) { \
case float_relation_unordered: \
fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
break; \
case float_relation_less: \
fsr &= ~(FSR_FCC1 << FS); \
fsr |= FSR_FCC0 << FS; \
break; \
case float_relation_greater: \
fsr &= ~(FSR_FCC0 << FS); \
fsr |= FSR_FCC1 << FS; \
break; \
default: \
fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
break; \
} \
env->fsr = fsr; \
}

GEN_FCMP_T(fcmps, float32, 0, 0);
GEN_FCMP_T(fcmpd, float64, 0, 0);

GEN_FCMP_T(fcmpes, float32, 0, 1);
GEN_FCMP_T(fcmped, float64, 0, 1);

GEN_FCMP(fcmpq, float128, 0, 0);
GEN_FCMP(fcmpeq, float128, 0, 1);
g_assert_not_reached();
}

#ifdef TARGET_SPARC64
GEN_FCMP_T(fcmps_fcc1, float32, 22, 0);
GEN_FCMP_T(fcmpd_fcc1, float64, 22, 0);
GEN_FCMP(fcmpq_fcc1, float128, 22, 0);
uint32_t helper_fcmps(CPUSPARCState *env, float32 src1, float32 src2)
{
FloatRelation r = float32_compare_quiet(src1, src2, &env->fp_status);
return finish_fcmp(env, r, GETPC());
}

GEN_FCMP_T(fcmps_fcc2, float32, 24, 0);
GEN_FCMP_T(fcmpd_fcc2, float64, 24, 0);
GEN_FCMP(fcmpq_fcc2, float128, 24, 0);
uint32_t helper_fcmpes(CPUSPARCState *env, float32 src1, float32 src2)
{
FloatRelation r = float32_compare(src1, src2, &env->fp_status);
return finish_fcmp(env, r, GETPC());
}

GEN_FCMP_T(fcmps_fcc3, float32, 26, 0);
GEN_FCMP_T(fcmpd_fcc3, float64, 26, 0);
GEN_FCMP(fcmpq_fcc3, float128, 26, 0);
uint32_t helper_fcmpd(CPUSPARCState *env, float64 src1, float64 src2)
{
FloatRelation r = float64_compare_quiet(src1, src2, &env->fp_status);
return finish_fcmp(env, r, GETPC());
}

GEN_FCMP_T(fcmpes_fcc1, float32, 22, 1);
GEN_FCMP_T(fcmped_fcc1, float64, 22, 1);
GEN_FCMP(fcmpeq_fcc1, float128, 22, 1);
uint32_t helper_fcmped(CPUSPARCState *env, float64 src1, float64 src2)
{
FloatRelation r = float64_compare(src1, src2, &env->fp_status);
return finish_fcmp(env, r, GETPC());
}

GEN_FCMP_T(fcmpes_fcc2, float32, 24, 1);
GEN_FCMP_T(fcmped_fcc2, float64, 24, 1);
GEN_FCMP(fcmpeq_fcc2, float128, 24, 1);
uint32_t helper_fcmpq(CPUSPARCState *env, Int128 src1, Int128 src2)
{
FloatRelation r = float128_compare_quiet(f128_in(src1), f128_in(src2),
&env->fp_status);
return finish_fcmp(env, r, GETPC());
}

GEN_FCMP_T(fcmpes_fcc3, float32, 26, 1);
GEN_FCMP_T(fcmped_fcc3, float64, 26, 1);
GEN_FCMP(fcmpeq_fcc3, float128, 26, 1);
#endif
#undef GEN_FCMP_T
#undef GEN_FCMP
uint32_t helper_fcmpeq(CPUSPARCState *env, Int128 src1, Int128 src2)
{
FloatRelation r = float128_compare(f128_in(src1), f128_in(src2),
&env->fp_status);
return finish_fcmp(env, r, GETPC());
}

target_ulong cpu_get_fsr(CPUSPARCState *env)
{
target_ulong fsr = env->fsr | env->fsr_cexc_ftt;

fsr |= env->fcc[0] << FSR_FCC0_SHIFT;
#ifdef TARGET_SPARC64
fsr |= (uint64_t)env->fcc[1] << FSR_FCC1_SHIFT;
fsr |= (uint64_t)env->fcc[2] << FSR_FCC2_SHIFT;
fsr |= (uint64_t)env->fcc[3] << FSR_FCC3_SHIFT;
#endif

/* VER is kept completely separate until re-assembly. */
fsr |= env->def.fpu_version;

Expand All @@ -465,7 +432,7 @@ static void set_fsr_nonsplit(CPUSPARCState *env, target_ulong fsr)
{
int rnd_mode;

env->fsr = fsr & ~(FSR_VER_MASK | FSR_CEXC_MASK | FSR_FTT_MASK);
env->fsr = fsr & (FSR_RD_MASK | FSR_TEM_MASK | FSR_AEXC_MASK);

switch (fsr & FSR_RD_MASK) {
case FSR_RD_NEAREST:
Expand All @@ -488,10 +455,18 @@ static void set_fsr_nonsplit(CPUSPARCState *env, target_ulong fsr)
void cpu_put_fsr(CPUSPARCState *env, target_ulong fsr)
{
env->fsr_cexc_ftt = fsr & (FSR_CEXC_MASK | FSR_FTT_MASK);

env->fcc[0] = extract32(fsr, FSR_FCC0_SHIFT, 2);
#ifdef TARGET_SPARC64
env->fcc[1] = extract64(fsr, FSR_FCC1_SHIFT, 2);
env->fcc[2] = extract64(fsr, FSR_FCC2_SHIFT, 2);
env->fcc[3] = extract64(fsr, FSR_FCC3_SHIFT, 2);
#endif

set_fsr_nonsplit(env, fsr);
}

void helper_set_fsr_noftt(CPUSPARCState *env, target_ulong fsr)
void helper_set_fsr_nofcc_noftt(CPUSPARCState *env, uint32_t fsr)
{
env->fsr_cexc_ftt &= FSR_FTT_MASK;
env->fsr_cexc_ftt |= fsr & FSR_CEXC_MASK;
Expand Down
34 changes: 7 additions & 27 deletions target/sparc/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,36 +36,16 @@ DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, i32)
DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32)
#endif
DEF_HELPER_FLAGS_1(get_fsr, TCG_CALL_NO_WG_SE, tl, env)
DEF_HELPER_FLAGS_2(set_fsr_noftt, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(set_fsr_nofcc_noftt, TCG_CALL_NO_RWG, void, env, i32)
DEF_HELPER_FLAGS_2(fsqrts, TCG_CALL_NO_WG, f32, env, f32)
DEF_HELPER_FLAGS_2(fsqrtd, TCG_CALL_NO_WG, f64, env, f64)
DEF_HELPER_FLAGS_2(fsqrtq, TCG_CALL_NO_WG, i128, env, i128)
DEF_HELPER_FLAGS_3(fcmps, TCG_CALL_NO_WG, void, env, f32, f32)
DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, void, env, f64, f64)
DEF_HELPER_FLAGS_3(fcmpes, TCG_CALL_NO_WG, void, env, f32, f32)
DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, void, env, f64, f64)
DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, void, env, i128, i128)
DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, void, env, i128, i128)
#ifdef TARGET_SPARC64
DEF_HELPER_FLAGS_3(fcmps_fcc1, TCG_CALL_NO_WG, void, env, f32, f32)
DEF_HELPER_FLAGS_3(fcmps_fcc2, TCG_CALL_NO_WG, void, env, f32, f32)
DEF_HELPER_FLAGS_3(fcmps_fcc3, TCG_CALL_NO_WG, void, env, f32, f32)
DEF_HELPER_FLAGS_3(fcmpd_fcc1, TCG_CALL_NO_WG, void, env, f64, f64)
DEF_HELPER_FLAGS_3(fcmpd_fcc2, TCG_CALL_NO_WG, void, env, f64, f64)
DEF_HELPER_FLAGS_3(fcmpd_fcc3, TCG_CALL_NO_WG, void, env, f64, f64)
DEF_HELPER_FLAGS_3(fcmpes_fcc1, TCG_CALL_NO_WG, void, env, f32, f32)
DEF_HELPER_FLAGS_3(fcmpes_fcc2, TCG_CALL_NO_WG, void, env, f32, f32)
DEF_HELPER_FLAGS_3(fcmpes_fcc3, TCG_CALL_NO_WG, void, env, f32, f32)
DEF_HELPER_FLAGS_3(fcmped_fcc1, TCG_CALL_NO_WG, void, env, f64, f64)
DEF_HELPER_FLAGS_3(fcmped_fcc2, TCG_CALL_NO_WG, void, env, f64, f64)
DEF_HELPER_FLAGS_3(fcmped_fcc3, TCG_CALL_NO_WG, void, env, f64, f64)
DEF_HELPER_FLAGS_3(fcmpq_fcc1, TCG_CALL_NO_WG, void, env, i128, i128)
DEF_HELPER_FLAGS_3(fcmpq_fcc2, TCG_CALL_NO_WG, void, env, i128, i128)
DEF_HELPER_FLAGS_3(fcmpq_fcc3, TCG_CALL_NO_WG, void, env, i128, i128)
DEF_HELPER_FLAGS_3(fcmpeq_fcc1, TCG_CALL_NO_WG, void, env, i128, i128)
DEF_HELPER_FLAGS_3(fcmpeq_fcc2, TCG_CALL_NO_WG, void, env, i128, i128)
DEF_HELPER_FLAGS_3(fcmpeq_fcc3, TCG_CALL_NO_WG, void, env, i128, i128)
#endif
DEF_HELPER_FLAGS_3(fcmps, TCG_CALL_NO_WG, i32, env, f32, f32)
DEF_HELPER_FLAGS_3(fcmpes, TCG_CALL_NO_WG, i32, env, f32, f32)
DEF_HELPER_FLAGS_3(fcmpd, TCG_CALL_NO_WG, i32, env, f64, f64)
DEF_HELPER_FLAGS_3(fcmped, TCG_CALL_NO_WG, i32, env, f64, f64)
DEF_HELPER_FLAGS_3(fcmpq, TCG_CALL_NO_WG, i32, env, i128, i128)
DEF_HELPER_FLAGS_3(fcmpeq, TCG_CALL_NO_WG, i32, env, i128, i128)
DEF_HELPER_2(raise_exception, noreturn, env, int)

DEF_HELPER_FLAGS_3(faddd, TCG_CALL_NO_WG, f64, env, f64, f64)
Expand Down

0 comments on commit 581628e

Please sign in to comment.