4 * Copyright (c) 2005-2007 CodeSourcery, LLC
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 void raise_exception(int tt)
25 env->exception_index = tt;
31 spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
35 spin_lock(&global_cpu_lock);
40 spin_unlock(&global_cpu_lock);
45 void do_vfp_abss(void)
47 FT0s = float32_abs(FT0s);
50 void do_vfp_absd(void)
52 FT0d = float64_abs(FT0d);
55 void do_vfp_sqrts(void)
57 FT0s = float32_sqrt(FT0s, &env->vfp.fp_status);
60 void do_vfp_sqrtd(void)
62 FT0d = float64_sqrt(FT0d, &env->vfp.fp_status);
65 /* XXX: check quiet/signaling case */
66 #define DO_VFP_cmp(p, size) \
67 void do_vfp_cmp##p(void) \
70 switch(float ## size ## _compare_quiet(FT0##p, FT1##p, &env->vfp.fp_status)) {\
71 case 0: flags = 0x6; break;\
72 case -1: flags = 0x8; break;\
73 case 1: flags = 0x2; break;\
74 default: case 2: flags = 0x3; break;\
76 env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28)\
77 | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
81 void do_vfp_cmpe##p(void) \
84 switch(float ## size ## _compare(FT0##p, FT1##p, &env->vfp.fp_status)) {\
85 case 0: flags = 0x6; break;\
86 case -1: flags = 0x8; break;\
87 case 1: flags = 0x2; break;\
88 default: case 2: flags = 0x3; break;\
90 env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28)\
91 | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
98 /* Convert host exception flags to vfp form. */
99 static inline int vfp_exceptbits_from_host(int host_bits)
103 if (host_bits & float_flag_invalid)
105 if (host_bits & float_flag_divbyzero)
107 if (host_bits & float_flag_overflow)
109 if (host_bits & float_flag_underflow)
111 if (host_bits & float_flag_inexact)
116 /* Convert vfp exception flags to target form. */
117 static inline int vfp_exceptbits_to_host(int target_bits)
122 host_bits |= float_flag_invalid;
124 host_bits |= float_flag_divbyzero;
126 host_bits |= float_flag_overflow;
128 host_bits |= float_flag_underflow;
129 if (target_bits & 0x10)
130 host_bits |= float_flag_inexact;
134 void do_vfp_set_fpscr(void)
139 changed = env->vfp.xregs[ARM_VFP_FPSCR];
140 env->vfp.xregs[ARM_VFP_FPSCR] = (T0 & 0xffc8ffff);
141 env->vfp.vec_len = (T0 >> 16) & 7;
142 env->vfp.vec_stride = (T0 >> 20) & 3;
145 if (changed & (3 << 22)) {
149 i = float_round_nearest_even;
155 i = float_round_down;
158 i = float_round_to_zero;
161 set_float_rounding_mode(i, &env->vfp.fp_status);
164 i = vfp_exceptbits_to_host((T0 >> 8) & 0x1f);
165 set_float_exception_flags(i, &env->vfp.fp_status);
166 /* XXX: FZ and DN are not implemented. */
169 void do_vfp_get_fpscr(void)
173 T0 = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff) | (env->vfp.vec_len << 16)
174 | (env->vfp.vec_stride << 20);
175 i = get_float_exception_flags(&env->vfp.fp_status);
176 T0 |= vfp_exceptbits_from_host(i);
179 float32 helper_recps_f32(float32 a, float32 b)
181 float_status *s = &env->vfp.fp_status;
182 float32 two = int32_to_float32(2, s);
183 return float32_sub(two, float32_mul(a, b, s), s);
186 float32 helper_rsqrts_f32(float32 a, float32 b)
188 float_status *s = &env->vfp.fp_status;
189 float32 three = int32_to_float32(3, s);
190 return float32_sub(three, float32_mul(a, b, s), s);
193 /* TODO: The architecture specifies the value that the estimate functions
194 should return. We return the exact reciprocal/root instead. */
195 float32 helper_recpe_f32(float32 a)
197 float_status *s = &env->vfp.fp_status;
198 float32 one = int32_to_float32(1, s);
199 return float32_div(one, a, s);
202 float32 helper_rsqrte_f32(float32 a)
204 float_status *s = &env->vfp.fp_status;
205 float32 one = int32_to_float32(1, s);
206 return float32_div(one, float32_sqrt(a, s), s);
209 uint32_t helper_recpe_u32(uint32_t a)
211 float_status *s = &env->vfp.fp_status;
213 tmp = int32_to_float32(a, s);
214 tmp = float32_scalbn(tmp, -32, s);
215 tmp = helper_recpe_f32(tmp);
216 tmp = float32_scalbn(tmp, 31, s);
217 return float32_to_int32(tmp, s);
220 uint32_t helper_rsqrte_u32(uint32_t a)
222 float_status *s = &env->vfp.fp_status;
224 tmp = int32_to_float32(a, s);
225 tmp = float32_scalbn(tmp, -32, s);
226 tmp = helper_rsqrte_f32(tmp);
227 tmp = float32_scalbn(tmp, 31, s);
228 return float32_to_int32(tmp, s);
231 void helper_neon_tbl(int rn, int maxindex)
239 table = (uint64_t *)&env->vfp.regs[rn];
242 for (shift = 0; shift < 32; shift += 8) {
243 index = (T1 >> shift) & 0xff;
244 if (index <= maxindex) {
245 tmp = (table[index >> 3] >> (index & 7)) & 0xff;
248 val |= T0 & (0xff << shift);
254 #if !defined(CONFIG_USER_ONLY)
256 #define MMUSUFFIX _mmu
258 # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
260 # define GETPC() (__builtin_return_address(0))
264 #include "softmmu_template.h"
267 #include "softmmu_template.h"
270 #include "softmmu_template.h"
273 #include "softmmu_template.h"
275 /* try to fill the TLB and return an exception if error. If retaddr is
276 NULL, it means that the function was called in C code (i.e. not
277 from generated code or from helper.c) */
278 /* XXX: fix it to restore all registers */
279 void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
281 TranslationBlock *tb;
286 /* XXX: hack to restore env in all cases, even if not called from
289 env = cpu_single_env;
290 ret = cpu_arm_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
291 if (__builtin_expect(ret, 0)) {
293 /* now we have a real cpu fault */
294 pc = (unsigned long)retaddr;
297 /* the PC is inside the translated code. It means that we have
298 a virtual CPU fault */
299 cpu_restore_state(tb, env, pc, NULL);
302 raise_exception(env->exception_index);
308 #define SIGNBIT (uint32_t)0x80000000
309 uint32_t HELPER(add_setq)(uint32_t a, uint32_t b)
311 uint32_t res = a + b;
312 if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT))
317 uint32_t HELPER(add_saturate)(uint32_t a, uint32_t b)
319 uint32_t res = a + b;
320 if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) {
322 res = ~(((int32_t)a >> 31) ^ SIGNBIT);
327 uint32_t HELPER(sub_saturate)(uint32_t a, uint32_t b)
329 uint32_t res = a - b;
330 if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) {
332 res = ~(((int32_t)a >> 31) ^ SIGNBIT);
337 uint32_t HELPER(double_saturate)(int32_t val)
340 if (val >= 0x40000000) {
343 } else if (val <= (int32_t)0xc0000000) {
352 uint32_t HELPER(add_usaturate)(uint32_t a, uint32_t b)
354 uint32_t res = a + b;
362 uint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b)
364 uint32_t res = a - b;
372 /* Signed saturation. */
373 static inline uint32_t do_ssat(int32_t val, int shift)
380 mask = (1u << shift) - 1;
384 } else if (top < -1) {
391 /* Unsigned saturation. */
392 static inline uint32_t do_usat(int32_t val, int shift)
397 max = (1u << shift) - 1;
401 } else if (val > max) {
408 /* Signed saturate. */
409 uint32_t HELPER(ssat)(uint32_t x, uint32_t shift)
411 return do_ssat(x, shift);
414 /* Dual halfword signed saturate. */
415 uint32_t HELPER(ssat16)(uint32_t x, uint32_t shift)
419 res = (uint16_t)do_ssat((int16_t)x, shift);
420 res |= do_ssat(((int32_t)x) >> 16, shift) << 16;
424 /* Unsigned saturate. */
425 uint32_t HELPER(usat)(uint32_t x, uint32_t shift)
427 return do_usat(x, shift);
430 /* Dual halfword unsigned saturate. */
431 uint32_t HELPER(usat16)(uint32_t x, uint32_t shift)
435 res = (uint16_t)do_usat((int16_t)x, shift);
436 res |= do_usat(((int32_t)x) >> 16, shift) << 16;