]> git.proxmox.com Git - qemu.git/blobdiff - target-arm/op_helper.c
user_only: compile everything with -fpie
[qemu.git] / target-arm / op_helper.c
index 79b3f1a456c365740137596fa495755be7bb4154..9b1a0143d24e2ca5e0822d039939f80da7e30df6 100644 (file)
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  */
 #include "exec.h"
 #include "helpers.h"
 
+#define SIGNBIT (uint32_t)0x80000000
+#define SIGNBIT64 ((uint64_t)1 << 63)
+
 void raise_exception(int tt)
 {
     env->exception_index = tt;
@@ -28,7 +30,7 @@ void raise_exception(int tt)
 
 /* thread support */
 
-spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
 
 void cpu_lock(void)
 {
@@ -40,37 +42,31 @@ void cpu_unlock(void)
     spin_unlock(&global_cpu_lock);
 }
 
-void helper_neon_tbl(int rn, int maxindex)
+uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def,
+                          uint32_t rn, uint32_t 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;
+        index = (ireg >> shift) & 0xff;
+        if (index < maxindex) {
+            tmp = (table[index >> 3] >> ((index & 7) << 3)) & 0xff;
             val |= tmp << shift;
         } else {
-            val |= T0 & (0xff << shift);
+            val |= def & (0xff << shift);
         }
     }
-    T0 = val;
+    return val;
 }
 
 #if !defined(CONFIG_USER_ONLY)
 
 #define MMUSUFFIX _mmu
-#ifdef __s390__
-# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
-#else
-# define GETPC() (__builtin_return_address(0))
-#endif
 
 #define SHIFT 0
 #include "softmmu_template.h"
@@ -100,7 +96,7 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
     saved_env = env;
     env = cpu_single_env;
     ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
-    if (__builtin_expect(ret, 0)) {
+    if (unlikely(ret)) {
         if (retaddr) {
             /* now we have a real cpu fault */
             pc = (unsigned long)retaddr;
@@ -117,7 +113,8 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
 }
 #endif
 
-#define SIGNBIT (uint32_t)0x80000000
+/* FIXME: Pass an axplicit pointer to QF to CPUState, and move saturating
+   instructions into helper.c  */
 uint32_t HELPER(add_setq)(uint32_t a, uint32_t b)
 {
     uint32_t res = a + b;
@@ -187,7 +184,6 @@ static inline uint32_t do_ssat(int32_t val, int shift)
     int32_t top;
     uint32_t mask;
 
-    shift = PARAM1;
     top = val >> shift;
     mask = (1u << shift) - 1;
     if (top > 0) {
@@ -205,7 +201,6 @@ static inline uint32_t do_usat(int32_t val, int shift)
 {
     uint32_t max;
 
-    shift = PARAM1;
     max = (1u << shift) - 1;
     if (val < 0) {
         env->QF = 1;
@@ -311,8 +306,8 @@ void HELPER(set_user_reg)(uint32_t regno, uint32_t val)
 uint32_t HELPER (add_cc)(uint32_t a, uint32_t b)
 {
     uint32_t result;
-    result = T0 + T1;
-    env->NZF = result;
+    result = a + b;
+    env->NF = env->ZF = result;
     env->CF = result < a;
     env->VF = (a ^ b ^ -1) & (a ^ result);
     return result;
@@ -329,7 +324,7 @@ uint32_t HELPER(adc_cc)(uint32_t a, uint32_t b)
         env->CF = result <= a;
     }
     env->VF = (a ^ b ^ -1) & (a ^ result);
-    env->NZF = result;
+    env->NF = env->ZF = result;
     return result;
 }
 
@@ -337,7 +332,7 @@ uint32_t HELPER(sub_cc)(uint32_t a, uint32_t b)
 {
     uint32_t result;
     result = a - b;
-    env->NZF = result;
+    env->NF = env->ZF = result;
     env->CF = a >= b;
     env->VF = (a ^ b) & (a ^ result);
     return result;
@@ -354,7 +349,7 @@ uint32_t HELPER(sbc_cc)(uint32_t a, uint32_t b)
         env->CF = a >= b;
     }
     env->VF = (a ^ b) & (a ^ result);
-    env->NZF = result;
+    env->NF = env->ZF = result;
     return result;
 }
 
@@ -384,14 +379,6 @@ uint32_t HELPER(sar)(uint32_t x, uint32_t i)
     return (int32_t)x >> shift;
 }
 
-uint32_t HELPER(ror)(uint32_t x, uint32_t i)
-{
-    int shift = i & 0xff;
-    if (shift == 0)
-        return x;
-    return (x >> shift) | (x << (32 - shift));
-}
-
 uint32_t HELPER(shl_cc)(uint32_t x, uint32_t i)
 {
     int shift = i & 0xff;
@@ -452,3 +439,51 @@ uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i)
     }
 }
 
+uint64_t HELPER(neon_add_saturate_s64)(uint64_t src1, uint64_t src2)
+{
+    uint64_t res;
+
+    res = src1 + src2;
+    if (((res ^ src1) & SIGNBIT64) && !((src1 ^ src2) & SIGNBIT64)) {
+        env->QF = 1;
+        res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64;
+    }
+    return res;
+}
+
+uint64_t HELPER(neon_add_saturate_u64)(uint64_t src1, uint64_t src2)
+{
+    uint64_t res;
+
+    res = src1 + src2;
+    if (res < src1) {
+        env->QF = 1;
+        res = ~(uint64_t)0;
+    }
+    return res;
+}
+
+uint64_t HELPER(neon_sub_saturate_s64)(uint64_t src1, uint64_t src2)
+{
+    uint64_t res;
+
+    res = src1 - src2;
+    if (((res ^ src1) & SIGNBIT64) && ((src1 ^ src2) & SIGNBIT64)) {
+        env->QF = 1;
+        res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64;
+    }
+    return res;
+}
+
+uint64_t HELPER(neon_sub_saturate_u64)(uint64_t src1, uint64_t src2)
+{
+    uint64_t res;
+
+    if (src1 < src2) {
+        env->QF = 1;
+        res = 0;
+    } else {
+        res = src1 - src2;
+    }
+    return res;
+}