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