[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 14/17] s390x: Implement opcode helpers
From: |
Peter Maydell |
Subject: |
Re: [Qemu-devel] [PATCH 14/17] s390x: Implement opcode helpers |
Date: |
Thu, 24 Mar 2011 17:29:26 +0000 |
On 24 March 2011 15:58, Alexander Graf <address@hidden> 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.
> +/* 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
- [Qemu-devel] [PATCH 10/17] s390x: Adjust GDB stub, (continued)
- [Qemu-devel] [PATCH 10/17] s390x: Adjust GDB stub, Alexander Graf, 2011/03/24
- [Qemu-devel] [PATCH 03/17] s390x: Enable disassembler for s390x, Alexander Graf, 2011/03/24
- [Qemu-devel] [PATCH 12/17] s390x: Prepare cpu.h for emulation, Alexander Graf, 2011/03/24
- [Qemu-devel] [PATCH 13/17] s390x: helper functions for system emulation, Alexander Graf, 2011/03/24
- [Qemu-devel] [PATCH 06/17] s390x: s390x-linux-user support, Alexander Graf, 2011/03/24
- [Qemu-devel] [PATCH 14/17] s390x: Implement opcode helpers, Alexander Graf, 2011/03/24
- Re: [Qemu-devel] [PATCH 14/17] s390x: Implement opcode helpers,
Peter Maydell <=
- Re: [Qemu-devel] [PATCH 14/17] s390x: Implement opcode helpers, Alexander Graf, 2011/03/24
- Re: [Qemu-devel] [PATCH 14/17] s390x: Implement opcode helpers, Alexander Graf, 2011/03/28
- Re: [Qemu-devel] [PATCH 14/17] s390x: Implement opcode helpers, Richard Henderson, 2011/03/28
- Re: [Qemu-devel] [PATCH 14/17] s390x: Implement opcode helpers, Peter Maydell, 2011/03/28
- Re: [Qemu-devel] [PATCH 14/17] s390x: Implement opcode helpers, Alexander Graf, 2011/03/29
[Qemu-devel] [PATCH 16/17] s390x: translate engine for s390x CPU, Alexander Graf, 2011/03/24