@@ -1687,15 +1687,19 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
16871687uint32_t vfp_get_fpscr (CPUARMState * env );
16881688void vfp_set_fpscr (CPUARMState * env , uint32_t val );
16891689
1690- /* FPCR, Floating Point Control Register
1691- * FPSR, Floating Poiht Status Register
1690+ /*
1691+ * FPCR, Floating Point Control Register
1692+ * FPSR, Floating Point Status Register
16921693 *
1693- * For A64 the FPSCR is split into two logically distinct registers,
1694- * FPCR and FPSR. However since they still use non-overlapping bits
1695- * we store the underlying state in fpscr and just mask on read/write.
1694+ * For A64 floating point control and status bits are stored in
1695+ * two logically distinct registers, FPCR and FPSR. We store these
1696+ * in QEMU in vfp.fpcr and vfp.fpsr.
1697+ * For A32 there was only one register, FPSCR. The bits are arranged
1698+ * such that FPSCR bits map to FPCR or FPSR bits in the same bit positions,
1699+ * so we can use appropriate masking to handle FPSCR reads and writes.
1700+ * Note that the FPCR has some bits which are not visible in the
1701+ * AArch32 view (for FEAT_AFP). Writing the FPSCR leaves these unchanged.
16961702 */
1697- #define FPSR_MASK 0xf800009f
1698- #define FPCR_MASK 0x07ff9f00
16991703
17001704/* FPCR bits */
17011705#define FPCR_IOE (1 << 8) /* Invalid Operation exception trap enable */
@@ -1704,7 +1708,9 @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
17041708#define FPCR_UFE (1 << 11) /* Underflow exception trap enable */
17051709#define FPCR_IXE (1 << 12) /* Inexact exception trap enable */
17061710#define FPCR_IDE (1 << 15) /* Input Denormal exception trap enable */
1711+ #define FPCR_LEN_MASK (7 << 16) /* LEN, A-profile only */
17071712#define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */
1713+ #define FPCR_STRIDE_MASK (3 << 20) /* Stride */
17081714#define FPCR_RMODE_MASK (3 << 22) /* Rounding mode */
17091715#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
17101716#define FPCR_DN (1 << 25) /* Default NaN enable bit */
@@ -1714,16 +1720,37 @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
17141720#define FPCR_LTPSIZE_MASK (7 << FPCR_LTPSIZE_SHIFT)
17151721#define FPCR_LTPSIZE_LENGTH 3
17161722
1723+ /* Cumulative exception trap enable bits */
1724+ #define FPCR_EEXC_MASK (FPCR_IOE | FPCR_DZE | FPCR_OFE | FPCR_UFE | FPCR_IXE | FPCR_IDE)
1725+
17171726/* FPSR bits */
1727+ #define FPSR_IOC (1 << 0) /* Invalid Operation cumulative exception */
1728+ #define FPSR_DZC (1 << 1) /* Divide by Zero cumulative exception */
1729+ #define FPSR_OFC (1 << 2) /* Overflow cumulative exception */
1730+ #define FPSR_UFC (1 << 3) /* Underflow cumulative exception */
1731+ #define FPSR_IXC (1 << 4) /* Inexact cumulative exception */
1732+ #define FPSR_IDC (1 << 7) /* Input Denormal cumulative exception */
17181733#define FPSR_QC (1 << 27) /* Cumulative saturation bit */
17191734#define FPSR_V (1 << 28) /* FP overflow flag */
17201735#define FPSR_C (1 << 29) /* FP carry flag */
17211736#define FPSR_Z (1 << 30) /* FP zero flag */
17221737#define FPSR_N (1 << 31) /* FP negative flag */
17231738
1739+ /* Cumulative exception status bits */
1740+ #define FPSR_CEXC_MASK (FPSR_IOC | FPSR_DZC | FPSR_OFC | FPSR_UFC | FPSR_IXC | FPSR_IDC)
1741+
17241742#define FPSR_NZCV_MASK (FPSR_N | FPSR_Z | FPSR_C | FPSR_V)
17251743#define FPSR_NZCVQC_MASK (FPSR_NZCV_MASK | FPSR_QC)
17261744
1745+ /* A32 FPSCR bits which architecturally map to FPSR bits */
1746+ #define FPSCR_FPSR_MASK (FPSR_NZCVQC_MASK | FPSR_CEXC_MASK)
1747+ /* A32 FPSCR bits which architecturally map to FPCR bits */
1748+ #define FPSCR_FPCR_MASK (FPCR_EEXC_MASK | FPCR_LEN_MASK | FPCR_FZ16 | \
1749+ FPCR_STRIDE_MASK | FPCR_RMODE_MASK | \
1750+ FPCR_FZ | FPCR_DN | FPCR_AHP)
1751+ /* These masks don't overlap: each bit lives in only one place */
1752+ QEMU_BUILD_BUG_ON (FPSCR_FPSR_MASK & FPSCR_FPCR_MASK );
1753+
17271754/**
17281755 * vfp_get_fpsr: read the AArch64 FPSR
17291756 * @env: CPU context
0 commit comments