⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 singlestep.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        {
        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 = &regs_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 = &regs_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 = &regs_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 = &regs_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 = &regs_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 + -