hontor <hontor@126.com> - fix simulation step errors
[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 = 0;
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 LOG_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 LOG_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 current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
273 arm_instruction_t instruction;
274 int instruction_size;
275 int retval = ERROR_OK;
276
277 if (armv4_5->core_state == ARMV4_5_STATE_ARM)
278 {
279 u32 opcode;
280
281 /* get current instruction, and identify it */
282 if((retval = target_read_u32(target, current_pc, &opcode)) != ERROR_OK)
283 {
284 return retval;
285 }
286 if((retval = arm_evaluate_opcode(opcode, current_pc, &instruction)) != ERROR_OK)
287 {
288 return retval;
289 }
290 instruction_size = 4;
291
292 /* check condition code (for all instructions) */
293 if (!pass_condition(buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32), opcode))
294 {
295 if (dry_run_pc)
296 {
297 *dry_run_pc = current_pc + instruction_size;
298 }
299 else
300 {
301 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, current_pc + instruction_size);
302 }
303
304 return ERROR_OK;
305 }
306 }
307 else
308 {
309 u16 opcode;
310
311 if((retval = target_read_u16(target, current_pc, &opcode)) != ERROR_OK)
312 {
313 return retval;
314 }
315 if((retval = thumb_evaluate_opcode(opcode, current_pc, &instruction)) != ERROR_OK)
316 {
317 return retval;
318 }
319 instruction_size = 2;
320
321 /* check condition code (only for branch instructions) */
322 if ((!thumb_pass_branch_condition(buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32), opcode)) &&
323 (instruction.type == ARM_B))
324 {
325 if (dry_run_pc)
326 {
327 *dry_run_pc = current_pc + instruction_size;
328 }
329 else
330 {
331 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, current_pc + instruction_size);
332 }
333
334 return ERROR_OK;
335 }
336 }
337
338 /* examine instruction type */
339
340 /* branch instructions */
341 if ((instruction.type >= ARM_B) && (instruction.type <= ARM_BLX))
342 {
343 u32 target;
344
345 if (instruction.info.b_bl_bx_blx.reg_operand == -1)
346 {
347 target = instruction.info.b_bl_bx_blx.target_address;
348 }
349 else
350 {
351 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);
352 }
353
354 if (dry_run_pc)
355 {
356 *dry_run_pc = target;
357 return ERROR_OK;
358 }
359 else
360 {
361 if (instruction.type == ARM_B)
362 {
363 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, target);
364 }
365 else if (instruction.type == ARM_BL)
366 {
367 u32 old_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
368 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 14).value, 0, 32, old_pc + 4);
369 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, target);
370 }
371 else if (instruction.type == ARM_BX)
372 {
373 if (target & 0x1)
374 {
375 armv4_5->core_state = ARMV4_5_STATE_THUMB;
376 }
377 else
378 {
379 armv4_5->core_state = ARMV4_5_STATE_ARM;
380 }
381 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, target & 0xfffffffe);
382 }
383 else if (instruction.type == ARM_BLX)
384 {
385 u32 old_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
386 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 14).value, 0, 32, old_pc + 4);
387
388 if (target & 0x1)
389 {
390 armv4_5->core_state = ARMV4_5_STATE_THUMB;
391 }
392 else
393 {
394 armv4_5->core_state = ARMV4_5_STATE_ARM;
395 }
396 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, target & 0xfffffffe);
397 }
398
399 return ERROR_OK;
400 }
401 }
402 /* data processing instructions, except compare instructions (CMP, CMN, TST, TEQ) */
403 else if (((instruction.type >= ARM_AND) && (instruction.type <= ARM_RSC))
404 || ((instruction.type >= ARM_ORR) && (instruction.type <= ARM_MVN)))
405 {
406 u32 Rd, Rn, shifter_operand;
407 u8 C = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 29, 1);
408 u8 carry_out;
409
410 Rd = 0x0;
411 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);
412 shifter_operand = arm_shifter_operand(armv4_5, instruction.info.data_proc.variant, instruction.info.data_proc.shifter_operand, &carry_out);
413
414 /* adjust Rn in case the PC is being read */
415 if (instruction.info.data_proc.Rn == 15)
416 Rn += 2 * instruction_size;
417
418 if (instruction.type == ARM_AND)
419 Rd = Rn & shifter_operand;
420 else if (instruction.type == ARM_EOR)
421 Rd = Rn ^ shifter_operand;
422 else if (instruction.type == ARM_SUB)
423 Rd = Rn - shifter_operand;
424 else if (instruction.type == ARM_RSB)
425 Rd = shifter_operand - Rn;
426 else if (instruction.type == ARM_ADD)
427 Rd = Rn + shifter_operand;
428 else if (instruction.type == ARM_ADC)
429 Rd = Rn + shifter_operand + (C & 1);
430 else if (instruction.type == ARM_SBC)
431 Rd = Rn - shifter_operand - (C & 1) ? 0 : 1;
432 else if (instruction.type == ARM_RSC)
433 Rd = shifter_operand - Rn - (C & 1) ? 0 : 1;
434 else if (instruction.type == ARM_ORR)
435 Rd = Rn | shifter_operand;
436 else if (instruction.type == ARM_BIC)
437 Rd = Rn & ~(shifter_operand);
438 else if (instruction.type == ARM_MOV)
439 Rd = shifter_operand;
440 else if (instruction.type == ARM_MVN)
441 Rd = ~shifter_operand;
442
443 if (dry_run_pc)
444 {
445 if (instruction.info.data_proc.Rd == 15)
446 {
447 *dry_run_pc = Rd;
448 return ERROR_OK;
449 }
450 else
451 {
452 *dry_run_pc = current_pc + instruction_size;
453 }
454
455 return ERROR_OK;
456 }
457 else
458 {
459 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);
460 LOG_WARNING("no updating of flags yet");
461
462 if (instruction.info.data_proc.Rd == 15)
463 return ERROR_OK;
464 }
465 }
466 /* compare instructions (CMP, CMN, TST, TEQ) */
467 else if ((instruction.type >= ARM_TST) && (instruction.type <= ARM_CMN))
468 {
469 if (dry_run_pc)
470 {
471 *dry_run_pc = current_pc + instruction_size;
472 return ERROR_OK;
473 }
474 else
475 {
476 LOG_WARNING("no updating of flags yet");
477 }
478 }
479 /* load register instructions */
480 else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDRSH))
481 {
482 u32 load_address = 0, modified_address = 0, load_value;
483 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);
484
485 /* adjust Rn in case the PC is being read */
486 if (instruction.info.load_store.Rn == 15)
487 Rn += 2 * instruction_size;
488
489 if (instruction.info.load_store.offset_mode == 0)
490 {
491 if (instruction.info.load_store.U)
492 modified_address = Rn + instruction.info.load_store.offset.offset;
493 else
494 modified_address = Rn - instruction.info.load_store.offset.offset;
495 }
496 else if (instruction.info.load_store.offset_mode == 1)
497 {
498 u32 offset;
499 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);
500 u8 shift = instruction.info.load_store.offset.reg.shift;
501 u8 shift_imm = instruction.info.load_store.offset.reg.shift_imm;
502 u8 carry = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 29, 1);
503
504 offset = arm_shift(shift, Rm, shift_imm, &carry);
505
506 if (instruction.info.load_store.U)
507 modified_address = Rn + offset;
508 else
509 modified_address = Rn - offset;
510 }
511 else
512 {
513 LOG_ERROR("BUG: offset_mode neither 0 (offset) nor 1 (scaled register)");
514 }
515
516 if (instruction.info.load_store.index_mode == 0)
517 {
518 /* offset mode
519 * we load from the modified address, but don't change the base address register */
520 load_address = modified_address;
521 modified_address = Rn;
522 }
523 else if (instruction.info.load_store.index_mode == 1)
524 {
525 /* pre-indexed mode
526 * we load from the modified address, and write it back to the base address register */
527 load_address = modified_address;
528 }
529 else if (instruction.info.load_store.index_mode == 2)
530 {
531 /* post-indexed mode
532 * we load from the unmodified address, and write the modified address back */
533 load_address = Rn;
534 }
535
536 if((!dry_run_pc) || (instruction.info.load_store.Rd == 15))
537 {
538 if((retval = target_read_u32(target, load_address, &load_value)) != ERROR_OK)
539 {
540 return retval;
541 }
542 }
543
544 if (dry_run_pc)
545 {
546 if (instruction.info.load_store.Rd == 15)
547 {
548 *dry_run_pc = load_value;
549 return ERROR_OK;
550 }
551 else
552 {
553 *dry_run_pc = current_pc + instruction_size;
554 }
555
556 return ERROR_OK;
557 }
558 else
559 {
560 if ((instruction.info.load_store.index_mode == 1) ||
561 (instruction.info.load_store.index_mode == 2))
562 {
563 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);
564 }
565 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);
566
567 if (instruction.info.load_store.Rd == 15)
568 return ERROR_OK;
569 }
570 }
571 /* load multiple instruction */
572 else if (instruction.type == ARM_LDM)
573 {
574 int i;
575 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);
576 u32 load_values[16];
577 int bits_set = 0;
578
579 for (i = 0; i < 16; i++)
580 {
581 if (instruction.info.load_store_multiple.register_list & (1 << i))
582 bits_set++;
583 }
584
585 switch (instruction.info.load_store_multiple.addressing_mode)
586 {
587 case 0: /* Increment after */
588 Rn = Rn;
589 break;
590 case 1: /* Increment before */
591 Rn = Rn + 4;
592 break;
593 case 2: /* Decrement after */
594 Rn = Rn - (bits_set * 4) + 4;
595 break;
596 case 3: /* Decrement before */
597 Rn = Rn - (bits_set * 4);
598 break;
599 }
600
601 for (i = 0; i < 16; i++)
602 {
603 if (instruction.info.load_store_multiple.register_list & (1 << i))
604 {
605 if((!dry_run_pc) || (i == 15))
606 {
607 target_read_u32(target, Rn, &load_values[i]);
608 }
609 Rn += 4;
610 }
611 }
612
613 if (dry_run_pc)
614 {
615 if (instruction.info.load_store_multiple.register_list & 0x8000)
616 {
617 *dry_run_pc = load_values[15];
618 return ERROR_OK;
619 }
620 }
621 else
622 {
623 enum armv4_5_mode mode = armv4_5->core_mode;
624 int update_cpsr = 0;
625
626 if (instruction.info.load_store_multiple.S)
627 {
628 if (instruction.info.load_store_multiple.register_list & 0x8000)
629 update_cpsr = 1;
630 else
631 mode = ARMV4_5_MODE_USR;
632 }
633
634 for (i = 0; i < 16; i++)
635 {
636 if (instruction.info.load_store_multiple.register_list & (1 << i))
637 {
638 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, i).value, 0, 32, load_values[i]);
639 }
640 }
641
642 if (update_cpsr)
643 {
644 u32 spsr = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32);
645 buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, spsr);
646 }
647
648 /* base register writeback */
649 if (instruction.info.load_store_multiple.W)
650 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);
651
652 if (instruction.info.load_store_multiple.register_list & 0x8000)
653 return ERROR_OK;
654 }
655 }
656 /* store multiple instruction */
657 else if (instruction.type == ARM_STM)
658 {
659 int i;
660
661 if (dry_run_pc)
662 {
663 /* STM wont affect PC (advance by instruction size */
664 }
665 else
666 {
667 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);
668 int bits_set = 0;
669 enum armv4_5_mode mode = armv4_5->core_mode;
670
671 for (i = 0; i < 16; i++)
672 {
673 if (instruction.info.load_store_multiple.register_list & (1 << i))
674 bits_set++;
675 }
676
677 if (instruction.info.load_store_multiple.S)
678 {
679 mode = ARMV4_5_MODE_USR;
680 }
681
682 switch (instruction.info.load_store_multiple.addressing_mode)
683 {
684 case 0: /* Increment after */
685 Rn = Rn;
686 break;
687 case 1: /* Increment before */
688 Rn = Rn + 4;
689 break;
690 case 2: /* Decrement after */
691 Rn = Rn - (bits_set * 4) + 4;
692 break;
693 case 3: /* Decrement before */
694 Rn = Rn - (bits_set * 4);
695 break;
696 }
697
698 for (i = 0; i < 16; i++)
699 {
700 if (instruction.info.load_store_multiple.register_list & (1 << i))
701 {
702 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));
703 Rn += 4;
704 }
705 }
706
707 /* base register writeback */
708 if (instruction.info.load_store_multiple.W)
709 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);
710
711 }
712 }
713 else if (!dry_run_pc)
714 {
715 /* the instruction wasn't handled, but we're supposed to simulate it
716 */
717 return ERROR_ARM_SIMULATOR_NOT_IMPLEMENTED;
718 }
719
720 if (dry_run_pc)
721 {
722 *dry_run_pc = current_pc + instruction_size;
723 return ERROR_OK;
724 }
725 else
726 {
727 buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, current_pc + instruction_size);
728 return ERROR_OK;
729 }
730
731 }

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)