summaryrefslogtreecommitdiff
path: root/target-arm/op_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-arm/op_helper.c')
-rw-r--r--target-arm/op_helper.c78
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