1 /***************************************************************************
2 * Copyright (C) 2006 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2008 by Hongtao Zheng *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
28 #include "arm_disassembler.h"
29 #include "arm_simulator.h"
31 #include "binarybuffer.h"
34 static uint32_t arm_shift(uint8_t shift
, uint32_t Rm
,
35 uint32_t shift_amount
, uint8_t *carry
)
37 uint32_t return_value
= 0;
40 if (shift
== 0x0) /* LSL */
42 if ((shift_amount
> 0) && (shift_amount
<= 32))
44 return_value
= Rm
<< shift_amount
;
45 *carry
= Rm
>> (32 - shift_amount
);
47 else if (shift_amount
> 32)
52 else /* (shift_amount == 0) */
57 else if (shift
== 0x1) /* LSR */
59 if ((shift_amount
> 0) && (shift_amount
<= 32))
61 return_value
= Rm
>> shift_amount
;
62 *carry
= (Rm
>> (shift_amount
- 1)) & 1;
64 else if (shift_amount
> 32)
69 else /* (shift_amount == 0) */
74 else if (shift
== 0x2) /* ASR */
76 if ((shift_amount
> 0) && (shift_amount
<= 32))
78 /* C right shifts of unsigned values are guaranteed to
79 * be logical (shift in zeroes); simulate an arithmetic
80 * shift (shift in signed-bit) by adding the sign bit
83 return_value
= Rm
>> shift_amount
;
85 return_value
|= 0xffffffff << (32 - shift_amount
);
87 else if (shift_amount
> 32)
91 return_value
= 0xffffffff;
100 else /* (shift_amount == 0) */
105 else if (shift
== 0x3) /* ROR */
107 if (shift_amount
== 0)
113 shift_amount
= shift_amount
% 32;
114 return_value
= (Rm
>> shift_amount
) | (Rm
<< (32 - shift_amount
));
115 *carry
= (return_value
>> 31) & 0x1;
118 else if (shift
== 0x4) /* RRX */
120 return_value
= Rm
>> 1;
130 static uint32_t arm_shifter_operand(struct arm_sim_interface
*sim
,
131 int variant
, union arm_shifter_operand shifter_operand
,
132 uint8_t *shifter_carry_out
)
134 uint32_t return_value
;
135 int instruction_size
;
137 if (sim
->get_state(sim
) == ARMV4_5_STATE_ARM
)
138 instruction_size
= 4;
140 instruction_size
= 2;
142 *shifter_carry_out
= sim
->get_cpsr(sim
, 29, 1);
144 if (variant
== 0) /* 32-bit immediate */
146 return_value
= shifter_operand
.immediate
.immediate
;
148 else if (variant
== 1) /* immediate shift */
150 uint32_t Rm
= sim
->get_reg_mode(sim
, shifter_operand
.immediate_shift
.Rm
);
152 /* adjust RM in case the PC is being read */
153 if (shifter_operand
.immediate_shift
.Rm
== 15)
154 Rm
+= 2 * instruction_size
;
156 return_value
= arm_shift(shifter_operand
.immediate_shift
.shift
,
157 Rm
, shifter_operand
.immediate_shift
.shift_imm
,
160 else if (variant
== 2) /* register shift */
162 uint32_t Rm
= sim
->get_reg_mode(sim
, shifter_operand
.register_shift
.Rm
);
163 uint32_t Rs
= sim
->get_reg_mode(sim
, shifter_operand
.register_shift
.Rs
);
165 /* adjust RM in case the PC is being read */
166 if (shifter_operand
.register_shift
.Rm
== 15)
167 Rm
+= 2 * instruction_size
;
169 return_value
= arm_shift(shifter_operand
.immediate_shift
.shift
,
170 Rm
, Rs
, shifter_carry_out
);
174 LOG_ERROR("BUG: shifter_operand.variant not 0, 1 or 2");
175 return_value
= 0xffffffff;
181 static int pass_condition(uint32_t cpsr
, uint32_t opcode
)
183 switch ((opcode
& 0xf0000000) >> 28)
186 if (cpsr
& 0x40000000)
191 if (!(cpsr
& 0x40000000))
196 if (cpsr
& 0x20000000)
201 if (!(cpsr
& 0x20000000))
206 if (cpsr
& 0x80000000)
211 if (!(cpsr
& 0x80000000))
216 if (cpsr
& 0x10000000)
221 if (!(cpsr
& 0x10000000))
226 if ((cpsr
& 0x20000000) && !(cpsr
& 0x40000000))
231 if (!(cpsr
& 0x20000000) || (cpsr
& 0x40000000))
236 if (((cpsr
& 0x80000000) && (cpsr
& 0x10000000))
237 || (!(cpsr
& 0x80000000) && !(cpsr
& 0x10000000)))
242 if (((cpsr
& 0x80000000) && !(cpsr
& 0x10000000))
243 || (!(cpsr
& 0x80000000) && (cpsr
& 0x10000000)))
248 if (!(cpsr
& 0x40000000) &&
249 (((cpsr
& 0x80000000) && (cpsr
& 0x10000000))
250 || (!(cpsr
& 0x80000000) && !(cpsr
& 0x10000000))))
255 if ((cpsr
& 0x40000000) ||
256 ((cpsr
& 0x80000000) && !(cpsr
& 0x10000000))
257 || (!(cpsr
& 0x80000000) && (cpsr
& 0x10000000)))
267 LOG_ERROR("BUG: should never get here");
271 static int thumb_pass_branch_condition(uint32_t cpsr
, uint16_t opcode
)
273 return pass_condition(cpsr
, (opcode
& 0x0f00) << 20);
276 /* simulate a single step (if possible)
277 * if the dry_run_pc argument is provided, no state is changed,
278 * but the new pc is stored in the variable pointed at by the argument
280 int arm_simulate_step_core(target_t
*target
,
281 uint32_t *dry_run_pc
, struct arm_sim_interface
*sim
)
283 uint32_t current_pc
= sim
->get_reg(sim
, 15);
284 arm_instruction_t instruction
;
285 int instruction_size
;
286 int retval
= ERROR_OK
;
288 if (sim
->get_state(sim
) == ARMV4_5_STATE_ARM
)
292 /* get current instruction, and identify it */
293 if ((retval
= target_read_u32(target
, current_pc
, &opcode
)) != ERROR_OK
)
297 if ((retval
= arm_evaluate_opcode(opcode
, current_pc
, &instruction
)) != ERROR_OK
)
301 instruction_size
= 4;
303 /* check condition code (for all instructions) */
304 if (!pass_condition(sim
->get_cpsr(sim
, 0, 32), opcode
))
308 *dry_run_pc
= current_pc
+ instruction_size
;
312 sim
->set_reg(sim
, 15, current_pc
+ instruction_size
);
322 retval
= target_read_u16(target
, current_pc
, &opcode
);
323 if (retval
!= ERROR_OK
)
325 retval
= thumb_evaluate_opcode(opcode
, current_pc
, &instruction
);
326 if (retval
!= ERROR_OK
)
328 instruction_size
= 2;
330 /* check condition code (only for branch (1) instructions) */
331 if ((opcode
& 0xf000) == 0xd000
332 && !thumb_pass_branch_condition(
333 sim
->get_cpsr(sim
, 0, 32), opcode
))
337 *dry_run_pc
= current_pc
+ instruction_size
;
341 sim
->set_reg(sim
, 15, current_pc
+ instruction_size
);
347 /* Deal with 32-bit BL/BLX */
348 if ((opcode
& 0xf800) == 0xf000) {
349 uint32_t high
= instruction
.info
.b_bl_bx_blx
.target_address
;
350 retval
= target_read_u16(target
, current_pc
+2, &opcode
);
351 if (retval
!= ERROR_OK
)
353 retval
= thumb_evaluate_opcode(opcode
, current_pc
, &instruction
);
354 if (retval
!= ERROR_OK
)
356 instruction
.info
.b_bl_bx_blx
.target_address
+= high
;
360 /* examine instruction type */
362 /* branch instructions */
363 if ((instruction
.type
>= ARM_B
) && (instruction
.type
<= ARM_BLX
))
367 if (instruction
.info
.b_bl_bx_blx
.reg_operand
== -1)
369 target
= instruction
.info
.b_bl_bx_blx
.target_address
;
373 target
= sim
->get_reg_mode(sim
, instruction
.info
.b_bl_bx_blx
.reg_operand
);
374 if (instruction
.info
.b_bl_bx_blx
.reg_operand
== 15)
376 target
+= 2 * instruction_size
;
382 *dry_run_pc
= target
& ~1;
387 if (instruction
.type
== ARM_B
)
389 sim
->set_reg(sim
, 15, target
);
391 else if (instruction
.type
== ARM_BL
)
393 uint32_t old_pc
= sim
->get_reg(sim
, 15);
394 int T
= (sim
->get_state(sim
) == ARMV4_5_STATE_THUMB
);
395 sim
->set_reg_mode(sim
, 14, old_pc
+ 4 + T
);
396 sim
->set_reg(sim
, 15, target
);
398 else if (instruction
.type
== ARM_BX
)
402 sim
->set_state(sim
, ARMV4_5_STATE_THUMB
);
406 sim
->set_state(sim
, ARMV4_5_STATE_ARM
);
408 sim
->set_reg(sim
, 15, target
& 0xfffffffe);
410 else if (instruction
.type
== ARM_BLX
)
412 uint32_t old_pc
= sim
->get_reg(sim
, 15);
413 int T
= (sim
->get_state(sim
) == ARMV4_5_STATE_THUMB
);
414 sim
->set_reg_mode(sim
, 14, old_pc
+ 4 + T
);
418 sim
->set_state(sim
, ARMV4_5_STATE_THUMB
);
422 sim
->set_state(sim
, ARMV4_5_STATE_ARM
);
424 sim
->set_reg(sim
, 15, target
& 0xfffffffe);
430 /* data processing instructions, except compare instructions (CMP, CMN, TST, TEQ) */
431 else if (((instruction
.type
>= ARM_AND
) && (instruction
.type
<= ARM_RSC
))
432 || ((instruction
.type
>= ARM_ORR
) && (instruction
.type
<= ARM_MVN
)))
434 uint32_t Rd
, Rn
, shifter_operand
;
435 uint8_t C
= sim
->get_cpsr(sim
, 29, 1);
439 /* ARM_MOV and ARM_MVN does not use Rn */
440 if ((instruction
.type
!= ARM_MOV
) && (instruction
.type
!= ARM_MVN
))
441 Rn
= sim
->get_reg_mode(sim
, instruction
.info
.data_proc
.Rn
);
445 shifter_operand
= arm_shifter_operand(sim
,
446 instruction
.info
.data_proc
.variant
,
447 instruction
.info
.data_proc
.shifter_operand
,
450 /* adjust Rn in case the PC is being read */
451 if (instruction
.info
.data_proc
.Rn
== 15)
452 Rn
+= 2 * instruction_size
;
454 if (instruction
.type
== ARM_AND
)
455 Rd
= Rn
& shifter_operand
;
456 else if (instruction
.type
== ARM_EOR
)
457 Rd
= Rn
^ shifter_operand
;
458 else if (instruction
.type
== ARM_SUB
)
459 Rd
= Rn
- shifter_operand
;
460 else if (instruction
.type
== ARM_RSB
)
461 Rd
= shifter_operand
- Rn
;
462 else if (instruction
.type
== ARM_ADD
)
463 Rd
= Rn
+ shifter_operand
;
464 else if (instruction
.type
== ARM_ADC
)
465 Rd
= Rn
+ shifter_operand
+ (C
& 1);
466 else if (instruction
.type
== ARM_SBC
)
467 Rd
= Rn
- shifter_operand
- (C
& 1) ? 0 : 1;
468 else if (instruction
.type
== ARM_RSC
)
469 Rd
= shifter_operand
- Rn
- (C
& 1) ? 0 : 1;
470 else if (instruction
.type
== ARM_ORR
)
471 Rd
= Rn
| shifter_operand
;
472 else if (instruction
.type
== ARM_BIC
)
473 Rd
= Rn
& ~(shifter_operand
);
474 else if (instruction
.type
== ARM_MOV
)
475 Rd
= shifter_operand
;
476 else if (instruction
.type
== ARM_MVN
)
477 Rd
= ~shifter_operand
;
479 LOG_WARNING("unhandled instruction type");
483 if (instruction
.info
.data_proc
.Rd
== 15)
484 *dry_run_pc
= Rd
& ~1;
486 *dry_run_pc
= current_pc
+ instruction_size
;
492 if (instruction
.info
.data_proc
.Rd
== 15) {
493 sim
->set_reg_mode(sim
, 15, Rd
& ~1);
495 sim
->set_state(sim
, ARMV4_5_STATE_THUMB
);
497 sim
->set_state(sim
, ARMV4_5_STATE_ARM
);
500 sim
->set_reg_mode(sim
, instruction
.info
.data_proc
.Rd
, Rd
);
501 LOG_WARNING("no updating of flags yet");
504 /* compare instructions (CMP, CMN, TST, TEQ) */
505 else if ((instruction
.type
>= ARM_TST
) && (instruction
.type
<= ARM_CMN
))
509 *dry_run_pc
= current_pc
+ instruction_size
;
514 LOG_WARNING("no updating of flags yet");
517 /* load register instructions */
518 else if ((instruction
.type
>= ARM_LDR
) && (instruction
.type
<= ARM_LDRSH
))
520 uint32_t load_address
= 0, modified_address
= 0, load_value
;
521 uint32_t Rn
= sim
->get_reg_mode(sim
, instruction
.info
.load_store
.Rn
);
523 /* adjust Rn in case the PC is being read */
524 if (instruction
.info
.load_store
.Rn
== 15)
525 Rn
+= 2 * instruction_size
;
527 if (instruction
.info
.load_store
.offset_mode
== 0)
529 if (instruction
.info
.load_store
.U
)
530 modified_address
= Rn
+ instruction
.info
.load_store
.offset
.offset
;
532 modified_address
= Rn
- instruction
.info
.load_store
.offset
.offset
;
534 else if (instruction
.info
.load_store
.offset_mode
== 1)
537 uint32_t Rm
= sim
->get_reg_mode(sim
,
538 instruction
.info
.load_store
.offset
.reg
.Rm
);
539 uint8_t shift
= instruction
.info
.load_store
.offset
.reg
.shift
;
540 uint8_t shift_imm
= instruction
.info
.load_store
.offset
.reg
.shift_imm
;
541 uint8_t carry
= sim
->get_cpsr(sim
, 29, 1);
543 offset
= arm_shift(shift
, Rm
, shift_imm
, &carry
);
545 if (instruction
.info
.load_store
.U
)
546 modified_address
= Rn
+ offset
;
548 modified_address
= Rn
- offset
;
552 LOG_ERROR("BUG: offset_mode neither 0 (offset) nor 1 (scaled register)");
555 if (instruction
.info
.load_store
.index_mode
== 0)
558 * we load from the modified address, but don't change
559 * the base address register
561 load_address
= modified_address
;
562 modified_address
= Rn
;
564 else if (instruction
.info
.load_store
.index_mode
== 1)
567 * we load from the modified address, and write it
568 * back to the base address register
570 load_address
= modified_address
;
572 else if (instruction
.info
.load_store
.index_mode
== 2)
575 * we load from the unmodified address, and write the
576 * modified address back
581 if ((!dry_run_pc
) || (instruction
.info
.load_store
.Rd
== 15))
583 retval
= target_read_u32(target
, load_address
, &load_value
);
584 if (retval
!= ERROR_OK
)
590 if (instruction
.info
.load_store
.Rd
== 15)
591 *dry_run_pc
= load_value
& ~1;
593 *dry_run_pc
= current_pc
+ instruction_size
;
598 if ((instruction
.info
.load_store
.index_mode
== 1) ||
599 (instruction
.info
.load_store
.index_mode
== 2))
601 sim
->set_reg_mode(sim
, instruction
.info
.load_store
.Rn
, modified_address
);
604 if (instruction
.info
.load_store
.Rd
== 15) {
605 sim
->set_reg_mode(sim
, 15, load_value
& ~1);
607 sim
->set_state(sim
, ARMV4_5_STATE_THUMB
);
609 sim
->set_state(sim
, ARMV4_5_STATE_ARM
);
612 sim
->set_reg_mode(sim
, instruction
.info
.load_store
.Rd
, load_value
);
615 /* load multiple instruction */
616 else if (instruction
.type
== ARM_LDM
)
619 uint32_t Rn
= sim
->get_reg_mode(sim
, instruction
.info
.load_store_multiple
.Rn
);
620 uint32_t load_values
[16];
623 for (i
= 0; i
< 16; i
++)
625 if (instruction
.info
.load_store_multiple
.register_list
& (1 << i
))
629 switch (instruction
.info
.load_store_multiple
.addressing_mode
)
631 case 0: /* Increment after */
634 case 1: /* Increment before */
637 case 2: /* Decrement after */
638 Rn
= Rn
- (bits_set
* 4) + 4;
640 case 3: /* Decrement before */
641 Rn
= Rn
- (bits_set
* 4);
645 for (i
= 0; i
< 16; i
++)
647 if (instruction
.info
.load_store_multiple
.register_list
& (1 << i
))
649 if ((!dry_run_pc
) || (i
== 15))
651 target_read_u32(target
, Rn
, &load_values
[i
]);
659 if (instruction
.info
.load_store_multiple
.register_list
& 0x8000)
661 *dry_run_pc
= load_values
[15] & ~1;
667 enum armv4_5_mode mode
= sim
->get_mode(sim
);
670 if (instruction
.info
.load_store_multiple
.S
)
672 if (instruction
.info
.load_store_multiple
.register_list
& 0x8000)
675 mode
= ARMV4_5_MODE_USR
;
678 for (i
= 0; i
< 16; i
++)
680 if (instruction
.info
.load_store_multiple
.register_list
& (1 << i
))
683 uint32_t val
= load_values
[i
];
684 sim
->set_reg_mode(sim
, i
, val
& ~1);
686 sim
->set_state(sim
, ARMV4_5_STATE_THUMB
);
688 sim
->set_state(sim
, ARMV4_5_STATE_ARM
);
690 sim
->set_reg_mode(sim
, i
, load_values
[i
]);
697 uint32_t spsr
= sim
->get_reg_mode(sim
, 16);
698 sim
->set_reg(sim
, ARMV4_5_CPSR
, spsr
);
701 /* base register writeback */
702 if (instruction
.info
.load_store_multiple
.W
)
703 sim
->set_reg_mode(sim
, instruction
.info
.load_store_multiple
.Rn
, Rn
);
705 if (instruction
.info
.load_store_multiple
.register_list
& 0x8000)
709 /* store multiple instruction */
710 else if (instruction
.type
== ARM_STM
)
716 /* STM wont affect PC (advance by instruction size */
720 uint32_t Rn
= sim
->get_reg_mode(sim
,
721 instruction
.info
.load_store_multiple
.Rn
);
723 enum armv4_5_mode mode
= sim
->get_mode(sim
);
725 for (i
= 0; i
< 16; i
++)
727 if (instruction
.info
.load_store_multiple
.register_list
& (1 << i
))
731 if (instruction
.info
.load_store_multiple
.S
)
733 mode
= ARMV4_5_MODE_USR
;
736 switch (instruction
.info
.load_store_multiple
.addressing_mode
)
738 case 0: /* Increment after */
741 case 1: /* Increment before */
744 case 2: /* Decrement after */
745 Rn
= Rn
- (bits_set
* 4) + 4;
747 case 3: /* Decrement before */
748 Rn
= Rn
- (bits_set
* 4);
752 for (i
= 0; i
< 16; i
++)
754 if (instruction
.info
.load_store_multiple
.register_list
& (1 << i
))
756 target_write_u32(target
, Rn
, sim
->get_reg_mode(sim
, i
));
761 /* base register writeback */
762 if (instruction
.info
.load_store_multiple
.W
)
763 sim
->set_reg_mode(sim
,
764 instruction
.info
.load_store_multiple
.Rn
, Rn
);
768 else if (!dry_run_pc
)
770 /* the instruction wasn't handled, but we're supposed to simulate it
772 LOG_ERROR("Unimplemented instruction, could not simulate it.");
778 *dry_run_pc
= current_pc
+ instruction_size
;
783 sim
->set_reg(sim
, 15, current_pc
+ instruction_size
);
789 static uint32_t armv4_5_get_reg(struct arm_sim_interface
*sim
, int reg
)
791 armv4_5_common_t
*armv4_5
= (armv4_5_common_t
*)sim
->user_data
;
793 return buf_get_u32(armv4_5
->core_cache
->reg_list
[reg
].value
, 0, 32);
796 static void armv4_5_set_reg(struct arm_sim_interface
*sim
, int reg
, uint32_t value
)
798 armv4_5_common_t
*armv4_5
= (armv4_5_common_t
*)sim
->user_data
;
800 buf_set_u32(armv4_5
->core_cache
->reg_list
[reg
].value
, 0, 32, value
);
803 static uint32_t armv4_5_get_reg_mode(struct arm_sim_interface
*sim
, int reg
)
805 armv4_5_common_t
*armv4_5
= (armv4_5_common_t
*)sim
->user_data
;
807 return buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
,
808 armv4_5
->core_mode
, reg
).value
, 0, 32);
811 static void armv4_5_set_reg_mode(struct arm_sim_interface
*sim
, int reg
, uint32_t value
)
813 armv4_5_common_t
*armv4_5
= (armv4_5_common_t
*)sim
->user_data
;
815 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
,
816 armv4_5
->core_mode
, reg
).value
, 0, 32, value
);
819 static uint32_t armv4_5_get_cpsr(struct arm_sim_interface
*sim
, int pos
, int bits
)
821 armv4_5_common_t
*armv4_5
= (armv4_5_common_t
*)sim
->user_data
;
823 return buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, pos
, bits
);
826 static enum armv4_5_state
armv4_5_get_state(struct arm_sim_interface
*sim
)
828 armv4_5_common_t
*armv4_5
= (armv4_5_common_t
*)sim
->user_data
;
830 return armv4_5
->core_state
;
833 static void armv4_5_set_state(struct arm_sim_interface
*sim
, enum armv4_5_state mode
)
835 armv4_5_common_t
*armv4_5
= (armv4_5_common_t
*)sim
->user_data
;
837 armv4_5
->core_state
= mode
;
841 static enum armv4_5_mode
armv4_5_get_mode(struct arm_sim_interface
*sim
)
843 armv4_5_common_t
*armv4_5
= (armv4_5_common_t
*)sim
->user_data
;
845 return armv4_5
->core_mode
;
850 int arm_simulate_step(target_t
*target
, uint32_t *dry_run_pc
)
852 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
853 struct arm_sim_interface sim
;
855 sim
.user_data
= armv4_5
;
856 sim
.get_reg
= &armv4_5_get_reg
;
857 sim
.set_reg
= &armv4_5_set_reg
;
858 sim
.get_reg_mode
= &armv4_5_get_reg_mode
;
859 sim
.set_reg_mode
= &armv4_5_set_reg_mode
;
860 sim
.get_cpsr
= &armv4_5_get_cpsr
;
861 sim
.get_mode
= &armv4_5_get_mode
;
862 sim
.get_state
= &armv4_5_get_state
;
863 sim
.set_state
= &armv4_5_set_state
;
865 return arm_simulate_step_core(target
, dry_run_pc
, &sim
);