- split fileio handling into fileio part and image handling
[openocd.git] / src / target / arm_simulator.c
1 /***************************************************************************
2 * Copyright (C) 2006 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "target.h"
25 #include "armv4_5.h"
26 #include "arm_disassembler.h"
27 #include "arm_simulator.h"
28 #include "log.h"
29 #include "binarybuffer.h"
30
31 #include <string.h>
32
33 u32 arm_shift(u8 shift, u32 Rm, u32 shift_amount, u8 *carry)
34 {
35 u32 return_value;
36 shift_amount &= 0xff;
37
38 if (shift == 0x0) /* LSL */
39 {
40 if ((shift_amount > 0) && (shift_amount <= 32))
41 {
42 return_value = Rm << shift_amount;
43 *carry = Rm >> (32 - shift_amount);
44 }
45 else if (shift_amount > 32)
46 {
47 return_value = 0x0;
48 *carry = 0x0;
49 }
50 else /* (shift_amount == 0) */
51 {
52 return_value = Rm;
53 }
54 }
55 else if (shift == 0x1) /* LSR */
56 {
57 if ((shift_amount > 0) && (shift_amount <= 32))
58 {
59 return_value = Rm >> shift_amount;
60 *carry = (Rm >> (shift_amount - 1)) & 1;
61 }
62 else if (shift_amount > 32)
63 {
64 return_value = 0x0;
65 *carry = 0x0;
66 }
67 else /* (shift_amount == 0) */
68 {
69 return_value = Rm;
70 }
71 }
72 else if (shift == 0x2) /* ASR */
73 {
74 if ((shift_amount > 0) && (shift_amount <= 32))
75 {
76 /* right shifts of unsigned values are guaranteed to be logical (shift in zeroes)
77 * simulate an arithmetic shift (shift in signed-bit) by adding the signed-bit manually */
78 return_value = Rm >> shift_amount;
79 if (Rm & 0x80000000)
80 return_value |= 0xffffffff << (32 - shift_amount);
81 }
82 else if (shift_amount > 32)
83 {
84 if (Rm & 0x80000000)
85 {
86 return_value = 0xffffffff;
87 *carry = 0x1;
88 }
89 else
90 {
91 return_value = 0x0;
92 *carry = 0x0;
93 }
94 }
95 else /* (shift_amount == 0) */
96 {
97 return_value = Rm;
98 }
99 }
100 else if (shift == 0x3) /* ROR */
101 {
102 if (shift_amount == 0)
103 {
104 return_value = Rm;
105 }
106 else
107 {
108 shift_amount = shift_amount % 32;
109 return_value = (Rm >> shift_amount) | (Rm << (32 - shift_amount));
110 *carry = (return_value >> 31) & 0x1;
111 }
112 }
113 else if (shift == 0x4) /* RRX */
114 {
115 return_value = Rm >> 1;
116 if (*carry)
117 Rm |= 0x80000000;
118 *carry = Rm & 0x1;
119 }
120
121 return return_value;
122 }
123
124 u32 arm_shifter_operand(armv4_5_common_t *armv4_5, int variant, union arm_shifter_operand shifter_operand, u8 *shifter_carry_out)
125 {
126 u32 return_value;
127 int instruction_size;
128
129 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
130 instruction_size = 4;
131 else
132 instruction_size = 2;
133
134 *shifter_carry_out = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 29, 1);
135
136 if (variant == 0) /* 32-bit immediate */
137 {
138 return_value = shifter_operand.immediate.immediate;
139 }
140 else if (variant == 1) /* immediate shift */
141 {
142 u32 Rm = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, shifter_operand.immediate_shift.Rm).value, 0, 32);
143
144 /* adjust RM in case the PC is being read */
145 if (shifter_operand.immediate_shift.Rm == 15)
146 Rm += 2 * instruction_size;
147
148 return_value = arm_shift(shifter_operand.immediate_shift.shift, Rm, shifter_operand.immediate_shift.shift_imm, shifter_carry_out);
149 }
150 else if (variant == 2) /* register shift */
151 {
152 u32 Rm = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, shifter_operand.register_shift.Rm).value, 0, 32);
153 u32 Rs = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, shifter_operand.register_shift.Rs).value, 0, 32);
154
155 /* adjust RM in case the PC is being read */
156 if (shifter_operand.register_shift.Rm == 15)
157 Rm += 2 * instruction_size;
158
159 return_value = arm_shift(shifter_operand.immediate_shift.shift, Rm, Rs, shifter_carry_out);
160 }
161 else
162 {
163 ERROR("BUG: shifter_operand.variant not 0, 1 or 2");
164 return_value = 0xffffffff;
165 }
166
167 return return_value;
168 }
169
170 int pass_condition(u32 cpsr, u32 opcode)
171 {
172 switch ((opcode & 0xf0000000) >> 28)
173 {
174 case 0x0: /* EQ */
175 if (cpsr & 0x40000000)
176 return 1;
177 else
178 return 0;
179 case 0x1: /* NE */
180 if (!(cpsr & 0x40000000))
181 return 1;
182 else
183 return 0;
184 case 0x2: /* CS */
185 if (cpsr & 0x20000000)
186 return 1;
187 else
188 return 0;
189 case 0x3: /* CC */
190 if (!(cpsr & 0x20000000))
191 return 1;
192 else
193 return 0;
194 case 0x4: /* MI */
195 if (cpsr & 0x80000000)
196 return 1;
197 else
198 return 0;
199 case 0x5: /* PL */
200 if (!(cpsr & 0x80000000))
201 return 1;
202 else
203 return 0;
204 case 0x6: /* VS */
205 if (cpsr & 0x10000000)
206 return 1;
207 else
208 return 0;
209 case 0x7: /* VC */
210 if (!(cpsr & 0x10000000))
211 return 1;
212 else
213 return 0;
214 case 0x8: /* HI */
215 if ((cpsr & 0x20000000) && !(cpsr & 0x40000000))
216 return 1;
217 else
218 return 0;
219 case 0x9: /* LS */
220 if (!(cpsr & 0x20000000) || (cpsr & 0x40000000))
221 return 1;
222 else
223 return 0;
224 case 0xa: /* GE */
225 if (((cpsr & 0x80000000) && (cpsr & 0x10000000))
226 || (!(cpsr & 0x80000000) && !(cpsr & 0x10000000)))
227 return 1;
228 else
229 return 0;
230 case 0xb: /* LT */
231 if (((cpsr & 0x80000000) && !(cpsr & 0x10000000))
232 || (!(cpsr & 0x80000000) && (cpsr & 0x10000000)))
233 return 1;
234 else
235 return 0;
236 case 0xc: /* GT */
237 if (!(cpsr & 0x40000000) &&
238 (((cpsr & 0x80000000) && (cpsr & 0x10000000))
239 || (!(cpsr & 0x80000000) && !(cpsr & 0x10000000))))
240 return 1;
241 else
242 return 0;
243 case 0xd: /* LE */
244 if ((cpsr & 0x40000000) &&
245 (((cpsr & 0x80000000) && !(cpsr & 0x10000000))
246 || (!(cpsr & 0x80000000) && (cpsr & 0x10000000))))
247 return 1;
248 else
249 return 0;
250 case 0xe:
251 case 0xf:
252 return 1;
253
254 }
255
256 ERROR("BUG: should never get here");
257 return 0;
258 }
259
260 int thumb_pass_branch_condition(u32 cpsr, u16 opcode)
261 {
262 return pass_condition(cpsr, (opcode & 0x0f00) << 20);
263 }
264
265 /* simulate a single step (if possible)
266 * if the dry_run_pc argument is provided, no state is changed,
267 * but the new pc is stored in the variable pointed at by the argument
268 */
269 int arm_simulate_step(target_t *target, u32 *dry_run_pc)
270 {
271 armv4_5_common_t *armv4_5 = target->arch_info;
272 u32 opcode;
273 u32 current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
274 arm_instruction_t instruction;
275 int instruction_size;
276
277 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
278 {
279 /* get current instruction, and identify it */
280 target_read_u32(target, current_pc, &opcode);
281 arm_evaluate_opcode(opcode, current_pc, &instruction);
282 instruction_size = 4;
283
284 /* check condition code (for all instructions) */
285 if (!pass_condition(buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32), opcode))
286 {
287 if (dry_run_pc)
288 {
289 *dry_run_pc = current_pc + instruction_size;
290 }
291 else
292 {
293 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, current_pc + instruction_size);
294 }
295
296 return ERROR_OK;
297 }
298 }
299 else
300 {
301 target_read_u32(target, current_pc, &opcode);
302 arm_evaluate_opcode(opcode, current_pc, &instruction);
303 instruction_size = 2;
304
305 /* check condition code (only for branch instructions) */
306 if ((!thumb_pass_branch_condition(buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32), opcode)) &&
307 (instruction.type == ARM_B))
308 {
309 if (dry_run_pc)
310 {
311 *dry_run_pc = current_pc + instruction_size;
312 }
313 else
314 {
315 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, current_pc + instruction_size);
316 }
317
318 return ERROR_OK;
319 }
320 }
321
322 /* examine instruction type */
323
324 /* branch instructions */
325 if ((instruction.type >= ARM_B) && (instruction.type <= ARM_BLX))
326 {
327 u32 target;
328
329 if (instruction.info.b_bl_bx_blx.reg_operand == -1)
330 {
331 target = instruction.info.b_bl_bx_blx.target_address;
332 }
333 else
334 {
335 target = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.b_bl_bx_blx.reg_operand).value, 0, 32);
336 }
337
338 if (dry_run_pc)
339 {
340 *dry_run_pc = target;
341 return ERROR_OK;
342 }
343 else
344 {
345 if (instruction.type == ARM_B)
346 {
347 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, target);
348 }
349 else if (instruction.type == ARM_BL)
350 {
351 u32 old_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
352 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 14).value, 0, 32, old_pc + 4);
353 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, target);
354 }
355 else if (instruction.type == ARM_BX)
356 {
357 if (target & 0x1)
358 {
359 armv4_5->core_state = ARMV4_5_STATE_THUMB;
360 }
361 else
362 {
363 armv4_5->core_state = ARMV4_5_STATE_ARM;
364 }
365 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, target & 0xfffffffe);
366 }
367 else if (instruction.type == ARM_BLX)
368 {
369 u32 old_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
370 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 14).value, 0, 32, old_pc + 4);
371
372 if (target & 0x1)
373 {
374 armv4_5->core_state = ARMV4_5_STATE_THUMB;
375 }
376 else
377 {
378 armv4_5->core_state = ARMV4_5_STATE_ARM;
379 }
380 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, target & 0xfffffffe);
381 }
382
383 return ERROR_OK;
384 }
385 }
386 /* data processing instructions, except compare instructions (CMP, CMN, TST, TEQ) */
387 else if (((instruction.type >= ARM_AND) && (instruction.type <= ARM_RSC))
388 || ((instruction.type >= ARM_ORR) && (instruction.type <= ARM_MVN)))
389 {
390 u32 Rd, Rn, shifter_operand;
391 u8 C = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 29, 1);
392 u8 carry_out;
393
394 Rd = 0x0;
395 Rn = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.data_proc.Rn).value, 0, 32);
396 shifter_operand = arm_shifter_operand(armv4_5, instruction.info.data_proc.variant, instruction.info.data_proc.shifter_operand, &carry_out);
397
398 /* adjust Rn in case the PC is being read */
399 if (instruction.info.data_proc.Rn == 15)
400 Rn += 2 * instruction_size;
401
402 if (instruction.type == ARM_AND)
403 Rd = Rn & shifter_operand;
404 else if (instruction.type == ARM_EOR)
405 Rd = Rn ^ shifter_operand;
406 else if (instruction.type == ARM_SUB)
407 Rd = Rn - shifter_operand;
408 else if (instruction.type == ARM_RSB)
409 Rd = shifter_operand - Rn;
410 else if (instruction.type == ARM_ADD)
411 Rd = Rn + shifter_operand;
412 else if (instruction.type == ARM_ADC)
413 Rd = Rn + shifter_operand + (C & 1);
414 else if (instruction.type == ARM_SBC)
415 Rd = Rn - shifter_operand - (C & 1) ? 0 : 1;
416 else if (instruction.type == ARM_RSC)
417 Rd = shifter_operand - Rn - (C & 1) ? 0 : 1;
418 else if (instruction.type == ARM_ORR)
419 Rd = Rn | shifter_operand;
420 else if (instruction.type == ARM_BIC)
421 Rd = Rn & ~(shifter_operand);
422 else if (instruction.type == ARM_MOV)
423 Rd = shifter_operand;
424 else if (instruction.type == ARM_MVN)
425 Rd = ~shifter_operand;
426
427 if (dry_run_pc)
428 {
429 if (instruction.info.data_proc.Rd == 15)
430 {
431 *dry_run_pc = Rd;
432 return ERROR_OK;
433 }
434 else
435 {
436 *dry_run_pc = current_pc + instruction_size;
437 }
438
439 return ERROR_OK;
440 }
441 else
442 {
443 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.data_proc.Rd).value, 0, 32, Rd);
444 WARNING("no updating of flags yet");
445
446 if (instruction.info.data_proc.Rd == 15)
447 return ERROR_OK;
448 }
449 }
450 /* compare instructions (CMP, CMN, TST, TEQ) */
451 else if ((instruction.type >= ARM_TST) && (instruction.type <= ARM_CMN))
452 {
453 if (dry_run_pc)
454 {
455 *dry_run_pc = current_pc + instruction_size;
456 return ERROR_OK;
457 }
458 else
459 {
460 WARNING("no updating of flags yet");
461 }
462 }
463 /* load register instructions */
464 else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDRSH))
465 {
466 u32 load_address, modified_address, load_value;
467 u32 Rn = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store.Rn).value, 0, 32);
468
469 /* adjust Rn in case the PC is being read */
470 if (instruction.info.load_store.Rn == 15)
471 Rn += 2 * instruction_size;
472
473 if (instruction.info.load_store.offset_mode == 0)
474 {
475 if (instruction.info.load_store.U)
476 modified_address = Rn + instruction.info.load_store.offset.offset;
477 else
478 modified_address = Rn - instruction.info.load_store.offset.offset;
479 }
480 else if (instruction.info.load_store.offset_mode == 1)
481 {
482 u32 offset;
483 u32 Rm = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store.offset.reg.Rm).value, 0, 32);
484 u8 shift = instruction.info.load_store.offset.reg.shift;
485 u8 shift_imm = instruction.info.load_store.offset.reg.shift_imm;
486 u8 carry = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 29, 1);
487
488 offset = arm_shift(shift, Rm, shift_imm, &carry);
489
490 if (instruction.info.load_store.U)
491 modified_address = Rn + offset;
492 else
493 modified_address = Rn - offset;
494 }
495 else
496 {
497 ERROR("BUG: offset_mode neither 0 (offset) nor 1 (scaled register)");
498 }
499
500 if (instruction.info.load_store.index_mode == 0)
501 {
502 /* offset mode
503 * we load from the modified address, but don't change the base address register */
504 load_address = modified_address;
505 modified_address = Rn;
506 }
507 else if (instruction.info.load_store.index_mode == 1)
508 {
509 /* pre-indexed mode
510 * we load from the modified address, and write it back to the base address register */
511 load_address = modified_address;
512 }
513 else if (instruction.info.load_store.index_mode == 2)
514 {
515 /* post-indexed mode
516 * we load from the unmodified address, and write the modified address back */
517 load_address = Rn;
518 }
519
520 target_read_u32(target, load_address, &load_value);
521
522 if (dry_run_pc)
523 {
524 if (instruction.info.load_store.Rd == 15)
525 {
526 *dry_run_pc = load_value;
527 return ERROR_OK;
528 }
529 else
530 {
531 *dry_run_pc = current_pc + instruction_size;
532 }
533
534 return ERROR_OK;
535 }
536 else
537 {
538 if ((instruction.info.load_store.index_mode == 1) ||
539 (instruction.info.load_store.index_mode == 2))
540 {
541 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store.Rn).value, 0, 32, modified_address);
542 }
543 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store.Rd).value, 0, 32, load_value);
544
545 if (instruction.info.load_store.Rd == 15)
546 return ERROR_OK;
547 }
548 }
549 /* load multiple instruction */
550 else if (instruction.type == ARM_LDM)
551 {
552 int i;
553 u32 Rn = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store_multiple.Rn).value, 0, 32);
554 u32 load_values[16];
555 int bits_set = 0;
556
557 for (i = 0; i < 16; i++)
558 {
559 if (instruction.info.load_store_multiple.register_list & (1 << i))
560 bits_set++;
561 }
562
563 switch (instruction.info.load_store_multiple.addressing_mode)
564 {
565 case 0: /* Increment after */
566 Rn = Rn;
567 break;
568 case 1: /* Increment before */
569 Rn = Rn + 4;
570 break;
571 case 2: /* Decrement after */
572 Rn = Rn - (bits_set * 4) + 4;
573 break;
574 case 3: /* Decrement before */
575 Rn = Rn - (bits_set * 4);
576 break;
577 }
578
579 for (i = 0; i < 16; i++)
580 {
581 if (instruction.info.load_store_multiple.register_list & (1 << i))
582 {
583 target_read_u32(target, Rn, &load_values[i]);
584 Rn += 4;
585 }
586 }
587
588 if (dry_run_pc)
589 {
590 if (instruction.info.load_store_multiple.register_list & 0x8000)
591 {
592 *dry_run_pc = load_values[15];
593 return ERROR_OK;
594 }
595 }
596 else
597 {
598 enum armv4_5_mode mode = armv4_5->core_mode;
599 int update_cpsr = 0;
600
601 if (instruction.info.load_store_multiple.S)
602 {
603 if (instruction.info.load_store_multiple.register_list & 0x8000)
604 update_cpsr = 1;
605 else
606 mode = ARMV4_5_MODE_USR;
607 }
608
609 for (i = 0; i < 16; i++)
610 {
611 if (instruction.info.load_store_multiple.register_list & (1 << i))
612 {
613 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, i).value, 0, 32, load_values[i]);
614 }
615 }
616
617 if (update_cpsr)
618 {
619 u32 spsr = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32);
620 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, spsr);
621 }
622
623 /* base register writeback */
624 if (instruction.info.load_store_multiple.W)
625 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store_multiple.Rn).value, 0, 32, Rn);
626
627 if (instruction.info.load_store_multiple.register_list & 0x8000)
628 return ERROR_OK;
629 }
630 }
631 /* store multiple instruction */
632 else if (instruction.type == ARM_STM)
633 {
634 int i;
635
636 if (dry_run_pc)
637 {
638 /* STM wont affect PC (advance by instruction size */
639 }
640 else
641 {
642 u32 Rn = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store_multiple.Rn).value, 0, 32);
643 int bits_set = 0;
644 enum armv4_5_mode mode = armv4_5->core_mode;
645
646 for (i = 0; i < 16; i++)
647 {
648 if (instruction.info.load_store_multiple.register_list & (1 << i))
649 bits_set++;
650 }
651
652 if (instruction.info.load_store_multiple.S)
653 {
654 mode = ARMV4_5_MODE_USR;
655 }
656
657 switch (instruction.info.load_store_multiple.addressing_mode)
658 {
659 case 0: /* Increment after */
660 Rn = Rn;
661 break;
662 case 1: /* Increment before */
663 Rn = Rn + 4;
664 break;
665 case 2: /* Decrement after */
666 Rn = Rn - (bits_set * 4) + 4;
667 break;
668 case 3: /* Decrement before */
669 Rn = Rn - (bits_set * 4);
670 break;
671 }
672
673 for (i = 0; i < 16; i++)
674 {
675 if (instruction.info.load_store_multiple.register_list & (1 << i))
676 {
677 target_write_u32(target, Rn, buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).value, 0, 32));
678 Rn += 4;
679 }
680 }
681
682 /* base register writeback */
683 if (instruction.info.load_store_multiple.W)
684 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store_multiple.Rn).value, 0, 32, Rn);
685
686 }
687 }
688 else if (!dry_run_pc)
689 {
690 /* the instruction wasn't handled, but we're supposed to simulate it
691 */
692 return ERROR_ARM_SIMULATOR_NOT_IMPLEMENTED;
693 }
694
695 if (dry_run_pc)
696 {
697 *dry_run_pc = current_pc + instruction_size;
698 return ERROR_OK;
699 }
700 else
701 {
702 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, current_pc + instruction_size);
703 return ERROR_OK;
704 }
705
706 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)