@@ -1833,5 +1833,14 @@ int alle1_tlbmask(CPUARMState *env);
void arm_set_default_fp_behaviours(float_status *s);
/* Set the float_status behaviour to match Arm FPCR.AH=1 behaviour */
void arm_set_ah_fp_behaviours(float_status *s);
+/* Read the float_status info and return the appropriate FPSR value */
+uint32_t vfp_get_fpsr_from_host(CPUARMState *env);
+/* Clear the exception status flags from all float_status fields */
+void vfp_clear_float_status_exc_flags(CPUARMState *env);
+/*
+ * Update float_status fields to handle the bits of the FPCR
+ * specified by mask changing to the values in val.
+ */
+void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask);
#endif
@@ -30,3 +30,25 @@ void assert_hflags_rebuild_correctly(CPUARMState *env)
void define_tlb_insn_regs(ARMCPU *cpu)
{
}
+
+/* With KVM, we never use float_status, so these can be no-ops */
+void arm_set_default_fp_behaviours(float_status *s)
+{
+}
+
+void arm_set_ah_fp_behaviours(float_status *s)
+{
+}
+
+uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
+{
+ return 0;
+}
+
+void vfp_clear_float_status_exc_flags(CPUARMState *env)
+{
+}
+
+void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
+{
+}
@@ -25,6 +25,234 @@
#include "fpu/softfloat.h"
#include "qemu/log.h"
+/*
+ * Set the float_status behaviour to match the Arm defaults:
+ * * tininess-before-rounding
+ * * 2-input NaN propagation prefers SNaN over QNaN, and then
+ * operand A over operand B (see FPProcessNaNs() pseudocode)
+ * * 3-input NaN propagation prefers SNaN over QNaN, and then
+ * operand C over A over B (see FPProcessNaNs3() pseudocode,
+ * but note that for QEMU muladd is a * b + c, whereas for
+ * the pseudocode function the arguments are in the order c, a, b.
+ * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
+ * and the input NaN if it is signalling
+ * * Default NaN has sign bit clear, msb frac bit set
+ */
+void arm_set_default_fp_behaviours(float_status *s)
+{
+ set_float_detect_tininess(float_tininess_before_rounding, s);
+ set_float_ftz_detection(float_ftz_before_rounding, s);
+ set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
+ set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
+ set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
+ set_float_default_nan_pattern(0b01000000, s);
+}
+
+/*
+ * Set the float_status behaviour to match the FEAT_AFP
+ * FPCR.AH=1 requirements:
+ * * tininess-after-rounding
+ * * 2-input NaN propagation prefers the first NaN
+ * * 3-input NaN propagation prefers a over b over c
+ * * 0 * Inf + NaN always returns the input NaN and doesn't
+ * set Invalid for a QNaN
+ * * default NaN has sign bit set, msb frac bit set
+ */
+void arm_set_ah_fp_behaviours(float_status *s)
+{
+ set_float_detect_tininess(float_tininess_after_rounding, s);
+ set_float_ftz_detection(float_ftz_after_rounding, s);
+ set_float_2nan_prop_rule(float_2nan_prop_ab, s);
+ set_float_3nan_prop_rule(float_3nan_prop_abc, s);
+ set_float_infzeronan_rule(float_infzeronan_dnan_never |
+ float_infzeronan_suppress_invalid, s);
+ set_float_default_nan_pattern(0b11000000, s);
+}
+
+/* Convert host exception flags to vfp form. */
+static inline uint32_t vfp_exceptbits_from_host(int host_bits, bool ah)
+{
+ uint32_t target_bits = 0;
+
+ if (host_bits & float_flag_invalid) {
+ target_bits |= FPSR_IOC;
+ }
+ if (host_bits & float_flag_divbyzero) {
+ target_bits |= FPSR_DZC;
+ }
+ if (host_bits & float_flag_overflow) {
+ target_bits |= FPSR_OFC;
+ }
+ if (host_bits & (float_flag_underflow | float_flag_output_denormal_flushed)) {
+ target_bits |= FPSR_UFC;
+ }
+ if (host_bits & float_flag_inexact) {
+ target_bits |= FPSR_IXC;
+ }
+ if (host_bits & float_flag_input_denormal_flushed) {
+ target_bits |= FPSR_IDC;
+ }
+ /*
+ * With FPCR.AH, IDC is set when an input denormal is used,
+ * and flushing an output denormal to zero sets both IXC and UFC.
+ */
+ if (ah && (host_bits & float_flag_input_denormal_used)) {
+ target_bits |= FPSR_IDC;
+ }
+ if (ah && (host_bits & float_flag_output_denormal_flushed)) {
+ target_bits |= FPSR_IXC;
+ }
+ return target_bits;
+}
+
+uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
+{
+ uint32_t a32_flags = 0, a64_flags = 0;
+
+ a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A32]);
+ a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_STD]);
+ /* FZ16 does not generate an input denormal exception. */
+ a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A32_F16])
+ & ~float_flag_input_denormal_flushed);
+ a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_STD_F16])
+ & ~float_flag_input_denormal_flushed);
+
+ a64_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A64]);
+ a64_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A64_F16])
+ & ~(float_flag_input_denormal_flushed | float_flag_input_denormal_used));
+ /*
+ * We do not merge in flags from FPST_AH or FPST_AH_F16, because
+ * they are used for insns that must not set the cumulative exception bits.
+ */
+
+ /*
+ * Flushing an input denormal *only* because FPCR.FIZ == 1 does
+ * not set FPSR.IDC; if FPCR.FZ is also set then this takes
+ * precedence and IDC is set (see the FPUnpackBase pseudocode).
+ * So squash it unless (FPCR.AH == 0 && FPCR.FZ == 1).
+ * We only do this for the a64 flags because FIZ has no effect
+ * on AArch32 even if it is set.
+ */
+ if ((env->vfp.fpcr & (FPCR_FZ | FPCR_AH)) != FPCR_FZ) {
+ a64_flags &= ~float_flag_input_denormal_flushed;
+ }
+ return vfp_exceptbits_from_host(a64_flags, env->vfp.fpcr & FPCR_AH) |
+ vfp_exceptbits_from_host(a32_flags, false);
+}
+
+void vfp_clear_float_status_exc_flags(CPUARMState *env)
+{
+ /*
+ * Clear out all the exception-flag information in the float_status
+ * values. The caller should have arranged for env->vfp.fpsr to
+ * be the architecturally up-to-date exception flag information first.
+ */
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32]);
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64]);
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32_F16]);
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64_F16]);
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD]);
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD_F16]);
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH]);
+ set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH_F16]);
+}
+
+static void vfp_sync_and_clear_float_status_exc_flags(CPUARMState *env)
+{
+ /*
+ * Synchronize any pending exception-flag information in the
+ * float_status values into env->vfp.fpsr, and then clear out
+ * the float_status data.
+ */
+ env->vfp.fpsr |= vfp_get_fpsr_from_host(env);
+ vfp_clear_float_status_exc_flags(env);
+}
+
+void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
+{
+ uint64_t changed = env->vfp.fpcr;
+
+ changed ^= val;
+ changed &= mask;
+ if (changed & (3 << 22)) {
+ int i = (val >> 22) & 3;
+ switch (i) {
+ case FPROUNDING_TIEEVEN:
+ i = float_round_nearest_even;
+ break;
+ case FPROUNDING_POSINF:
+ i = float_round_up;
+ break;
+ case FPROUNDING_NEGINF:
+ i = float_round_down;
+ break;
+ case FPROUNDING_ZERO:
+ i = float_round_to_zero;
+ break;
+ }
+ set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32]);
+ set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64]);
+ set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32_F16]);
+ set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64_F16]);
+ }
+ if (changed & FPCR_FZ16) {
+ bool ftz_enabled = val & FPCR_FZ16;
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
+ }
+ if (changed & FPCR_FZ) {
+ bool ftz_enabled = val & FPCR_FZ;
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
+ set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64]);
+ /* FIZ is A64 only so FZ always makes A32 code flush inputs to zero */
+ set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
+ }
+ if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
+ /*
+ * A64: Flush denormalized inputs to zero if FPCR.FIZ = 1, or
+ * both FPCR.AH = 0 and FPCR.FZ = 1.
+ */
+ bool fitz_enabled = (val & FPCR_FIZ) ||
+ (val & (FPCR_FZ | FPCR_AH)) == FPCR_FZ;
+ set_flush_inputs_to_zero(fitz_enabled, &env->vfp.fp_status[FPST_A64]);
+ }
+ if (changed & FPCR_DN) {
+ bool dnan_enabled = val & FPCR_DN;
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32]);
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64]);
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32_F16]);
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64_F16]);
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH]);
+ set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH_F16]);
+ }
+ if (changed & FPCR_AH) {
+ bool ah_enabled = val & FPCR_AH;
+
+ if (ah_enabled) {
+ /* Change behaviours for A64 FP operations */
+ arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
+ arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
+ } else {
+ arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
+ arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
+ }
+ }
+ /*
+ * If any bits changed that we look at in vfp_get_fpsr_from_host(),
+ * we must sync the float_status flags into vfp.fpsr now (under the
+ * old regime) before we update vfp.fpcr.
+ */
+ if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
+ vfp_sync_and_clear_float_status_exc_flags(env);
+ }
+}
+
/*
* VFP support. We follow the convention used for VFP instructions:
* Single precision routines have a "s" suffix, double precision a
@@ -21,254 +21,6 @@
#include "cpu.h"
#include "internals.h"
#include "cpu-features.h"
-#include "fpu/softfloat.h"
-
-/*
- * Set the float_status behaviour to match the Arm defaults:
- * * tininess-before-rounding
- * * 2-input NaN propagation prefers SNaN over QNaN, and then
- * operand A over operand B (see FPProcessNaNs() pseudocode)
- * * 3-input NaN propagation prefers SNaN over QNaN, and then
- * operand C over A over B (see FPProcessNaNs3() pseudocode,
- * but note that for QEMU muladd is a * b + c, whereas for
- * the pseudocode function the arguments are in the order c, a, b.
- * * 0 * Inf + NaN returns the default NaN if the input NaN is quiet,
- * and the input NaN if it is signalling
- * * Default NaN has sign bit clear, msb frac bit set
- */
-void arm_set_default_fp_behaviours(float_status *s)
-{
- set_float_detect_tininess(float_tininess_before_rounding, s);
- set_float_ftz_detection(float_ftz_before_rounding, s);
- set_float_2nan_prop_rule(float_2nan_prop_s_ab, s);
- set_float_3nan_prop_rule(float_3nan_prop_s_cab, s);
- set_float_infzeronan_rule(float_infzeronan_dnan_if_qnan, s);
- set_float_default_nan_pattern(0b01000000, s);
-}
-
-/*
- * Set the float_status behaviour to match the FEAT_AFP
- * FPCR.AH=1 requirements:
- * * tininess-after-rounding
- * * 2-input NaN propagation prefers the first NaN
- * * 3-input NaN propagation prefers a over b over c
- * * 0 * Inf + NaN always returns the input NaN and doesn't
- * set Invalid for a QNaN
- * * default NaN has sign bit set, msb frac bit set
- */
-void arm_set_ah_fp_behaviours(float_status *s)
-{
- set_float_detect_tininess(float_tininess_after_rounding, s);
- set_float_ftz_detection(float_ftz_after_rounding, s);
- set_float_2nan_prop_rule(float_2nan_prop_ab, s);
- set_float_3nan_prop_rule(float_3nan_prop_abc, s);
- set_float_infzeronan_rule(float_infzeronan_dnan_never |
- float_infzeronan_suppress_invalid, s);
- set_float_default_nan_pattern(0b11000000, s);
-}
-
-#ifdef CONFIG_TCG
-
-/* Convert host exception flags to vfp form. */
-static inline uint32_t vfp_exceptbits_from_host(int host_bits, bool ah)
-{
- uint32_t target_bits = 0;
-
- if (host_bits & float_flag_invalid) {
- target_bits |= FPSR_IOC;
- }
- if (host_bits & float_flag_divbyzero) {
- target_bits |= FPSR_DZC;
- }
- if (host_bits & float_flag_overflow) {
- target_bits |= FPSR_OFC;
- }
- if (host_bits & (float_flag_underflow | float_flag_output_denormal_flushed)) {
- target_bits |= FPSR_UFC;
- }
- if (host_bits & float_flag_inexact) {
- target_bits |= FPSR_IXC;
- }
- if (host_bits & float_flag_input_denormal_flushed) {
- target_bits |= FPSR_IDC;
- }
- /*
- * With FPCR.AH, IDC is set when an input denormal is used,
- * and flushing an output denormal to zero sets both IXC and UFC.
- */
- if (ah && (host_bits & float_flag_input_denormal_used)) {
- target_bits |= FPSR_IDC;
- }
- if (ah && (host_bits & float_flag_output_denormal_flushed)) {
- target_bits |= FPSR_IXC;
- }
- return target_bits;
-}
-
-static uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
-{
- uint32_t a32_flags = 0, a64_flags = 0;
-
- a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A32]);
- a32_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_STD]);
- /* FZ16 does not generate an input denormal exception. */
- a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A32_F16])
- & ~float_flag_input_denormal_flushed);
- a32_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_STD_F16])
- & ~float_flag_input_denormal_flushed);
-
- a64_flags |= get_float_exception_flags(&env->vfp.fp_status[FPST_A64]);
- a64_flags |= (get_float_exception_flags(&env->vfp.fp_status[FPST_A64_F16])
- & ~(float_flag_input_denormal_flushed | float_flag_input_denormal_used));
- /*
- * We do not merge in flags from FPST_AH or FPST_AH_F16, because
- * they are used for insns that must not set the cumulative exception bits.
- */
-
- /*
- * Flushing an input denormal *only* because FPCR.FIZ == 1 does
- * not set FPSR.IDC; if FPCR.FZ is also set then this takes
- * precedence and IDC is set (see the FPUnpackBase pseudocode).
- * So squash it unless (FPCR.AH == 0 && FPCR.FZ == 1).
- * We only do this for the a64 flags because FIZ has no effect
- * on AArch32 even if it is set.
- */
- if ((env->vfp.fpcr & (FPCR_FZ | FPCR_AH)) != FPCR_FZ) {
- a64_flags &= ~float_flag_input_denormal_flushed;
- }
- return vfp_exceptbits_from_host(a64_flags, env->vfp.fpcr & FPCR_AH) |
- vfp_exceptbits_from_host(a32_flags, false);
-}
-
-static void vfp_clear_float_status_exc_flags(CPUARMState *env)
-{
- /*
- * Clear out all the exception-flag information in the float_status
- * values. The caller should have arranged for env->vfp.fpsr to
- * be the architecturally up-to-date exception flag information first.
- */
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32]);
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64]);
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A32_F16]);
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_A64_F16]);
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD]);
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_STD_F16]);
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH]);
- set_float_exception_flags(0, &env->vfp.fp_status[FPST_AH_F16]);
-}
-
-static void vfp_sync_and_clear_float_status_exc_flags(CPUARMState *env)
-{
- /*
- * Synchronize any pending exception-flag information in the
- * float_status values into env->vfp.fpsr, and then clear out
- * the float_status data.
- */
- env->vfp.fpsr |= vfp_get_fpsr_from_host(env);
- vfp_clear_float_status_exc_flags(env);
-}
-
-static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
-{
- uint64_t changed = env->vfp.fpcr;
-
- changed ^= val;
- changed &= mask;
- if (changed & (3 << 22)) {
- int i = (val >> 22) & 3;
- switch (i) {
- case FPROUNDING_TIEEVEN:
- i = float_round_nearest_even;
- break;
- case FPROUNDING_POSINF:
- i = float_round_up;
- break;
- case FPROUNDING_NEGINF:
- i = float_round_down;
- break;
- case FPROUNDING_ZERO:
- i = float_round_to_zero;
- break;
- }
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32]);
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64]);
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A32_F16]);
- set_float_rounding_mode(i, &env->vfp.fp_status[FPST_A64_F16]);
- }
- if (changed & FPCR_FZ16) {
- bool ftz_enabled = val & FPCR_FZ16;
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32_F16]);
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64_F16]);
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_STD_F16]);
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_AH_F16]);
- }
- if (changed & FPCR_FZ) {
- bool ftz_enabled = val & FPCR_FZ;
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
- set_flush_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A64]);
- /* FIZ is A64 only so FZ always makes A32 code flush inputs to zero */
- set_flush_inputs_to_zero(ftz_enabled, &env->vfp.fp_status[FPST_A32]);
- }
- if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
- /*
- * A64: Flush denormalized inputs to zero if FPCR.FIZ = 1, or
- * both FPCR.AH = 0 and FPCR.FZ = 1.
- */
- bool fitz_enabled = (val & FPCR_FIZ) ||
- (val & (FPCR_FZ | FPCR_AH)) == FPCR_FZ;
- set_flush_inputs_to_zero(fitz_enabled, &env->vfp.fp_status[FPST_A64]);
- }
- if (changed & FPCR_DN) {
- bool dnan_enabled = val & FPCR_DN;
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32]);
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64]);
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A32_F16]);
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_A64_F16]);
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH]);
- set_default_nan_mode(dnan_enabled, &env->vfp.fp_status[FPST_AH_F16]);
- }
- if (changed & FPCR_AH) {
- bool ah_enabled = val & FPCR_AH;
-
- if (ah_enabled) {
- /* Change behaviours for A64 FP operations */
- arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
- arm_set_ah_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
- } else {
- arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64]);
- arm_set_default_fp_behaviours(&env->vfp.fp_status[FPST_A64_F16]);
- }
- }
- /*
- * If any bits changed that we look at in vfp_get_fpsr_from_host(),
- * we must sync the float_status flags into vfp.fpsr now (under the
- * old regime) before we update vfp.fpcr.
- */
- if (changed & (FPCR_FZ | FPCR_AH | FPCR_FIZ)) {
- vfp_sync_and_clear_float_status_exc_flags(env);
- }
-}
-
-#else
-
-static uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
-{
- return 0;
-}
-
-static void vfp_clear_float_status_exc_flags(CPUARMState *env)
-{
-}
-
-static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
-{
-}
-
-#endif
uint32_t vfp_get_fpcr(CPUARMState *env)
{
The softfloat (i.e. TCG) specific handling for the FPCR and FPSR is abstracted behind five functions: arm_set_default_fp_behaviours arm_set_ah_fp_behaviours vfp_get_fpsr_from_host vfp_clear_float_status_exc_flags vfp_set_fpsr_to_host Currently we rely on the first two calling softfloat functions that work even in a KVM-only compile because they're defined as inline in the softfloat header file, and we provide stub versions of the last three in arm/vfp_helper.c if CONFIG_TCG isn't defined. Move the softfloat-specific versions of these functions to tcg/vfp_helper.c, and provide the non-TCG stub versions in tcg-stubs.c. This lets us drop the softfloat header include and the last set of CONFIG_TCG ifdefs from arm/vfp_helper.c. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- target/arm/internals.h | 9 ++ target/arm/tcg-stubs.c | 22 ++++ target/arm/tcg/vfp_helper.c | 228 +++++++++++++++++++++++++++++++++ target/arm/vfp_helper.c | 248 ------------------------------------ 4 files changed, 259 insertions(+), 248 deletions(-)