env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
}
-#define HELPER(x) helper_##x
/* Sign/zero extend */
uint32_t HELPER(sxtb16)(uint32_t x)
{
}
#endif
-
-#ifndef DEF_HELPER
#define DEF_HELPER(name, ret, args) ret helper_##name args;
+
+#ifdef GEN_HELPER
+#define DEF_HELPER_1_1(name, ret, args) \
+DEF_HELPER(name, ret, args) \
+static inline void gen_helper_##name(TCGv ret, TCGv arg1) \
+{ \
+ tcg_gen_helper_1_1(helper_##name, ret, arg1); \
+}
+#define DEF_HELPER_1_2(name, ret, args) \
+DEF_HELPER(name, ret, args) \
+static inline void gen_helper_##name(TCGv ret, TCGv arg1, TCGv arg2) \
+{ \
+ tcg_gen_helper_1_2(helper_##name, ret, arg1, arg2); \
+}
+#else /* !GEN_HELPER */
+#define DEF_HELPER_1_1 DEF_HELPER
+#define DEF_HELPER_1_2 DEF_HELPER
+#define HELPER(x) helper_##x
#endif
-DEF_HELPER(clz, uint32_t, (uint32_t))
-DEF_HELPER(sxtb16, uint32_t, (uint32_t))
-DEF_HELPER(uxtb16, uint32_t, (uint32_t))
+DEF_HELPER_1_1(clz, uint32_t, (uint32_t))
+DEF_HELPER_1_1(sxtb16, uint32_t, (uint32_t))
+DEF_HELPER_1_1(uxtb16, uint32_t, (uint32_t))
+
+DEF_HELPER_1_2(add_setq, uint32_t, (uint32_t, uint32_t))
+DEF_HELPER_1_2(add_saturate, uint32_t, (uint32_t, uint32_t))
+DEF_HELPER_1_2(sub_saturate, uint32_t, (uint32_t, uint32_t))
+DEF_HELPER_1_2(add_usaturate, uint32_t, (uint32_t, uint32_t))
+DEF_HELPER_1_2(sub_usaturate, uint32_t, (uint32_t, uint32_t))
+DEF_HELPER_1_1(double_saturate, uint32_t, (int32_t))
+
+#undef DEF_HELPER
+#undef DEF_HELPER_1_1
+#undef DEF_HELPER_1_2
+#undef GEN_HELPER
FORCE_RET();
}
-/* misc */
-#define SIGNBIT (uint32_t)0x80000000
-/* saturating arithmetic */
-void OPPROTO op_addl_T0_T1_setq(void)
-{
- uint32_t res;
-
- res = T0 + T1;
- if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT))
- env->QF = 1;
-
- T0 = res;
- FORCE_RET();
-}
-
-void OPPROTO op_addl_T0_T1_saturate(void)
-{
- uint32_t res;
-
- res = T0 + T1;
- if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT)) {
- env->QF = 1;
- if (T0 & SIGNBIT)
- T0 = 0x80000000;
- else
- T0 = 0x7fffffff;
- }
- else
- T0 = res;
-
- FORCE_RET();
-}
-
-void OPPROTO op_subl_T0_T1_saturate(void)
-{
- uint32_t res;
-
- res = T0 - T1;
- if (((res ^ T0) & SIGNBIT) && ((T0 ^ T1) & SIGNBIT)) {
- env->QF = 1;
- if (T0 & SIGNBIT)
- T0 = 0x80000000;
- else
- T0 = 0x7fffffff;
- }
- else
- T0 = res;
-
- FORCE_RET();
-}
-
-void OPPROTO op_double_T1_saturate(void)
-{
- int32_t val;
-
- val = T1;
- if (val >= 0x40000000) {
- T1 = 0x7fffffff;
- env->QF = 1;
- } else if (val <= (int32_t)0xc0000000) {
- T1 = 0x80000000;
- env->QF = 1;
- } else {
- T1 = val << 1;
- }
- FORCE_RET();
-}
-
-/* Unsigned saturating arithmetic for NEON. */
-void OPPROTO op_addl_T0_T1_usaturate(void)
-{
- uint32_t res;
-
- res = T0 + T1;
- if (res < T0) {
- env->QF = 1;
- T0 = 0xffffffff;
- } else {
- T0 = res;
- }
-
- FORCE_RET();
-}
-
-void OPPROTO op_subl_T0_T1_usaturate(void)
-{
- uint32_t res;
-
- res = T0 - T1;
- if (res > T0) {
- env->QF = 1;
- T0 = 0;
- } else {
- T0 = res;
- }
-
- FORCE_RET();
-}
-
/* exceptions */
void OPPROTO op_swi(void)
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "exec.h"
+#include "helpers.h"
void raise_exception(int tt)
{
env = saved_env;
}
#endif
+
+#define SIGNBIT (uint32_t)0x80000000
+uint32_t HELPER(add_setq)(uint32_t a, uint32_t b)
+{
+ uint32_t res = a + b;
+ if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT))
+ env->QF = 1;
+ return res;
+}
+
+uint32_t HELPER(add_saturate)(uint32_t a, uint32_t b)
+{
+ uint32_t res = a + b;
+ if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) {
+ env->QF = 1;
+ res = ~(((int32_t)a >> 31) ^ SIGNBIT);
+ }
+ return res;
+}
+
+uint32_t HELPER(sub_saturate)(uint32_t a, uint32_t b)
+{
+ uint32_t res = a - b;
+ if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) {
+ env->QF = 1;
+ res = ~(((int32_t)a >> 31) ^ SIGNBIT);
+ }
+ return res;
+}
+
+uint32_t HELPER(double_saturate)(int32_t val)
+{
+ uint32_t res;
+ if (val >= 0x40000000) {
+ res = ~SIGNBIT;
+ env->QF = 1;
+ } else if (val <= (int32_t)0xc0000000) {
+ res = SIGNBIT;
+ env->QF = 1;
+ } else {
+ res = val << 1;
+ }
+ return res;
+}
+
+uint32_t HELPER(add_usaturate)(uint32_t a, uint32_t b)
+{
+ uint32_t res = a + b;
+ if (res < a) {
+ env->QF = 1;
+ res = ~0;
+ }
+ return res;
+}
+
+uint32_t HELPER(sub_usaturate)(uint32_t a, uint32_t b)
+{
+ uint32_t res = a - b;
+ if (res > a) {
+ env->QF = 1;
+ res = 0;
+ }
+ return res;
+}
+
/* Note that for NEON an "l" prefix means it is a wide operation, unlike
scalar arm ops where it means a word size operation. */
+#define SIGNBIT (uint32_t)0x80000000
/* ??? NEON ops should probably have their own float status. */
#define NFS &env->vfp.fp_status
#define NEON_OP(name) void OPPROTO op_neon_##name (void)
#include "exec-all.h"
#include "disas.h"
#include "tcg-op.h"
+
+#define GEN_HELPER 1
#include "helpers.h"
#define ENABLE_ARCH_5J 0
#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
-#define HELPER_ADDR(x) helper_##x
-
-#define gen_sxtb16(var) tcg_gen_helper_1_1(HELPER_ADDR(sxtb16), var, var)
-#define gen_uxtb16(var) tcg_gen_helper_1_1(HELPER_ADDR(uxtb16), var, var)
+#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
+#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
-#define gen_op_clz_T0(var) \
- tcg_gen_helper_1_1(HELPER_ADDR(clz), cpu_T[0], cpu_T[0])
+#define gen_op_addl_T0_T1_setq() \
+ gen_helper_add_setq(cpu_T[0], cpu_T[0], cpu_T[1])
+#define gen_op_addl_T0_T1_saturate() \
+ gen_helper_add_saturate(cpu_T[0], cpu_T[0], cpu_T[1])
+#define gen_op_subl_T0_T1_saturate() \
+ gen_helper_sub_saturate(cpu_T[0], cpu_T[0], cpu_T[1])
+#define gen_op_addl_T0_T1_usaturate() \
+ gen_helper_add_usaturate(cpu_T[0], cpu_T[0], cpu_T[1])
+#define gen_op_subl_T0_T1_usaturate() \
+ gen_helper_sub_usaturate(cpu_T[0], cpu_T[0], cpu_T[1])
/* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
tmp = (t0 ^ t1) & 0x8000;
switch (size) {
case 0: gen_op_neon_clz_u8(); break;
case 1: gen_op_neon_clz_u16(); break;
- case 2: gen_op_clz_T0(); break;
+ case 2: gen_helper_clz(cpu_T[0], cpu_T[0]); break;
default: return 1;
}
break;
} else if (op1 == 3) {
/* clz */
rd = (insn >> 12) & 0xf;
- gen_movl_T0_reg(s, rm);
- gen_op_clz_T0();
- gen_movl_reg_T0(s, rd);
+ tmp = load_reg(s, rm);
+ gen_helper_clz(tmp, tmp);
+ store_reg(s, rd, tmp);
} else {
goto illegal_op;
}
gen_movl_T0_reg(s, rm);
gen_movl_T1_reg(s, rn);
if (op1 & 2)
- gen_op_double_T1_saturate();
+ gen_helper_double_saturate(cpu_T[1], cpu_T[1]);
if (op1 & 1)
gen_op_subl_T0_T1_saturate();
else
gen_movl_T0_reg(s, rm);
gen_movl_T1_reg(s, rn);
if (op & 2)
- gen_op_double_T1_saturate();
+ gen_helper_double_saturate(cpu_T[1], cpu_T[1]);
if (op & 1)
gen_op_subl_T0_T1_saturate();
else
gen_op_sel_T0_T1();
break;
case 0x18: /* clz */
- gen_op_clz_T0();
+ gen_helper_clz(cpu_T[0], cpu_T[0]);
break;
default:
goto illegal_op;