+ switch (number) {
+ case 0:
+ return ARM_MODE_USR;
+ case 1:
+ return ARM_MODE_FIQ;
+ case 2:
+ return ARM_MODE_IRQ;
+ case 3:
+ return ARM_MODE_SVC;
+ case 4:
+ return ARM_MODE_ABT;
+ case 5:
+ return ARM_MODE_UND;
+ case 6:
+ return ARM_MODE_SYS;
+ case 7:
+ return ARM_MODE_MON;
+ default:
+ LOG_ERROR("mode index out of bounds %d", number);
+ return ARM_MODE_ANY;
+ }
+}
+
+static const char *arm_state_strings[] = {
+ "ARM", "Thumb", "Jazelle", "ThumbEE",
+};
+
+/* Templates for ARM core registers.
+ *
+ * NOTE: offsets in this table are coupled to the arm_mode_data
+ * table above, the armv4_5_core_reg_map array below, and also to
+ * the ARMV4_5_CPSR symbol (which should vanish after ARM11 updates).
+ */
+static const struct {
+ /* The name is used for e.g. the "regs" command. */
+ const char *name;
+
+ /* The {cookie, mode} tuple uniquely identifies one register.
+ * In a given mode, cookies 0..15 map to registers R0..R15,
+ * with R13..R15 usually called SP, LR, PC.
+ *
+ * MODE_ANY is used as *input* to the mapping, and indicates
+ * various special cases (sigh) and errors.
+ *
+ * Cookie 16 is (currently) confusing, since it indicates
+ * CPSR -or- SPSR depending on whether 'mode' is MODE_ANY.
+ * (Exception modes have both CPSR and SPSR registers ...)
+ */
+ unsigned cookie;
+ unsigned gdb_index;
+ enum arm_mode mode;
+} arm_core_regs[] = {
+ /* IMPORTANT: we guarantee that the first eight cached registers
+ * correspond to r0..r7, and the fifteenth to PC, so that callers
+ * don't need to map them.
+ */
+ { .name = "r0", .cookie = 0, .mode = ARM_MODE_ANY, .gdb_index = 0, },
+ { .name = "r1", .cookie = 1, .mode = ARM_MODE_ANY, .gdb_index = 1, },
+ { .name = "r2", .cookie = 2, .mode = ARM_MODE_ANY, .gdb_index = 2, },
+ { .name = "r3", .cookie = 3, .mode = ARM_MODE_ANY, .gdb_index = 3, },
+ { .name = "r4", .cookie = 4, .mode = ARM_MODE_ANY, .gdb_index = 4, },
+ { .name = "r5", .cookie = 5, .mode = ARM_MODE_ANY, .gdb_index = 5, },
+ { .name = "r6", .cookie = 6, .mode = ARM_MODE_ANY, .gdb_index = 6, },
+ { .name = "r7", .cookie = 7, .mode = ARM_MODE_ANY, .gdb_index = 7, },
+
+ /* NOTE: regs 8..12 might be shadowed by FIQ ... flagging
+ * them as MODE_ANY creates special cases. (ANY means
+ * "not mapped" elsewhere; here it's "everything but FIQ".)
+ */
+ { .name = "r8", .cookie = 8, .mode = ARM_MODE_ANY, .gdb_index = 8, },
+ { .name = "r9", .cookie = 9, .mode = ARM_MODE_ANY, .gdb_index = 9, },
+ { .name = "r10", .cookie = 10, .mode = ARM_MODE_ANY, .gdb_index = 10, },
+ { .name = "r11", .cookie = 11, .mode = ARM_MODE_ANY, .gdb_index = 11, },
+ { .name = "r12", .cookie = 12, .mode = ARM_MODE_ANY, .gdb_index = 12, },
+
+ /* Historical GDB mapping of indices:
+ * - 13-14 are sp and lr, but banked counterparts are used
+ * - 16-24 are left for deprecated 8 FPA + 1 FPS
+ * - 25 is the cpsr
+ */
+
+ /* NOTE all MODE_USR registers are equivalent to MODE_SYS ones */
+ { .name = "sp_usr", .cookie = 13, .mode = ARM_MODE_USR, .gdb_index = 26, },
+ { .name = "lr_usr", .cookie = 14, .mode = ARM_MODE_USR, .gdb_index = 27, },
+
+ /* guaranteed to be at index 15 */
+ { .name = "pc", .cookie = 15, .mode = ARM_MODE_ANY, .gdb_index = 15, },
+ { .name = "r8_fiq", .cookie = 8, .mode = ARM_MODE_FIQ, .gdb_index = 28, },
+ { .name = "r9_fiq", .cookie = 9, .mode = ARM_MODE_FIQ, .gdb_index = 29, },
+ { .name = "r10_fiq", .cookie = 10, .mode = ARM_MODE_FIQ, .gdb_index = 30, },
+ { .name = "r11_fiq", .cookie = 11, .mode = ARM_MODE_FIQ, .gdb_index = 31, },
+ { .name = "r12_fiq", .cookie = 12, .mode = ARM_MODE_FIQ, .gdb_index = 32, },
+
+ { .name = "sp_fiq", .cookie = 13, .mode = ARM_MODE_FIQ, .gdb_index = 33, },
+ { .name = "lr_fiq", .cookie = 14, .mode = ARM_MODE_FIQ, .gdb_index = 34, },
+
+ { .name = "sp_irq", .cookie = 13, .mode = ARM_MODE_IRQ, .gdb_index = 35, },
+ { .name = "lr_irq", .cookie = 14, .mode = ARM_MODE_IRQ, .gdb_index = 36, },
+
+ { .name = "sp_svc", .cookie = 13, .mode = ARM_MODE_SVC, .gdb_index = 37, },
+ { .name = "lr_svc", .cookie = 14, .mode = ARM_MODE_SVC, .gdb_index = 38, },
+
+ { .name = "sp_abt", .cookie = 13, .mode = ARM_MODE_ABT, .gdb_index = 39, },
+ { .name = "lr_abt", .cookie = 14, .mode = ARM_MODE_ABT, .gdb_index = 40, },
+
+ { .name = "sp_und", .cookie = 13, .mode = ARM_MODE_UND, .gdb_index = 41, },
+ { .name = "lr_und", .cookie = 14, .mode = ARM_MODE_UND, .gdb_index = 42, },
+
+ { .name = "cpsr", .cookie = 16, .mode = ARM_MODE_ANY, .gdb_index = 25, },
+ { .name = "spsr_fiq", .cookie = 16, .mode = ARM_MODE_FIQ, .gdb_index = 43, },
+ { .name = "spsr_irq", .cookie = 16, .mode = ARM_MODE_IRQ, .gdb_index = 44, },
+ { .name = "spsr_svc", .cookie = 16, .mode = ARM_MODE_SVC, .gdb_index = 45, },
+ { .name = "spsr_abt", .cookie = 16, .mode = ARM_MODE_ABT, .gdb_index = 46, },
+ { .name = "spsr_und", .cookie = 16, .mode = ARM_MODE_UND, .gdb_index = 47, },
+
+ /* These are only used for GDB target description, banked registers are accessed instead */
+ { .name = "sp", .cookie = 13, .mode = ARM_MODE_ANY, .gdb_index = 13, },
+ { .name = "lr", .cookie = 14, .mode = ARM_MODE_ANY, .gdb_index = 14, },
+
+ /* These exist only when the Security Extension (TrustZone) is present */
+ { .name = "sp_mon", .cookie = 13, .mode = ARM_MODE_MON, .gdb_index = 48, },
+ { .name = "lr_mon", .cookie = 14, .mode = ARM_MODE_MON, .gdb_index = 49, },
+ { .name = "spsr_mon", .cookie = 16, .mode = ARM_MODE_MON, .gdb_index = 50, },
+
+};
+
+static const struct {
+ unsigned int id;
+ const char *name;
+ uint32_t bits;
+ enum arm_mode mode;
+ enum reg_type type;
+ const char *group;
+ const char *feature;
+} arm_vfp_v3_regs[] = {
+ { ARM_VFP_V3_D0, "d0", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D1, "d1", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D2, "d2", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D3, "d3", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D4, "d4", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D5, "d5", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D6, "d6", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D7, "d7", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D8, "d8", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D9, "d9", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D10, "d10", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D11, "d11", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D12, "d12", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D13, "d13", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D14, "d14", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D15, "d15", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D16, "d16", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D17, "d17", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D18, "d18", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D19, "d19", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D20, "d20", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D21, "d21", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D22, "d22", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D23, "d23", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D24, "d24", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D25, "d25", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D26, "d26", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D27, "d27", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D28, "d28", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D29, "d29", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D30, "d30", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D31, "d31", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_FPSCR, "fpscr", 32, ARM_MODE_ANY, REG_TYPE_INT, "float", "org.gnu.gdb.arm.vfp"},
+};
+
+/* map core mode (USR, FIQ, ...) and register number to
+ * indices into the register cache
+ */
+const int armv4_5_core_reg_map[8][17] = {