📄 singlestep.c
字号:
{
case 0x0: break;
case 0x1: mem_value = ror(mem_value, 8); break;
case 0x2: mem_value = ror(mem_value, 16); break;
case 0x3: mem_value = ror(mem_value, 24); break;
}
} else {
/*
* Byte load of the PC
*/
if (bsp_memory_read((void*)operand, 0, 8, 1, &mem_value) == 0)
{
/*
* Unable to read the memory address.
* Don't try any further.
*/
#if DEBUG_SINGLESTEP
bsp_printf("Setting BP at *(0x%08lx): Error\n", operand & ~0x3);
#endif /* DEBUG_SINGLESTEP */
return;
} else {
#if DEBUG_SINGLESTEP
bsp_printf("Setting BP at *(0x%08lx): data <0x%08lx>\n", operand & ~0x3, mem_value);
#endif /* DEBUG_SINGLESTEP */
}
}
insert_ss_break((unsigned long *)mem_value);
}
/*
* Calculate a load/store w/ Immediate offset operand based on input
* source register, offset value, and opcode (add/sub)
*/
static unsigned long load_store_immediate_operand(ex_regs_t *regs,
unsigned p_bit,
unsigned u_bit,
unsigned Rn,
unsigned offset)
{
unsigned char *regs_array = (unsigned char *)regs;
unsigned char *reg_ptr = ®s_array[bsp_regbyte(Rn)];
unsigned long rc = *((unsigned long *)(reg_ptr));
BSP_ASSERT((Rn >= 0) && (Rn <= 0xf));
BSP_ASSERT(bsp_regsize(Rn) == sizeof(unsigned long));
BSP_ASSERT((offset >= 0) && (offset <= 0xfff));
BSP_ASSERT((p_bit >= 0) && (p_bit <= 1));
BSP_ASSERT((u_bit >= 0) && (u_bit <= 1));
/*
* According to the ARM(R) Manual, if Rn is PC then,
* the value used is the address of the current instruction
* plus 8
*/
if (Rn == REG_PC)
rc += 8;
/*
* Do the update pre-index update
*/
if (p_bit == LS_INDEX_PRE)
{
if (u_bit == LS_OFFSET_SUB)
rc -= offset;
else /* opcode == LS_OFFSET_ADD */
rc += offset;
}
return (rc);
}
/*
* Calculate a load/store w/ Register offset operand based on input
* source register, offset value, and opcode (add/sub)
*
* This calculates the appropriate pre-indexed operand
*/
static unsigned long load_store_register_operand(ex_regs_t *regs,
unsigned p_bit,
unsigned u_bit,
unsigned Rn,
unsigned Rm,
unsigned shift,
unsigned shift_immed)
{
unsigned char *regs_array = (unsigned char *)regs;
unsigned char *Rn_ptr = ®s_array[bsp_regbyte(Rn)];
unsigned long Rn_val = *((unsigned long *)(Rn_ptr));
unsigned long rc, index;
BSP_ASSERT((Rn >= 0) && (Rn <= 0xf));
BSP_ASSERT((Rm >= 0) && (Rm <= 0xf));
BSP_ASSERT(bsp_regsize(Rn) == sizeof(unsigned long));
BSP_ASSERT(bsp_regsize(Rm) == sizeof(unsigned long));
BSP_ASSERT((p_bit >= 0) && (p_bit <= 1));
BSP_ASSERT((u_bit >= 0) && (u_bit <= 1));
BSP_ASSERT((shift >= 0) && (shift <= 0x3));
BSP_ASSERT((shift_immed >= 0) && (shift_immed <= 0x1F));
/*
* According to the ARM(R) Manual, if Rn is PC then
* the value used is the address of the current
* instruction plus 8
*/
if (Rn == REG_PC)
Rn_val += 8;
/*
* According to the ARM(R) Manual, if Rm is PC then
* the result is unpredictable. Don't do anything
* here. Just return.
*/
if (Rm == REG_PC)
return 0;
index = immediate_shift_operand(regs, shift_immed, shift, Rm);
rc = Rn_val;
/*
* Do the update pre-index update
*/
if (p_bit == LS_INDEX_PRE)
{
if (u_bit == LS_OFFSET_SUB)
rc = Rn_val - index;
else /* opcode == LS_OFFSET_ADD */
rc = Rn_val + index;
}
return (rc);
}
/*
* Decode all data processing immediate instructions
*/
static void decode_dpi_inst(ex_regs_t *regs, union arm_insn inst)
{
if (inst.dpi.Rd == REG_PC)
{
unsigned long operand = ror(inst.dpi.immediate, (inst.dpi.rotate << 1));
unsigned long *dest = 0;
unsigned carry = ((union arm_psr)(unsigned long)(regs->_cpsr)).psr.c_bit;
unsigned char *regs_array = (unsigned char *)regs;
unsigned char *Rn_ptr = ®s_array[bsp_regbyte(inst.dpi.Rn)];
unsigned long Rn_val = *((unsigned long *)(Rn_ptr));
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("Decoded an data processing immediate instruction.\n");
bsp_printf("inst.dpi.immediate = 0x%x\n", inst.dpi.immediate);
bsp_printf("inst.dpi.rotate = 0x%x\n", inst.dpi.rotate);
bsp_printf("inst.dpi.Rd = 0x%x\n", inst.dpi.Rd);
bsp_printf("inst.dpi.Rn = 0x%x\n", inst.dpi.Rn);
bsp_printf("inst.dpi.S_bit = 0x%x\n", inst.dpi.S_bit);
bsp_printf("inst.dpi.opcode = 0x%x\n", inst.dpi.opcode);
bsp_printf("inst.dpi.cond = 0x%x\n", inst.dpi.cond);
bsp_printf("operand = 0x%x\n", operand);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
/*
* According to the ARM(R) Manual, if Rn is PC then
* the value used is the address of the current
* instruction plus 8
*/
if (inst.dpi.Rn == REG_PC)
Rn_val += 8;
switch (inst.dpi.opcode) {
case DP_OPCODE_ADC: dest = (unsigned long *)(Rn_val + operand + carry); break;
case DP_OPCODE_ADD: dest = (unsigned long *)(Rn_val + operand); break;
case DP_OPCODE_AND: dest = (unsigned long *)(Rn_val & operand); break;
case DP_OPCODE_BIC: dest = (unsigned long *)(Rn_val & ~operand); break;
case DP_OPCODE_EOR: dest = (unsigned long *)(Rn_val ^ operand); break;
case DP_OPCODE_MOV: dest = (unsigned long *)operand; break;
case DP_OPCODE_MVN: dest = (unsigned long *)(~operand); break;
case DP_OPCODE_ORR: dest = (unsigned long *)(Rn_val | operand); break;
case DP_OPCODE_RSB: dest = (unsigned long *)(operand - Rn_val); break;
case DP_OPCODE_RSC: dest = (unsigned long *)(operand - Rn_val - !carry); break;
case DP_OPCODE_SBC: dest = (unsigned long *)(Rn_val - operand - !carry); break;
case DP_OPCODE_SUB: dest = (unsigned long *)(Rn_val - operand); break;
default: dest = (unsigned long *)0; break;
}
dest = (unsigned long *)((unsigned long)dest & ~0x3);
insert_ss_break(dest);
}
}
/*
* Decode all data processing immediate w/ shift instructions
*/
static void decode_dpis_inst(ex_regs_t *regs, union arm_insn inst)
{
if (inst.dpis.Rd == REG_PC)
{
unsigned long operand = immediate_shift_operand(regs, inst.dpis.shift_immed,
inst.dpis.shift, inst.dpis.Rm);
unsigned long *dest = 0;
unsigned carry = ((union arm_psr)(unsigned long)(regs->_cpsr)).psr.c_bit;
unsigned char *regs_array = (unsigned char *)regs;
unsigned char *Rn_ptr = ®s_array[bsp_regbyte(inst.dpis.Rn)];
unsigned long Rn_val = *((unsigned long *)(Rn_ptr));
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("Decoded an data processing immediate shift instruction.\n");
bsp_printf("inst.dpis.Rm = 0x%x\n", inst.dpis.Rm);
bsp_printf("inst.dpis.shift = 0x%x\n", inst.dpis.shift);
bsp_printf("inst.dpis.shift_immed = 0x%x\n", inst.dpis.shift_immed);
bsp_printf("inst.dpis.Rd = 0x%x\n", inst.dpis.Rd);
bsp_printf("inst.dpis.Rn = 0x%x\n", inst.dpis.Rn);
bsp_printf("inst.dpis.S_bit = 0x%x\n", inst.dpis.S_bit);
bsp_printf("inst.dpis.opcode = 0x%x\n", inst.dpis.opcode);
bsp_printf("inst.dpis.cond = 0x%x\n", inst.dpis.cond);
bsp_printf("operand = 0x%x\n", operand);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
/*
* According to the ARM(R) Manual, if Rn is PC then
* the value used is the address of the current
* instruction plus 8
*/
if (inst.dpis.Rn == REG_PC)
Rn_val += 8;
switch (inst.dpis.opcode) {
case DP_OPCODE_ADC: dest = (unsigned long *)(Rn_val + operand + carry); break;
case DP_OPCODE_ADD: dest = (unsigned long *)(Rn_val + operand); break;
case DP_OPCODE_AND: dest = (unsigned long *)(Rn_val & operand); break;
case DP_OPCODE_BIC: dest = (unsigned long *)(Rn_val & ~operand); break;
case DP_OPCODE_EOR: dest = (unsigned long *)(Rn_val ^ operand); break;
case DP_OPCODE_MOV: dest = (unsigned long *)operand; break;
case DP_OPCODE_MVN: dest = (unsigned long *)(~operand); break;
case DP_OPCODE_ORR: dest = (unsigned long *)(Rn_val | operand); break;
case DP_OPCODE_RSB: dest = (unsigned long *)(operand - Rn_val); break;
case DP_OPCODE_RSC: dest = (unsigned long *)(operand - Rn_val - !carry); break;
case DP_OPCODE_SBC: dest = (unsigned long *)(Rn_val - operand - !carry); break;
case DP_OPCODE_SUB: dest = (unsigned long *)(Rn_val - operand); break;
default: dest = (unsigned long *)0; break;
}
dest = (unsigned long *)((unsigned long)dest & ~0x3);
insert_ss_break(dest);
}
}
/*
* Decode all data processing register w/ shift instructions
*/
static void decode_dprs_inst(ex_regs_t *regs, union arm_insn inst)
{
if (inst.dprs.Rd == REG_PC)
{
unsigned long operand = register_shift_operand(regs, inst.dprs.Rs,
inst.dprs.shift, inst.dprs.Rm);
unsigned long *dest = 0;
unsigned carry = ((union arm_psr)(unsigned long)(regs->_cpsr)).psr.c_bit;
unsigned char *regs_array = (unsigned char *)regs;
unsigned char *Rn_ptr = ®s_array[bsp_regbyte(inst.dprs.Rn)];
unsigned long Rn_val = *((unsigned long *)(Rn_ptr));
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("Decoded an data processing register shift instruction.\n");
bsp_printf("inst.dprs.Rm = 0x%x\n", inst.dprs.Rm);
bsp_printf("inst.dprs.rsv3 = 0x%x\n", inst.dprs.rsv3);
bsp_printf("inst.dprs.shift = 0x%x\n", inst.dprs.shift);
bsp_printf("inst.dprs.rsv2 = 0x%x\n", inst.dprs.rsv2);
bsp_printf("inst.dprs.Rs = 0x%x\n", inst.dprs.Rs);
bsp_printf("inst.dprs.Rd = 0x%x\n", inst.dprs.Rd);
bsp_printf("inst.dprs.Rn = 0x%x\n", inst.dprs.Rn);
bsp_printf("inst.dprs.S_bit = 0x%x\n", inst.dprs.S_bit);
bsp_printf("inst.dprs.opcode = 0x%x\n", inst.dprs.opcode);
bsp_printf("inst.dprs.rsv1 = 0x%x\n", inst.dprs.rsv1);
bsp_printf("inst.dprs.cond = 0x%x\n", inst.dprs.cond);
bsp_printf("operand = 0x%x\n", operand);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
/*
* According to the ARM(R) Manual, if Rn is PC then
* the value used is the address of the current
* instruction plus 8
*/
if (inst.dprs.Rn == REG_PC)
Rn_val += 8;
switch (inst.dprs.opcode) {
case DP_OPCODE_ADC: dest = (unsigned long *)(Rn_val + operand + carry); break;
case DP_OPCODE_ADD: dest = (unsigned long *)(Rn_val + operand); break;
case DP_OPCODE_AND: dest = (unsigned long *)(Rn_val & operand); break;
case DP_OPCODE_BIC: dest = (unsigned long *)(Rn_val & ~operand); break;
case DP_OPCODE_EOR: dest = (unsigned long *)(Rn_val ^ operand); break;
case DP_OPCODE_MOV: dest = (unsigned long *)operand; break;
case DP_OPCODE_MVN: dest = (unsigned long *)(~operand); break;
case DP_OPCODE_ORR: dest = (unsigned long *)(Rn_val | operand); break;
case DP_OPCODE_RSB: dest = (unsigned long *)(operand - Rn_val); break;
case DP_OPCODE_RSC: dest = (unsigned long *)(operand - Rn_val - !carry); break;
case DP_OPCODE_SBC: dest = (unsigned long *)(Rn_val - operand - !carry); break;
case DP_OPCODE_SUB: dest = (unsigned long *)(Rn_val - operand); break;
default: dest = (unsigned long *)0; break;
}
dest = (unsigned long *)((unsigned long)dest & ~0x3);
insert_ss_break(dest);
}
}
/*
* Decode all multiply instructions
*/
static void decode_m_inst(ex_regs_t *regs, union arm_insn inst)
{
/*
* According to the ARM(R) Manual, if Rd is PC then
* the result is unpredictable. Don't do anything
* here. Just return.
*/
}
/*
* Decode all multiply long instructions
*/
static void decode_ml_inst(ex_regs_t *regs, union arm_insn inst)
{
/*
* According to the ARM(R) Manual, if Rd is PC then
* the result is unpredictable. Don't do anything
* here. Just return.
*/
}
/*
* Decode all move from status register instructions
*/
static void decode_mrs_inst(ex_regs_t *regs, union arm_insn inst)
{
#if 0
if (inst.mrs.Rd == REG_PC)
{
unsigned long *dest = 0;
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("Decoded an move from status register instruction.\n");
bsp_printf("inst.mrs.SBZ = 0x%x\n", inst.mrs.SBZ);
bsp_printf("inst.mrs.Rd = 0x%x\n", inst.mrs.Rd);
bsp_printf("inst.mrs.SBO = 0x%x\n", inst.mrs.SBO);
bsp_printf("inst.mrs.rsv2 = 0x%x\n", inst.mrs.rsv2);
bsp_printf("inst.mrs.R_bit = 0x%x\n", inst.mrs.R_bit);
bsp_printf("inst.mrs.rsv1 = 0x%x\n", inst.mrs.rsv1);
bsp_printf("inst.mrs.cond = 0x%x\n", inst.mrs.cond);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
if (inst.mrs.R_bit == 1)
dest = (unsigned long *)regs->_spsr;
else
dest = (unsigned long *)regs->_cpsr;
dest = (unsigned long *)((unsigned long)dest & ~0x3);
insert_ss_break(dest);
}
#endif
}
/*
* Decode all move immediate to status register instructions
*/
static void decode_misr_inst(ex_regs_t *regs, union arm_insn inst)
{
/*
* Can't update the PC w/ this instruction.
* Don't set any more breakpoints
*/
}
/*
* Decode all move register to status registers instructions
*/
static void decode_mrsr_inst(ex_regs_t *regs, union arm_insn inst)
{
/*
* Can't update the PC w/ this instruction.
* Don't set any more breakpoints
*/
}
/*
* Decode all branch/exchange instructions
*/
static void decode_bx_inst(ex_regs_t *regs, union arm_insn inst)
{
unsigned long operand = branch_exchange_operand(regs, inst.bx.Rm);
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("Decoded an branch/exchange shift instruction.\n");
bsp_printf("inst.bx.Rm = 0x%x\n", inst.bx.Rm);
bsp_printf("inst.bx.rsv2 = 0x%x\n", inst.bx.rsv2);
bsp_printf("inst.bx.SBO3 = 0x%x\n", inst.bx.SBO3);
bsp_printf("inst.bx.SBO2 = 0x%x\n", inst.bx.SBO2);
bsp_printf("inst.bx.SBO1 = 0x%x\n", inst.bx.SBO1);
bsp_printf("inst.bx.rsv1 = 0x%x\n", inst.bx.rsv1);
bsp_printf("inst.bx.cond = 0x%x\n", inst.bx.cond);
bsp_printf("operand = 0x%x\n", operand);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
insert_ss_break((unsigned long *)operand);
}
/*
* Decode all load/store immediate offset instructions
*/
static void decode_lsio_inst(ex_regs_t *regs, union arm_insn inst)
{
/*
* Only support direct loads of the PC
*
* According to the ARM(R) manual, automatic updates of the PC
* are UNPREDICTABLE (ie implementation defined).
*/
if ((inst.lsio.Rd == REG_PC) && (inst.lsio.L_bit == LS_LOAD))
{
unsigned long operand = load_store_immediate_operand(regs, inst.lsio.P_bit,
inst.lsio.U_bit, inst.lsio.Rn,
inst.lsio.immediate);
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("Decoded an load/store w/ immediate offset instruction.\n");
bsp_printf("inst.lsio.immediate = 0x%x\n", inst.lsio.immediate);
bsp_printf("inst.lsio.Rd = 0x%x\n", inst.lsio.Rd);
bsp_printf("inst.lsio.Rn = 0x%x\n", inst.lsio.Rn);
bsp_printf("inst.lsio.L_bit = 0x%x\n", inst.lsio.L_bit);
bsp_printf("inst.lsio.W_bit = 0x%x\n", inst.lsio.W_bit);
bsp_printf("inst.lsio.B_bit = 0x%x\n", inst.lsio.B_bit);
bsp_printf("inst.lsio.U_bit = 0x%x\n", inst.lsio.U_bit);
bsp_printf("inst.lsio.P_bit = 0x%x\n", inst.lsio.P_bit);
bsp_printf("inst.lsio.rsv1 = 0x%x\n", inst.lsio.rsv1);
bsp_printf("inst.lsio.cond = 0x%x\n", inst.lsio.cond);
bsp_printf("operand = 0x%x\n", operand);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -