+/**
+ * Configures host-side ARM records to reflect the specified CPSR.
+ * Later, code can use arm_reg_current() to map register numbers
+ * according to how they are exposed by this mode.
+ */
+void arm_set_cpsr(struct arm *arm, uint32_t cpsr)
+{
+ enum armv4_5_mode mode = cpsr & 0x1f;
+ int num;
+
+ /* NOTE: this may be called very early, before the register
+ * cache is set up. We can't defend against many errors, in
+ * particular against CPSRs that aren't valid *here* ...
+ */
+ if (arm->cpsr) {
+ buf_set_u32(arm->cpsr->value, 0, 32, cpsr);
+ arm->cpsr->valid = 1;
+ arm->cpsr->dirty = 0;
+ }
+
+ arm->core_mode = mode;
+
+ /* mode_to_number() warned; set up a somewhat-sane mapping */
+ num = armv4_5_mode_to_number(mode);
+ if (num < 0) {
+ mode = ARMV4_5_MODE_USR;
+ num = 0;
+ }
+
+ arm->map = &armv4_5_core_reg_map[num][0];
+ arm->spsr = (mode == ARMV4_5_MODE_USR || mode == ARMV4_5_MODE_SYS)
+ ? NULL
+ : arm->core_cache->reg_list + arm->map[16];
+}
+
+/**
+ * Returns handle to the register currently mapped to a given number.
+ * Someone must have called arm_set_cpsr() before.
+ *
+ * \param arm This core's state and registers are used.
+ * \param regnum From 0..15 corresponding to R0..R14 and PC.
+ * Note that R0..R7 don't require mapping; you may access those
+ * as the first eight entries in the register cache. Likewise
+ * R15 (PC) doesn't need mapping; you may also access it directly.
+ * However, R8..R14, and SPSR (arm->spsr) *must* be mapped.
+ * CPSR (arm->cpsr) is also not mapped.
+ */
+struct reg *arm_reg_current(struct arm *arm, unsigned regnum)
+{
+ struct reg *r;
+
+ if (regnum > 16)
+ return NULL;
+
+ r = arm->core_cache->reg_list + arm->map[regnum];
+
+ /* e.g. invalid CPSR said "secure monitor" mode on a core
+ * that doesn't support it...
+ */
+ if (!r) {
+ LOG_ERROR("Invalid CPSR mode");
+ r = arm->core_cache->reg_list + regnum;
+ }
+
+ return r;
+}
+