diff options
Diffstat (limited to 'target-arm/op_helper.c')
-rw-r--r-- | target-arm/op_helper.c | 78 |
1 files changed, 76 insertions, 2 deletions
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 6e14a4dff2..a9bd95b057 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -1,7 +1,7 @@ /* * ARM helper routines * - * Copyright (c) 2005 CodeSourcery, LLC + * Copyright (c) 2005-2007 CodeSourcery, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -175,6 +175,81 @@ void do_vfp_get_fpscr(void) T0 |= vfp_exceptbits_from_host(i); } +float32 helper_recps_f32(float32 a, float32 b) +{ + float_status *s = &env->vfp.fp_status; + float32 two = int32_to_float32(2, s); + return float32_sub(two, float32_mul(a, b, s), s); +} + +float32 helper_rsqrts_f32(float32 a, float32 b) +{ + float_status *s = &env->vfp.fp_status; + float32 three = int32_to_float32(3, s); + return float32_sub(three, float32_mul(a, b, s), s); +} + +/* TODO: The architecture specifies the value that the estimate functions + should return. We return the exact reciprocal/root instead. */ +float32 helper_recpe_f32(float32 a) +{ + float_status *s = &env->vfp.fp_status; + float32 one = int32_to_float32(1, s); + return float32_div(one, a, s); +} + +float32 helper_rsqrte_f32(float32 a) +{ + float_status *s = &env->vfp.fp_status; + float32 one = int32_to_float32(1, s); + return float32_div(one, float32_sqrt(a, s), s); +} + +uint32_t helper_recpe_u32(uint32_t a) +{ + float_status *s = &env->vfp.fp_status; + float32 tmp; + tmp = int32_to_float32(a, s); + tmp = float32_scalbn(tmp, -32, s); + tmp = helper_recpe_f32(tmp); + tmp = float32_scalbn(tmp, 31, s); + return float32_to_int32(tmp, s); +} + +uint32_t helper_rsqrte_u32(uint32_t a) +{ + float_status *s = &env->vfp.fp_status; + float32 tmp; + tmp = int32_to_float32(a, s); + tmp = float32_scalbn(tmp, -32, s); + tmp = helper_rsqrte_f32(tmp); + tmp = float32_scalbn(tmp, 31, s); + return float32_to_int32(tmp, s); +} + +void helper_neon_tbl(int rn, int maxindex) +{ + uint32_t val; + uint32_t mask; + uint32_t tmp; + int index; + int shift; + uint64_t *table; + table = (uint64_t *)&env->vfp.regs[rn]; + val = 0; + mask = 0; + for (shift = 0; shift < 32; shift += 8) { + index = (T1 >> shift) & 0xff; + if (index <= maxindex) { + tmp = (table[index >> 3] >> (index & 7)) & 0xff; + val |= tmp << shift; + } else { + val |= T0 & (0xff << shift); + } + } + T0 = val; +} + #if !defined(CONFIG_USER_ONLY) #define MMUSUFFIX _mmu @@ -227,5 +302,4 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) } env = saved_env; } - #endif |