X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farm_simulator.c;h=00fbb2d78fdb9bb8fa77a2b14f10a21f505a91ff;hp=b47606d633bb55a20852f50df3ab88881cc45ebc;hb=68b05c55759970657c32607b3ce27c42e65cdad0;hpb=542df344112808c700940769d3f5ab134a0e1e75 diff --git a/src/target/arm_simulator.c b/src/target/arm_simulator.c index b47606d633..00fbb2d78f 100644 --- a/src/target/arm_simulator.c +++ b/src/target/arm_simulator.c @@ -2,6 +2,9 @@ * Copyright (C) 2006 by Dominic Rath * * Dominic.Rath@gmx.de * * * + * Copyright (C) 2008 by Hongtao Zheng * + * hontor@126.com * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -21,14 +24,12 @@ #include "config.h" #endif -#include "target.h" #include "armv4_5.h" #include "arm_disassembler.h" #include "arm_simulator.h" #include "log.h" #include "binarybuffer.h" -#include u32 arm_shift(u8 shift, u32 Rm, u32 shift_amount, u8 *carry) { @@ -160,7 +161,7 @@ u32 arm_shifter_operand(armv4_5_common_t *armv4_5, int variant, union arm_shifte } else { - ERROR("BUG: shifter_operand.variant not 0, 1 or 2"); + LOG_ERROR("BUG: shifter_operand.variant not 0, 1 or 2"); return_value = 0xffffffff; } @@ -253,7 +254,7 @@ int pass_condition(u32 cpsr, u32 opcode) } - ERROR("BUG: should never get here"); + LOG_ERROR("BUG: should never get here"); return 0; } @@ -272,14 +273,21 @@ int arm_simulate_step(target_t *target, u32 *dry_run_pc) u32 current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32); arm_instruction_t instruction; int instruction_size; + int retval = ERROR_OK; if (armv4_5->core_state == ARMV4_5_STATE_ARM) { u32 opcode; /* get current instruction, and identify it */ - target_read_u32(target, current_pc, &opcode); - arm_evaluate_opcode(opcode, current_pc, &instruction); + if((retval = target_read_u32(target, current_pc, &opcode)) != ERROR_OK) + { + return retval; + } + if((retval = arm_evaluate_opcode(opcode, current_pc, &instruction)) != ERROR_OK) + { + return retval; + } instruction_size = 4; /* check condition code (for all instructions) */ @@ -301,8 +309,14 @@ int arm_simulate_step(target_t *target, u32 *dry_run_pc) { u16 opcode; - target_read_u16(target, current_pc, &opcode); - thumb_evaluate_opcode(opcode, current_pc, &instruction); + if((retval = target_read_u16(target, current_pc, &opcode)) != ERROR_OK) + { + return retval; + } + if((retval = thumb_evaluate_opcode(opcode, current_pc, &instruction)) != ERROR_OK) + { + return retval; + } instruction_size = 2; /* check condition code (only for branch instructions) */ @@ -336,6 +350,10 @@ int arm_simulate_step(target_t *target, u32 *dry_run_pc) else { 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); + if(instruction.info.b_bl_bx_blx.reg_operand == 15) + { + target += 2 * instruction_size; + } } if (dry_run_pc) @@ -395,7 +413,12 @@ int arm_simulate_step(target_t *target, u32 *dry_run_pc) u8 carry_out; Rd = 0x0; - 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); + /* ARM_MOV and ARM_MVN does not use Rn */ + if ((instruction.type != ARM_MOV) && (instruction.type != ARM_MVN)) + 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); + else + Rn = 0; + shifter_operand = arm_shifter_operand(armv4_5, instruction.info.data_proc.variant, instruction.info.data_proc.shifter_operand, &carry_out); /* adjust Rn in case the PC is being read */ @@ -426,6 +449,8 @@ int arm_simulate_step(target_t *target, u32 *dry_run_pc) Rd = shifter_operand; else if (instruction.type == ARM_MVN) Rd = ~shifter_operand; + else + LOG_WARNING("unhandled instruction type"); if (dry_run_pc) { @@ -444,7 +469,7 @@ int arm_simulate_step(target_t *target, u32 *dry_run_pc) else { 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); - WARNING("no updating of flags yet"); + LOG_WARNING("no updating of flags yet"); if (instruction.info.data_proc.Rd == 15) return ERROR_OK; @@ -460,7 +485,7 @@ int arm_simulate_step(target_t *target, u32 *dry_run_pc) } else { - WARNING("no updating of flags yet"); + LOG_WARNING("no updating of flags yet"); } } /* load register instructions */ @@ -497,7 +522,7 @@ int arm_simulate_step(target_t *target, u32 *dry_run_pc) } else { - ERROR("BUG: offset_mode neither 0 (offset) nor 1 (scaled register)"); + LOG_ERROR("BUG: offset_mode neither 0 (offset) nor 1 (scaled register)"); } if (instruction.info.load_store.index_mode == 0) @@ -520,7 +545,13 @@ int arm_simulate_step(target_t *target, u32 *dry_run_pc) load_address = Rn; } - target_read_u32(target, load_address, &load_value); + if((!dry_run_pc) || (instruction.info.load_store.Rd == 15)) + { + if((retval = target_read_u32(target, load_address, &load_value)) != ERROR_OK) + { + return retval; + } + } if (dry_run_pc) { @@ -583,7 +614,10 @@ int arm_simulate_step(target_t *target, u32 *dry_run_pc) { if (instruction.info.load_store_multiple.register_list & (1 << i)) { - target_read_u32(target, Rn, &load_values[i]); + if((!dry_run_pc) || (i == 15)) + { + target_read_u32(target, Rn, &load_values[i]); + } Rn += 4; } }