@@ -202,6 +202,61 @@ typedef struct ARMMMUFaultInfo ARMMMUFaultInfo;
typedef struct NVICState NVICState;
+/*
+ * Enum for indexing vfp.fp_status[].
+ *
+ * FPST_A32: is the "normal" fp status for AArch32 insns
+ * FPST_A64: is the "normal" fp status for AArch64 insns
+ * FPST_A32_F16: used for AArch32 half-precision calculations
+ * FPST_A64_F16: used for AArch64 half-precision calculations
+ * FPST_STD: the ARM "Standard FPSCR Value"
+ * FPST_STD_F16: used for half-precision
+ * calculations with the ARM "Standard FPSCR Value"
+ * FPST_AH: used for the A64 insns which change behaviour
+ * when FPCR.AH == 1 (bfloat16 conversions and multiplies,
+ * and the reciprocal and square root estimate/step insns)
+ * FPST_AH_F16: used for the A64 insns which change behaviour
+ * when FPCR.AH == 1 (bfloat16 conversions and multiplies,
+ * and the reciprocal and square root estimate/step insns);
+ * for half-precision
+ *
+ * Half-precision operations are governed by a separate
+ * flush-to-zero control bit in FPSCR:FZ16. We pass a separate
+ * status structure to control this.
+ *
+ * The "Standard FPSCR", ie default-NaN, flush-to-zero,
+ * round-to-nearest and is used by any operations (generally
+ * Neon) which the architecture defines as controlled by the
+ * standard FPSCR value rather than the FPSCR.
+ *
+ * The "standard FPSCR but for fp16 ops" is needed because
+ * the "standard FPSCR" tracks the FPSCR.FZ16 bit rather than
+ * using a fixed value for it.
+ *
+ * The ah_fp_status is needed because some insns have different
+ * behaviour when FPCR.AH == 1: they don't update cumulative
+ * exception flags, they act like FPCR.{FZ,FIZ} = {1,1} and
+ * they ignore FPCR.RMode. But they don't ignore FPCR.FZ16,
+ * which means we need an ah_fp_status_f16 as well.
+ *
+ * To avoid having to transfer exception bits around, we simply
+ * say that the FPSCR cumulative exception flags are the logical
+ * OR of the flags in the four fp statuses. This relies on the
+ * only thing which needs to read the exception flags being
+ * an explicit FPSCR read.
+ */
+typedef enum ARMFPStatusFlavour {
+ FPST_A32,
+ FPST_A64,
+ FPST_A32_F16,
+ FPST_A64_F16,
+ FPST_AH,
+ FPST_AH_F16,
+ FPST_STD,
+ FPST_STD_F16,
+} ARMFPStatusFlavour;
+#define FPST_COUNT 8
+
typedef struct CPUArchState {
/* Regs for current mode. */
uint32_t regs[16];
@@ -631,56 +686,20 @@ typedef struct CPUArchState {
/* Scratch space for aa32 neon expansion. */
uint32_t scratch[8];
- /* There are a number of distinct float control structures:
- *
- * fp_status_a32: is the "normal" fp status for AArch32 insns
- * fp_status_a64: is the "normal" fp status for AArch64 insns
- * fp_status_fp16_a32: used for AArch32 half-precision calculations
- * fp_status_fp16_a64: used for AArch64 half-precision calculations
- * standard_fp_status : the ARM "Standard FPSCR Value"
- * standard_fp_status_fp16 : used for half-precision
- * calculations with the ARM "Standard FPSCR Value"
- * ah_fp_status: used for the A64 insns which change behaviour
- * when FPCR.AH == 1 (bfloat16 conversions and multiplies,
- * and the reciprocal and square root estimate/step insns)
- * ah_fp_status_f16: used for the A64 insns which change behaviour
- * when FPCR.AH == 1 (bfloat16 conversions and multiplies,
- * and the reciprocal and square root estimate/step insns);
- * for half-precision
- *
- * Half-precision operations are governed by a separate
- * flush-to-zero control bit in FPSCR:FZ16. We pass a separate
- * status structure to control this.
- *
- * The "Standard FPSCR", ie default-NaN, flush-to-zero,
- * round-to-nearest and is used by any operations (generally
- * Neon) which the architecture defines as controlled by the
- * standard FPSCR value rather than the FPSCR.
- *
- * The "standard FPSCR but for fp16 ops" is needed because
- * the "standard FPSCR" tracks the FPSCR.FZ16 bit rather than
- * using a fixed value for it.
- *
- * The ah_fp_status is needed because some insns have different
- * behaviour when FPCR.AH == 1: they don't update cumulative
- * exception flags, they act like FPCR.{FZ,FIZ} = {1,1} and
- * they ignore FPCR.RMode. But they don't ignore FPCR.FZ16,
- * which means we need an ah_fp_status_f16 as well.
- *
- * To avoid having to transfer exception bits around, we simply
- * say that the FPSCR cumulative exception flags are the logical
- * OR of the flags in the four fp statuses. This relies on the
- * only thing which needs to read the exception flags being
- * an explicit FPSCR read.
- */
- float_status fp_status_a32;
- float_status fp_status_a64;
- float_status fp_status_f16_a32;
- float_status fp_status_f16_a64;
- float_status standard_fp_status;
- float_status standard_fp_status_f16;
- float_status ah_fp_status;
- float_status ah_fp_status_f16;
+ /* There are a number of distinct float control structures. */
+ union {
+ float_status fp_status[FPST_COUNT];
+ struct {
+ float_status fp_status_a32;
+ float_status fp_status_a64;
+ float_status fp_status_f16_a32;
+ float_status fp_status_f16_a64;
+ float_status ah_fp_status;
+ float_status ah_fp_status_f16;
+ float_status standard_fp_status;
+ float_status standard_fp_status_f16;
+ };
+ };
uint64_t zcr_el[4]; /* ZCR_EL[1-3] */
uint64_t smcr_el[4]; /* SMCR_EL[1-3] */
@@ -670,80 +670,18 @@ static inline CPUARMTBFlags arm_tbflags_from_tb(const TranslationBlock *tb)
return (CPUARMTBFlags){ tb->flags, tb->cs_base };
}
-/*
- * Enum for argument to fpstatus_ptr().
- */
-typedef enum ARMFPStatusFlavour {
- FPST_A32,
- FPST_A64,
- FPST_A32_F16,
- FPST_A64_F16,
- FPST_AH,
- FPST_AH_F16,
- FPST_STD,
- FPST_STD_F16,
-} ARMFPStatusFlavour;
-
/**
* fpstatus_ptr: return TCGv_ptr to the specified fp_status field
*
* We have multiple softfloat float_status fields in the Arm CPU state struct
* (see the comment in cpu.h for details). Return a TCGv_ptr which has
* been set up to point to the requested field in the CPU state struct.
- * The options are:
- *
- * FPST_A32
- * for AArch32 non-FP16 operations controlled by the FPCR
- * FPST_A64
- * for AArch64 non-FP16 operations controlled by the FPCR
- * FPST_A32_F16
- * for AArch32 operations controlled by the FPCR where FPCR.FZ16 is to be used
- * FPST_A64_F16
- * for AArch64 operations controlled by the FPCR where FPCR.FZ16 is to be used
- * FPST_AH:
- * for AArch64 operations which change behaviour when AH=1 (specifically,
- * bfloat16 conversions and multiplies, and the reciprocal and square root
- * estimate/step insns)
- * FPST_AH_F16:
- * ditto, but for half-precision operations
- * FPST_STD
- * for A32/T32 Neon operations using the "standard FPSCR value"
- * FPST_STD_F16
- * as FPST_STD, but where FPCR.FZ16 is to be used
*/
static inline TCGv_ptr fpstatus_ptr(ARMFPStatusFlavour flavour)
{
TCGv_ptr statusptr = tcg_temp_new_ptr();
- int offset;
+ int offset = offsetof(CPUARMState, vfp.fp_status[flavour]);
- switch (flavour) {
- case FPST_A32:
- offset = offsetof(CPUARMState, vfp.fp_status_a32);
- break;
- case FPST_A64:
- offset = offsetof(CPUARMState, vfp.fp_status_a64);
- break;
- case FPST_A32_F16:
- offset = offsetof(CPUARMState, vfp.fp_status_f16_a32);
- break;
- case FPST_A64_F16:
- offset = offsetof(CPUARMState, vfp.fp_status_f16_a64);
- break;
- case FPST_AH:
- offset = offsetof(CPUARMState, vfp.ah_fp_status);
- break;
- case FPST_AH_F16:
- offset = offsetof(CPUARMState, vfp.ah_fp_status_f16);
- break;
- case FPST_STD:
- offset = offsetof(CPUARMState, vfp.standard_fp_status);
- break;
- case FPST_STD_F16:
- offset = offsetof(CPUARMState, vfp.standard_fp_status_f16);
- break;
- default:
- g_assert_not_reached();
- }
tcg_gen_addi_ptr(statusptr, tcg_env, offset);
return statusptr;
}