* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
* *
- * ARMv7-M Architecture, Application Level Reference Manual *
+ * ARMv7-M Architecture, Application Level Reference Manual *
* ARM DDI 0405C (September 2008) *
* *
***************************************************************************/
#define _DEBUG_INSTRUCTION_EXECUTION_
#endif
-static char *armv7m_exception_strings[] = {
+static const char * const armv7m_exception_strings[] = {
"", "Reset", "NMI", "HardFault",
"MemManage", "BusFault", "UsageFault", "RESERVED",
"RESERVED", "RESERVED", "RESERVED", "SVCall",
};
/* PSP is used in some thread modes */
-const int armv7m_psp_reg_map[17] = {
+const int armv7m_psp_reg_map[ARMV7M_NUM_CORE_REGS] = {
ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
};
/* MSP is used in handler and some thread modes */
-const int armv7m_msp_reg_map[17] = {
+const int armv7m_msp_reg_map[ARMV7M_NUM_CORE_REGS] = {
ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
ARMV7M_xPSR,
};
-#ifdef ARMV7_GDB_HACKS
-uint8_t armv7m_gdb_dummy_cpsr_value[] = {0, 0, 0, 0};
-
-struct reg armv7m_gdb_dummy_cpsr_reg = {
- .name = "GDB dummy cpsr register",
- .value = armv7m_gdb_dummy_cpsr_value,
- .dirty = 0,
- .valid = 1,
- .size = 32,
- .arch_info = NULL,
-};
-#endif
-
/*
* These registers are not memory-mapped. The ARMv7-M profile includes
* memory mapped registers too, such as for the NVIC (interrupt controller)
unsigned id;
const char *name;
unsigned bits;
+ enum reg_type type;
+ const char *group;
+ const char *feature;
} armv7m_regs[] = {
- { ARMV7M_R0, "r0", 32 },
- { ARMV7M_R1, "r1", 32 },
- { ARMV7M_R2, "r2", 32 },
- { ARMV7M_R3, "r3", 32 },
-
- { ARMV7M_R4, "r4", 32 },
- { ARMV7M_R5, "r5", 32 },
- { ARMV7M_R6, "r6", 32 },
- { ARMV7M_R7, "r7", 32 },
-
- { ARMV7M_R8, "r8", 32 },
- { ARMV7M_R9, "r9", 32 },
- { ARMV7M_R10, "r10", 32 },
- { ARMV7M_R11, "r11", 32 },
-
- { ARMV7M_R12, "r12", 32 },
- { ARMV7M_R13, "sp", 32 },
- { ARMV7M_R14, "lr", 32 },
- { ARMV7M_PC, "pc", 32 },
-
- { ARMV7M_xPSR, "xPSR", 32 },
- { ARMV7M_MSP, "msp", 32 },
- { ARMV7M_PSP, "psp", 32 },
-
- { ARMV7M_PRIMASK, "primask", 1 },
- { ARMV7M_BASEPRI, "basepri", 8 },
- { ARMV7M_FAULTMASK, "faultmask", 1 },
- { ARMV7M_CONTROL, "control", 2 },
+ { ARMV7M_R0, "r0", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R1, "r1", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R2, "r2", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R3, "r3", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R4, "r4", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R5, "r5", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R6, "r6", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R7, "r7", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R8, "r8", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R9, "r9", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R10, "r10", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R11, "r11", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R12, "r12", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R13, "sp", 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_R14, "lr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_PC, "pc", 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.m-profile" },
+ { ARMV7M_xPSR, "xPSR", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
+
+ { ARMV7M_MSP, "msp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" },
+ { ARMV7M_PSP, "psp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" },
+
+ { ARMV7M_PRIMASK, "primask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
+ { ARMV7M_BASEPRI, "basepri", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
+ { ARMV7M_FAULTMASK, "faultmask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
+ { ARMV7M_CONTROL, "control", 2, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
+
+ { ARMV7M_D0, "d0", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+ { ARMV7M_D1, "d1", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+ { ARMV7M_D2, "d2", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+ { ARMV7M_D3, "d3", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+ { ARMV7M_D4, "d4", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+ { ARMV7M_D5, "d5", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+ { ARMV7M_D6, "d6", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+ { ARMV7M_D7, "d7", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+ { ARMV7M_D8, "d8", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+ { ARMV7M_D9, "d9", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+ { ARMV7M_D10, "d10", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+ { ARMV7M_D11, "d11", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+ { ARMV7M_D12, "d12", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+ { ARMV7M_D13, "d13", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+ { ARMV7M_D14, "d14", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+ { ARMV7M_D15, "d15", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
+
+ { ARMV7M_FPSCR, "fpscr", 32, REG_TYPE_INT, "float", "org.gnu.gdb.arm.vfp" },
};
#define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
for (i = ARMV7M_NUM_REGS - 1; i >= 0; i--) {
if (cache->reg_list[i].dirty) {
- uint32_t value = buf_get_u32(cache->reg_list[i].value, 0, 32);
- armv7m->arm.write_core_reg(target, &cache->reg_list[i], i, ARM_MODE_ANY, value);
+ armv7m->arm.write_core_reg(target, &cache->reg_list[i], i,
+ ARM_MODE_ANY, cache->reg_list[i].value);
}
}
* They are assigned by vendors, which generally assign different numbers to
* peripherals (such as UART0 or a USB peripheral controller).
*/
-char *armv7m_exception_string(int number)
+const char *armv7m_exception_string(int number)
{
static char enamebuf[32];
{
struct arm_reg *armv7m_reg = reg->arch_info;
struct target *target = armv7m_reg->target;
- uint32_t value = buf_get_u32(buf, 0, 32);
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
- buf_set_u32(reg->value, 0, 32, value);
+ buf_cpy(buf, reg->value, reg->size);
reg->dirty = 1;
reg->valid = 1;
assert(num < (int)armv7m->arm.core_cache->num_regs);
armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info;
- retval = armv7m->load_core_reg_u32(target,
- armv7m_core_reg->num, ®_value);
- buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32, reg_value);
+ if ((armv7m_core_reg->num >= ARMV7M_D0) && (armv7m_core_reg->num <= ARMV7M_D15)) {
+ /* map D0..D15 to S0..S31 */
+ size_t regidx = ARMV7M_S0 + 2 * (armv7m_core_reg->num - ARMV7M_D0);
+ retval = armv7m->load_core_reg_u32(target, regidx, ®_value);
+ if (retval != ERROR_OK)
+ return retval;
+ buf_set_u32(armv7m->arm.core_cache->reg_list[num].value,
+ 0, 32, reg_value);
+ retval = armv7m->load_core_reg_u32(target, regidx + 1, ®_value);
+ if (retval != ERROR_OK)
+ return retval;
+ buf_set_u32(armv7m->arm.core_cache->reg_list[num].value + 4,
+ 0, 32, reg_value);
+ } else {
+ retval = armv7m->load_core_reg_u32(target,
+ armv7m_core_reg->num, ®_value);
+ if (retval != ERROR_OK)
+ return retval;
+ buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32, reg_value);
+ }
+
armv7m->arm.core_cache->reg_list[num].valid = 1;
armv7m->arm.core_cache->reg_list[num].dirty = 0;
}
static int armv7m_write_core_reg(struct target *target, struct reg *r,
- int num, enum arm_mode mode, uint32_t value)
+ int num, enum arm_mode mode, uint8_t *value)
{
int retval;
- uint32_t reg_value;
struct arm_reg *armv7m_core_reg;
struct armv7m_common *armv7m = target_to_armv7m(target);
assert(num < (int)armv7m->arm.core_cache->num_regs);
- reg_value = buf_get_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32);
armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info;
- retval = armv7m->store_core_reg_u32(target,
- armv7m_core_reg->num,
- reg_value);
- if (retval != ERROR_OK) {
- LOG_ERROR("JTAG failure");
- armv7m->arm.core_cache->reg_list[num].dirty = armv7m->arm.core_cache->reg_list[num].valid;
- return ERROR_JTAG_DEVICE_ERROR;
+
+ if ((armv7m_core_reg->num >= ARMV7M_D0) && (armv7m_core_reg->num <= ARMV7M_D15)) {
+ /* map D0..D15 to S0..S31 */
+ size_t regidx = ARMV7M_S0 + 2 * (armv7m_core_reg->num - ARMV7M_D0);
+
+ uint32_t t = buf_get_u32(value, 0, 32);
+ retval = armv7m->store_core_reg_u32(target, regidx, t);
+ if (retval != ERROR_OK)
+ goto out_error;
+
+ t = buf_get_u32(value + 4, 0, 32);
+ retval = armv7m->store_core_reg_u32(target, regidx + 1, t);
+ if (retval != ERROR_OK)
+ goto out_error;
+ } else {
+ uint32_t t = buf_get_u32(value, 0, 32);
+
+ LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, t);
+ retval = armv7m->store_core_reg_u32(target, armv7m_core_reg->num, t);
+ if (retval != ERROR_OK)
+ goto out_error;
}
- LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value);
armv7m->arm.core_cache->reg_list[num].valid = 1;
armv7m->arm.core_cache->reg_list[num].dirty = 0;
return ERROR_OK;
+
+out_error:
+ LOG_ERROR("Error setting register");
+ armv7m->arm.core_cache->reg_list[num].dirty = armv7m->arm.core_cache->reg_list[num].valid;
+ return ERROR_JTAG_DEVICE_ERROR;
}
/**
* Returns generic ARM userspace registers to GDB.
- * GDB doesn't quite understand that most ARMs don't have floating point
- * hardware, so this also fakes a set of long-obsolete FPA registers that
- * are not used in EABI based software stacks.
*/
-int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
+int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
+ int *reg_list_size, enum target_register_class reg_class)
{
struct armv7m_common *armv7m = target_to_armv7m(target);
int i;
- *reg_list_size = 26;
+ if (reg_class == REG_CLASS_ALL)
+ *reg_list_size = ARMV7M_NUM_REGS;
+ else
+ *reg_list_size = ARMV7M_NUM_CORE_REGS;
+
*reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
+ if (*reg_list == NULL)
+ return ERROR_FAIL;
- /*
- * GDB register packet format for ARM:
- * - the first 16 registers are r0..r15
- * - (obsolete) 8 FPA registers
- * - (obsolete) FPA status
- * - CPSR
- */
- for (i = 0; i < 16; i++)
+ for (i = 0; i < *reg_list_size; i++)
(*reg_list)[i] = &armv7m->arm.core_cache->reg_list[i];
- for (i = 16; i < 24; i++)
- (*reg_list)[i] = &arm_gdb_dummy_fp_reg;
- (*reg_list)[24] = &arm_gdb_dummy_fps_reg;
-
-#ifdef ARMV7_GDB_HACKS
- /* use dummy cpsr reg otherwise gdb may try and set the thumb bit */
- (*reg_list)[25] = &armv7m_gdb_dummy_cpsr_reg;
-
- /* ARMV7M is always in thumb mode, try to make GDB understand this
- * if it does not support this arch */
- *((char *)armv7m->arm.pc->value) |= 1;
-#else
- (*reg_list)[25] = &armv7m->arm.core_cache->reg_list[ARMV7M_xPSR];
-#endif
-
return ERROR_OK;
}
struct reg_cache *cache = malloc(sizeof(struct reg_cache));
struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg));
+ struct reg_feature *feature;
int i;
-#ifdef ARMV7_GDB_HACKS
- register_init_dummy(&armv7m_gdb_dummy_cpsr_reg);
-#endif
-
/* Build the process context cache */
cache->name = "arm v7m registers";
cache->next = NULL;
reg_list[i].name = armv7m_regs[i].name;
reg_list[i].size = armv7m_regs[i].bits;
- reg_list[i].value = calloc(1, 4);
+ size_t storage_size = DIV_ROUND_UP(armv7m_regs[i].bits, 8);
+ if (storage_size < 4)
+ storage_size = 4;
+ reg_list[i].value = calloc(1, storage_size);
reg_list[i].dirty = 0;
reg_list[i].valid = 0;
reg_list[i].type = &armv7m_reg_type;
reg_list[i].arch_info = &arch_info[i];
+
+ reg_list[i].group = armv7m_regs[i].group;
+ reg_list[i].number = i;
+ reg_list[i].exist = true;
+ reg_list[i].caller_save = true; /* gdb defaults to true */
+
+ feature = calloc(1, sizeof(struct reg_feature));
+ if (feature) {
+ feature->name = armv7m_regs[i].feature;
+ reg_list[i].feature = feature;
+ } else
+ LOG_ERROR("unable to allocate feature list");
+
+ reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
+ if (reg_list[i].reg_data_type)
+ reg_list[i].reg_data_type->type = armv7m_regs[i].type;
+ else
+ LOG_ERROR("unable to allocate reg type list");
}
arm->cpsr = reg_list + ARMV7M_xPSR;
arm->pc = reg_list + ARMV7M_PC;
arm->core_cache = cache;
+
return cache;
}
/* see contrib/loaders/checksum/armv7m_crc.s for src */
- static const uint8_t cortex_m3_crc_code[] = {
+ static const uint8_t cortex_m_crc_code[] = {
/* main: */
0x02, 0x46, /* mov r2, r0 */
0x00, 0x20, /* movs r0, #0 */
0xB7, 0x1D, 0xC1, 0x04 /* CRC32XOR: .word 0x04c11db7 */
};
- retval = target_alloc_working_area(target, sizeof(cortex_m3_crc_code), &crc_algorithm);
+ retval = target_alloc_working_area(target, sizeof(cortex_m_crc_code), &crc_algorithm);
if (retval != ERROR_OK)
return retval;
retval = target_write_buffer(target, crc_algorithm->address,
- sizeof(cortex_m3_crc_code), (uint8_t *)cortex_m3_crc_code);
+ sizeof(cortex_m_crc_code), (uint8_t *)cortex_m_crc_code);
if (retval != ERROR_OK)
goto cleanup;
int timeout = 20000 * (1 + (count / (1024 * 1024)));
retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
- crc_algorithm->address + (sizeof(cortex_m3_crc_code) - 6),
+ crc_algorithm->address + (sizeof(cortex_m_crc_code) - 6),
timeout, &armv7m_info);
if (retval == ERROR_OK)
*checksum = buf_get_u32(reg_params[0].value, 0, 32);
else
- LOG_ERROR("error executing cortex_m3 crc algorithm");
+ LOG_ERROR("error executing cortex_m crc algorithm");
destroy_reg_param(®_params[0]);
destroy_reg_param(®_params[1]);