soft floats for SPARC (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2000 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
ee6c0b51e9
commit
65ce8c2fb4
2
configure
vendored
2
configure
vendored
@ -850,7 +850,7 @@ if test "$target_user_only" = "yes" ; then
|
||||
echo "#define CONFIG_USER_ONLY 1" >> $config_h
|
||||
fi
|
||||
|
||||
if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" ; then
|
||||
if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64"; then
|
||||
echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
|
||||
echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
|
||||
fi
|
||||
|
@ -12,7 +12,7 @@
|
||||
#define TARGET_FPREGS 64
|
||||
#define TARGET_PAGE_BITS 12 /* XXX */
|
||||
#endif
|
||||
#define TARGET_FPREG_T float
|
||||
#define TARGET_FPREG_T float32
|
||||
|
||||
#include "cpu-defs.h"
|
||||
|
||||
@ -146,7 +146,7 @@
|
||||
typedef struct CPUSPARCState {
|
||||
target_ulong gregs[8]; /* general registers */
|
||||
target_ulong *regwptr; /* pointer to current register window */
|
||||
TARGET_FPREG_T fpr[TARGET_FPREGS]; /* floating point registers */
|
||||
float32 fpr[TARGET_FPREGS]; /* floating point registers */
|
||||
target_ulong pc; /* program counter */
|
||||
target_ulong npc; /* next program counter */
|
||||
target_ulong y; /* multiply/divide register */
|
||||
@ -187,8 +187,8 @@ typedef struct CPUSPARCState {
|
||||
uint32_t mmuregs[16];
|
||||
#endif
|
||||
/* temporary float registers */
|
||||
float ft0, ft1;
|
||||
double dt0, dt1;
|
||||
float32 ft0, ft1;
|
||||
float64 dt0, dt1;
|
||||
float_status fp_status;
|
||||
#if defined(TARGET_SPARC64)
|
||||
#define MAXTL 4
|
||||
@ -236,8 +236,6 @@ typedef struct CPUSPARCState {
|
||||
CPUSPARCState *cpu_sparc_init(void);
|
||||
int cpu_sparc_exec(CPUSPARCState *s);
|
||||
int cpu_sparc_close(CPUSPARCState *s);
|
||||
void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f);
|
||||
double cpu_put_fp64(uint64_t mant, uint16_t exp);
|
||||
|
||||
/* Fake impl 0, version 4 */
|
||||
#define GET_PSR(env) ((0 << 28) | (4 << 24) | (env->psr & PSR_ICC) | \
|
||||
|
@ -1339,94 +1339,66 @@ void OPPROTO op_flush_T0(void)
|
||||
helper_flush(T0);
|
||||
}
|
||||
|
||||
void OPPROTO op_fnegs(void)
|
||||
#define F_OP(name, p) void OPPROTO op_f##name##p(void)
|
||||
|
||||
#define F_BINOP(name) \
|
||||
F_OP(name, s) \
|
||||
{ \
|
||||
FT0 = float32_ ## name (FT0, FT1, &env->fp_status); \
|
||||
} \
|
||||
F_OP(name, d) \
|
||||
{ \
|
||||
DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
|
||||
}
|
||||
|
||||
F_BINOP(add);
|
||||
F_BINOP(sub);
|
||||
F_BINOP(mul);
|
||||
F_BINOP(div);
|
||||
#undef F_BINOP
|
||||
|
||||
void OPPROTO op_fsmuld(void)
|
||||
{
|
||||
FT0 = -FT1;
|
||||
DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
|
||||
float32_to_float64(FT1, &env->fp_status),
|
||||
&env->fp_status);
|
||||
}
|
||||
|
||||
void OPPROTO op_fabss(void)
|
||||
#define F_HELPER(name) \
|
||||
F_OP(name, s) \
|
||||
{ \
|
||||
do_f##name##s(); \
|
||||
} \
|
||||
F_OP(name, d) \
|
||||
{ \
|
||||
do_f##name##d(); \
|
||||
}
|
||||
|
||||
F_HELPER(sqrt);
|
||||
|
||||
F_OP(neg, s)
|
||||
{
|
||||
FT0 = float32_chs(FT1);
|
||||
}
|
||||
|
||||
F_OP(abs, s)
|
||||
{
|
||||
do_fabss();
|
||||
}
|
||||
|
||||
F_HELPER(cmp);
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
void OPPROTO op_fnegd(void)
|
||||
F_OP(neg, d)
|
||||
{
|
||||
DT0 = -DT1;
|
||||
DT0 = float64_chs(DT1);
|
||||
}
|
||||
|
||||
void OPPROTO op_fabsd(void)
|
||||
F_OP(abs, d)
|
||||
{
|
||||
do_fabsd();
|
||||
}
|
||||
#endif
|
||||
|
||||
void OPPROTO op_fsqrts(void)
|
||||
{
|
||||
do_fsqrts();
|
||||
}
|
||||
|
||||
void OPPROTO op_fsqrtd(void)
|
||||
{
|
||||
do_fsqrtd();
|
||||
}
|
||||
|
||||
void OPPROTO op_fmuls(void)
|
||||
{
|
||||
FT0 *= FT1;
|
||||
}
|
||||
|
||||
void OPPROTO op_fmuld(void)
|
||||
{
|
||||
DT0 *= DT1;
|
||||
}
|
||||
|
||||
void OPPROTO op_fsmuld(void)
|
||||
{
|
||||
DT0 = FT0 * FT1;
|
||||
}
|
||||
|
||||
void OPPROTO op_fadds(void)
|
||||
{
|
||||
FT0 += FT1;
|
||||
}
|
||||
|
||||
void OPPROTO op_faddd(void)
|
||||
{
|
||||
DT0 += DT1;
|
||||
}
|
||||
|
||||
void OPPROTO op_fsubs(void)
|
||||
{
|
||||
FT0 -= FT1;
|
||||
}
|
||||
|
||||
void OPPROTO op_fsubd(void)
|
||||
{
|
||||
DT0 -= DT1;
|
||||
}
|
||||
|
||||
void OPPROTO op_fdivs(void)
|
||||
{
|
||||
FT0 /= FT1;
|
||||
}
|
||||
|
||||
void OPPROTO op_fdivd(void)
|
||||
{
|
||||
DT0 /= DT1;
|
||||
}
|
||||
|
||||
void OPPROTO op_fcmps(void)
|
||||
{
|
||||
do_fcmps();
|
||||
}
|
||||
|
||||
void OPPROTO op_fcmpd(void)
|
||||
{
|
||||
do_fcmpd();
|
||||
}
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
void OPPROTO op_fcmps_fcc1(void)
|
||||
{
|
||||
do_fcmps_fcc1();
|
||||
@ -1458,69 +1430,65 @@ void OPPROTO op_fcmpd_fcc3(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Integer to float conversion. */
|
||||
#ifdef USE_INT_TO_FLOAT_HELPERS
|
||||
void OPPROTO op_fitos(void)
|
||||
{
|
||||
do_fitos();
|
||||
}
|
||||
|
||||
void OPPROTO op_fitod(void)
|
||||
{
|
||||
do_fitod();
|
||||
}
|
||||
F_HELPER(ito);
|
||||
#else
|
||||
void OPPROTO op_fitos(void)
|
||||
F_OP(ito, s)
|
||||
{
|
||||
FT0 = (float) *((int32_t *)&FT1);
|
||||
FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
|
||||
}
|
||||
|
||||
void OPPROTO op_fitod(void)
|
||||
F_OP(ito, d)
|
||||
{
|
||||
DT0 = (double) *((int32_t *)&FT1);
|
||||
DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
|
||||
}
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
void OPPROTO op_fxtos(void)
|
||||
F_OP(xto, s)
|
||||
{
|
||||
FT0 = (float) *((int64_t *)&DT1);
|
||||
FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
|
||||
}
|
||||
|
||||
void OPPROTO op_fxtod(void)
|
||||
F_OP(xto, d)
|
||||
{
|
||||
DT0 = (double) *((int64_t *)&DT1);
|
||||
DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#undef F_HELPER
|
||||
|
||||
/* floating point conversion */
|
||||
void OPPROTO op_fdtos(void)
|
||||
{
|
||||
FT0 = (float) DT1;
|
||||
FT0 = float64_to_float32(DT1, &env->fp_status);
|
||||
}
|
||||
|
||||
void OPPROTO op_fstod(void)
|
||||
{
|
||||
DT0 = (double) FT1;
|
||||
DT0 = float32_to_float64(FT1, &env->fp_status);
|
||||
}
|
||||
|
||||
/* Float to integer conversion. */
|
||||
void OPPROTO op_fstoi(void)
|
||||
{
|
||||
*((int32_t *)&FT0) = (int32_t) FT1;
|
||||
*((int32_t *)&FT0) = float32_to_int32(FT1, &env->fp_status);
|
||||
}
|
||||
|
||||
void OPPROTO op_fdtoi(void)
|
||||
{
|
||||
*((int32_t *)&FT0) = (int32_t) DT1;
|
||||
*((int32_t *)&FT0) = float64_to_int32(DT1, &env->fp_status);
|
||||
}
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
void OPPROTO op_fstox(void)
|
||||
{
|
||||
*((int64_t *)&DT0) = (int64_t) FT1;
|
||||
*((int64_t *)&DT0) = float32_to_int64(FT1, &env->fp_status);
|
||||
}
|
||||
|
||||
void OPPROTO op_fdtox(void)
|
||||
{
|
||||
*((int64_t *)&DT0) = (int64_t) DT1;
|
||||
*((int64_t *)&DT0) = float64_to_int64(DT1, &env->fp_status);
|
||||
}
|
||||
|
||||
void OPPROTO op_fmovs_cc(void)
|
||||
|
@ -12,12 +12,12 @@ void raise_exception(int tt)
|
||||
#ifdef USE_INT_TO_FLOAT_HELPERS
|
||||
void do_fitos(void)
|
||||
{
|
||||
FT0 = (float) *((int32_t *)&FT1);
|
||||
FT0 = int32_to_float32(*((int32_t *)&FT1));
|
||||
}
|
||||
|
||||
void do_fitod(void)
|
||||
{
|
||||
DT0 = (double) *((int32_t *)&FT1);
|
||||
DT0 = int32_to_float64(*((int32_t *)&FT1));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -43,182 +43,45 @@ void do_fsqrtd(void)
|
||||
DT0 = float64_sqrt(DT1, &env->fp_status);
|
||||
}
|
||||
|
||||
#define FS 0
|
||||
void do_fcmps (void)
|
||||
{
|
||||
env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
|
||||
if (isnan(FT0) || isnan(FT1)) {
|
||||
T0 = (FSR_FCC1 | FSR_FCC0) << FS;
|
||||
if (env->fsr & FSR_NVM) {
|
||||
env->fsr |= T0;
|
||||
raise_exception(TT_FP_EXCP);
|
||||
} else {
|
||||
env->fsr |= FSR_NVA;
|
||||
}
|
||||
} else if (FT0 < FT1) {
|
||||
T0 = FSR_FCC0 << FS;
|
||||
} else if (FT0 > FT1) {
|
||||
T0 = FSR_FCC1 << FS;
|
||||
} else {
|
||||
T0 = 0;
|
||||
#define GEN_FCMP(name, size, reg1, reg2, FS) \
|
||||
void glue(do_, name) (void) \
|
||||
{ \
|
||||
env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
|
||||
switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
|
||||
case float_relation_unordered: \
|
||||
T0 = (FSR_FCC1 | FSR_FCC0) << FS; \
|
||||
if (env->fsr & FSR_NVM) { \
|
||||
env->fsr |= T0; \
|
||||
raise_exception(TT_FP_EXCP); \
|
||||
} else { \
|
||||
env->fsr |= FSR_NVA; \
|
||||
} \
|
||||
break; \
|
||||
case float_relation_less: \
|
||||
T0 = FSR_FCC0 << FS; \
|
||||
break; \
|
||||
case float_relation_greater: \
|
||||
T0 = FSR_FCC1 << FS; \
|
||||
break; \
|
||||
default: \
|
||||
T0 = 0; \
|
||||
break; \
|
||||
} \
|
||||
env->fsr |= T0; \
|
||||
}
|
||||
env->fsr |= T0;
|
||||
}
|
||||
|
||||
void do_fcmpd (void)
|
||||
{
|
||||
env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
|
||||
if (isnan(DT0) || isnan(DT1)) {
|
||||
T0 = (FSR_FCC1 | FSR_FCC0) << FS;
|
||||
if (env->fsr & FSR_NVM) {
|
||||
env->fsr |= T0;
|
||||
raise_exception(TT_FP_EXCP);
|
||||
} else {
|
||||
env->fsr |= FSR_NVA;
|
||||
}
|
||||
} else if (DT0 < DT1) {
|
||||
T0 = FSR_FCC0 << FS;
|
||||
} else if (DT0 > DT1) {
|
||||
T0 = FSR_FCC1 << FS;
|
||||
} else {
|
||||
T0 = 0;
|
||||
}
|
||||
env->fsr |= T0;
|
||||
}
|
||||
GEN_FCMP(fcmps, float32, FT0, FT1, 0);
|
||||
GEN_FCMP(fcmpd, float64, DT0, DT1, 0);
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
#undef FS
|
||||
#define FS 22
|
||||
void do_fcmps_fcc1 (void)
|
||||
{
|
||||
env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
|
||||
if (isnan(FT0) || isnan(FT1)) {
|
||||
T0 = (FSR_FCC1 | FSR_FCC0) << FS;
|
||||
if (env->fsr & FSR_NVM) {
|
||||
env->fsr |= T0;
|
||||
raise_exception(TT_FP_EXCP);
|
||||
} else {
|
||||
env->fsr |= FSR_NVA;
|
||||
}
|
||||
} else if (FT0 < FT1) {
|
||||
T0 = FSR_FCC0 << FS;
|
||||
} else if (FT0 > FT1) {
|
||||
T0 = FSR_FCC1 << FS;
|
||||
} else {
|
||||
T0 = 0;
|
||||
}
|
||||
env->fsr |= T0;
|
||||
}
|
||||
GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22);
|
||||
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22);
|
||||
|
||||
void do_fcmpd_fcc1 (void)
|
||||
{
|
||||
env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
|
||||
if (isnan(DT0) || isnan(DT1)) {
|
||||
T0 = (FSR_FCC1 | FSR_FCC0) << FS;
|
||||
if (env->fsr & FSR_NVM) {
|
||||
env->fsr |= T0;
|
||||
raise_exception(TT_FP_EXCP);
|
||||
} else {
|
||||
env->fsr |= FSR_NVA;
|
||||
}
|
||||
} else if (DT0 < DT1) {
|
||||
T0 = FSR_FCC0 << FS;
|
||||
} else if (DT0 > DT1) {
|
||||
T0 = FSR_FCC1 << FS;
|
||||
} else {
|
||||
T0 = 0;
|
||||
}
|
||||
env->fsr |= T0;
|
||||
}
|
||||
GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24);
|
||||
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24);
|
||||
|
||||
#undef FS
|
||||
#define FS 24
|
||||
void do_fcmps_fcc2 (void)
|
||||
{
|
||||
env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
|
||||
if (isnan(FT0) || isnan(FT1)) {
|
||||
T0 = (FSR_FCC1 | FSR_FCC0) << FS;
|
||||
if (env->fsr & FSR_NVM) {
|
||||
env->fsr |= T0;
|
||||
raise_exception(TT_FP_EXCP);
|
||||
} else {
|
||||
env->fsr |= FSR_NVA;
|
||||
}
|
||||
} else if (FT0 < FT1) {
|
||||
T0 = FSR_FCC0 << FS;
|
||||
} else if (FT0 > FT1) {
|
||||
T0 = FSR_FCC1 << FS;
|
||||
} else {
|
||||
T0 = 0;
|
||||
}
|
||||
env->fsr |= T0;
|
||||
}
|
||||
|
||||
void do_fcmpd_fcc2 (void)
|
||||
{
|
||||
env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
|
||||
if (isnan(DT0) || isnan(DT1)) {
|
||||
T0 = (FSR_FCC1 | FSR_FCC0) << FS;
|
||||
if (env->fsr & FSR_NVM) {
|
||||
env->fsr |= T0;
|
||||
raise_exception(TT_FP_EXCP);
|
||||
} else {
|
||||
env->fsr |= FSR_NVA;
|
||||
}
|
||||
} else if (DT0 < DT1) {
|
||||
T0 = FSR_FCC0 << FS;
|
||||
} else if (DT0 > DT1) {
|
||||
T0 = FSR_FCC1 << FS;
|
||||
} else {
|
||||
T0 = 0;
|
||||
}
|
||||
env->fsr |= T0;
|
||||
}
|
||||
|
||||
#undef FS
|
||||
#define FS 26
|
||||
void do_fcmps_fcc3 (void)
|
||||
{
|
||||
env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
|
||||
if (isnan(FT0) || isnan(FT1)) {
|
||||
T0 = (FSR_FCC1 | FSR_FCC0) << FS;
|
||||
if (env->fsr & FSR_NVM) {
|
||||
env->fsr |= T0;
|
||||
raise_exception(TT_FP_EXCP);
|
||||
} else {
|
||||
env->fsr |= FSR_NVA;
|
||||
}
|
||||
} else if (FT0 < FT1) {
|
||||
T0 = FSR_FCC0 << FS;
|
||||
} else if (FT0 > FT1) {
|
||||
T0 = FSR_FCC1 << FS;
|
||||
} else {
|
||||
T0 = 0;
|
||||
}
|
||||
env->fsr |= T0;
|
||||
}
|
||||
|
||||
void do_fcmpd_fcc3 (void)
|
||||
{
|
||||
env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
|
||||
if (isnan(DT0) || isnan(DT1)) {
|
||||
T0 = (FSR_FCC1 | FSR_FCC0) << FS;
|
||||
if (env->fsr & FSR_NVM) {
|
||||
env->fsr |= T0;
|
||||
raise_exception(TT_FP_EXCP);
|
||||
} else {
|
||||
env->fsr |= FSR_NVA;
|
||||
}
|
||||
} else if (DT0 < DT1) {
|
||||
T0 = FSR_FCC0 << FS;
|
||||
} else if (DT0 > DT1) {
|
||||
T0 = FSR_FCC1 << FS;
|
||||
} else {
|
||||
T0 = 0;
|
||||
}
|
||||
env->fsr |= T0;
|
||||
}
|
||||
#undef FS
|
||||
GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26);
|
||||
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
@ -783,19 +646,6 @@ void helper_ldfsr(void)
|
||||
set_float_rounding_mode(rnd_mode, &env->fp_status);
|
||||
}
|
||||
|
||||
void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f)
|
||||
{
|
||||
int exptemp;
|
||||
|
||||
*pmant = ldexp(frexp(f, &exptemp), 53);
|
||||
*pexp = exptemp;
|
||||
}
|
||||
|
||||
double cpu_put_fp64(uint64_t mant, uint16_t exp)
|
||||
{
|
||||
return ldexp((double) mant, exp - 53);
|
||||
}
|
||||
|
||||
void helper_debug()
|
||||
{
|
||||
env->exception_index = EXCP_DEBUG;
|
||||
|
Loading…
Reference in New Issue
Block a user