diff options
Diffstat (limited to 'target-arm/neon_helper.c')
-rw-r--r-- | target-arm/neon_helper.c | 269 |
1 files changed, 124 insertions, 145 deletions
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c index 002a9c11a6..f5b173aa71 100644 --- a/target-arm/neon_helper.c +++ b/target-arm/neon_helper.c @@ -10,39 +10,15 @@ #include <stdio.h> #include "cpu.h" -#include "exec-all.h" -#include "helpers.h" +#include "exec.h" +#include "helper.h" #define SIGNBIT (uint32_t)0x80000000 #define SIGNBIT64 ((uint64_t)1 << 63) #define SET_QC() env->vfp.xregs[ARM_VFP_FPSCR] = CPSR_Q -static float_status neon_float_status; -#define NFS &neon_float_status - -/* Helper routines to perform bitwise copies between float and int. */ -static inline float32 vfp_itos(uint32_t i) -{ - union { - uint32_t i; - float32 s; - } v; - - v.i = i; - return v.s; -} - -static inline uint32_t vfp_stoi(float32 s) -{ - union { - uint32_t i; - float32 s; - } v; - - v.s = s; - return v.i; -} +#define NFS (&env->vfp.standard_fp_status) #define NEON_TYPE1(name, type) \ typedef struct \ @@ -139,10 +115,6 @@ NEON_TYPE1(u32, uint32_t) uint32_t HELPER(glue(neon_,name))(uint32_t arg1, uint32_t arg2) \ NEON_VOP_BODY(vtype, n) -#define NEON_VOP_ENV(name, vtype, n) \ -uint32_t HELPER(glue(neon_,name))(CPUState *env, uint32_t arg1, uint32_t arg2) \ -NEON_VOP_BODY(vtype, n) - /* Pairwise operations. */ /* For 32-bit elements each segment only contains a single element, so the elementwise and pairwise operations are the same. */ @@ -191,14 +163,14 @@ uint32_t HELPER(glue(neon_,name))(uint32_t arg) \ dest = tmp; \ }} while(0) #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint8_t) -NEON_VOP_ENV(qadd_u8, neon_u8, 4) +NEON_VOP(qadd_u8, neon_u8, 4) #undef NEON_FN #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint16_t) -NEON_VOP_ENV(qadd_u16, neon_u16, 2) +NEON_VOP(qadd_u16, neon_u16, 2) #undef NEON_FN #undef NEON_USAT -uint32_t HELPER(neon_qadd_u32)(CPUState *env, uint32_t a, uint32_t b) +uint32_t HELPER(neon_qadd_u32)(uint32_t a, uint32_t b) { uint32_t res = a + b; if (res < a) { @@ -208,7 +180,7 @@ uint32_t HELPER(neon_qadd_u32)(CPUState *env, uint32_t a, uint32_t b) return res; } -uint64_t HELPER(neon_qadd_u64)(CPUState *env, uint64_t src1, uint64_t src2) +uint64_t HELPER(neon_qadd_u64)(uint64_t src1, uint64_t src2) { uint64_t res; @@ -233,14 +205,14 @@ uint64_t HELPER(neon_qadd_u64)(CPUState *env, uint64_t src1, uint64_t src2) dest = tmp; \ } while(0) #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int8_t) -NEON_VOP_ENV(qadd_s8, neon_s8, 4) +NEON_VOP(qadd_s8, neon_s8, 4) #undef NEON_FN #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int16_t) -NEON_VOP_ENV(qadd_s16, neon_s16, 2) +NEON_VOP(qadd_s16, neon_s16, 2) #undef NEON_FN #undef NEON_SSAT -uint32_t HELPER(neon_qadd_s32)(CPUState *env, uint32_t a, uint32_t b) +uint32_t HELPER(neon_qadd_s32)(uint32_t a, uint32_t b) { uint32_t res = a + b; if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) { @@ -250,7 +222,7 @@ uint32_t HELPER(neon_qadd_s32)(CPUState *env, uint32_t a, uint32_t b) return res; } -uint64_t HELPER(neon_qadd_s64)(CPUState *env, uint64_t src1, uint64_t src2) +uint64_t HELPER(neon_qadd_s64)(uint64_t src1, uint64_t src2) { uint64_t res; @@ -271,14 +243,14 @@ uint64_t HELPER(neon_qadd_s64)(CPUState *env, uint64_t src1, uint64_t src2) dest = tmp; \ }} while(0) #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint8_t) -NEON_VOP_ENV(qsub_u8, neon_u8, 4) +NEON_VOP(qsub_u8, neon_u8, 4) #undef NEON_FN #define NEON_FN(dest, src1, src2) NEON_USAT(dest, src1, src2, uint16_t) -NEON_VOP_ENV(qsub_u16, neon_u16, 2) +NEON_VOP(qsub_u16, neon_u16, 2) #undef NEON_FN #undef NEON_USAT -uint32_t HELPER(neon_qsub_u32)(CPUState *env, uint32_t a, uint32_t b) +uint32_t HELPER(neon_qsub_u32)(uint32_t a, uint32_t b) { uint32_t res = a - b; if (res > a) { @@ -288,7 +260,7 @@ uint32_t HELPER(neon_qsub_u32)(CPUState *env, uint32_t a, uint32_t b) return res; } -uint64_t HELPER(neon_qsub_u64)(CPUState *env, uint64_t src1, uint64_t src2) +uint64_t HELPER(neon_qsub_u64)(uint64_t src1, uint64_t src2) { uint64_t res; @@ -314,14 +286,14 @@ uint64_t HELPER(neon_qsub_u64)(CPUState *env, uint64_t src1, uint64_t src2) dest = tmp; \ } while(0) #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int8_t) -NEON_VOP_ENV(qsub_s8, neon_s8, 4) +NEON_VOP(qsub_s8, neon_s8, 4) #undef NEON_FN #define NEON_FN(dest, src1, src2) NEON_SSAT(dest, src1, src2, int16_t) -NEON_VOP_ENV(qsub_s16, neon_s16, 2) +NEON_VOP(qsub_s16, neon_s16, 2) #undef NEON_FN #undef NEON_SSAT -uint32_t HELPER(neon_qsub_s32)(CPUState *env, uint32_t a, uint32_t b) +uint32_t HELPER(neon_qsub_s32)(uint32_t a, uint32_t b) { uint32_t res = a - b; if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) { @@ -331,7 +303,7 @@ uint32_t HELPER(neon_qsub_s32)(CPUState *env, uint32_t a, uint32_t b) return res; } -uint64_t HELPER(neon_qsub_s64)(CPUState *env, uint64_t src1, uint64_t src2) +uint64_t HELPER(neon_qsub_s64)(uint64_t src1, uint64_t src2) { uint64_t res; @@ -682,12 +654,12 @@ uint64_t HELPER(neon_rshl_u64)(uint64_t val, uint64_t shiftop) dest = ~0; \ } \ }} while (0) -NEON_VOP_ENV(qshl_u8, neon_u8, 4) -NEON_VOP_ENV(qshl_u16, neon_u16, 2) -NEON_VOP_ENV(qshl_u32, neon_u32, 1) +NEON_VOP(qshl_u8, neon_u8, 4) +NEON_VOP(qshl_u16, neon_u16, 2) +NEON_VOP(qshl_u32, neon_u32, 1) #undef NEON_FN -uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop) +uint64_t HELPER(neon_qshl_u64)(uint64_t val, uint64_t shiftop) { int8_t shift = (int8_t)shiftop; if (shift >= 64) { @@ -737,12 +709,12 @@ uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop) } \ } \ }} while (0) -NEON_VOP_ENV(qshl_s8, neon_s8, 4) -NEON_VOP_ENV(qshl_s16, neon_s16, 2) -NEON_VOP_ENV(qshl_s32, neon_s32, 1) +NEON_VOP(qshl_s8, neon_s8, 4) +NEON_VOP(qshl_s16, neon_s16, 2) +NEON_VOP(qshl_s32, neon_s32, 1) #undef NEON_FN -uint64_t HELPER(neon_qshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop) +uint64_t HELPER(neon_qshl_s64)(uint64_t valop, uint64_t shiftop) { int8_t shift = (uint8_t)shiftop; int64_t val = valop; @@ -792,26 +764,26 @@ uint64_t HELPER(neon_qshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop) } \ } \ }} while (0) -NEON_VOP_ENV(qshlu_s8, neon_u8, 4) -NEON_VOP_ENV(qshlu_s16, neon_u16, 2) +NEON_VOP(qshlu_s8, neon_u8, 4) +NEON_VOP(qshlu_s16, neon_u16, 2) #undef NEON_FN -uint32_t HELPER(neon_qshlu_s32)(CPUState *env, uint32_t valop, uint32_t shiftop) +uint32_t HELPER(neon_qshlu_s32)(uint32_t valop, uint32_t shiftop) { if ((int32_t)valop < 0) { SET_QC(); return 0; } - return helper_neon_qshl_u32(env, valop, shiftop); + return helper_neon_qshl_u32(valop, shiftop); } -uint64_t HELPER(neon_qshlu_s64)(CPUState *env, uint64_t valop, uint64_t shiftop) +uint64_t HELPER(neon_qshlu_s64)(uint64_t valop, uint64_t shiftop) { if ((int64_t)valop < 0) { SET_QC(); return 0; } - return helper_neon_qshl_u64(env, valop, shiftop); + return helper_neon_qshl_u64(valop, shiftop); } /* FIXME: This is wrong. */ @@ -838,13 +810,13 @@ uint64_t HELPER(neon_qshlu_s64)(CPUState *env, uint64_t valop, uint64_t shiftop) dest = ~0; \ } \ }} while (0) -NEON_VOP_ENV(qrshl_u8, neon_u8, 4) -NEON_VOP_ENV(qrshl_u16, neon_u16, 2) +NEON_VOP(qrshl_u8, neon_u8, 4) +NEON_VOP(qrshl_u16, neon_u16, 2) #undef NEON_FN /* The addition of the rounding constant may overflow, so we use an * intermediate 64 bits accumulator. */ -uint32_t HELPER(neon_qrshl_u32)(CPUState *env, uint32_t val, uint32_t shiftop) +uint32_t HELPER(neon_qrshl_u32)(uint32_t val, uint32_t shiftop) { uint32_t dest; int8_t shift = (int8_t)shiftop; @@ -874,7 +846,7 @@ uint32_t HELPER(neon_qrshl_u32)(CPUState *env, uint32_t val, uint32_t shiftop) /* Handling addition overflow with 64 bits inputs values is more * tricky than with 32 bits values. */ -uint64_t HELPER(neon_qrshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop) +uint64_t HELPER(neon_qrshl_u64)(uint64_t val, uint64_t shiftop) { int8_t shift = (int8_t)shiftop; if (shift >= 64) { @@ -935,13 +907,13 @@ uint64_t HELPER(neon_qrshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop) } \ } \ }} while (0) -NEON_VOP_ENV(qrshl_s8, neon_s8, 4) -NEON_VOP_ENV(qrshl_s16, neon_s16, 2) +NEON_VOP(qrshl_s8, neon_s8, 4) +NEON_VOP(qrshl_s16, neon_s16, 2) #undef NEON_FN /* The addition of the rounding constant may overflow, so we use an * intermediate 64 bits accumulator. */ -uint32_t HELPER(neon_qrshl_s32)(CPUState *env, uint32_t valop, uint32_t shiftop) +uint32_t HELPER(neon_qrshl_s32)(uint32_t valop, uint32_t shiftop) { int32_t dest; int32_t val = (int32_t)valop; @@ -970,7 +942,7 @@ uint32_t HELPER(neon_qrshl_s32)(CPUState *env, uint32_t valop, uint32_t shiftop) /* Handling addition overflow with 64 bits inputs values is more * tricky than with 32 bits values. */ -uint64_t HELPER(neon_qrshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop) +uint64_t HELPER(neon_qrshl_s64)(uint64_t valop, uint64_t shiftop) { int8_t shift = (uint8_t)shiftop; int64_t val = valop; @@ -1179,10 +1151,10 @@ uint32_t HELPER(neon_cnt_u8)(uint32_t x) dest = tmp >> 16; \ } while(0) #define NEON_FN(dest, src1, src2) NEON_QDMULH16(dest, src1, src2, 0) -NEON_VOP_ENV(qdmulh_s16, neon_s16, 2) +NEON_VOP(qdmulh_s16, neon_s16, 2) #undef NEON_FN #define NEON_FN(dest, src1, src2) NEON_QDMULH16(dest, src1, src2, 1) -NEON_VOP_ENV(qrdmulh_s16, neon_s16, 2) +NEON_VOP(qrdmulh_s16, neon_s16, 2) #undef NEON_FN #undef NEON_QDMULH16 @@ -1205,10 +1177,10 @@ NEON_VOP_ENV(qrdmulh_s16, neon_s16, 2) dest = tmp >> 32; \ } while(0) #define NEON_FN(dest, src1, src2) NEON_QDMULH32(dest, src1, src2, 0) -NEON_VOP_ENV(qdmulh_s32, neon_s32, 1) +NEON_VOP(qdmulh_s32, neon_s32, 1) #undef NEON_FN #define NEON_FN(dest, src1, src2) NEON_QDMULH32(dest, src1, src2, 1) -NEON_VOP_ENV(qrdmulh_s32, neon_s32, 1) +NEON_VOP(qrdmulh_s32, neon_s32, 1) #undef NEON_FN #undef NEON_QDMULH32 @@ -1249,7 +1221,7 @@ uint32_t HELPER(neon_narrow_round_high_u16)(uint64_t x) return ((x >> 16) & 0xffff) | ((x >> 32) & 0xffff0000); } -uint32_t HELPER(neon_unarrow_sat8)(CPUState *env, uint64_t x) +uint32_t HELPER(neon_unarrow_sat8)(uint64_t x) { uint16_t s; uint8_t d; @@ -1276,7 +1248,7 @@ uint32_t HELPER(neon_unarrow_sat8)(CPUState *env, uint64_t x) return res; } -uint32_t HELPER(neon_narrow_sat_u8)(CPUState *env, uint64_t x) +uint32_t HELPER(neon_narrow_sat_u8)(uint64_t x) { uint16_t s; uint8_t d; @@ -1299,7 +1271,7 @@ uint32_t HELPER(neon_narrow_sat_u8)(CPUState *env, uint64_t x) return res; } -uint32_t HELPER(neon_narrow_sat_s8)(CPUState *env, uint64_t x) +uint32_t HELPER(neon_narrow_sat_s8)(uint64_t x) { int16_t s; uint8_t d; @@ -1322,7 +1294,7 @@ uint32_t HELPER(neon_narrow_sat_s8)(CPUState *env, uint64_t x) return res; } -uint32_t HELPER(neon_unarrow_sat16)(CPUState *env, uint64_t x) +uint32_t HELPER(neon_unarrow_sat16)(uint64_t x) { uint32_t high; uint32_t low; @@ -1345,7 +1317,7 @@ uint32_t HELPER(neon_unarrow_sat16)(CPUState *env, uint64_t x) return low | (high << 16); } -uint32_t HELPER(neon_narrow_sat_u16)(CPUState *env, uint64_t x) +uint32_t HELPER(neon_narrow_sat_u16)(uint64_t x) { uint32_t high; uint32_t low; @@ -1362,7 +1334,7 @@ uint32_t HELPER(neon_narrow_sat_u16)(CPUState *env, uint64_t x) return low | (high << 16); } -uint32_t HELPER(neon_narrow_sat_s16)(CPUState *env, uint64_t x) +uint32_t HELPER(neon_narrow_sat_s16)(uint64_t x) { int32_t low; int32_t high; @@ -1379,7 +1351,7 @@ uint32_t HELPER(neon_narrow_sat_s16)(CPUState *env, uint64_t x) return (uint16_t)low | (high << 16); } -uint32_t HELPER(neon_unarrow_sat32)(CPUState *env, uint64_t x) +uint32_t HELPER(neon_unarrow_sat32)(uint64_t x) { if (x & 0x8000000000000000ull) { SET_QC(); @@ -1392,7 +1364,7 @@ uint32_t HELPER(neon_unarrow_sat32)(CPUState *env, uint64_t x) return x; } -uint32_t HELPER(neon_narrow_sat_u32)(CPUState *env, uint64_t x) +uint32_t HELPER(neon_narrow_sat_u32)(uint64_t x) { if (x > 0xffffffffu) { SET_QC(); @@ -1401,7 +1373,7 @@ uint32_t HELPER(neon_narrow_sat_u32)(CPUState *env, uint64_t x) return x; } -uint32_t HELPER(neon_narrow_sat_s32)(CPUState *env, uint64_t x) +uint32_t HELPER(neon_narrow_sat_s32)(uint64_t x) { if ((int64_t)x != (int32_t)x) { SET_QC(); @@ -1508,7 +1480,7 @@ uint64_t HELPER(neon_subl_u32)(uint64_t a, uint64_t b) return (a - b) ^ mask; } -uint64_t HELPER(neon_addl_saturate_s32)(CPUState *env, uint64_t a, uint64_t b) +uint64_t HELPER(neon_addl_saturate_s32)(uint64_t a, uint64_t b) { uint32_t x, y; uint32_t low, high; @@ -1530,7 +1502,7 @@ uint64_t HELPER(neon_addl_saturate_s32)(CPUState *env, uint64_t a, uint64_t b) return low | ((uint64_t)high << 32); } -uint64_t HELPER(neon_addl_saturate_s64)(CPUState *env, uint64_t a, uint64_t b) +uint64_t HELPER(neon_addl_saturate_s64)(uint64_t a, uint64_t b) { uint64_t result; @@ -1542,9 +1514,13 @@ uint64_t HELPER(neon_addl_saturate_s64)(CPUState *env, uint64_t a, uint64_t b) return result; } -#define DO_ABD(dest, x, y, type) do { \ - type tmp_x = x; \ - type tmp_y = y; \ +/* We have to do the arithmetic in a larger type than + * the input type, because for example with a signed 32 bit + * op the absolute difference can overflow a signed 32 bit value. + */ +#define DO_ABD(dest, x, y, intype, arithtype) do { \ + arithtype tmp_x = (intype)(x); \ + arithtype tmp_y = (intype)(y); \ dest = ((tmp_x > tmp_y) ? tmp_x - tmp_y : tmp_y - tmp_x); \ } while(0) @@ -1552,12 +1528,12 @@ uint64_t HELPER(neon_abdl_u16)(uint32_t a, uint32_t b) { uint64_t tmp; uint64_t result; - DO_ABD(result, a, b, uint8_t); - DO_ABD(tmp, a >> 8, b >> 8, uint8_t); + DO_ABD(result, a, b, uint8_t, uint32_t); + DO_ABD(tmp, a >> 8, b >> 8, uint8_t, uint32_t); result |= tmp << 16; - DO_ABD(tmp, a >> 16, b >> 16, uint8_t); + DO_ABD(tmp, a >> 16, b >> 16, uint8_t, uint32_t); result |= tmp << 32; - DO_ABD(tmp, a >> 24, b >> 24, uint8_t); + DO_ABD(tmp, a >> 24, b >> 24, uint8_t, uint32_t); result |= tmp << 48; return result; } @@ -1566,12 +1542,12 @@ uint64_t HELPER(neon_abdl_s16)(uint32_t a, uint32_t b) { uint64_t tmp; uint64_t result; - DO_ABD(result, a, b, int8_t); - DO_ABD(tmp, a >> 8, b >> 8, int8_t); + DO_ABD(result, a, b, int8_t, int32_t); + DO_ABD(tmp, a >> 8, b >> 8, int8_t, int32_t); result |= tmp << 16; - DO_ABD(tmp, a >> 16, b >> 16, int8_t); + DO_ABD(tmp, a >> 16, b >> 16, int8_t, int32_t); result |= tmp << 32; - DO_ABD(tmp, a >> 24, b >> 24, int8_t); + DO_ABD(tmp, a >> 24, b >> 24, int8_t, int32_t); result |= tmp << 48; return result; } @@ -1580,8 +1556,8 @@ uint64_t HELPER(neon_abdl_u32)(uint32_t a, uint32_t b) { uint64_t tmp; uint64_t result; - DO_ABD(result, a, b, uint16_t); - DO_ABD(tmp, a >> 16, b >> 16, uint16_t); + DO_ABD(result, a, b, uint16_t, uint32_t); + DO_ABD(tmp, a >> 16, b >> 16, uint16_t, uint32_t); return result | (tmp << 32); } @@ -1589,22 +1565,22 @@ uint64_t HELPER(neon_abdl_s32)(uint32_t a, uint32_t b) { uint64_t tmp; uint64_t result; - DO_ABD(result, a, b, int16_t); - DO_ABD(tmp, a >> 16, b >> 16, int16_t); + DO_ABD(result, a, b, int16_t, int32_t); + DO_ABD(tmp, a >> 16, b >> 16, int16_t, int32_t); return result | (tmp << 32); } uint64_t HELPER(neon_abdl_u64)(uint32_t a, uint32_t b) { uint64_t result; - DO_ABD(result, a, b, uint32_t); + DO_ABD(result, a, b, uint32_t, uint64_t); return result; } uint64_t HELPER(neon_abdl_s64)(uint32_t a, uint32_t b) { uint64_t result; - DO_ABD(result, a, b, int32_t); + DO_ABD(result, a, b, int32_t, int64_t); return result; } #undef DO_ABD @@ -1702,7 +1678,7 @@ uint64_t HELPER(neon_negl_u64)(uint64_t x) } else if (x < 0) { \ x = -x; \ }} while (0) -uint32_t HELPER(neon_qabs_s8)(CPUState *env, uint32_t x) +uint32_t HELPER(neon_qabs_s8)(uint32_t x) { neon_s8 vec; NEON_UNPACK(neon_s8, vec, x); @@ -1722,7 +1698,7 @@ uint32_t HELPER(neon_qabs_s8)(CPUState *env, uint32_t x) } else { \ x = -x; \ }} while (0) -uint32_t HELPER(neon_qneg_s8)(CPUState *env, uint32_t x) +uint32_t HELPER(neon_qneg_s8)(uint32_t x) { neon_s8 vec; NEON_UNPACK(neon_s8, vec, x); @@ -1742,7 +1718,7 @@ uint32_t HELPER(neon_qneg_s8)(CPUState *env, uint32_t x) } else if (x < 0) { \ x = -x; \ }} while (0) -uint32_t HELPER(neon_qabs_s16)(CPUState *env, uint32_t x) +uint32_t HELPER(neon_qabs_s16)(uint32_t x) { neon_s16 vec; NEON_UNPACK(neon_s16, vec, x); @@ -1760,7 +1736,7 @@ uint32_t HELPER(neon_qabs_s16)(CPUState *env, uint32_t x) } else { \ x = -x; \ }} while (0) -uint32_t HELPER(neon_qneg_s16)(CPUState *env, uint32_t x) +uint32_t HELPER(neon_qneg_s16)(uint32_t x) { neon_s16 vec; NEON_UNPACK(neon_s16, vec, x); @@ -1771,7 +1747,7 @@ uint32_t HELPER(neon_qneg_s16)(CPUState *env, uint32_t x) } #undef DO_QNEG16 -uint32_t HELPER(neon_qabs_s32)(CPUState *env, uint32_t x) +uint32_t HELPER(neon_qabs_s32)(uint32_t x) { if (x == SIGNBIT) { SET_QC(); @@ -1782,7 +1758,7 @@ uint32_t HELPER(neon_qabs_s32)(CPUState *env, uint32_t x) return x; } -uint32_t HELPER(neon_qneg_s32)(CPUState *env, uint32_t x) +uint32_t HELPER(neon_qneg_s32)(uint32_t x) { if (x == SIGNBIT) { SET_QC(); @@ -1796,73 +1772,76 @@ uint32_t HELPER(neon_qneg_s32)(CPUState *env, uint32_t x) /* NEON Float helpers. */ uint32_t HELPER(neon_min_f32)(uint32_t a, uint32_t b) { - float32 f0 = vfp_itos(a); - float32 f1 = vfp_itos(b); - return (float32_compare_quiet(f0, f1, NFS) == -1) ? a : b; + return float32_val(float32_min(make_float32(a), make_float32(b), NFS)); } uint32_t HELPER(neon_max_f32)(uint32_t a, uint32_t b) { - float32 f0 = vfp_itos(a); - float32 f1 = vfp_itos(b); - return (float32_compare_quiet(f0, f1, NFS) == 1) ? a : b; + return float32_val(float32_max(make_float32(a), make_float32(b), NFS)); } uint32_t HELPER(neon_abd_f32)(uint32_t a, uint32_t b) { - float32 f0 = vfp_itos(a); - float32 f1 = vfp_itos(b); - return vfp_stoi((float32_compare_quiet(f0, f1, NFS) == 1) - ? float32_sub(f0, f1, NFS) - : float32_sub(f1, f0, NFS)); + float32 f0 = make_float32(a); + float32 f1 = make_float32(b); + return float32_val(float32_abs(float32_sub(f0, f1, NFS))); } uint32_t HELPER(neon_add_f32)(uint32_t a, uint32_t b) { - return vfp_stoi(float32_add(vfp_itos(a), vfp_itos(b), NFS)); + return float32_val(float32_add(make_float32(a), make_float32(b), NFS)); } uint32_t HELPER(neon_sub_f32)(uint32_t a, uint32_t b) { - return vfp_stoi(float32_sub(vfp_itos(a), vfp_itos(b), NFS)); + return float32_val(float32_sub(make_float32(a), make_float32(b), NFS)); } uint32_t HELPER(neon_mul_f32)(uint32_t a, uint32_t b) { - return vfp_stoi(float32_mul(vfp_itos(a), vfp_itos(b), NFS)); + return float32_val(float32_mul(make_float32(a), make_float32(b), NFS)); } /* Floating point comparisons produce an integer result. */ -#define NEON_VOP_FCMP(name, cmp) \ +#define NEON_VOP_FCMP(name, ok) \ uint32_t HELPER(neon_##name)(uint32_t a, uint32_t b) \ { \ - if (float32_compare_quiet(vfp_itos(a), vfp_itos(b), NFS) cmp 0) \ - return ~0; \ - else \ - return 0; \ + switch (float32_compare_quiet(make_float32(a), make_float32(b), NFS)) { \ + ok return ~0; \ + default: return 0; \ + } \ } -NEON_VOP_FCMP(ceq_f32, ==) -NEON_VOP_FCMP(cge_f32, >=) -NEON_VOP_FCMP(cgt_f32, >) +NEON_VOP_FCMP(ceq_f32, case float_relation_equal:) +NEON_VOP_FCMP(cge_f32, case float_relation_equal: case float_relation_greater:) +NEON_VOP_FCMP(cgt_f32, case float_relation_greater:) uint32_t HELPER(neon_acge_f32)(uint32_t a, uint32_t b) { - float32 f0 = float32_abs(vfp_itos(a)); - float32 f1 = float32_abs(vfp_itos(b)); - return (float32_compare_quiet(f0, f1,NFS) >= 0) ? ~0 : 0; + float32 f0 = float32_abs(make_float32(a)); + float32 f1 = float32_abs(make_float32(b)); + switch (float32_compare_quiet(f0, f1, NFS)) { + case float_relation_equal: + case float_relation_greater: + return ~0; + default: + return 0; + } } uint32_t HELPER(neon_acgt_f32)(uint32_t a, uint32_t b) { - float32 f0 = float32_abs(vfp_itos(a)); - float32 f1 = float32_abs(vfp_itos(b)); - return (float32_compare_quiet(f0, f1, NFS) > 0) ? ~0 : 0; + float32 f0 = float32_abs(make_float32(a)); + float32 f1 = float32_abs(make_float32(b)); + if (float32_compare_quiet(f0, f1, NFS) == float_relation_greater) { + return ~0; + } + return 0; } #define ELEM(V, N, SIZE) (((V) >> ((N) * (SIZE))) & ((1ull << (SIZE)) - 1)) -void HELPER(neon_qunzip8)(CPUState *env, uint32_t rd, uint32_t rm) +void HELPER(neon_qunzip8)(uint32_t rd, uint32_t rm) { uint64_t zm0 = float64_val(env->vfp.regs[rm]); uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]); @@ -1890,7 +1869,7 @@ void HELPER(neon_qunzip8)(CPUState *env, uint32_t rd, uint32_t rm) env->vfp.regs[rd + 1] = make_float64(d1); } -void HELPER(neon_qunzip16)(CPUState *env, uint32_t rd, uint32_t rm) +void HELPER(neon_qunzip16)(uint32_t rd, uint32_t rm) { uint64_t zm0 = float64_val(env->vfp.regs[rm]); uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]); @@ -1910,7 +1889,7 @@ void HELPER(neon_qunzip16)(CPUState *env, uint32_t rd, uint32_t rm) env->vfp.regs[rd + 1] = make_float64(d1); } -void HELPER(neon_qunzip32)(CPUState *env, uint32_t rd, uint32_t rm) +void HELPER(neon_qunzip32)(uint32_t rd, uint32_t rm) { uint64_t zm0 = float64_val(env->vfp.regs[rm]); uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]); @@ -1926,7 +1905,7 @@ void HELPER(neon_qunzip32)(CPUState *env, uint32_t rd, uint32_t rm) env->vfp.regs[rd + 1] = make_float64(d1); } -void HELPER(neon_unzip8)(CPUState *env, uint32_t rd, uint32_t rm) +void HELPER(neon_unzip8)(uint32_t rd, uint32_t rm) { uint64_t zm = float64_val(env->vfp.regs[rm]); uint64_t zd = float64_val(env->vfp.regs[rd]); @@ -1942,7 +1921,7 @@ void HELPER(neon_unzip8)(CPUState *env, uint32_t rd, uint32_t rm) env->vfp.regs[rd] = make_float64(d0); } -void HELPER(neon_unzip16)(CPUState *env, uint32_t rd, uint32_t rm) +void HELPER(neon_unzip16)(uint32_t rd, uint32_t rm) { uint64_t zm = float64_val(env->vfp.regs[rm]); uint64_t zd = float64_val(env->vfp.regs[rd]); @@ -1954,7 +1933,7 @@ void HELPER(neon_unzip16)(CPUState *env, uint32_t rd, uint32_t rm) env->vfp.regs[rd] = make_float64(d0); } -void HELPER(neon_qzip8)(CPUState *env, uint32_t rd, uint32_t rm) +void HELPER(neon_qzip8)(uint32_t rd, uint32_t rm) { uint64_t zm0 = float64_val(env->vfp.regs[rm]); uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]); @@ -1982,7 +1961,7 @@ void HELPER(neon_qzip8)(CPUState *env, uint32_t rd, uint32_t rm) env->vfp.regs[rd + 1] = make_float64(d1); } -void HELPER(neon_qzip16)(CPUState *env, uint32_t rd, uint32_t rm) +void HELPER(neon_qzip16)(uint32_t rd, uint32_t rm) { uint64_t zm0 = float64_val(env->vfp.regs[rm]); uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]); @@ -2002,7 +1981,7 @@ void HELPER(neon_qzip16)(CPUState *env, uint32_t rd, uint32_t rm) env->vfp.regs[rd + 1] = make_float64(d1); } -void HELPER(neon_qzip32)(CPUState *env, uint32_t rd, uint32_t rm) +void HELPER(neon_qzip32)(uint32_t rd, uint32_t rm) { uint64_t zm0 = float64_val(env->vfp.regs[rm]); uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]); @@ -2018,7 +1997,7 @@ void HELPER(neon_qzip32)(CPUState *env, uint32_t rd, uint32_t rm) env->vfp.regs[rd + 1] = make_float64(d1); } -void HELPER(neon_zip8)(CPUState *env, uint32_t rd, uint32_t rm) +void HELPER(neon_zip8)(uint32_t rd, uint32_t rm) { uint64_t zm = float64_val(env->vfp.regs[rm]); uint64_t zd = float64_val(env->vfp.regs[rd]); @@ -2034,7 +2013,7 @@ void HELPER(neon_zip8)(CPUState *env, uint32_t rd, uint32_t rm) env->vfp.regs[rd] = make_float64(d0); } -void HELPER(neon_zip16)(CPUState *env, uint32_t rd, uint32_t rm) +void HELPER(neon_zip16)(uint32_t rd, uint32_t rm) { uint64_t zm = float64_val(env->vfp.regs[rm]); uint64_t zd = float64_val(env->vfp.regs[rd]); |