diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2006-06-21 18:37:05 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2006-06-21 18:37:05 +0000 |
commit | 65ce8c2fb438c8685dbcd28784a0b0ba2b484e5f (patch) | |
tree | e5c5f2f4c38d8d2d22101bb9070488c32885cc12 /target-sparc | |
parent | ee6c0b51e97c8bcad32181f42e63765b18c30354 (diff) |
soft floats for SPARC (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2000 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-sparc')
-rw-r--r-- | target-sparc/cpu.h | 10 | ||||
-rw-r--r-- | target-sparc/op.c | 148 | ||||
-rw-r--r-- | target-sparc/op_helper.c | 220 |
3 files changed, 97 insertions, 281 deletions
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 28efab758f..c6d5621b11 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -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) | \ diff --git a/target-sparc/op.c b/target-sparc/op.c index 4609cdf1ec..d5df859db1 100644 --- a/target-sparc/op.c +++ b/target-sparc/op.c @@ -1339,94 +1339,66 @@ void OPPROTO op_flush_T0(void) helper_flush(T0); } -void OPPROTO op_fnegs(void) -{ - FT0 = -FT1; -} - -void OPPROTO op_fabss(void) -{ - do_fabss(); -} - -#ifdef TARGET_SPARC64 -void OPPROTO op_fnegd(void) -{ - DT0 = -DT1; -} - -void OPPROTO op_fabsd(void) -{ - do_fabsd(); -} -#endif - -void OPPROTO op_fsqrts(void) -{ - do_fsqrts(); -} - -void OPPROTO op_fsqrtd(void) -{ - do_fsqrtd(); -} - -void OPPROTO op_fmuls(void) -{ - FT0 *= FT1; -} +#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); \ + } -void OPPROTO op_fmuld(void) -{ - DT0 *= DT1; -} +F_BINOP(add); +F_BINOP(sub); +F_BINOP(mul); +F_BINOP(div); +#undef F_BINOP void OPPROTO op_fsmuld(void) { - DT0 = FT0 * FT1; -} - -void OPPROTO op_fadds(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_faddd(void) -{ - DT0 += DT1; -} +#define F_HELPER(name) \ + F_OP(name, s) \ + { \ + do_f##name##s(); \ + } \ + F_OP(name, d) \ + { \ + do_f##name##d(); \ + } -void OPPROTO op_fsubs(void) -{ - FT0 -= FT1; -} +F_HELPER(sqrt); -void OPPROTO op_fsubd(void) +F_OP(neg, s) { - DT0 -= DT1; + FT0 = float32_chs(FT1); } -void OPPROTO op_fdivs(void) +F_OP(abs, s) { - FT0 /= FT1; + do_fabss(); } -void OPPROTO op_fdivd(void) -{ - DT0 /= DT1; -} +F_HELPER(cmp); -void OPPROTO op_fcmps(void) +#ifdef TARGET_SPARC64 +F_OP(neg, d) { - do_fcmps(); + DT0 = float64_chs(DT1); } -void OPPROTO op_fcmpd(void) +F_OP(abs, d) { - do_fcmpd(); + do_fabsd(); } -#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) diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index 030b2f78ad..5f88459ab8 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -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; -} - -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_fcc1, float32, FT0, FT1, 22); +GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22); -#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; -} +GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24); +GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24); -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; |