aboutsummaryrefslogtreecommitdiff
path: root/target-alpha/int_helper.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-05-22 10:06:33 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-05-22 10:06:33 +0100
commit27e1259a69c49ee2dd53385f4ca4ca14b822191d (patch)
tree3b6d8b7c48c3d1afa7e6ce6ae29bd0c5b01cdf9c /target-alpha/int_helper.c
parent9e549d36e989b14423279fb991b71728a2a4ae7c (diff)
parent32ad48abd74a997220b841e4e913edeb267aa362 (diff)
downloadqemu-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.c126
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;
}