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"
30 #include <helper/binarybuffer.h>
32 #include <helper/log.h>
35 static uint32_t arm_shift(uint8_t shift
, uint32_t Rm
,
36 uint32_t shift_amount
, uint8_t *carry
)
38 uint32_t return_value
= 0;
41 if (shift
== 0x0) /* LSL */
43 if ((shift_amount
> 0) && (shift_amount
<= 32))
45 return_value
= Rm
<< shift_amount
;
46 *carry
= Rm
>> (32 - shift_amount
);
48 else if (shift_amount
> 32)
53 else /* (shift_amount == 0) */
58 else if (shift
== 0x1) /* LSR */
60 if ((shift_amount
> 0) && (shift_amount
<= 32))
62 return_value
= Rm
>> shift_amount
;
63 *carry
= (Rm
>> (shift_amount
- 1)) & 1;
65 else if (shift_amount
> 32)
70 else /* (shift_amount == 0) */
75 else if (shift
== 0x2) /* ASR */
77 if ((shift_amount
> 0) && (shift_amount
<= 32))
79 /* C right shifts of unsigned values are guaranteed to
80 * be logical (shift in zeroes); simulate an arithmetic
81 * shift (shift in signed-bit) by adding the sign bit
84 return_value
= Rm
>> shift_amount
;
86 return_value
|= 0xffffffff << (32 - shift_amount
);
88 else if (shift_amount
> 32)
92 return_value
= 0xffffffff;
101 else /* (shift_amount == 0) */
106 else if (shift
== 0x3) /* ROR */
108 if (shift_amount
== 0)
114 shift_amount
= shift_amount
% 32;
115 return_value
= (Rm
>> shift_amount
) | (Rm
<< (32 - shift_amount
));
116 *carry
= (return_value
>> 31) & 0x1;
119 else if (shift
== 0x4) /* RRX */
121 return_value
= Rm
>> 1;
131 static uint32_t arm_shifter_operand(struct arm_sim_interface
*sim
,
132 int variant
, union arm_shifter_operand shifter_operand
,
133 uint8_t *shifter_carry_out
)
135 uint32_t return_value
;
136 int instruction_size
;
138 if (sim
->get_state(sim
) == ARM_STATE_ARM
)
139 instruction_size
= 4;
141 instruction_size
= 2;
143 *shifter_carry_out
= sim
->get_cpsr(sim
, 29, 1);
145 if (variant
== 0) /* 32-bit immediate */
147 return_value
= shifter_operand
.immediate
.immediate
;
149 else if (variant
== 1) /* immediate shift */
151 uint32_t Rm
= sim
->get_reg_mode(sim
, shifter_operand
.immediate_shift
.Rm
);
153 /* adjust RM in case the PC is being read */
154 if (shifter_operand
.immediate_shift
.Rm
== 15)
155 Rm
+= 2 * instruction_size
;
157 return_value
= arm_shift(shifter_operand
.immediate_shift
.shift
,
158 Rm
, shifter_operand
.immediate_shift
.shift_imm
,
161 else if (variant
== 2) /* register shift */
163 uint32_t Rm
= sim
->get_reg_mode(sim
, shifter_operand
.register_shift
.Rm
);
164 uint32_t Rs
= sim
->get_reg_mode(sim
, shifter_operand
.register_shift
.Rs
);
166 /* adjust RM in case the PC is being read */
167 if (shifter_operand
.register_shift
.Rm
== 15)
168 Rm
+= 2 * instruction_size
;
170 return_value
= arm_shift(shifter_operand
.immediate_shift
.shift
,
171 Rm
, Rs
, shifter_carry_out
);
175 LOG_ERROR("BUG: shifter_operand.variant not 0, 1 or 2");
176 return_value
= 0xffffffff;
182 static int pass_condition(uint32_t cpsr
, uint32_t opcode
)
184 switch ((opcode
& 0xf0000000) >> 28)
187 if (cpsr
& 0x40000000)
192 if (!(cpsr
& 0x40000000))
197 if (cpsr
& 0x20000000)
202 if (!(cpsr
& 0x20000000))
207 if (cpsr
& 0x80000000)
212 if (!(cpsr
& 0x80000000))
217 if (cpsr
& 0x10000000)
222 if (!(cpsr
& 0x10000000))
227 if ((cpsr
& 0x20000000) && !(cpsr
& 0x40000000))
232 if (!(cpsr
& 0x20000000) || (cpsr
& 0x40000000))
237 if (((cpsr
& 0x80000000) && (cpsr
& 0x10000000))
238 || (!(cpsr
& 0x80000000) && !(cpsr
& 0x10000000)))
243 if (((cpsr
& 0x80000000) && !(cpsr
& 0x10000000))
244 || (!(cpsr
& 0x80000000) && (cpsr
& 0x10000000)))
249 if (!(cpsr
& 0x40000000) &&
250 (((cpsr
& 0x80000000) && (cpsr
& 0x10000000))
251 || (!(cpsr
& 0x80000000) && !(cpsr
& 0x10000000))))
256 if ((cpsr
& 0x40000000) ||
257 ((cpsr
& 0x80000000) && !(cpsr
& 0x10000000))
258 || (!(cpsr
& 0x80000000) && (cpsr
& 0x10000000)))
268 LOG_ERROR("BUG: should never get here");
272 static int thumb_pass_branch_condition(uint32_t cpsr
, uint16_t opcode
)
274 return pass_condition(cpsr
, (opcode
& 0x0f00) << 20);
277 /* simulate a single step (if possible)
278 * if the dry_run_pc argument is provided, no state is changed,
279 * but the new pc is stored in the variable pointed at by the argument
281 int arm_simulate_step_core(struct target
*target
,
282 uint32_t *dry_run_pc
, struct arm_sim_interface
*sim
)
284 uint32_t current_pc
= sim
->get_reg(sim
, 15);
285 struct arm_instruction instruction
;
286 int instruction_size
;
287 int retval
= ERROR_OK
;
289 if (sim
->get_state(sim
) == ARM_STATE_ARM
)
293 /* get current instruction, and identify it */
294 if ((retval
= target_read_u32(target
, current_pc
, &opcode
)) != ERROR_OK
)
298 if ((retval
= arm_evaluate_opcode(opcode
, current_pc
, &instruction
)) != ERROR_OK
)
302 instruction_size
= 4;
304 /* check condition code (for all instructions) */
305 if (!pass_condition(sim
->get_cpsr(sim
, 0, 32), opcode
))
309 *dry_run_pc
= current_pc
+ instruction_size
;
313 sim
->set_reg(sim
, 15, current_pc
+ instruction_size
);
323 retval
= target_read_u16(target
, current_pc
, &opcode
);
324 if (retval
!= ERROR_OK
)
326 retval
= thumb_evaluate_opcode(opcode
, current_pc
, &instruction
);
327 if (retval
!= ERROR_OK
)
329 instruction_size
= 2;
331 /* check condition code (only for branch (1) instructions) */
332 if ((opcode
& 0xf000) == 0xd000
333 && !thumb_pass_branch_condition(
334 sim
->get_cpsr(sim
, 0, 32), opcode
))
338 *dry_run_pc
= current_pc
+ instruction_size
;
342 sim
->set_reg(sim
, 15, current_pc
+ instruction_size
);
348 /* Deal with 32-bit BL/BLX */
349 if ((opcode
& 0xf800) == 0xf000) {
350 uint32_t high
= instruction
.info
.b_bl_bx_blx
.target_address
;
351 retval
= target_read_u16(target
, current_pc
+2, &opcode
);
352 if (retval
!= ERROR_OK
)
354 retval
= thumb_evaluate_opcode(opcode
, current_pc
, &instruction
);
355 if (retval
!= ERROR_OK
)
357 instruction
.info
.b_bl_bx_blx
.target_address
+= high
;
361 /* examine instruction type */
363 /* branch instructions */
364 if ((instruction
.type
>= ARM_B
) && (instruction
.type
<= ARM_BLX
))
368 if (instruction
.info
.b_bl_bx_blx
.reg_operand
== -1)
370 target
= instruction
.info
.b_bl_bx_blx
.target_address
;
374 target
= sim
->get_reg_mode(sim
, instruction
.info
.b_bl_bx_blx
.reg_operand
);
375 if (instruction
.info
.b_bl_bx_blx
.reg_operand
== 15)
377 target
+= 2 * instruction_size
;
383 *dry_run_pc
= target
& ~1;
388 if (instruction
.type
== ARM_B
)
390 sim
->set_reg(sim
, 15, target
);
392 else if (instruction
.type
== ARM_BL
)
394 uint32_t old_pc
= sim
->get_reg(sim
, 15);
395 int T
= (sim
->get_state(sim
) == ARM_STATE_THUMB
);
396 sim
->set_reg_mode(sim
, 14, old_pc
+ 4 + T
);
397 sim
->set_reg(sim
, 15, target
);
399 else if (instruction
.type
== ARM_BX
)
403 sim
->set_state(sim
, ARM_STATE_THUMB
);
407 sim
->set_state(sim
, ARM_STATE_ARM
);
409 sim
->set_reg(sim
, 15, target
& 0xfffffffe);
411 else if (instruction
.type
== ARM_BLX
)
413 uint32_t old_pc
= sim
->get_reg(sim
, 15);
414 int T
= (sim
->get_state(sim
) == ARM_STATE_THUMB
);
415 sim
->set_reg_mode(sim
, 14, old_pc
+ 4 + T
);
419 sim
->set_state(sim
, ARM_STATE_THUMB
);
423 sim
->set_state(sim
, ARM_STATE_ARM
);
425 sim
->set_reg(sim
, 15, target
& 0xfffffffe);
431 /* data processing instructions, except compare instructions (CMP, CMN, TST, TEQ) */
432 else if (((instruction
.type
>= ARM_AND
) && (instruction
.type
<= ARM_RSC
))
433 || ((instruction
.type
>= ARM_ORR
) && (instruction
.type
<= ARM_MVN
)))
435 uint32_t Rd
, Rn
, shifter_operand
;
436 uint8_t C
= sim
->get_cpsr(sim
, 29, 1);
440 /* ARM_MOV and ARM_MVN does not use Rn */
441 if ((instruction
.type
!= ARM_MOV
) && (instruction
.type
!= ARM_MVN
))
442 Rn
= sim
->get_reg_mode(sim
, instruction
.info
.data_proc
.Rn
);
446 shifter_operand
= arm_shifter_operand(sim
,
447 instruction
.info
.data_proc
.variant
,
448 instruction
.info
.data_proc
.shifter_operand
,
451 /* adjust Rn in case the PC is being read */
452 if (instruction
.info
.data_proc
.Rn
== 15)
453 Rn
+= 2 * instruction_size
;
455 if (instruction
.type
== ARM_AND
)
456 Rd
= Rn
& shifter_operand
;
457 else if (instruction
.type
== ARM_EOR
)
458 Rd
= Rn
^ shifter_operand
;
459 else if (instruction
.type
== ARM_SUB
)
460 Rd
= Rn
- shifter_operand
;
461 else if (instruction
.type
== ARM_RSB
)
462 Rd
= shifter_operand
- Rn
;
463 else if (instruction
.type
== ARM_ADD
)
464 Rd
= Rn
+ shifter_operand
;
465 else if (instruction
.type
== ARM_ADC
)
466 Rd
= Rn
+ shifter_operand
+ (C
& 1);
467 else if (instruction
.type
== ARM_SBC
)
468 Rd
= Rn
- shifter_operand
- (C
& 1) ? 0 : 1;
469 else if (instruction
.type
== ARM_RSC
)
470 Rd
= shifter_operand
- Rn
- (C
& 1) ? 0 : 1;
471 else if (instruction
.type
== ARM_ORR
)
472 Rd
= Rn
| shifter_operand
;
473 else if (instruction
.type
== ARM_BIC
)
474 Rd
= Rn
& ~(shifter_operand
);
475 else if (instruction
.type
== ARM_MOV
)
476 Rd
= shifter_operand
;
477 else if (instruction
.type
== ARM_MVN
)
478 Rd
= ~shifter_operand
;
480 LOG_WARNING("unhandled instruction type");
484 if (instruction
.info
.data_proc
.Rd
== 15)
485 *dry_run_pc
= Rd
& ~1;
487 *dry_run_pc
= current_pc
+ instruction_size
;
493 if (instruction
.info
.data_proc
.Rd
== 15) {
494 sim
->set_reg_mode(sim
, 15, Rd
& ~1);
496 sim
->set_state(sim
, ARM_STATE_THUMB
);
498 sim
->set_state(sim
, ARM_STATE_ARM
);
501 sim
->set_reg_mode(sim
, instruction
.info
.data_proc
.Rd
, Rd
);
502 LOG_WARNING("no updating of flags yet");
505 /* compare instructions (CMP, CMN, TST, TEQ) */
506 else if ((instruction
.type
>= ARM_TST
) && (instruction
.type
<= ARM_CMN
))
510 *dry_run_pc
= current_pc
+ instruction_size
;
515 LOG_WARNING("no updating of flags yet");
518 /* load register instructions */
519 else if ((instruction
.type
>= ARM_LDR
) && (instruction
.type
<= ARM_LDRSH
))
521 uint32_t load_address
= 0, modified_address
= 0, load_value
;
522 uint32_t Rn
= sim
->get_reg_mode(sim
, instruction
.info
.load_store
.Rn
);
524 /* adjust Rn in case the PC is being read */
525 if (instruction
.info
.load_store
.Rn
== 15)
526 Rn
+= 2 * instruction_size
;
528 if (instruction
.info
.load_store
.offset_mode
== 0)
530 if (instruction
.info
.load_store
.U
)
531 modified_address
= Rn
+ instruction
.info
.load_store
.offset
.offset
;
533 modified_address
= Rn
- instruction
.info
.load_store
.offset
.offset
;
535 else if (instruction
.info
.load_store
.offset_mode
== 1)
538 uint32_t Rm
= sim
->get_reg_mode(sim
,
539 instruction
.info
.load_store
.offset
.reg
.Rm
);
540 uint8_t shift
= instruction
.info
.load_store
.offset
.reg
.shift
;
541 uint8_t shift_imm
= instruction
.info
.load_store
.offset
.reg
.shift_imm
;
542 uint8_t carry
= sim
->get_cpsr(sim
, 29, 1);
544 offset
= arm_shift(shift
, Rm
, shift_imm
, &carry
);
546 if (instruction
.info
.load_store
.U
)
547 modified_address
= Rn
+ offset
;
549 modified_address
= Rn
- offset
;
553 LOG_ERROR("BUG: offset_mode neither 0 (offset) nor 1 (scaled register)");
556 if (instruction
.info
.load_store
.index_mode
== 0)
559 * we load from the modified address, but don't change
560 * the base address register
562 load_address
= modified_address
;
563 modified_address
= Rn
;
565 else if (instruction
.info
.load_store
.index_mode
== 1)
568 * we load from the modified address, and write it
569 * back to the base address register
571 load_address
= modified_address
;
573 else if (instruction
.info
.load_store
.index_mode
== 2)
576 * we load from the unmodified address, and write the
577 * modified address back
582 if ((!dry_run_pc
) || (instruction
.info
.load_store
.Rd
== 15))
584 retval
= target_read_u32(target
, load_address
, &load_value
);
585 if (retval
!= ERROR_OK
)
591 if (instruction
.info
.load_store
.Rd
== 15)
592 *dry_run_pc
= load_value
& ~1;
594 *dry_run_pc
= current_pc
+ instruction_size
;
599 if ((instruction
.info
.load_store
.index_mode
== 1) ||
600 (instruction
.info
.load_store
.index_mode
== 2))
602 sim
->set_reg_mode(sim
, instruction
.info
.load_store
.Rn
, modified_address
);
605 if (instruction
.info
.load_store
.Rd
== 15) {
606 sim
->set_reg_mode(sim
, 15, load_value
& ~1);
608 sim
->set_state(sim
, ARM_STATE_THUMB
);
610 sim
->set_state(sim
, ARM_STATE_ARM
);
613 sim
->set_reg_mode(sim
, instruction
.info
.load_store
.Rd
, load_value
);
616 /* load multiple instruction */
617 else if (instruction
.type
== ARM_LDM
)
620 uint32_t Rn
= sim
->get_reg_mode(sim
, instruction
.info
.load_store_multiple
.Rn
);
621 uint32_t load_values
[16];
624 for (i
= 0; i
< 16; i
++)
626 if (instruction
.info
.load_store_multiple
.register_list
& (1 << i
))
630 switch (instruction
.info
.load_store_multiple
.addressing_mode
)
632 case 0: /* Increment after */
635 case 1: /* Increment before */
638 case 2: /* Decrement after */
639 Rn
= Rn
- (bits_set
* 4) + 4;
641 case 3: /* Decrement before */
642 Rn
= Rn
- (bits_set
* 4);
646 for (i
= 0; i
< 16; i
++)
648 if (instruction
.info
.load_store_multiple
.register_list
& (1 << i
))
650 if ((!dry_run_pc
) || (i
== 15))
652 target_read_u32(target
, Rn
, &load_values
[i
]);
660 if (instruction
.info
.load_store_multiple
.register_list
& 0x8000)
662 *dry_run_pc
= load_values
[15] & ~1;
668 enum armv4_5_mode mode
= sim
->get_mode(sim
);
671 if (instruction
.info
.load_store_multiple
.S
)
673 if (instruction
.info
.load_store_multiple
.register_list
& 0x8000)
679 for (i
= 0; i
< 16; i
++)
681 if (instruction
.info
.load_store_multiple
.register_list
& (1 << i
))
684 uint32_t val
= load_values
[i
];
685 sim
->set_reg_mode(sim
, i
, val
& ~1);
687 sim
->set_state(sim
, ARM_STATE_THUMB
);
689 sim
->set_state(sim
, ARM_STATE_ARM
);
691 sim
->set_reg_mode(sim
, i
, load_values
[i
]);
698 uint32_t spsr
= sim
->get_reg_mode(sim
, 16);
699 sim
->set_reg(sim
, ARMV4_5_CPSR
, spsr
);
702 /* base register writeback */
703 if (instruction
.info
.load_store_multiple
.W
)
704 sim
->set_reg_mode(sim
, instruction
.info
.load_store_multiple
.Rn
, Rn
);
706 if (instruction
.info
.load_store_multiple
.register_list
& 0x8000)
710 /* store multiple instruction */
711 else if (instruction
.type
== ARM_STM
)
717 /* STM wont affect PC (advance by instruction size */
721 uint32_t Rn
= sim
->get_reg_mode(sim
,
722 instruction
.info
.load_store_multiple
.Rn
);
724 enum armv4_5_mode mode
= sim
->get_mode(sim
);
726 for (i
= 0; i
< 16; i
++)
728 if (instruction
.info
.load_store_multiple
.register_list
& (1 << i
))
732 if (instruction
.info
.load_store_multiple
.S
)
737 switch (instruction
.info
.load_store_multiple
.addressing_mode
)
739 case 0: /* Increment after */
742 case 1: /* Increment before */
745 case 2: /* Decrement after */
746 Rn
= Rn
- (bits_set
* 4) + 4;
748 case 3: /* Decrement before */
749 Rn
= Rn
- (bits_set
* 4);
753 for (i
= 0; i
< 16; i
++)
755 if (instruction
.info
.load_store_multiple
.register_list
& (1 << i
))
757 target_write_u32(target
, Rn
, sim
->get_reg_mode(sim
, i
));
762 /* base register writeback */
763 if (instruction
.info
.load_store_multiple
.W
)
764 sim
->set_reg_mode(sim
,
765 instruction
.info
.load_store_multiple
.Rn
, Rn
);
769 else if (!dry_run_pc
)
771 /* the instruction wasn't handled, but we're supposed to simulate it
773 LOG_ERROR("Unimplemented instruction, could not simulate it.");
779 *dry_run_pc
= current_pc
+ instruction_size
;
784 sim
->set_reg(sim
, 15, current_pc
+ instruction_size
);
790 static uint32_t armv4_5_get_reg(struct arm_sim_interface
*sim
, int reg
)
792 struct arm
*armv4_5
= (struct arm
*)sim
->user_data
;
794 return buf_get_u32(armv4_5
->core_cache
->reg_list
[reg
].value
, 0, 32);
797 static void armv4_5_set_reg(struct arm_sim_interface
*sim
, int reg
, uint32_t value
)
799 struct arm
*armv4_5
= (struct arm
*)sim
->user_data
;
801 buf_set_u32(armv4_5
->core_cache
->reg_list
[reg
].value
, 0, 32, value
);
804 static uint32_t armv4_5_get_reg_mode(struct arm_sim_interface
*sim
, int reg
)
806 struct arm
*armv4_5
= (struct arm
*)sim
->user_data
;
808 return buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
,
809 armv4_5
->core_mode
, reg
).value
, 0, 32);
812 static void armv4_5_set_reg_mode(struct arm_sim_interface
*sim
, int reg
, uint32_t value
)
814 struct arm
*armv4_5
= (struct arm
*)sim
->user_data
;
816 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
,
817 armv4_5
->core_mode
, reg
).value
, 0, 32, value
);
820 static uint32_t armv4_5_get_cpsr(struct arm_sim_interface
*sim
, int pos
, int bits
)
822 struct arm
*armv4_5
= (struct arm
*)sim
->user_data
;
824 return buf_get_u32(armv4_5
->cpsr
->value
, pos
, bits
);
827 static enum armv4_5_state
armv4_5_get_state(struct arm_sim_interface
*sim
)
829 struct arm
*armv4_5
= (struct arm
*)sim
->user_data
;
831 return armv4_5
->core_state
;
834 static void armv4_5_set_state(struct arm_sim_interface
*sim
, enum armv4_5_state mode
)
836 struct arm
*armv4_5
= (struct arm
*)sim
->user_data
;
838 armv4_5
->core_state
= mode
;
842 static enum armv4_5_mode
armv4_5_get_mode(struct arm_sim_interface
*sim
)
844 struct arm
*armv4_5
= (struct arm
*)sim
->user_data
;
846 return armv4_5
->core_mode
;
851 int arm_simulate_step(struct target
*target
, uint32_t *dry_run_pc
)
853 struct arm
*armv4_5
= target_to_armv4_5(target
);
854 struct arm_sim_interface sim
;
856 sim
.user_data
= armv4_5
;
857 sim
.get_reg
= &armv4_5_get_reg
;
858 sim
.set_reg
= &armv4_5_set_reg
;
859 sim
.get_reg_mode
= &armv4_5_get_reg_mode
;
860 sim
.set_reg_mode
= &armv4_5_set_reg_mode
;
861 sim
.get_cpsr
= &armv4_5_get_cpsr
;
862 sim
.get_mode
= &armv4_5_get_mode
;
863 sim
.get_state
= &armv4_5_get_state
;
864 sim
.set_state
= &armv4_5_set_state
;
866 return arm_simulate_step_core(target
, dry_run_pc
, &sim
);