📄 singlestep.c
字号:
handle_pc_load(inst.lsio.B_bit, operand);
}
}
/*
* Decode all load/store register offset instructions
*/
static void decode_lsro_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.lsro.Rd == REG_PC) && (inst.lsro.L_bit == LS_LOAD))
{
unsigned long operand = load_store_register_operand(regs,
inst.lsro.P_bit,
inst.lsro.U_bit,
inst.lsro.Rn,
inst.lsro.Rm,
inst.lsro.shift,
inst.lsro.shift_immed);
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("Decoded an load/store w/ register offset instruction.\n");
bsp_printf("inst.lsro.Rm = 0x%x\n", inst.lsro.Rm);
bsp_printf("inst.lsro.rsv2 = 0x%x\n", inst.lsro.rsv2);
bsp_printf("inst.lsro.shift = 0x%x\n", inst.lsro.shift);
bsp_printf("inst.lsro.shift_immed = 0x%x\n", inst.lsro.shift_immed);
bsp_printf("inst.lsro.Rd = 0x%x\n", inst.lsro.Rd);
bsp_printf("inst.lsro.Rn = 0x%x\n", inst.lsro.Rn);
bsp_printf("inst.lsro.L_bit = 0x%x\n", inst.lsro.L_bit);
bsp_printf("inst.lsro.W_bit = 0x%x\n", inst.lsro.W_bit);
bsp_printf("inst.lsro.B_bit = 0x%x\n", inst.lsro.B_bit);
bsp_printf("inst.lsro.U_bit = 0x%x\n", inst.lsro.U_bit);
bsp_printf("inst.lsro.P_bit = 0x%x\n", inst.lsro.P_bit);
bsp_printf("inst.lsro.rsv1 = 0x%x\n", inst.lsro.rsv1);
bsp_printf("inst.lsro.cond = 0x%x\n", inst.lsro.cond);
bsp_printf("operand = 0x%x\n", operand);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
handle_pc_load(inst.lsro.B_bit, operand);
}
}
/*
* Decode all load/store halfword/signed byte immediate offset instructions
*/
static void decode_lshwi_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 load/store halfword/signed byte register offset instructions
*/
static void decode_lshwr_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 swap/swap byte instructions
*/
static void decode_swap_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 load/store multiple instructions
*/
static void decode_lsm_inst(ex_regs_t *regs, union arm_insn inst)
{
/*
* Only support direct load multiples where the PC is in the
* register list.
*
* According to the ARM(R) manual, automatic updates of the PC
* are UNPREDICTABLE (ie implementation defined).
*/
if ((inst.lsm.L_bit == LS_LOAD) && (inst.lsm.Reg_List & (0x1 << REG_PC)))
{
unsigned char *regs_array = (unsigned char *)regs;
unsigned char *Rn_ptr = ®s_array[bsp_regbyte(inst.lsm.Rn)];
unsigned long Rn_val = *((unsigned long *)(Rn_ptr));
unsigned long offset_to_pc = 0;
int i;
unsigned long **dest = 0;
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("Decoded an load multiple instruction.\n");
bsp_printf("inst.lsm.Reg_List = 0x%x\n", inst.lsm.Reg_List);
bsp_printf("inst.lsm.Rn = 0x%x\n", inst.lsm.Rn);
bsp_printf("inst.lsm.L_bit = 0x%x\n", inst.lsm.L_bit);
bsp_printf("inst.lsm.W_bit = 0x%x\n", inst.lsm.W_bit);
bsp_printf("inst.lsm.S_bit = 0x%x\n", inst.lsm.S_bit);
bsp_printf("inst.lsm.U_bit = 0x%x\n", inst.lsm.U_bit);
bsp_printf("inst.lsm.P_bit = 0x%x\n", inst.lsm.P_bit);
bsp_printf("inst.lsm.rsv1 = 0x%x\n", inst.lsm.rsv1);
bsp_printf("inst.lsm.cond = 0x%x\n", inst.lsm.cond);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
if (inst.lsm.U_bit == 0)
{
/*
* We are using a ascending stack.
* That means the PC is actually the register
* nearest to Rn currently.
*/
if (inst.lsm.P_bit == 1)
/*
* Using a pre-decrement.
*/
offset_to_pc = -bsp_regsize(REG_PC);
else
offset_to_pc = 0;
} else {
/*
* We are using an descending stack.
* That means the PC is actually the register
* farthest from Rn currently.
*
* Find the number of registers stored before the PC
*/
for (i = 0; i < REG_PC; i++)
{
if ((inst.lsm.Reg_List & (0x1 << i)) != 0)
{
/*
* Bit #i is set. Increment our count.
*/
offset_to_pc += bsp_regsize(i);
}
}
/*
* Adjust the offset if we do a decrement/increment __BEFORE__
* the write.
*/
if (inst.lsm.P_bit == 1)
offset_to_pc += bsp_regsize(REG_PC);
}
/*
* Now let's calculate the real address of the stored PC
* making sure to mask out the two LO bits.
*/
dest = (unsigned long **)((Rn_val + offset_to_pc) & ~0x3);
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("Rn_val = 0x%08lx\n", Rn_val);
bsp_printf("offset_to_pc = 0x%08lx\n", offset_to_pc);
bsp_printf("dest = 0x%08lx\n", dest);
bsp_printf("*dest = 0x%08lx\n", *dest);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
insert_ss_break(*dest);
}
}
/*
* Decode all coprocessor data processing instructions
*/
static void decode_cpdp_inst(ex_regs_t *regs, union arm_insn inst)
{
/*
* Can't possibly predict what this instruction will do.
* Don't do anything here. Just return.
*/
}
/*
* Decode all coprocessor register transfer instructions
*/
static void decode_cprt_inst(ex_regs_t *regs, union arm_insn inst)
{
/*
* Can't possibly predict what this instruction will do.
* Don't do anything here. Just return.
*/
}
/*
* Decode all coprocessor load/store instructions
*/
static void decode_cpls_inst(ex_regs_t *regs, union arm_insn inst)
{
/*
* Can't possibly predict what this instruction will do.
* Don't do anything here. Just return.
*/
}
/*
* Decode all branch/branch w/ link instructions
*/
static void decode_bbl_inst(ex_regs_t *regs, union arm_insn inst)
{
unsigned long disp = inst.bbl.offset;
/*
* Sign extend the 24 bit value
*/
if (disp & 0x00800000)
disp |= 0xff000000;
/*
* Convert to long words
*/
disp <<= 2;
/*
* Note: when the processor actually executes this instruction, the pc
* will point to the address of the current instruction + 8 because
* of the fetch/decode/execute cycle
*/
disp += 8;
insert_ss_break((unsigned long *)(regs->_pc + disp));
}
/*
* Decode all swi instructions
*/
static void decode_swi_inst(ex_regs_t *regs, union arm_insn inst)
{
/*
* Can't possibly predict where we should set the breakpoint for this.
* Don't do anything here. Just return.
*/
}
/*
* Decode all undefined instructions
*/
static void decode_undef_inst(ex_regs_t *regs, union arm_insn inst)
{
/*
* Can't possibly predict what this instruction will do.
* Don't do anything here. Just return.
*/
}
/*
* Set breakpoint instructions for single stepping.
*/
void
bsp_singlestep_setup(void *registers)
{
ex_regs_t *regs = (ex_regs_t *)registers;
union arm_insn inst;
if (bsp_memory_read((void*)(regs->_pc), 0, ARM_INST_SIZE * 8, 1, &(inst.word)) == 0)
{
/*
* Unable to read the instruction at the current address.
* Let's not do anything with this. We can't set breakpoints
* so let's get out now.
*/
return;
}
/*
* Handle the simple case -- linear code
*/
insert_ss_break((unsigned long *)(regs->_pc + ARM_INST_SIZE));
/*
* Now, we need to decode the instructions and figure out what
* they would do.
*/
if ((inst.mrs.rsv1 == MRS_RSV1_VALUE) &&
(inst.mrs.rsv2 == MRS_RSV2_VALUE)) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("MRS type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_mrs_inst(regs, inst);
} else if ((inst.misr.rsv1 == MISR_RSV1_VALUE) &&
(inst.misr.rsv2 == MISR_RSV2_VALUE)) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("MISR type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_misr_inst(regs, inst);
} else if ((inst.mrsr.rsv1 == MRSR_RSV1_VALUE) &&
(inst.mrsr.rsv2 == MRSR_RSV2_VALUE) &&
(inst.mrsr.rsv3 == MRSR_RSV3_VALUE)) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("MRSR type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_mrsr_inst(regs, inst);
} else if (inst.dpi.rsv1 == DPI_RSV1_VALUE) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("DPI type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_dpi_inst(regs, inst);
} else if ((inst.bx.rsv1 == BX_RSV1_VALUE) &&
(inst.bx.rsv2 == BX_RSV2_VALUE)) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("BX type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_bx_inst(regs, inst);
} else if ((inst.dpis.rsv1 == DPIS_RSV1_VALUE) &&
(inst.dpis.rsv2 == DPIS_RSV2_VALUE)) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("DPIS type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_dpis_inst(regs, inst);
} else if ((inst.dprs.rsv1 == DPRS_RSV1_VALUE) &&
(inst.dprs.rsv2 == DPRS_RSV2_VALUE) &&
(inst.dprs.rsv3 == DPRS_RSV3_VALUE)) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("DPRS type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_dprs_inst(regs, inst);
} else if ((inst.m.rsv1 == M_RSV1_VALUE) &&
(inst.m.rsv2 == M_RSV2_VALUE)) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("M type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_m_inst(regs, inst);
} else if ((inst.ml.rsv1 == ML_RSV1_VALUE) &&
(inst.ml.rsv2 == ML_RSV2_VALUE)) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("ML type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_ml_inst(regs, inst);
} else if (inst.lsio.rsv1 == LSIO_RSV1_VALUE) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("LSIO type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_lsio_inst(regs, inst);
} else if ((inst.lsro.rsv1 == LSRO_RSV1_VALUE) &&
(inst.lsro.rsv2 == LSRO_RSV2_VALUE)) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("LSRO type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_lsro_inst(regs, inst);
} else if ((inst.lshwi.rsv1 == LSHWI_RSV1_VALUE) &&
(inst.lshwi.rsv2 == LSHWI_RSV2_VALUE) &&
(inst.lshwi.rsv3 == LSHWI_RSV3_VALUE) &&
(inst.lshwi.rsv4 == LSHWI_RSV4_VALUE)) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("LSHWI type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_lshwi_inst(regs, inst);
} else if ((inst.lshwr.rsv1 == LSHWR_RSV1_VALUE) &&
(inst.lshwr.rsv2 == LSHWR_RSV2_VALUE) &&
(inst.lshwr.rsv3 == LSHWR_RSV3_VALUE) &&
(inst.lshwr.rsv4 == LSHWR_RSV4_VALUE)) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("LSHWR type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_lshwr_inst(regs, inst);
} else if ((inst.swap.rsv1 == SWAP_RSV1_VALUE) &&
(inst.swap.rsv2 == SWAP_RSV2_VALUE) &&
(inst.swap.rsv3 == SWAP_RSV3_VALUE)) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("SWAP type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_swap_inst(regs, inst);
} else if (inst.lsm.rsv1 == LSM_RSV1_VALUE) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("LSM type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_lsm_inst(regs, inst);
} else if ((inst.cpdp.rsv1 == CPDP_RSV1_VALUE) &&
(inst.cpdp.rsv2 == CPDP_RSV2_VALUE)) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("CPDP type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_cpdp_inst(regs, inst);
} else if ((inst.cprt.rsv1 == CPRT_RSV1_VALUE) &&
(inst.cprt.rsv2 == CPRT_RSV2_VALUE)) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("CPRT type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_cprt_inst(regs, inst);
} else if (inst.cpls.rsv1 == CPLS_RSV1_VALUE) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("CPLS type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_cpls_inst(regs, inst);
} else if (inst.bbl.rsv1 == BBL_RSV1_VALUE) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("BBL type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_bbl_inst(regs, inst);
} else if (inst.swi.rsv1 == SWI_RSV1_VALUE) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("SWI type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_swi_inst(regs, inst);
} else if ((inst.undef.rsv1 == UNDEF_RSV1_VALUE) &&
(inst.undef.rsv2 == UNDEF_RSV2_VALUE)) {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("UNDEF type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
decode_undef_inst(regs, inst);
} else {
#if DEBUG_SINGLESTEP_VERBOSE
bsp_printf("Unknown instruction type: 0x%08lx\n", inst.word);
#endif /* DEBUG_SINGLESTEP_VERBOSE */
}
}
void
bsp_skip_instruction(void *registers)
{
ex_regs_t *regs = (ex_regs_t *)registers;
regs->_pc += ARM_INST_SIZE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -