You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1100 lines
36 KiB

  1. /***************************************************************************
  2. * Copyright (C) 2005 by Dominic Rath *
  3. * Dominic.Rath@gmx.de *
  4. * *
  5. * Copyright (C) 2006 by Magnus Lundin *
  6. * lundin@mlu.mine.nu *
  7. * *
  8. * Copyright (C) 2008 by Spencer Oliver *
  9. * spen@spen-soft.co.uk *
  10. * *
  11. * Copyright (C) 2007,2008 Øyvind Harboe *
  12. * oyvind.harboe@zylin.com *
  13. * *
  14. * Copyright (C) 2018 by Liviu Ionescu *
  15. * <ilg@livius.net> *
  16. * *
  17. * Copyright (C) 2019 by Tomas Vanek *
  18. * vanekt@fbl.cz *
  19. * *
  20. * This program is free software; you can redistribute it and/or modify *
  21. * it under the terms of the GNU General Public License as published by *
  22. * the Free Software Foundation; either version 2 of the License, or *
  23. * (at your option) any later version. *
  24. * *
  25. * This program is distributed in the hope that it will be useful, *
  26. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  27. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  28. * GNU General Public License for more details. *
  29. * *
  30. * You should have received a copy of the GNU General Public License *
  31. * along with this program. If not, see <http://www.gnu.org/licenses/>. *
  32. * *
  33. * ARMv7-M Architecture, Application Level Reference Manual *
  34. * ARM DDI 0405C (September 2008) *
  35. * *
  36. ***************************************************************************/
  37. #ifdef HAVE_CONFIG_H
  38. #include "config.h"
  39. #endif
  40. #include "breakpoints.h"
  41. #include "armv7m.h"
  42. #include "algorithm.h"
  43. #include "register.h"
  44. #include "semihosting_common.h"
  45. #if 0
  46. #define _DEBUG_INSTRUCTION_EXECUTION_
  47. #endif
  48. static const char * const armv7m_exception_strings[] = {
  49. "", "Reset", "NMI", "HardFault",
  50. "MemManage", "BusFault", "UsageFault", "SecureFault",
  51. "RESERVED", "RESERVED", "RESERVED", "SVCall",
  52. "DebugMonitor", "RESERVED", "PendSV", "SysTick"
  53. };
  54. /* PSP is used in some thread modes */
  55. const int armv7m_psp_reg_map[ARMV7M_NUM_CORE_REGS] = {
  56. ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
  57. ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
  58. ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
  59. ARMV7M_R12, ARMV7M_PSP, ARMV7M_R14, ARMV7M_PC,
  60. ARMV7M_xPSR,
  61. };
  62. /* MSP is used in handler and some thread modes */
  63. const int armv7m_msp_reg_map[ARMV7M_NUM_CORE_REGS] = {
  64. ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
  65. ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
  66. ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
  67. ARMV7M_R12, ARMV7M_MSP, ARMV7M_R14, ARMV7M_PC,
  68. ARMV7M_xPSR,
  69. };
  70. /*
  71. * These registers are not memory-mapped. The ARMv7-M profile includes
  72. * memory mapped registers too, such as for the NVIC (interrupt controller)
  73. * and SysTick (timer) modules; those can mostly be treated as peripherals.
  74. *
  75. * The ARMv6-M profile is almost identical in this respect, except that it
  76. * doesn't include basepri or faultmask registers.
  77. */
  78. static const struct {
  79. unsigned id;
  80. const char *name;
  81. unsigned bits;
  82. enum reg_type type;
  83. const char *group;
  84. const char *feature;
  85. } armv7m_regs[] = {
  86. { ARMV7M_R0, "r0", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
  87. { ARMV7M_R1, "r1", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
  88. { ARMV7M_R2, "r2", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
  89. { ARMV7M_R3, "r3", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
  90. { ARMV7M_R4, "r4", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
  91. { ARMV7M_R5, "r5", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
  92. { ARMV7M_R6, "r6", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
  93. { ARMV7M_R7, "r7", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
  94. { ARMV7M_R8, "r8", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
  95. { ARMV7M_R9, "r9", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
  96. { ARMV7M_R10, "r10", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
  97. { ARMV7M_R11, "r11", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
  98. { ARMV7M_R12, "r12", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
  99. { ARMV7M_R13, "sp", 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.m-profile" },
  100. { ARMV7M_R14, "lr", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
  101. { ARMV7M_PC, "pc", 32, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.m-profile" },
  102. { ARMV7M_xPSR, "xPSR", 32, REG_TYPE_INT, "general", "org.gnu.gdb.arm.m-profile" },
  103. { ARMV7M_MSP, "msp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" },
  104. { ARMV7M_PSP, "psp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" },
  105. /* A working register for packing/unpacking special regs, hidden from gdb */
  106. { ARMV7M_PMSK_BPRI_FLTMSK_CTRL, "pmsk_bpri_fltmsk_ctrl", 32, REG_TYPE_INT, NULL, NULL },
  107. /* WARNING: If you use armv7m_write_core_reg() on one of 4 following
  108. * special registers, the new data go to ARMV7M_PMSK_BPRI_FLTMSK_CTRL
  109. * cache only and are not flushed to CPU HW register.
  110. * To trigger write to CPU HW register, add
  111. * armv7m_write_core_reg(,,ARMV7M_PMSK_BPRI_FLTMSK_CTRL,);
  112. */
  113. { ARMV7M_PRIMASK, "primask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
  114. { ARMV7M_BASEPRI, "basepri", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
  115. { ARMV7M_FAULTMASK, "faultmask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
  116. { ARMV7M_CONTROL, "control", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
  117. /* ARMv8-M specific registers */
  118. { ARMV8M_MSP_NS, "msp_ns", 32, REG_TYPE_DATA_PTR, "stack", "v8-m.sp" },
  119. { ARMV8M_PSP_NS, "psp_ns", 32, REG_TYPE_DATA_PTR, "stack", "v8-m.sp" },
  120. { ARMV8M_MSP_S, "msp_s", 32, REG_TYPE_DATA_PTR, "stack", "v8-m.sp" },
  121. { ARMV8M_PSP_S, "psp_s", 32, REG_TYPE_DATA_PTR, "stack", "v8-m.sp" },
  122. { ARMV8M_MSPLIM_S, "msplim_s", 32, REG_TYPE_DATA_PTR, "stack", "v8-m.sp" },
  123. { ARMV8M_PSPLIM_S, "psplim_s", 32, REG_TYPE_DATA_PTR, "stack", "v8-m.sp" },
  124. { ARMV8M_MSPLIM_NS, "msplim_ns", 32, REG_TYPE_DATA_PTR, "stack", "v8-m.sp" },
  125. { ARMV8M_PSPLIM_NS, "psplim_ns", 32, REG_TYPE_DATA_PTR, "stack", "v8-m.sp" },
  126. { ARMV8M_PMSK_BPRI_FLTMSK_CTRL_S, "pmsk_bpri_fltmsk_ctrl_s", 32, REG_TYPE_INT, NULL, NULL },
  127. { ARMV8M_PRIMASK_S, "primask_s", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
  128. { ARMV8M_BASEPRI_S, "basepri_s", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
  129. { ARMV8M_FAULTMASK_S, "faultmask_s", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
  130. { ARMV8M_CONTROL_S, "control_s", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
  131. { ARMV8M_PMSK_BPRI_FLTMSK_CTRL_NS, "pmsk_bpri_fltmsk_ctrl_ns", 32, REG_TYPE_INT, NULL, NULL },
  132. { ARMV8M_PRIMASK_NS, "primask_ns", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
  133. { ARMV8M_BASEPRI_NS, "basepri_ns", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
  134. { ARMV8M_FAULTMASK_NS, "faultmask_ns", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
  135. { ARMV8M_CONTROL_NS, "control_ns", 3, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" },
  136. /* FPU registers */
  137. { ARMV7M_D0, "d0", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  138. { ARMV7M_D1, "d1", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  139. { ARMV7M_D2, "d2", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  140. { ARMV7M_D3, "d3", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  141. { ARMV7M_D4, "d4", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  142. { ARMV7M_D5, "d5", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  143. { ARMV7M_D6, "d6", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  144. { ARMV7M_D7, "d7", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  145. { ARMV7M_D8, "d8", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  146. { ARMV7M_D9, "d9", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  147. { ARMV7M_D10, "d10", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  148. { ARMV7M_D11, "d11", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  149. { ARMV7M_D12, "d12", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  150. { ARMV7M_D13, "d13", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  151. { ARMV7M_D14, "d14", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  152. { ARMV7M_D15, "d15", 64, REG_TYPE_IEEE_DOUBLE, "float", "org.gnu.gdb.arm.vfp" },
  153. { ARMV7M_FPSCR, "fpscr", 32, REG_TYPE_INT, "float", "org.gnu.gdb.arm.vfp" },
  154. };
  155. #define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
  156. /**
  157. * Restores target context using the cache of core registers set up
  158. * by armv7m_build_reg_cache(), calling optional core-specific hooks.
  159. */
  160. int armv7m_restore_context(struct target *target)
  161. {
  162. int i;
  163. struct armv7m_common *armv7m = target_to_armv7m(target);
  164. struct reg_cache *cache = armv7m->arm.core_cache;
  165. LOG_DEBUG(" ");
  166. if (armv7m->pre_restore_context)
  167. armv7m->pre_restore_context(target);
  168. /* The descending order of register writes is crucial for correct
  169. * packing of ARMV7M_PMSK_BPRI_FLTMSK_CTRL!
  170. * See also comments in the register table above */
  171. for (i = cache->num_regs - 1; i >= 0; i--) {
  172. struct reg *r = &cache->reg_list[i];
  173. if (r->exist && r->dirty)
  174. armv7m->arm.write_core_reg(target, r, i, ARM_MODE_ANY, r->value);
  175. }
  176. return ERROR_OK;
  177. }
  178. /* Core state functions */
  179. /**
  180. * Maps ISR number (from xPSR) to name.
  181. * Note that while names and meanings for the first sixteen are standardized
  182. * (with zero not a true exception), external interrupts are only numbered.
  183. * They are assigned by vendors, which generally assign different numbers to
  184. * peripherals (such as UART0 or a USB peripheral controller).
  185. */
  186. const char *armv7m_exception_string(int number)
  187. {
  188. static char enamebuf[32];
  189. if ((number < 0) | (number > 511))
  190. return "Invalid exception";
  191. if (number < 16)
  192. return armv7m_exception_strings[number];
  193. sprintf(enamebuf, "External Interrupt(%i)", number - 16);
  194. return enamebuf;
  195. }
  196. static int armv7m_get_core_reg(struct reg *reg)
  197. {
  198. int retval;
  199. struct arm_reg *armv7m_reg = reg->arch_info;
  200. struct target *target = armv7m_reg->target;
  201. struct arm *arm = target_to_arm(target);
  202. if (target->state != TARGET_HALTED)
  203. return ERROR_TARGET_NOT_HALTED;
  204. retval = arm->read_core_reg(target, reg, reg->number, arm->core_mode);
  205. return retval;
  206. }
  207. static int armv7m_set_core_reg(struct reg *reg, uint8_t *buf)
  208. {
  209. struct arm_reg *armv7m_reg = reg->arch_info;
  210. struct target *target = armv7m_reg->target;
  211. if (target->state != TARGET_HALTED)
  212. return ERROR_TARGET_NOT_HALTED;
  213. buf_cpy(buf, reg->value, reg->size);
  214. reg->dirty = true;
  215. reg->valid = true;
  216. return ERROR_OK;
  217. }
  218. static uint32_t armv7m_map_id_to_regsel(unsigned int arm_reg_id)
  219. {
  220. switch (arm_reg_id) {
  221. case ARMV7M_R0 ... ARMV7M_R14:
  222. case ARMV7M_PC:
  223. case ARMV7M_xPSR:
  224. case ARMV7M_MSP:
  225. case ARMV7M_PSP:
  226. /* NOTE: we "know" here that the register identifiers
  227. * match the Cortex-M DCRSR.REGSEL selectors values
  228. * for R0..R14, PC, xPSR, MSP, and PSP.
  229. */
  230. return arm_reg_id;
  231. case ARMV7M_PMSK_BPRI_FLTMSK_CTRL:
  232. return ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL;
  233. case ARMV8M_MSP_NS...ARMV8M_PSPLIM_NS:
  234. return arm_reg_id - ARMV8M_MSP_NS + ARMV8M_REGSEL_MSP_NS;
  235. case ARMV8M_PMSK_BPRI_FLTMSK_CTRL_S:
  236. return ARMV8M_REGSEL_PMSK_BPRI_FLTMSK_CTRL_S;
  237. case ARMV8M_PMSK_BPRI_FLTMSK_CTRL_NS:
  238. return ARMV8M_REGSEL_PMSK_BPRI_FLTMSK_CTRL_NS;
  239. case ARMV7M_FPSCR:
  240. return ARMV7M_REGSEL_FPSCR;
  241. case ARMV7M_D0 ... ARMV7M_D15:
  242. return ARMV7M_REGSEL_S0 + 2 * (arm_reg_id - ARMV7M_D0);
  243. default:
  244. LOG_ERROR("Bad register ID %u", arm_reg_id);
  245. return arm_reg_id;
  246. }
  247. }
  248. static bool armv7m_map_reg_packing(unsigned int arm_reg_id,
  249. unsigned int *reg32_id, uint32_t *offset)
  250. {
  251. switch (arm_reg_id) {
  252. case ARMV7M_PRIMASK...ARMV7M_CONTROL:
  253. *reg32_id = ARMV7M_PMSK_BPRI_FLTMSK_CTRL;
  254. *offset = arm_reg_id - ARMV7M_PRIMASK;
  255. return true;
  256. case ARMV8M_PRIMASK_S...ARMV8M_CONTROL_S:
  257. *reg32_id = ARMV8M_PMSK_BPRI_FLTMSK_CTRL_S;
  258. *offset = arm_reg_id - ARMV8M_PRIMASK_S;
  259. return true;
  260. case ARMV8M_PRIMASK_NS...ARMV8M_CONTROL_NS:
  261. *reg32_id = ARMV8M_PMSK_BPRI_FLTMSK_CTRL_NS;
  262. *offset = arm_reg_id - ARMV8M_PRIMASK_NS;
  263. return true;
  264. default:
  265. return false;
  266. }
  267. }
  268. static int armv7m_read_core_reg(struct target *target, struct reg *r,
  269. int num, enum arm_mode mode)
  270. {
  271. uint32_t reg_value;
  272. int retval;
  273. struct armv7m_common *armv7m = target_to_armv7m(target);
  274. assert(num < (int)armv7m->arm.core_cache->num_regs);
  275. assert(num == (int)r->number);
  276. /* If a code calls read_reg, it expects the cache is no more dirty.
  277. * Clear the dirty flag regardless of the later read succeeds or not
  278. * to prevent unwanted cache flush after a read error */
  279. r->dirty = false;
  280. if (r->size <= 8) {
  281. /* any 8-bit or shorter register is packed */
  282. uint32_t offset;
  283. unsigned int reg32_id;
  284. bool is_packed = armv7m_map_reg_packing(num, &reg32_id, &offset);
  285. if (!is_packed) {
  286. /* We should not get here as all 8-bit or shorter registers
  287. * are packed */
  288. assert(false);
  289. /* assert() does nothing if NDEBUG is defined */
  290. return ERROR_FAIL;
  291. }
  292. struct reg *r32 = &armv7m->arm.core_cache->reg_list[reg32_id];
  293. /* Read 32-bit container register if not cached */
  294. if (!r32->valid) {
  295. retval = armv7m_read_core_reg(target, r32, reg32_id, mode);
  296. if (retval != ERROR_OK)
  297. return retval;
  298. }
  299. /* Copy required bits of 32-bit container register */
  300. buf_cpy(r32->value + offset, r->value, r->size);
  301. } else {
  302. assert(r->size == 32 || r->size == 64);
  303. struct arm_reg *armv7m_core_reg = r->arch_info;
  304. uint32_t regsel = armv7m_map_id_to_regsel(armv7m_core_reg->num);
  305. retval = armv7m->load_core_reg_u32(target, regsel, &reg_value);
  306. if (retval != ERROR_OK)
  307. return retval;
  308. buf_set_u32(r->value, 0, 32, reg_value);
  309. if (r->size == 64) {
  310. retval = armv7m->load_core_reg_u32(target, regsel + 1, &reg_value);
  311. if (retval != ERROR_OK) {
  312. r->valid = false;
  313. return retval;
  314. }
  315. buf_set_u32(r->value + 4, 0, 32, reg_value);
  316. uint64_t q = buf_get_u64(r->value, 0, 64);
  317. LOG_DEBUG("read %s value 0x%016" PRIx64, r->name, q);
  318. } else {
  319. LOG_DEBUG("read %s value 0x%08" PRIx32, r->name, reg_value);
  320. }
  321. }
  322. r->valid = true;
  323. return ERROR_OK;
  324. }
  325. static int armv7m_write_core_reg(struct target *target, struct reg *r,
  326. int num, enum arm_mode mode, uint8_t *value)
  327. {
  328. int retval;
  329. uint32_t t;
  330. struct armv7m_common *armv7m = target_to_armv7m(target);
  331. assert(num < (int)armv7m->arm.core_cache->num_regs);
  332. assert(num == (int)r->number);
  333. if (value != r->value) {
  334. /* If we are not flushing the cache, store the new value to the cache */
  335. buf_cpy(value, r->value, r->size);
  336. }
  337. if (r->size <= 8) {
  338. /* any 8-bit or shorter register is packed */
  339. uint32_t offset;
  340. unsigned int reg32_id;
  341. bool is_packed = armv7m_map_reg_packing(num, &reg32_id, &offset);
  342. if (!is_packed) {
  343. /* We should not get here as all 8-bit or shorter registers
  344. * are packed */
  345. assert(false);
  346. /* assert() does nothing if NDEBUG is defined */
  347. return ERROR_FAIL;
  348. }
  349. struct reg *r32 = &armv7m->arm.core_cache->reg_list[reg32_id];
  350. if (!r32->valid) {
  351. /* Before merging with other parts ensure the 32-bit register is valid */
  352. retval = armv7m_read_core_reg(target, r32, reg32_id, mode);
  353. if (retval != ERROR_OK)
  354. return retval;
  355. }
  356. /* Write a part to the 32-bit container register */
  357. buf_cpy(value, r32->value + offset, r->size);
  358. r32->dirty = true;
  359. } else {
  360. assert(r->size == 32 || r->size == 64);
  361. struct arm_reg *armv7m_core_reg = r->arch_info;
  362. uint32_t regsel = armv7m_map_id_to_regsel(armv7m_core_reg->num);
  363. t = buf_get_u32(value, 0, 32);
  364. retval = armv7m->store_core_reg_u32(target, regsel, t);
  365. if (retval != ERROR_OK)
  366. goto out_error;
  367. if (r->size == 64) {
  368. t = buf_get_u32(value + 4, 0, 32);
  369. retval = armv7m->store_core_reg_u32(target, regsel + 1, t);
  370. if (retval != ERROR_OK)
  371. goto out_error;
  372. uint64_t q = buf_get_u64(value, 0, 64);
  373. LOG_DEBUG("write %s value 0x%016" PRIx64, r->name, q);
  374. } else {
  375. LOG_DEBUG("write %s value 0x%08" PRIx32, r->name, t);
  376. }
  377. }
  378. r->valid = true;
  379. r->dirty = false;
  380. return ERROR_OK;
  381. out_error:
  382. r->dirty = true;
  383. LOG_ERROR("Error setting register %s", r->name);
  384. return retval;
  385. }
  386. /**
  387. * Returns generic ARM userspace registers to GDB.
  388. */
  389. int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
  390. int *reg_list_size, enum target_register_class reg_class)
  391. {
  392. struct armv7m_common *armv7m = target_to_armv7m(target);
  393. int i, size;
  394. if (reg_class == REG_CLASS_ALL)
  395. size = armv7m->arm.core_cache->num_regs;
  396. else
  397. size = ARMV7M_NUM_CORE_REGS;
  398. *reg_list = malloc(sizeof(struct reg *) * size);
  399. if (!*reg_list)
  400. return ERROR_FAIL;
  401. for (i = 0; i < size; i++)
  402. (*reg_list)[i] = &armv7m->arm.core_cache->reg_list[i];
  403. *reg_list_size = size;
  404. return ERROR_OK;
  405. }
  406. /** Runs a Thumb algorithm in the target. */
  407. int armv7m_run_algorithm(struct target *target,
  408. int num_mem_params, struct mem_param *mem_params,
  409. int num_reg_params, struct reg_param *reg_params,
  410. target_addr_t entry_point, target_addr_t exit_point,
  411. int timeout_ms, void *arch_info)
  412. {
  413. int retval;
  414. retval = armv7m_start_algorithm(target,
  415. num_mem_params, mem_params,
  416. num_reg_params, reg_params,
  417. entry_point, exit_point,
  418. arch_info);
  419. if (retval == ERROR_OK)
  420. retval = armv7m_wait_algorithm(target,
  421. num_mem_params, mem_params,
  422. num_reg_params, reg_params,
  423. exit_point, timeout_ms,
  424. arch_info);
  425. return retval;
  426. }
  427. /** Starts a Thumb algorithm in the target. */
  428. int armv7m_start_algorithm(struct target *target,
  429. int num_mem_params, struct mem_param *mem_params,
  430. int num_reg_params, struct reg_param *reg_params,
  431. target_addr_t entry_point, target_addr_t exit_point,
  432. void *arch_info)
  433. {
  434. struct armv7m_common *armv7m = target_to_armv7m(target);
  435. struct armv7m_algorithm *armv7m_algorithm_info = arch_info;
  436. enum arm_mode core_mode = armv7m->arm.core_mode;
  437. int retval = ERROR_OK;
  438. /* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
  439. * at the exit point */
  440. if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) {
  441. LOG_ERROR("current target isn't an ARMV7M target");
  442. return ERROR_TARGET_INVALID;
  443. }
  444. if (target->state != TARGET_HALTED) {
  445. LOG_WARNING("target not halted");
  446. return ERROR_TARGET_NOT_HALTED;
  447. }
  448. /* Store all non-debug execution registers to armv7m_algorithm_info context */
  449. for (unsigned i = 0; i < armv7m->arm.core_cache->num_regs; i++) {
  450. armv7m_algorithm_info->context[i] = buf_get_u32(
  451. armv7m->arm.core_cache->reg_list[i].value,
  452. 0,
  453. 32);
  454. }
  455. for (int i = 0; i < num_mem_params; i++) {
  456. if (mem_params[i].direction == PARAM_IN)
  457. continue;
  458. retval = target_write_buffer(target, mem_params[i].address,
  459. mem_params[i].size,
  460. mem_params[i].value);
  461. if (retval != ERROR_OK)
  462. return retval;
  463. }
  464. for (int i = 0; i < num_reg_params; i++) {
  465. if (reg_params[i].direction == PARAM_IN)
  466. continue;
  467. struct reg *reg =
  468. register_get_by_name(armv7m->arm.core_cache, reg_params[i].reg_name, false);
  469. /* uint32_t regvalue; */
  470. if (!reg) {
  471. LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
  472. return ERROR_COMMAND_SYNTAX_ERROR;
  473. }
  474. if (reg->size != reg_params[i].size) {
  475. LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
  476. reg_params[i].reg_name);
  477. return ERROR_COMMAND_SYNTAX_ERROR;
  478. }
  479. /* regvalue = buf_get_u32(reg_params[i].value, 0, 32); */
  480. armv7m_set_core_reg(reg, reg_params[i].value);
  481. }
  482. {
  483. /*
  484. * Ensure xPSR.T is set to avoid trying to run things in arm
  485. * (non-thumb) mode, which armv7m does not support.
  486. *
  487. * We do this by setting the entirety of xPSR, which should
  488. * remove all the unknowns about xPSR state.
  489. *
  490. * Because xPSR.T is populated on reset from the vector table,
  491. * it might be 0 if the vector table has "bad" data in it.
  492. */
  493. struct reg *reg = &armv7m->arm.core_cache->reg_list[ARMV7M_xPSR];
  494. buf_set_u32(reg->value, 0, 32, 0x01000000);
  495. reg->valid = true;
  496. reg->dirty = true;
  497. }
  498. if (armv7m_algorithm_info->core_mode != ARM_MODE_ANY &&
  499. armv7m_algorithm_info->core_mode != core_mode) {
  500. /* we cannot set ARM_MODE_HANDLER, so use ARM_MODE_THREAD instead */
  501. if (armv7m_algorithm_info->core_mode == ARM_MODE_HANDLER) {
  502. armv7m_algorithm_info->core_mode = ARM_MODE_THREAD;
  503. LOG_INFO("ARM_MODE_HANDLER not currently supported, using ARM_MODE_THREAD instead");
  504. }
  505. LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
  506. buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value,
  507. 0, 1, armv7m_algorithm_info->core_mode);
  508. armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = true;
  509. armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = true;
  510. }
  511. /* save previous core mode */
  512. armv7m_algorithm_info->core_mode = core_mode;
  513. retval = target_resume(target, 0, entry_point, 1, 1);
  514. return retval;
  515. }
  516. /** Waits for an algorithm in the target. */
  517. int armv7m_wait_algorithm(struct target *target,
  518. int num_mem_params, struct mem_param *mem_params,
  519. int num_reg_params, struct reg_param *reg_params,
  520. target_addr_t exit_point, int timeout_ms,
  521. void *arch_info)
  522. {
  523. struct armv7m_common *armv7m = target_to_armv7m(target);
  524. struct armv7m_algorithm *armv7m_algorithm_info = arch_info;
  525. int retval = ERROR_OK;
  526. /* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
  527. * at the exit point */
  528. if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) {
  529. LOG_ERROR("current target isn't an ARMV7M target");
  530. return ERROR_TARGET_INVALID;
  531. }
  532. retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
  533. /* If the target fails to halt due to the breakpoint, force a halt */
  534. if (retval != ERROR_OK || target->state != TARGET_HALTED) {
  535. retval = target_halt(target);
  536. if (retval != ERROR_OK)
  537. return retval;
  538. retval = target_wait_state(target, TARGET_HALTED, 500);
  539. if (retval != ERROR_OK)
  540. return retval;
  541. return ERROR_TARGET_TIMEOUT;
  542. }
  543. if (exit_point) {
  544. /* PC value has been cached in cortex_m_debug_entry() */
  545. uint32_t pc = buf_get_u32(armv7m->arm.pc->value, 0, 32);
  546. if (pc != exit_point) {
  547. LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 ", expected 0x%" TARGET_PRIxADDR,
  548. pc, exit_point);
  549. return ERROR_TARGET_ALGO_EXIT;
  550. }
  551. }
  552. /* Read memory values to mem_params[] */
  553. for (int i = 0; i < num_mem_params; i++) {
  554. if (mem_params[i].direction != PARAM_OUT) {
  555. retval = target_read_buffer(target, mem_params[i].address,
  556. mem_params[i].size,
  557. mem_params[i].value);
  558. if (retval != ERROR_OK)
  559. return retval;
  560. }
  561. }
  562. /* Copy core register values to reg_params[] */
  563. for (int i = 0; i < num_reg_params; i++) {
  564. if (reg_params[i].direction != PARAM_OUT) {
  565. struct reg *reg = register_get_by_name(armv7m->arm.core_cache,
  566. reg_params[i].reg_name,
  567. false);
  568. if (!reg) {
  569. LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
  570. return ERROR_COMMAND_SYNTAX_ERROR;
  571. }
  572. if (reg->size != reg_params[i].size) {
  573. LOG_ERROR(
  574. "BUG: register '%s' size doesn't match reg_params[i].size",
  575. reg_params[i].reg_name);
  576. return ERROR_COMMAND_SYNTAX_ERROR;
  577. }
  578. buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
  579. }
  580. }
  581. for (int i = armv7m->arm.core_cache->num_regs - 1; i >= 0; i--) {
  582. uint32_t regvalue;
  583. regvalue = buf_get_u32(armv7m->arm.core_cache->reg_list[i].value, 0, 32);
  584. if (regvalue != armv7m_algorithm_info->context[i]) {
  585. LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
  586. armv7m->arm.core_cache->reg_list[i].name,
  587. armv7m_algorithm_info->context[i]);
  588. buf_set_u32(armv7m->arm.core_cache->reg_list[i].value,
  589. 0, 32, armv7m_algorithm_info->context[i]);
  590. armv7m->arm.core_cache->reg_list[i].valid = true;
  591. armv7m->arm.core_cache->reg_list[i].dirty = true;
  592. }
  593. }
  594. /* restore previous core mode */
  595. if (armv7m_algorithm_info->core_mode != armv7m->arm.core_mode) {
  596. LOG_DEBUG("restoring core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
  597. buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value,
  598. 0, 1, armv7m_algorithm_info->core_mode);
  599. armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = true;
  600. armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = true;
  601. }
  602. armv7m->arm.core_mode = armv7m_algorithm_info->core_mode;
  603. return retval;
  604. }
  605. /** Logs summary of ARMv7-M state for a halted target. */
  606. int armv7m_arch_state(struct target *target)
  607. {
  608. struct armv7m_common *armv7m = target_to_armv7m(target);
  609. struct arm *arm = &armv7m->arm;
  610. uint32_t ctrl, sp;
  611. /* avoid filling log waiting for fileio reply */
  612. if (target->semihosting && target->semihosting->hit_fileio)
  613. return ERROR_OK;
  614. ctrl = buf_get_u32(arm->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32);
  615. sp = buf_get_u32(arm->core_cache->reg_list[ARMV7M_R13].value, 0, 32);
  616. LOG_USER("target halted due to %s, current mode: %s %s\n"
  617. "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32 "%s%s",
  618. debug_reason_name(target),
  619. arm_mode_name(arm->core_mode),
  620. armv7m_exception_string(armv7m->exception_number),
  621. buf_get_u32(arm->cpsr->value, 0, 32),
  622. buf_get_u32(arm->pc->value, 0, 32),
  623. (ctrl & 0x02) ? 'p' : 'm',
  624. sp,
  625. (target->semihosting && target->semihosting->is_active) ? ", semihosting" : "",
  626. (target->semihosting && target->semihosting->is_fileio) ? " fileio" : "");
  627. return ERROR_OK;
  628. }
  629. static const struct reg_arch_type armv7m_reg_type = {
  630. .get = armv7m_get_core_reg,
  631. .set = armv7m_set_core_reg,
  632. };
  633. /** Builds cache of architecturally defined registers. */
  634. struct reg_cache *armv7m_build_reg_cache(struct target *target)
  635. {
  636. struct armv7m_common *armv7m = target_to_armv7m(target);
  637. struct arm *arm = &armv7m->arm;
  638. int num_regs = ARMV7M_NUM_REGS;
  639. struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
  640. struct reg_cache *cache = malloc(sizeof(struct reg_cache));
  641. struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
  642. struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg));
  643. struct reg_feature *feature;
  644. int i;
  645. /* Build the process context cache */
  646. cache->name = "arm v7m registers";
  647. cache->next = NULL;
  648. cache->reg_list = reg_list;
  649. cache->num_regs = num_regs;
  650. (*cache_p) = cache;
  651. for (i = 0; i < num_regs; i++) {
  652. arch_info[i].num = armv7m_regs[i].id;
  653. arch_info[i].target = target;
  654. arch_info[i].arm = arm;
  655. reg_list[i].name = armv7m_regs[i].name;
  656. reg_list[i].size = armv7m_regs[i].bits;
  657. reg_list[i].value = arch_info[i].value;
  658. reg_list[i].dirty = false;
  659. reg_list[i].valid = false;
  660. reg_list[i].hidden = (i == ARMV7M_PMSK_BPRI_FLTMSK_CTRL ||
  661. i == ARMV8M_PMSK_BPRI_FLTMSK_CTRL_NS || i == ARMV8M_PMSK_BPRI_FLTMSK_CTRL_S);
  662. reg_list[i].type = &armv7m_reg_type;
  663. reg_list[i].arch_info = &arch_info[i];
  664. reg_list[i].group = armv7m_regs[i].group;
  665. reg_list[i].number = i;
  666. reg_list[i].exist = true;
  667. reg_list[i].caller_save = true; /* gdb defaults to true */
  668. if (reg_list[i].hidden)
  669. continue;
  670. feature = calloc(1, sizeof(struct reg_feature));
  671. if (feature) {
  672. feature->name = armv7m_regs[i].feature;
  673. reg_list[i].feature = feature;
  674. } else
  675. LOG_ERROR("unable to allocate feature list");
  676. reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
  677. if (reg_list[i].reg_data_type)
  678. reg_list[i].reg_data_type->type = armv7m_regs[i].type;
  679. else
  680. LOG_ERROR("unable to allocate reg type list");
  681. }
  682. arm->cpsr = reg_list + ARMV7M_xPSR;
  683. arm->pc = reg_list + ARMV7M_PC;
  684. arm->core_cache = cache;
  685. return cache;
  686. }
  687. void armv7m_free_reg_cache(struct target *target)
  688. {
  689. struct armv7m_common *armv7m = target_to_armv7m(target);
  690. struct arm *arm = &armv7m->arm;
  691. struct reg_cache *cache;
  692. struct reg *reg;
  693. unsigned int i;
  694. cache = arm->core_cache;
  695. if (!cache)
  696. return;
  697. for (i = 0; i < cache->num_regs; i++) {
  698. reg = &cache->reg_list[i];
  699. free(reg->feature);
  700. free(reg->reg_data_type);
  701. }
  702. free(cache->reg_list[0].arch_info);
  703. free(cache->reg_list);
  704. free(cache);
  705. arm->core_cache = NULL;
  706. }
  707. static int armv7m_setup_semihosting(struct target *target, int enable)
  708. {
  709. /* nothing todo for armv7m */
  710. return ERROR_OK;
  711. }
  712. /** Sets up target as a generic ARMv7-M core */
  713. int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m)
  714. {
  715. struct arm *arm = &armv7m->arm;
  716. armv7m->common_magic = ARMV7M_COMMON_MAGIC;
  717. armv7m->fp_feature = FP_NONE;
  718. armv7m->trace_config.trace_bus_id = 1;
  719. /* Enable stimulus port #0 by default */
  720. armv7m->trace_config.itm_ter[0] = 1;
  721. arm->core_type = ARM_CORE_TYPE_M_PROFILE;
  722. arm->arch_info = armv7m;
  723. arm->setup_semihosting = armv7m_setup_semihosting;
  724. arm->read_core_reg = armv7m_read_core_reg;
  725. arm->write_core_reg = armv7m_write_core_reg;
  726. return arm_init_arch_info(target, arm);
  727. }
  728. /** Generates a CRC32 checksum of a memory region. */
  729. int armv7m_checksum_memory(struct target *target,
  730. target_addr_t address, uint32_t count, uint32_t *checksum)
  731. {
  732. struct working_area *crc_algorithm;
  733. struct armv7m_algorithm armv7m_info;
  734. struct reg_param reg_params[2];
  735. int retval;
  736. static const uint8_t cortex_m_crc_code[] = {
  737. #include "../../contrib/loaders/checksum/armv7m_crc.inc"
  738. };
  739. retval = target_alloc_working_area(target, sizeof(cortex_m_crc_code), &crc_algorithm);
  740. if (retval != ERROR_OK)
  741. return retval;
  742. retval = target_write_buffer(target, crc_algorithm->address,
  743. sizeof(cortex_m_crc_code), (uint8_t *)cortex_m_crc_code);
  744. if (retval != ERROR_OK)
  745. goto cleanup;
  746. armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
  747. armv7m_info.core_mode = ARM_MODE_THREAD;
  748. init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
  749. init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
  750. buf_set_u32(reg_params[0].value, 0, 32, address);
  751. buf_set_u32(reg_params[1].value, 0, 32, count);
  752. int timeout = 20000 * (1 + (count / (1024 * 1024)));
  753. retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
  754. crc_algorithm->address + (sizeof(cortex_m_crc_code) - 6),
  755. timeout, &armv7m_info);
  756. if (retval == ERROR_OK)
  757. *checksum = buf_get_u32(reg_params[0].value, 0, 32);
  758. else
  759. LOG_ERROR("error executing cortex_m crc algorithm");
  760. destroy_reg_param(&reg_params[0]);
  761. destroy_reg_param(&reg_params[1]);
  762. cleanup:
  763. target_free_working_area(target, crc_algorithm);
  764. return retval;
  765. }
  766. /** Checks an array of memory regions whether they are erased. */
  767. int armv7m_blank_check_memory(struct target *target,
  768. struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value)
  769. {
  770. struct working_area *erase_check_algorithm;
  771. struct working_area *erase_check_params;
  772. struct reg_param reg_params[2];
  773. struct armv7m_algorithm armv7m_info;
  774. int retval;
  775. static bool timed_out;
  776. static const uint8_t erase_check_code[] = {
  777. #include "../../contrib/loaders/erase_check/armv7m_erase_check.inc"
  778. };
  779. const uint32_t code_size = sizeof(erase_check_code);
  780. /* make sure we have a working area */
  781. if (target_alloc_working_area(target, code_size,
  782. &erase_check_algorithm) != ERROR_OK)
  783. return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
  784. retval = target_write_buffer(target, erase_check_algorithm->address,
  785. code_size, erase_check_code);
  786. if (retval != ERROR_OK)
  787. goto cleanup1;
  788. /* prepare blocks array for algo */
  789. struct algo_block {
  790. union {
  791. uint32_t size;
  792. uint32_t result;
  793. };
  794. uint32_t address;
  795. };
  796. uint32_t avail = target_get_working_area_avail(target);
  797. int blocks_to_check = avail / sizeof(struct algo_block) - 1;
  798. if (num_blocks < blocks_to_check)
  799. blocks_to_check = num_blocks;
  800. struct algo_block *params = malloc((blocks_to_check+1)*sizeof(struct algo_block));
  801. if (!params) {
  802. retval = ERROR_FAIL;
  803. goto cleanup1;
  804. }
  805. int i;
  806. uint32_t total_size = 0;
  807. for (i = 0; i < blocks_to_check; i++) {
  808. total_size += blocks[i].size;
  809. target_buffer_set_u32(target, (uint8_t *)&(params[i].size),
  810. blocks[i].size / sizeof(uint32_t));
  811. target_buffer_set_u32(target, (uint8_t *)&(params[i].address),
  812. blocks[i].address);
  813. }
  814. target_buffer_set_u32(target, (uint8_t *)&(params[blocks_to_check].size), 0);
  815. uint32_t param_size = (blocks_to_check + 1) * sizeof(struct algo_block);
  816. if (target_alloc_working_area(target, param_size,
  817. &erase_check_params) != ERROR_OK) {
  818. retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
  819. goto cleanup2;
  820. }
  821. retval = target_write_buffer(target, erase_check_params->address,
  822. param_size, (uint8_t *)params);
  823. if (retval != ERROR_OK)
  824. goto cleanup3;
  825. uint32_t erased_word = erased_value | (erased_value << 8)
  826. | (erased_value << 16) | (erased_value << 24);
  827. LOG_DEBUG("Starting erase check of %d blocks, parameters@"
  828. TARGET_ADDR_FMT, blocks_to_check, erase_check_params->address);
  829. armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
  830. armv7m_info.core_mode = ARM_MODE_THREAD;
  831. init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
  832. buf_set_u32(reg_params[0].value, 0, 32, erase_check_params->address);
  833. init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
  834. buf_set_u32(reg_params[1].value, 0, 32, erased_word);
  835. /* assume CPU clk at least 1 MHz */
  836. int timeout = (timed_out ? 30000 : 2000) + total_size * 3 / 1000;
  837. retval = target_run_algorithm(target,
  838. 0, NULL,
  839. ARRAY_SIZE(reg_params), reg_params,
  840. erase_check_algorithm->address,
  841. erase_check_algorithm->address + (code_size - 2),
  842. timeout,
  843. &armv7m_info);
  844. timed_out = retval == ERROR_TARGET_TIMEOUT;
  845. if (retval != ERROR_OK && !timed_out)
  846. goto cleanup4;
  847. retval = target_read_buffer(target, erase_check_params->address,
  848. param_size, (uint8_t *)params);
  849. if (retval != ERROR_OK)
  850. goto cleanup4;
  851. for (i = 0; i < blocks_to_check; i++) {
  852. uint32_t result = target_buffer_get_u32(target,
  853. (uint8_t *)&(params[i].result));
  854. if (result != 0 && result != 1)
  855. break;
  856. blocks[i].result = result;
  857. }
  858. if (i && timed_out)
  859. LOG_INFO("Slow CPU clock: %d blocks checked, %d remain. Continuing...", i, num_blocks-i);
  860. retval = i; /* return number of blocks really checked */
  861. cleanup4:
  862. destroy_reg_param(&reg_params[0]);
  863. destroy_reg_param(&reg_params[1]);
  864. cleanup3:
  865. target_free_working_area(target, erase_check_params);
  866. cleanup2:
  867. free(params);
  868. cleanup1:
  869. target_free_working_area(target, erase_check_algorithm);
  870. return retval;
  871. }
  872. int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found)
  873. {
  874. struct armv7m_common *armv7m = target_to_armv7m(target);
  875. struct reg *r = armv7m->arm.pc;
  876. bool result = false;
  877. /* if we halted last time due to a bkpt instruction
  878. * then we have to manually step over it, otherwise
  879. * the core will break again */
  880. if (target->debug_reason == DBG_REASON_BREAKPOINT) {
  881. uint16_t op;
  882. uint32_t pc = buf_get_u32(r->value, 0, 32);
  883. pc &= ~1;
  884. if (target_read_u16(target, pc, &op) == ERROR_OK) {
  885. if ((op & 0xFF00) == 0xBE00) {
  886. pc = buf_get_u32(r->value, 0, 32) + 2;
  887. buf_set_u32(r->value, 0, 32, pc);
  888. r->dirty = true;
  889. r->valid = true;
  890. result = true;
  891. LOG_DEBUG("Skipping over BKPT instruction");
  892. }
  893. }
  894. }
  895. if (inst_found)
  896. *inst_found = result;
  897. return ERROR_OK;
  898. }
  899. const struct command_registration armv7m_command_handlers[] = {
  900. {
  901. .chain = arm_command_handlers,
  902. },
  903. COMMAND_REGISTRATION_DONE
  904. };