@@ -123,6 +123,28 @@ typedef struct {
uint32_t base_mask;
} TCR;
+/* Holds the state needed to create an instruction syndrome. */
+typedef struct ARMInsnSyndrome {
+ /* Data Abort section. */
+ struct {
+ bool valid;
+ unsigned int sas;
+ bool sse;
+ unsigned int srt;
+ bool sf;
+ bool ar;
+ } dabt;
+
+ /* SWStep section. */
+ struct {
+ /* True if the insn just emitted was a load-exclusive instruction
+ * (necessary for syndrome information for single step exceptions),
+ * ie A64 LDX*, LDAX*, A32/T32 LDREX*, LDAEX*.
+ */
+ bool ex;
+ } swstep;
+} ARMInsnSyndrome;
+
typedef struct CPUARMState {
/* Regs for current mode. */
uint32_t regs[16];
@@ -151,4 +151,61 @@ void arm_free_cc(DisasCompare *cmp);
void arm_jump_cc(DisasCompare *cmp, TCGLabel *label);
void arm_gen_test_cc(int cc, TCGLabel *label);
+
+/* The following describes the packing and unpacking of the Data Abort
+ * section of an ARMInsnSyndrome from/into an u32.
+ */
+
+/* Field widths. */
+#define ISYN_WIDTH_valid 1
+#define ISYN_WIDTH_sas 2
+#define ISYN_WIDTH_sse 1
+#define ISYN_WIDTH_srt 5
+#define ISYN_WIDTH_sf 1
+#define ISYN_WIDTH_ar 1
+
+/* We use 64bit deposit to allow for overflow checking. */
+#define ISYN_SHIFT_IN(val, isyn, field) \
+ { \
+ unsigned int width = xglue(ISYN_WIDTH_, field); \
+ val <<= width; \
+ val = deposit64(val, 0, width, (isyn).field); \
+ } while (0)
+
+#define ISYN_SHIFT_OUT(val, isyn, field) \
+ { \
+ unsigned int width = xglue(ISYN_WIDTH_, field); \
+ (isyn).field = extract32(val, 0, width); \
+ val >>= width; \
+ } while (0)
+
+static inline uint32_t arm_encode_dabt_isyn_u32(ARMInsnSyndrome *isyn)
+{
+ uint64_t v = 0;
+ uint32_t v32;
+
+ ISYN_SHIFT_IN(v, isyn->dabt, valid);
+ ISYN_SHIFT_IN(v, isyn->dabt, sas);
+ ISYN_SHIFT_IN(v, isyn->dabt, sse);
+ ISYN_SHIFT_IN(v, isyn->dabt, srt);
+ ISYN_SHIFT_IN(v, isyn->dabt, sf);
+ ISYN_SHIFT_IN(v, isyn->dabt, ar);
+ /* Check for overflows. */
+ v32 = v;
+ assert(v32 == v);
+ return v32;
+}
+
+static inline void arm_decode_dabt_isyn_u32(ARMInsnSyndrome *isyn, uint32_t v)
+{
+ /* The fields must be shifted out in reverse order. */
+ ISYN_SHIFT_OUT(v, isyn->dabt, ar);
+ ISYN_SHIFT_OUT(v, isyn->dabt, sf);
+ ISYN_SHIFT_OUT(v, isyn->dabt, srt);
+ ISYN_SHIFT_OUT(v, isyn->dabt, sse);
+ ISYN_SHIFT_OUT(v, isyn->dabt, sas);
+ ISYN_SHIFT_OUT(v, isyn->dabt, valid);
+ assert(v == 0);
+}
+
#endif /* TARGET_ARM_TRANSLATE_H */