Include cpu-idregs.h.inc multiple times with different definitions for the
X-macros. This will generate tables for all Arm64 ID registers and their
fields. Additionally, initialize the tables with all architecturally defined
values. These tables will be consumed by the property layer in future
patches.

Co-authored-by: Khushit Shah <[email protected]>
Signed-off-by: Shaju Abraham <[email protected]>
---
 target/arm/cpu-idregs.c | 124 ++++++++++++++++++++++++++++++++++++++++
 target/arm/cpu-idregs.h |  81 ++++++++++++++++++++++++++
 target/arm/meson.build  |   1 +
 3 files changed, 206 insertions(+)
 create mode 100644 target/arm/cpu-idregs.c

diff --git a/target/arm/cpu-idregs.c b/target/arm/cpu-idregs.c
new file mode 100644
index 0000000000..8fced7d8d7
--- /dev/null
+++ b/target/arm/cpu-idregs.c
@@ -0,0 +1,124 @@
+/*
+ *   ARM ID register field table.
+ *
+ *   Builds the per-id-register field descriptor arrays and the global
+ *   arm_idregs[] table.
+ *
+ *  SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "cpu-idregs.h"
+
+/* generate an array of architecturely defined values for bitfields
+ * in arch-value format*/
+#define IDREG_START(reg)
+#define IDREG_END(reg)
+#define IDREG_FIELD_START(reg, field, shift, length, safe, defval) \
+    static const ArmIdRegArchVal reg##_##field##_arch_vals[] = {
+#define IDREG_FIELD_ARCH_VAL(v, n) { (v), (n) },
+#define IDREG_FIELD_ARCH_VAL_ANY   { 0xffffffffUL, NULL },
+#define IDREG_FIELD_END(reg, field) \
+    };
+#include "cpu-idregs.h.inc"
+#undef IDREG_START
+#undef IDREG_END
+#undef IDREG_FIELD_START
+#undef IDREG_FIELD_ARCH_VAL
+#undef IDREG_FIELD_ARCH_VAL_ANY
+#undef IDREG_FIELD_END
+/* generate an array of per-register ArmIdRegField[] descriptors */
+#define IDREG_FIELD_ARCH_VAL(v, n)
+#define IDREG_FIELD_ARCH_VAL_ANY
+#define IDREG_FIELD_END(reg, field)
+#define IDREG_START(reg) \
+    static ArmIdRegField reg##_fields[] = {
+
+#define IDREG_END(reg) \
+    };
+
+#define IDREG_FIELD_START(reg, field, _shift, _length, safe, defval) \
+    { \
+        .name = #field, \
+        .shift = (_shift), \
+        .length = (_length), \
+        .safe_rule = IDREG_SAFE_##safe, \
+        .default_val = (defval), \
+        .arch_vals = (ArmIdRegArchVal *)reg##_##field##_arch_vals, \
+        .arch_vals_count = ARRAY_SIZE(reg##_##field##_arch_vals), \
+    },
+#include "cpu-idregs.h.inc"
+#undef IDREG_START
+#undef IDREG_END
+#undef IDREG_FIELD_START
+#undef IDREG_FIELD_ARCH_VAL
+#undef IDREG_FIELD_END
+
+/* generate an array of top level ID registers */
+#define IDREG_END(reg)
+#define IDREG_FIELD_START(reg, field, shift, length, safe, defval)
+#define IDREG_FIELD_ARCH_VAL(v, n)
+#define IDREG_FIELD_ARCH_VAL_ANY
+#define IDREG_FIELD_END(reg, field)
+
+#define IDREG_START(reg) \
+    [reg##_IDX] = { \
+        .name = #reg, \
+        .fields = reg##_fields, \
+        .fields_count = ARRAY_SIZE(reg##_fields), \
+    },
+
+ArmIdReg arm_idregs[NUM_ID_IDX] = {
+#include "cpu-idregs.h.inc"
+};
+#undef IDREG_START
+#undef IDREG_END
+#undef IDREG_FIELD_START
+#undef IDREG_FIELD_ARCH_VAL
+#undef IDREG_FIELD_END
+
+
+/* Per-register field position enums (0..N-1 inside each register). */
+#define IDREG_START(reg) enum {
+#define IDREG_END(reg)   reg##_FIELD_POS__MAX };
+#define IDREG_FIELD_START(reg, field, shift, length, safe, defval) \
+    reg##_FIELD_POS_##field,
+#define IDREG_FIELD_ARCH_VAL(v, n)
+#define IDREG_FIELD_ARCH_VAL_ANY
+#define IDREG_FIELD_END(reg, field)
+
+#include "cpu-idregs.h.inc"
+
+#undef IDREG_FIELD_END
+#undef IDREG_FIELD_ARCH_VAL_ANY
+#undef IDREG_FIELD_ARCH_VAL
+#undef IDREG_FIELD_START
+#undef IDREG_END
+#undef IDREG_START
+
+/* Flat ArmFieldIdx -> {reg, field slot, shift, length}. */
+#define IDREG_START(reg)
+#define IDREG_END(reg)
+#define IDREG_FIELD_START(reg, field, _shift, _length, safe, defval) \
+    [ARM_FIELD_##reg##_##field] = {                                \
+        .reg_idx = reg##_IDX,                                  \
+        .field_idx = reg##_FIELD_POS_##field,                      \
+        .shift = (_shift),                                          \
+        .length = (_length),                                        \
+    },
+#define IDREG_FIELD_ARCH_VAL(v, n)
+#define IDREG_FIELD_ARCH_VAL_ANY
+#define IDREG_FIELD_END(reg, field)
+
+const ArmIdRegFieldLoc arm_field_locs[ARM_FIELD__MAX] = {
+#include "cpu-idregs.h.inc"
+};
+
+#undef IDREG_FIELD_END
+#undef IDREG_FIELD_ARCH_VAL_ANY
+#undef IDREG_FIELD_ARCH_VAL
+#undef IDREG_FIELD_START
+#undef IDREG_END
+#undef IDREG_START
diff --git a/target/arm/cpu-idregs.h b/target/arm/cpu-idregs.h
index 403190cbd7..4e568e877d 100644
--- a/target/arm/cpu-idregs.h
+++ b/target/arm/cpu-idregs.h
@@ -7,6 +7,8 @@
 #ifndef CPU_IDREGS_H
 #define CPU_IDREGS_H
 
+#include "cpu-sysregs.h"
+
 typedef enum ArmIdRegSafeRule {
     IDREG_SAFE_LOWER,
     IDREG_SAFE_HIGHER,
@@ -37,5 +39,84 @@ typedef struct ArmIdReg {
     uint32_t fields_count;
 } ArmIdReg;
 
+/* Map short register names to canonical _EL1/_EL0 IDX values */
+#define ID_AA64ISAR0_IDX  ID_AA64ISAR0_EL1_IDX
+#define ID_AA64ISAR1_IDX  ID_AA64ISAR1_EL1_IDX
+#define ID_AA64ISAR2_IDX  ID_AA64ISAR2_EL1_IDX
+#define ID_AA64ISAR3_IDX  ID_AA64ISAR3_EL1_IDX
+#define ID_AA64PFR0_IDX   ID_AA64PFR0_EL1_IDX
+#define ID_AA64PFR1_IDX   ID_AA64PFR1_EL1_IDX
+#define ID_AA64PFR2_IDX   ID_AA64PFR2_EL1_IDX
+#define ID_AA64MMFR0_IDX  ID_AA64MMFR0_EL1_IDX
+#define ID_AA64MMFR1_IDX  ID_AA64MMFR1_EL1_IDX
+#define ID_AA64MMFR2_IDX  ID_AA64MMFR2_EL1_IDX
+#define ID_AA64MMFR3_IDX  ID_AA64MMFR3_EL1_IDX
+#define ID_AA64MMFR4_IDX  ID_AA64MMFR4_EL1_IDX
+#define ID_AA64DFR0_IDX   ID_AA64DFR0_EL1_IDX
+#define ID_AA64DFR1_IDX   ID_AA64DFR1_EL1_IDX
+#define ID_AA64ZFR0_IDX   ID_AA64ZFR0_EL1_IDX
+#define ID_AA64SMFR0_IDX  ID_AA64SMFR0_EL1_IDX
+#define ID_AA64AFR0_IDX   ID_AA64AFR0_EL1_IDX
+#define ID_AA64AFR1_IDX   ID_AA64AFR1_EL1_IDX
+#define ID_AA64FPFR0_IDX  ID_AA64FPFR0_EL1_IDX
+#define ID_PFR0_IDX       ID_PFR0_EL1_IDX
+#define ID_PFR1_IDX       ID_PFR1_EL1_IDX
+#define ID_PFR2_IDX       ID_PFR2_EL1_IDX
+#define ID_DFR0_IDX       ID_DFR0_EL1_IDX
+#define ID_DFR1_IDX       ID_DFR1_EL1_IDX
+#define ID_AFR0_IDX       ID_AFR0_EL1_IDX
+#define ID_MMFR0_IDX      ID_MMFR0_EL1_IDX
+#define ID_MMFR1_IDX      ID_MMFR1_EL1_IDX
+#define ID_MMFR2_IDX      ID_MMFR2_EL1_IDX
+#define ID_MMFR3_IDX      ID_MMFR3_EL1_IDX
+#define ID_MMFR4_IDX      ID_MMFR4_EL1_IDX
+#define ID_MMFR5_IDX      ID_MMFR5_EL1_IDX
+#define ID_ISAR0_IDX      ID_ISAR0_EL1_IDX
+#define ID_ISAR1_IDX      ID_ISAR1_EL1_IDX
+#define ID_ISAR2_IDX      ID_ISAR2_EL1_IDX
+#define ID_ISAR3_IDX      ID_ISAR3_EL1_IDX
+#define ID_ISAR4_IDX      ID_ISAR4_EL1_IDX
+#define ID_ISAR5_IDX      ID_ISAR5_EL1_IDX
+#define ID_ISAR6_IDX      ID_ISAR6_EL1_IDX
+#define MVFR0_IDX         MVFR0_EL1_IDX
+#define MVFR1_IDX         MVFR1_EL1_IDX
+#define MVFR2_IDX         MVFR2_EL1_IDX
+#define MIDR_IDX          MIDR_EL1_IDX
+#define REVIDR_IDX        REVIDR_EL1_IDX
+#define AIDR_IDX          AIDR_EL1_IDX
+#define DCZID_IDX         DCZID_EL0_IDX
+
+/* ArmFieldIdx: per-field enum generated from cpu-idregs.h.inc */
+#define IDREG_START(reg)
+#define IDREG_END(reg)
+#define IDREG_FIELD_START(reg, field, shift, length, safe, defval) \
+    ARM_FIELD_##reg##_##field,
+#define IDREG_FIELD_ARCH_VAL(v, n)
+#define IDREG_FIELD_ARCH_VAL_ANY
+#define IDREG_FIELD_END(reg, field)
+typedef enum ArmFieldIdx {
+#include "cpu-idregs.h.inc"
+    ARM_FIELD__MAX,
+} ArmFieldIdx;
+#undef IDREG_FIELD_END
+#undef IDREG_FIELD_ARCH_VAL_ANY
+#undef IDREG_FIELD_ARCH_VAL
+#undef IDREG_FIELD_START
+#undef IDREG_END
+#undef IDREG_START
+
+typedef struct ArmIdRegFieldLoc {
+    ARMIDRegisterIdx reg_idx;
+    uint16_t field_idx;
+    uint8_t shift;
+    uint8_t length;
+} ArmIdRegFieldLoc;
+extern const ArmIdRegFieldLoc arm_field_locs[ARM_FIELD__MAX];
+#define ARM_FIELD_REG(idx)       (arm_field_locs[(idx)].reg_idx)
+#define ARM_FIELD_REG_FIELD(idx) (arm_field_locs[(idx)].field_idx)
+#define ARM_FIELD_SHIFT(idx)     (arm_field_locs[(idx)].shift)
+#define ARM_FIELD_LENGTH(idx)    (arm_field_locs[(idx)].length)
+#define ARM_FIELD_IDX(reg, field) ARM_FIELD_##reg##_##field
 
+extern ArmIdReg arm_idregs[NUM_ID_IDX];
 #endif /* CPU_IDREGS_H */
diff --git a/target/arm/meson.build b/target/arm/meson.build
index 4723f9f170..64d1ec63ab 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -19,6 +19,7 @@ arm_common_ss.add(files(
 
 arm_common_system_ss.add(files(
   'arm-qmp-cmds.c',
+  'cpu-idregs.c',
 ))
 arm_system_ss.add(when: 'CONFIG_KVM', if_true: files('hyp_gdbstub.c', 'kvm.c'))
 arm_system_ss.add(when: 'CONFIG_HVF', if_true: files('hyp_gdbstub.c'))
-- 
2.52.0


Reply via email to