aboutsummaryrefslogtreecommitdiff
path: root/target-arm
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2011-05-19 14:46:19 +0100
committerAurelien Jarno <aurelien@aurel32.net>2011-05-23 22:39:36 +0200
commit5500b06cb5091c352a7ce6552da02c9e1958bf3b (patch)
tree5fd93bad4e53a0b6272215927e63937bcc7118c2 /target-arm
parent36802b6b1ed7887aeae5d027f86a969400f8824a (diff)
target-arm: Use correct float status for Neon int-float conversions
The Neon versions of int-float conversions must use the "standard FPSCR" rather than the default FPSCR. Implement this by having the helper functions take a pointer to the appropriate float_status value rather than simply taking a pointer to the entire CPUState, and making translate.c pass a pointer to vfp.fp_status or vfp.standard_fp_status appropriately for whether the instruction being translated is Neon or VFP. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'target-arm')
-rw-r--r--target-arm/helper.c132
-rw-r--r--target-arm/helper.h60
-rw-r--r--target-arm/translate.c148
3 files changed, 146 insertions, 194 deletions
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 05b3ccca2d..1cc492d8a3 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2526,99 +2526,39 @@ DO_VFP_cmp(s, float32)
DO_VFP_cmp(d, float64)
#undef DO_VFP_cmp
-/* Integer to float conversion. */
-float32 VFP_HELPER(uito, s)(uint32_t x, CPUState *env)
-{
- return uint32_to_float32(x, &env->vfp.fp_status);
-}
+/* Integer to float and float to integer conversions */
-float64 VFP_HELPER(uito, d)(uint32_t x, CPUState *env)
-{
- return uint32_to_float64(x, &env->vfp.fp_status);
-}
-
-float32 VFP_HELPER(sito, s)(uint32_t x, CPUState *env)
-{
- return int32_to_float32(x, &env->vfp.fp_status);
-}
-
-float64 VFP_HELPER(sito, d)(uint32_t x, CPUState *env)
-{
- return int32_to_float64(x, &env->vfp.fp_status);
-}
-
-/* Float to integer conversion. */
-uint32_t VFP_HELPER(toui, s)(float32 x, CPUState *env)
-{
- if (float32_is_any_nan(x)) {
- float_raise(float_flag_invalid, &env->vfp.fp_status);
- return 0;
- }
- return float32_to_uint32(x, &env->vfp.fp_status);
-}
-
-uint32_t VFP_HELPER(toui, d)(float64 x, CPUState *env)
-{
- if (float64_is_any_nan(x)) {
- float_raise(float_flag_invalid, &env->vfp.fp_status);
- return 0;
- }
- return float64_to_uint32(x, &env->vfp.fp_status);
-}
-
-uint32_t VFP_HELPER(tosi, s)(float32 x, CPUState *env)
-{
- if (float32_is_any_nan(x)) {
- float_raise(float_flag_invalid, &env->vfp.fp_status);
- return 0;
- }
- return float32_to_int32(x, &env->vfp.fp_status);
-}
-
-uint32_t VFP_HELPER(tosi, d)(float64 x, CPUState *env)
-{
- if (float64_is_any_nan(x)) {
- float_raise(float_flag_invalid, &env->vfp.fp_status);
- return 0;
- }
- return float64_to_int32(x, &env->vfp.fp_status);
+#define CONV_ITOF(name, fsz, sign) \
+ float##fsz HELPER(name)(uint32_t x, void *fpstp) \
+{ \
+ float_status *fpst = fpstp; \
+ return sign##int32_to_##float##fsz(x, fpst); \
}
-uint32_t VFP_HELPER(touiz, s)(float32 x, CPUState *env)
-{
- if (float32_is_any_nan(x)) {
- float_raise(float_flag_invalid, &env->vfp.fp_status);
- return 0;
- }
- return float32_to_uint32_round_to_zero(x, &env->vfp.fp_status);
+#define CONV_FTOI(name, fsz, sign, round) \
+uint32_t HELPER(name)(float##fsz x, void *fpstp) \
+{ \
+ float_status *fpst = fpstp; \
+ if (float##fsz##_is_any_nan(x)) { \
+ float_raise(float_flag_invalid, fpst); \
+ return 0; \
+ } \
+ return float##fsz##_to_##sign##int32##round(x, fpst); \
}
-uint32_t VFP_HELPER(touiz, d)(float64 x, CPUState *env)
-{
- if (float64_is_any_nan(x)) {
- float_raise(float_flag_invalid, &env->vfp.fp_status);
- return 0;
- }
- return float64_to_uint32_round_to_zero(x, &env->vfp.fp_status);
-}
+#define FLOAT_CONVS(name, p, fsz, sign) \
+CONV_ITOF(vfp_##name##to##p, fsz, sign) \
+CONV_FTOI(vfp_to##name##p, fsz, sign, ) \
+CONV_FTOI(vfp_to##name##z##p, fsz, sign, _round_to_zero)
-uint32_t VFP_HELPER(tosiz, s)(float32 x, CPUState *env)
-{
- if (float32_is_any_nan(x)) {
- float_raise(float_flag_invalid, &env->vfp.fp_status);
- return 0;
- }
- return float32_to_int32_round_to_zero(x, &env->vfp.fp_status);
-}
+FLOAT_CONVS(si, s, 32, )
+FLOAT_CONVS(si, d, 64, )
+FLOAT_CONVS(ui, s, 32, u)
+FLOAT_CONVS(ui, d, 64, u)
-uint32_t VFP_HELPER(tosiz, d)(float64 x, CPUState *env)
-{
- if (float64_is_any_nan(x)) {
- float_raise(float_flag_invalid, &env->vfp.fp_status);
- return 0;
- }
- return float64_to_int32_round_to_zero(x, &env->vfp.fp_status);
-}
+#undef CONV_ITOF
+#undef CONV_FTOI
+#undef FLOAT_CONVS
/* floating point conversion */
float64 VFP_HELPER(fcvtd, s)(float32 x, CPUState *env)
@@ -2641,23 +2581,25 @@ float32 VFP_HELPER(fcvts, d)(float64 x, CPUState *env)
/* VFP3 fixed point conversion. */
#define VFP_CONV_FIX(name, p, fsz, itype, sign) \
-float##fsz VFP_HELPER(name##to, p)(uint##fsz##_t x, uint32_t shift, \
- CPUState *env) \
+float##fsz HELPER(vfp_##name##to##p)(uint##fsz##_t x, uint32_t shift, \
+ void *fpstp) \
{ \
+ float_status *fpst = fpstp; \
float##fsz tmp; \
- tmp = sign##int32_to_##float##fsz ((itype##_t)x, &env->vfp.fp_status); \
- return float##fsz##_scalbn(tmp, -(int)shift, &env->vfp.fp_status); \
+ tmp = sign##int32_to_##float##fsz((itype##_t)x, fpst); \
+ return float##fsz##_scalbn(tmp, -(int)shift, fpst); \
} \
-uint##fsz##_t VFP_HELPER(to##name, p)(float##fsz x, uint32_t shift, \
- CPUState *env) \
+uint##fsz##_t HELPER(vfp_to##name##p)(float##fsz x, uint32_t shift, \
+ void *fpstp) \
{ \
+ float_status *fpst = fpstp; \
float##fsz tmp; \
if (float##fsz##_is_any_nan(x)) { \
- float_raise(float_flag_invalid, &env->vfp.fp_status); \
+ float_raise(float_flag_invalid, fpst); \
return 0; \
} \
- tmp = float##fsz##_scalbn(x, shift, &env->vfp.fp_status); \
- return float##fsz##_to_##itype##_round_to_zero(tmp, &env->vfp.fp_status); \
+ tmp = float##fsz##_scalbn(x, shift, fpst); \
+ return float##fsz##_to_##itype##_round_to_zero(tmp, fpst); \
}
VFP_CONV_FIX(sh, d, 64, int16, )
diff --git a/target-arm/helper.h b/target-arm/helper.h
index ae701e8451..7d5533f613 100644
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
@@ -96,36 +96,36 @@ DEF_HELPER_3(vfp_cmped, void, f64, f64, env)
DEF_HELPER_2(vfp_fcvtds, f64, f32, env)
DEF_HELPER_2(vfp_fcvtsd, f32, f64, env)
-DEF_HELPER_2(vfp_uitos, f32, i32, env)
-DEF_HELPER_2(vfp_uitod, f64, i32, env)
-DEF_HELPER_2(vfp_sitos, f32, i32, env)
-DEF_HELPER_2(vfp_sitod, f64, i32, env)
-
-DEF_HELPER_2(vfp_touis, i32, f32, env)
-DEF_HELPER_2(vfp_touid, i32, f64, env)
-DEF_HELPER_2(vfp_touizs, i32, f32, env)
-DEF_HELPER_2(vfp_touizd, i32, f64, env)
-DEF_HELPER_2(vfp_tosis, i32, f32, env)
-DEF_HELPER_2(vfp_tosid, i32, f64, env)
-DEF_HELPER_2(vfp_tosizs, i32, f32, env)
-DEF_HELPER_2(vfp_tosizd, i32, f64, env)
-
-DEF_HELPER_3(vfp_toshs, i32, f32, i32, env)
-DEF_HELPER_3(vfp_tosls, i32, f32, i32, env)
-DEF_HELPER_3(vfp_touhs, i32, f32, i32, env)
-DEF_HELPER_3(vfp_touls, i32, f32, i32, env)
-DEF_HELPER_3(vfp_toshd, i64, f64, i32, env)
-DEF_HELPER_3(vfp_tosld, i64, f64, i32, env)
-DEF_HELPER_3(vfp_touhd, i64, f64, i32, env)
-DEF_HELPER_3(vfp_tould, i64, f64, i32, env)
-DEF_HELPER_3(vfp_shtos, f32, i32, i32, env)
-DEF_HELPER_3(vfp_sltos, f32, i32, i32, env)
-DEF_HELPER_3(vfp_uhtos, f32, i32, i32, env)
-DEF_HELPER_3(vfp_ultos, f32, i32, i32, env)
-DEF_HELPER_3(vfp_shtod, f64, i64, i32, env)
-DEF_HELPER_3(vfp_sltod, f64, i64, i32, env)
-DEF_HELPER_3(vfp_uhtod, f64, i64, i32, env)
-DEF_HELPER_3(vfp_ultod, f64, i64, i32, env)
+DEF_HELPER_2(vfp_uitos, f32, i32, ptr)
+DEF_HELPER_2(vfp_uitod, f64, i32, ptr)
+DEF_HELPER_2(vfp_sitos, f32, i32, ptr)
+DEF_HELPER_2(vfp_sitod, f64, i32, ptr)
+
+DEF_HELPER_2(vfp_touis, i32, f32, ptr)
+DEF_HELPER_2(vfp_touid, i32, f64, ptr)
+DEF_HELPER_2(vfp_touizs, i32, f32, ptr)
+DEF_HELPER_2(vfp_touizd, i32, f64, ptr)
+DEF_HELPER_2(vfp_tosis, i32, f32, ptr)
+DEF_HELPER_2(vfp_tosid, i32, f64, ptr)
+DEF_HELPER_2(vfp_tosizs, i32, f32, ptr)
+DEF_HELPER_2(vfp_tosizd, i32, f64, ptr)
+
+DEF_HELPER_3(vfp_toshs, i32, f32, i32, ptr)
+DEF_HELPER_3(vfp_tosls, i32, f32, i32, ptr)
+DEF_HELPER_3(vfp_touhs, i32, f32, i32, ptr)
+DEF_HELPER_3(vfp_touls, i32, f32, i32, ptr)
+DEF_HELPER_3(vfp_toshd, i64, f64, i32, ptr)
+DEF_HELPER_3(vfp_tosld, i64, f64, i32, ptr)
+DEF_HELPER_3(vfp_touhd, i64, f64, i32, ptr)
+DEF_HELPER_3(vfp_tould, i64, f64, i32, ptr)
+DEF_HELPER_3(vfp_shtos, f32, i32, i32, ptr)
+DEF_HELPER_3(vfp_sltos, f32, i32, i32, ptr)
+DEF_HELPER_3(vfp_uhtos, f32, i32, i32, ptr)
+DEF_HELPER_3(vfp_ultos, f32, i32, i32, ptr)
+DEF_HELPER_3(vfp_shtod, f64, i64, i32, ptr)
+DEF_HELPER_3(vfp_sltod, f64, i64, i32, ptr)
+DEF_HELPER_3(vfp_uhtod, f64, i64, i32, ptr)
+DEF_HELPER_3(vfp_ultod, f64, i64, i32, ptr)
DEF_HELPER_2(vfp_fcvt_f16_to_f32, f32, i32, env)
DEF_HELPER_2(vfp_fcvt_f32_to_f16, i32, f32, env)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index a8a3b2cd64..1501db1b1f 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -977,63 +977,73 @@ static inline void gen_vfp_F1_ld0(int dp)
tcg_gen_movi_i32(cpu_F1s, 0);
}
-static inline void gen_vfp_uito(int dp)
-{
- if (dp)
- gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
- else
- gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
-}
-
-static inline void gen_vfp_sito(int dp)
-{
- if (dp)
- gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
- else
- gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
-}
-
-static inline void gen_vfp_toui(int dp)
-{
- if (dp)
- gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
- else
- gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
+#define VFP_GEN_ITOF(name) \
+static inline void gen_vfp_##name(int dp, int neon) \
+{ \
+ TCGv statusptr = tcg_temp_new_i32(); \
+ int offset; \
+ if (neon) { \
+ offset = offsetof(CPUState, vfp.standard_fp_status); \
+ } else { \
+ offset = offsetof(CPUState, vfp.fp_status); \
+ } \
+ tcg_gen_addi_i32(statusptr, cpu_env, offset); \
+ if (dp) { \
+ gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
+ } else { \
+ gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
+ } \
+ tcg_temp_free_i32(statusptr); \
}
-static inline void gen_vfp_touiz(int dp)
-{
- if (dp)
- gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
- else
- gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
-}
+VFP_GEN_ITOF(uito)
+VFP_GEN_ITOF(sito)
+#undef VFP_GEN_ITOF
-static inline void gen_vfp_tosi(int dp)
-{
- if (dp)
- gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
- else
- gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
+#define VFP_GEN_FTOI(name) \
+static inline void gen_vfp_##name(int dp, int neon) \
+{ \
+ TCGv statusptr = tcg_temp_new_i32(); \
+ int offset; \
+ if (neon) { \
+ offset = offsetof(CPUState, vfp.standard_fp_status); \
+ } else { \
+ offset = offsetof(CPUState, vfp.fp_status); \
+ } \
+ tcg_gen_addi_i32(statusptr, cpu_env, offset); \
+ if (dp) { \
+ gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
+ } else { \
+ gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
+ } \
+ tcg_temp_free_i32(statusptr); \
}
-static inline void gen_vfp_tosiz(int dp)
-{
- if (dp)
- gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
- else
- gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
-}
+VFP_GEN_FTOI(toui)
+VFP_GEN_FTOI(touiz)
+VFP_GEN_FTOI(tosi)
+VFP_GEN_FTOI(tosiz)
+#undef VFP_GEN_FTOI
#define VFP_GEN_FIX(name) \
-static inline void gen_vfp_##name(int dp, int shift) \
+static inline void gen_vfp_##name(int dp, int shift, int neon) \
{ \
TCGv tmp_shift = tcg_const_i32(shift); \
- if (dp) \
- gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
- else \
- gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
+ TCGv statusptr = tcg_temp_new_i32(); \
+ int offset; \
+ if (neon) { \
+ offset = offsetof(CPUState, vfp.standard_fp_status); \
+ } else { \
+ offset = offsetof(CPUState, vfp.fp_status); \
+ } \
+ tcg_gen_addi_i32(statusptr, cpu_env, offset); \
+ if (dp) { \
+ gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \
+ } else { \
+ gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \
+ } \
tcg_temp_free_i32(tmp_shift); \
+ tcg_temp_free_i32(statusptr); \
}
VFP_GEN_FIX(tosh)
VFP_GEN_FIX(tosl)
@@ -3183,62 +3193,62 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
break;
case 16: /* fuito */
- gen_vfp_uito(dp);
+ gen_vfp_uito(dp, 0);
break;
case 17: /* fsito */
- gen_vfp_sito(dp);
+ gen_vfp_sito(dp, 0);
break;
case 20: /* fshto */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
- gen_vfp_shto(dp, 16 - rm);
+ gen_vfp_shto(dp, 16 - rm, 0);
break;
case 21: /* fslto */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
- gen_vfp_slto(dp, 32 - rm);
+ gen_vfp_slto(dp, 32 - rm, 0);
break;
case 22: /* fuhto */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
- gen_vfp_uhto(dp, 16 - rm);
+ gen_vfp_uhto(dp, 16 - rm, 0);
break;
case 23: /* fulto */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
- gen_vfp_ulto(dp, 32 - rm);
+ gen_vfp_ulto(dp, 32 - rm, 0);
break;
case 24: /* ftoui */
- gen_vfp_toui(dp);
+ gen_vfp_toui(dp, 0);
break;
case 25: /* ftouiz */
- gen_vfp_touiz(dp);
+ gen_vfp_touiz(dp, 0);
break;
case 26: /* ftosi */
- gen_vfp_tosi(dp);
+ gen_vfp_tosi(dp, 0);
break;
case 27: /* ftosiz */
- gen_vfp_tosiz(dp);
+ gen_vfp_tosiz(dp, 0);
break;
case 28: /* ftosh */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
- gen_vfp_tosh(dp, 16 - rm);
+ gen_vfp_tosh(dp, 16 - rm, 0);
break;
case 29: /* ftosl */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
- gen_vfp_tosl(dp, 32 - rm);
+ gen_vfp_tosl(dp, 32 - rm, 0);
break;
case 30: /* ftouh */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
- gen_vfp_touh(dp, 16 - rm);
+ gen_vfp_touh(dp, 16 - rm, 0);
break;
case 31: /* ftoul */
if (!arm_feature(env, ARM_FEATURE_VFP3))
return 1;
- gen_vfp_toul(dp, 32 - rm);
+ gen_vfp_toul(dp, 32 - rm, 0);
break;
default: /* undefined */
printf ("rn:%d\n", rn);
@@ -5251,14 +5261,14 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
if (!(op & 1)) {
if (u)
- gen_vfp_ulto(0, shift);
+ gen_vfp_ulto(0, shift, 1);
else
- gen_vfp_slto(0, shift);
+ gen_vfp_slto(0, shift, 1);
} else {
if (u)
- gen_vfp_toul(0, shift);
+ gen_vfp_toul(0, shift, 1);
else
- gen_vfp_tosl(0, shift);
+ gen_vfp_tosl(0, shift, 1);
}
tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
}
@@ -6071,16 +6081,16 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
break;
case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
- gen_vfp_sito(0);
+ gen_vfp_sito(0, 1);
break;
case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
- gen_vfp_uito(0);
+ gen_vfp_uito(0, 1);
break;
case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
- gen_vfp_tosiz(0);
+ gen_vfp_tosiz(0, 1);
break;
case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
- gen_vfp_touiz(0);
+ gen_vfp_touiz(0, 1);
break;
default:
/* Reserved op values were caught by the