From: "Edgar E. Iglesias" <edgar.igles...@xilinx.com> Add the ARMInsnSyndrome type including helper functions to encode and decode it into an u32. This is in preparation for Instruction Syndrome generation for Data Aborts.
No functional change. Signed-off-by: Edgar E. Iglesias <edgar.igles...@xilinx.com> --- target-arm/cpu.h | 22 +++++++++++++++++++ target-arm/translate.h | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 5137632..a00a121 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -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]; diff --git a/target-arm/translate.h b/target-arm/translate.h index 53ef971..a94e17e 100644 --- a/target-arm/translate.h +++ b/target-arm/translate.h @@ -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 */ -- 1.9.1