/* just read the register -- rely on the core mode being right */ static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) { uint32_t value; int retval; switch (regnum) { case 0 ... 14: /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */ retval = dpm->instr_read_data_dcc(dpm, ARMV4_5_MCR(14, 0, regnum, 0, 5, 0), &value); break; case 15:/* PC * "MOV r0, pc"; then return via DCC */ retval = dpm->instr_read_data_r0(dpm, 0xe1a0000f, &value); /* NOTE: this seems like a slightly awkward place to update * this value ... but if the PC gets written (the only way * to change what we compute), the arch spec says subsequent * reads return values which are "unpredictable". So this * is always right except in those broken-by-intent cases. */ switch (dpm->arm->core_state) { case ARM_STATE_ARM: value -= 8; break; case ARM_STATE_THUMB: case ARM_STATE_THUMB_EE: value -= 4; break; case ARM_STATE_JAZELLE: /* core-specific ... ? */ LOG_WARNING("Jazelle PC adjustment unknown"); break; } break; default: /* 16: "MRS r0, CPSR"; then return via DCC * 17: "MRS r0, SPSR"; then return via DCC */ retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRS(0, regnum & 1), &value); break; } if (retval == ERROR_OK) { buf_set_u32(r->value, 0, 32, value); r->valid = true; r->dirty = false; LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value); } return retval; }
/** * Read basic registers of the the current context: R0 to R15, and CPSR; * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb). * In normal operation this is called on entry to halting debug state, * possibly after some other operations supporting restore of debug state * or making sure the CPU is fully idle (drain write buffer, etc). */ int arm_dpm_read_current_registers(struct arm_dpm *dpm) { struct arm *arm = dpm->arm; uint32_t cpsr; int retval; struct reg *r; retval = dpm->prepare(dpm); if (retval != ERROR_OK) return retval; /* read R0 first (it's used for scratch), then CPSR */ r = arm->core_cache->reg_list + 0; if (!r->valid) { retval = dpm_read_reg(dpm, r, 0); if (retval != ERROR_OK) goto fail; } r->dirty = true; retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRS(0, 0), &cpsr); if (retval != ERROR_OK) goto fail; /* update core mode and state, plus shadow mapping for R8..R14 */ arm_set_cpsr(arm, cpsr); /* REVISIT we can probably avoid reading R1..R14, saving time... */ for (unsigned i = 1; i < 16; i++) { r = arm_reg_current(arm, i); if (r->valid) continue; retval = dpm_read_reg(dpm, r, i); if (retval != ERROR_OK) goto fail; } /* NOTE: SPSR ignored (if it's even relevant). */ /* REVISIT the debugger can trigger various exceptions. See the * ARMv7A architecture spec, section C5.7, for more info about * what defenses are needed; v6 debug has the most issues. */ fail: /* (void) */ dpm->finish(dpm); return retval; }
static void arm7tdmi_read_xpsr(struct target *target, uint32_t *xpsr, int spsr) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* MRS r0, cpsr */ arm7tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), NULL, 0); /* STR r0, [r15] */ arm7tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), NULL, 0); /* fetch NOP, STR in DECODE stage */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* fetch NOP, STR in EXECUTE stage (1st cycle) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* nothing fetched, STR still in EXECUTE (2nd cycle) */ arm7tdmi_clock_data_in(jtag_info, xpsr); }
void arm9tdmi_read_xpsr(target_t *target, u32 *xpsr, int spsr) { /* get pointers to arch-specific information */ armv4_5_common_t *armv4_5 = target->arch_info; arm7_9_common_t *arm7_9 = armv4_5->arch_info; arm_jtag_t *jtag_info = &arm7_9->jtag_info; /* MRS r0, cpsr */ arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* STR r0, [r15] */ arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0); /* fetch NOP, STR in DECODE stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, STR in EXECUTE stage (1st cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, STR in MEMORY */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0); }
static void fa526_read_xpsr(struct target *target, uint32_t *xpsr, int spsr) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* MRS r0, cpsr */ arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* STR r0, [r15] */ arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0); /* fetch NOP, STR in DECODE stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, STR in SHIFT stage */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* fetch NOP, STR in EXECUTE stage (1st cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0); /* nothing fetched, STR in MEMORY */ arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0); }