diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2015-05-22 10:06:33 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2015-05-22 10:06:33 +0100 |
commit | 27e1259a69c49ee2dd53385f4ca4ca14b822191d (patch) | |
tree | 3b6d8b7c48c3d1afa7e6ce6ae29bd0c5b01cdf9c /target-alpha/int_helper.c | |
parent | 9e549d36e989b14423279fb991b71728a2a4ae7c (diff) | |
parent | 32ad48abd74a997220b841e4e913edeb267aa362 (diff) | |
download | qemu-27e1259a69c49ee2dd53385f4ca4ca14b822191d.zip qemu-27e1259a69c49ee2dd53385f4ca4ca14b822191d.tar.gz qemu-27e1259a69c49ee2dd53385f4ca4ca14b822191d.tar.bz2 |
Merge remote-tracking branch 'remotes/rth/tags/pull-axp-20150521' into staging
Rewrite fp exceptions
# gpg: Signature made Thu May 21 18:35:52 2015 BST using RSA key ID 4DD0279B
# gpg: Good signature from "Richard Henderson <rth7680@gmail.com>"
# gpg: aka "Richard Henderson <rth@redhat.com>"
# gpg: aka "Richard Henderson <rth@twiddle.net>"
* remotes/rth/tags/pull-axp-20150521:
target-alpha: Add vector implementation for CMPBGE
target-alpha: Rewrite helper_zapnot
target-alpha: Raise IOV from CVTQL
target-alpha: Suppress underflow from CVTTQ if DNZ
target-alpha: Raise EXC_M_INV properly for fp inputs
target-alpha: Disallow literal operand to 1C.30 to 1C.37
target-alpha: Implement WH64EN
target-alpha: Fix integer overflow checking insns
target-alpha: Fix cvttq vs inf
target-alpha: Fix cvttq vs large integers
target-alpha: Raise IOV from CVTTQ
target-alpha: Set EXC_M_SWC for exceptions from /S insns
target-alpha: Set fpcr_exc_status even for disabled exceptions
target-alpha: Tidy FPCR representation
target-alpha: Set PC correctly for floating-point exceptions
target-alpha: Forget installed round mode after MT_FPCR
target-alpha: Rename floating-point subroutines
target-alpha: Move VAX helpers to a new file
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target-alpha/int_helper.c')
-rw-r--r-- | target-alpha/int_helper.c | 126 |
1 files changed, 51 insertions, 75 deletions
diff --git a/target-alpha/int_helper.c b/target-alpha/int_helper.c index 7a205eb..29e927f 100644 --- a/target-alpha/int_helper.c +++ b/target-alpha/int_helper.c @@ -37,35 +37,65 @@ uint64_t helper_cttz(uint64_t arg) return ctz64(arg); } -static inline uint64_t byte_zap(uint64_t op, uint8_t mskb) +uint64_t helper_zapnot(uint64_t val, uint64_t mskb) { uint64_t mask; - mask = 0; - mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL; - mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL; - mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL; - mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL; - mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL; - mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL; - mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL; - mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL; - - return op & ~mask; -} + mask = -(mskb & 0x01) & 0x00000000000000ffull; + mask |= -(mskb & 0x02) & 0x000000000000ff00ull; + mask |= -(mskb & 0x04) & 0x0000000000ff0000ull; + mask |= -(mskb & 0x08) & 0x00000000ff000000ull; + mask |= -(mskb & 0x10) & 0x000000ff00000000ull; + mask |= -(mskb & 0x20) & 0x0000ff0000000000ull; + mask |= -(mskb & 0x40) & 0x00ff000000000000ull; + mask |= -(mskb & 0x80) & 0xff00000000000000ull; -uint64_t helper_zap(uint64_t val, uint64_t mask) -{ - return byte_zap(val, mask); + return val & mask; } -uint64_t helper_zapnot(uint64_t val, uint64_t mask) +uint64_t helper_zap(uint64_t val, uint64_t mask) { - return byte_zap(val, ~mask); + return helper_zapnot(val, ~mask); } uint64_t helper_cmpbge(uint64_t op1, uint64_t op2) { +#if defined(__SSE2__) + uint64_t r; + + /* The cmpbge instruction is heavily used in the implementation of + every string function on Alpha. We can do much better than either + the default loop below, or even an unrolled version by using the + native vector support. */ + { + typedef uint64_t Q __attribute__((vector_size(16))); + typedef uint8_t B __attribute__((vector_size(16))); + + Q q1 = (Q){ op1, 0 }; + Q q2 = (Q){ op2, 0 }; + + q1 = (Q)((B)q1 >= (B)q2); + + r = q1[0]; + } + + /* Select only one bit from each byte. */ + r &= 0x0101010101010101; + + /* Collect the bits into the bottom byte. */ + /* .......A.......B.......C.......D.......E.......F.......G.......H */ + r |= r >> (8 - 1); + + /* .......A......AB......BC......CD......DE......EF......FG......GH */ + r |= r >> (16 - 2); + + /* .......A......AB.....ABC....ABCD....BCDE....CDEF....DEFG....EFGH */ + r |= r >> (32 - 4); + + /* .......A......AB.....ABC....ABCD...ABCDE..ABCDEF.ABCDEFGABCDEFGH */ + /* Return only the low 8 bits. */ + return r & 0xff; +#else uint8_t opa, opb, res; int i; @@ -78,6 +108,7 @@ uint64_t helper_cmpbge(uint64_t op1, uint64_t op2) } } return res; +#endif } uint64_t helper_minub8(uint64_t op1, uint64_t op2) @@ -249,64 +280,9 @@ uint64_t helper_unpkbw(uint64_t op1) | ((op1 & 0xff000000) << 24)); } -uint64_t helper_addqv(CPUAlphaState *env, uint64_t op1, uint64_t op2) +void helper_check_overflow(CPUAlphaState *env, uint64_t op1, uint64_t op2) { - uint64_t tmp = op1; - op1 += op2; - if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) { - arith_excp(env, GETPC(), EXC_M_IOV, 0); - } - return op1; -} - -uint64_t helper_addlv(CPUAlphaState *env, uint64_t op1, uint64_t op2) -{ - uint64_t tmp = op1; - op1 = (uint32_t)(op1 + op2); - if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) { - arith_excp(env, GETPC(), EXC_M_IOV, 0); - } - return op1; -} - -uint64_t helper_subqv(CPUAlphaState *env, uint64_t op1, uint64_t op2) -{ - uint64_t res; - res = op1 - op2; - if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) { - arith_excp(env, GETPC(), EXC_M_IOV, 0); - } - return res; -} - -uint64_t helper_sublv(CPUAlphaState *env, uint64_t op1, uint64_t op2) -{ - uint32_t res; - res = op1 - op2; - if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) { - arith_excp(env, GETPC(), EXC_M_IOV, 0); - } - return res; -} - -uint64_t helper_mullv(CPUAlphaState *env, uint64_t op1, uint64_t op2) -{ - int64_t res = (int64_t)op1 * (int64_t)op2; - - if (unlikely((int32_t)res != res)) { - arith_excp(env, GETPC(), EXC_M_IOV, 0); - } - return (int64_t)((int32_t)res); -} - -uint64_t helper_mulqv(CPUAlphaState *env, uint64_t op1, uint64_t op2) -{ - uint64_t tl, th; - - muls64(&tl, &th, op1, op2); - /* If th != 0 && th != -1, then we had an overflow */ - if (unlikely((th + 1) > 1)) { + if (unlikely(op1 != op2)) { arith_excp(env, GETPC(), EXC_M_IOV, 0); } - return tl; } |