Am 24.03.2011 um 18:29 schrieb Peter Maydell <peter.mayd...@linaro.org>:
> On 24 March 2011 15:58, Alexander Graf <ag...@suse.de> wrote: > > This is more random comments in passing than a thorough review; sorry. > >> +#if HOST_LONG_BITS == 64 && defined(__GNUC__) >> + /* assuming 64-bit hosts have __uint128_t */ >> + __uint128_t dividend = (((__uint128_t)env->regs[r1]) << 64) | >> + (env->regs[r1+1]); >> + __uint128_t quotient = dividend / divisor; >> + env->regs[r1+1] = quotient; >> + __uint128_t remainder = dividend % divisor; >> + env->regs[r1] = remainder; >> +#else >> + /* 32-bit hosts would need special wrapper functionality - just >> abort if >> + we encounter such a case; it's very unlikely anyways. */ >> + cpu_abort(env, "128 -> 64/64 division not implemented\n"); >> +#endif > > ...I'm still using a 32 bit system :-) > >> +/* condition codes for binary FP ops */ >> +static uint32_t set_cc_f32(float32 v1, float32 v2) >> +{ >> + if (float32_is_any_nan(v1) || float32_is_any_nan(v2)) { >> + return 3; >> + } else if (float32_eq(v1, v2, &env->fpu_status)) { >> + return 0; >> + } else if (float32_lt(v1, v2, &env->fpu_status)) { >> + return 1; >> + } else { >> + return 2; >> + } >> +} > > Can you not use float32_compare_quiet() (returns a value > telling you if it's less/equal/greater/unordered)? > If not, needs a comment saying why you need to do it the hard way. Phew - I really have (almost) no clue about fp. Those parts come from Uli. So I guess it's the easiest to just ask him :) > >> +/* negative absolute of 32-bit float */ >> +uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2) >> +{ >> + env->fregs[f1].l.upper = float32_sub(float32_zero, >> env->fregs[f2].l.upper, >> + &env->fpu_status); >> + return set_cc_nz_f32(env->fregs[f1].l.upper); >> +} > > Google suggests this is wrong: > http://publib.boulder.ibm.com/cgi-bin/bookmgr/BOOKS/DZ9AR006/19.4.10?SHELF=&DT=19990630131355&CASE= > says for lcebr that: > "The sign is inverted for any operand, including a QNaN or SNaN, > without causing an arithmetic exception." > > but float32_sub will raise exceptions for NaNs. You want > float32_chs() (and similarly for the other types). > >> +/* convert 64-bit float to 128-bit float */ >> +uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2) > > Wrong comment? Looks like another invert-sign op from > the online POO. > >> +/* 128-bit FP compare RR */ >> +uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2) >> +{ >> + CPU_QuadU v1; >> + v1.ll.upper = env->fregs[f1].ll; >> + v1.ll.lower = env->fregs[f1 + 2].ll; >> + CPU_QuadU v2; >> + v2.ll.upper = env->fregs[f2].ll; >> + v2.ll.lower = env->fregs[f2 + 2].ll; >> + if (float128_is_any_nan(v1.q) || float128_is_any_nan(v2.q)) { >> + return 3; >> + } else if (float128_eq(v1.q, v2.q, &env->fpu_status)) { >> + return 0; >> + } else if (float128_lt(v1.q, v2.q, &env->fpu_status)) { >> + return 1; >> + } else { >> + return 2; >> + } >> +} > > float128_compare_quiet() again? > >> +/* convert 32-bit float to 64-bit int */ >> +uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3) >> +{ >> + float32 v2 = env->fregs[f2].l.upper; >> + set_round_mode(m3); >> + env->regs[r1] = float32_to_int64(v2, &env->fpu_status); >> + return set_cc_nz_f32(v2); >> +} > > Should this really be permanently setting the rounding mode > for future instructions as well as for the op it does itself? > >> +/* load 32-bit FP zero */ >> +void HELPER(lzer)(uint32_t f1) >> +{ >> + env->fregs[f1].l.upper = float32_zero; >> +} > > Surely this is trivial enough to inline rather than > calling a helper function... > >> +/* load 128-bit FP zero */ >> +void HELPER(lzxr)(uint32_t f1) >> +{ >> + CPU_QuadU x; >> + x.q = float64_to_float128(float64_zero, &env->fpu_status); > > Yuck. Just define a float128_zero if we need one. > >> +uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2) >> +{ >> + float32 v1 = env->fregs[f1].l.upper; >> + int neg = float32_is_neg(v1); >> + uint32_t cc = 0; >> + >> + HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __FUNCTION__, (long)v1, >> m2, neg); >> + if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) || >> + (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) || >> + (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || >> + (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { >> + cc = 1; >> + } else if (m2 & (1 << (9-neg))) { >> + /* assume normalized number */ >> + cc = 1; >> + } >> + >> + /* FIXME: denormalized? */ >> + return cc; >> +} > > There's a float32_is_zero_or_denormal(); if you need a > float32_is_denormal() which is false for real zero we > could add it, I guess. > >> +static inline uint32_t cc_calc_nabs_32(CPUState *env, int32_t dst) >> +{ >> + return !!dst; >> +} > > Another candidate for inlining. > > -- PMM