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

📄 singlestep.c

📁 eCos1.31版
💻 C
📖 第 1 页 / 共 3 页
字号:
//==========================================================================////      singlestep.c////      ARM(R) specific single-step support.////==========================================================================//####COPYRIGHTBEGIN####//                                                                          // -------------------------------------------                              // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in         // compliance with the License.  You may obtain a copy of the License at    // http://www.redhat.com/                                                   //                                                                          // Software distributed under the License is distributed on an "AS IS"      // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the // License for the specific language governing rights and limitations under // the License.                                                             //                                                                          // The Original Code is eCos - Embedded Configurable Operating System,      // released September 30, 1998.                                             //                                                                          // The Initial Developer of the Original Code is Red Hat.                   // Portions created by Red Hat are                                          // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             // All Rights Reserved.                                                     // -------------------------------------------                              //                                                                          //####COPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    // Contributors: gthomas// Date:         1999-10-20// Purpose:      ARM(R) specific single-step support. // Description:  ARM is a Registered Trademark of Advanced RISC Machines Limited.//               Other Brands and Trademarks are the property of their//               respective owners.////####DESCRIPTIONEND####////=========================================================================#include <stdlib.h>#include <bsp/bsp.h>#include <bsp/cpu.h>#include "insn.h"#define DEBUG_SINGLESTEP         0#define DEBUG_SINGLESTEP_VERBOSE 0/* * Structure to hold opcodes hoisted when breakpoints are * set for single-stepping or async interruption. */struct _bp_save {    unsigned long *addr;    unsigned long opcode;};#define NUM_BREAKS_SAVED 2static struct _bp_save _breaks[NUM_BREAKS_SAVED];/* *  Insert a breakpoint at 'pc' using first available *  _bp_save struct. */static voidinsert_ss_break(unsigned long *pc){    struct _bp_save *p = _breaks;    union arm_insn inst;    if (p->addr && (++p)->addr)	return;    /*     * We can't set a breakpoint at 0     */    if (pc == 0)    {#if DEBUG_SINGLESTEP        bsp_printf("Setting BP at <0x%08lx>: Error\n", pc);#endif /* DEBUG_SINGLESTEP */        return;    }    /*     * Make sure we are on a long word boundary.     */    if (((unsigned long)pc & 0x3) != 0)    {        /*         * All ARM(R) instructions are on a word boundary.         * This would be invalid.  Don't set a bkpt here.         */#if DEBUG_SINGLESTEP        bsp_printf("Setting BP at <0x%08lx>: Error\n", pc);#endif /* DEBUG_SINGLESTEP */        return;    }    /*     * What is the current instruction     */    if (bsp_memory_read(pc, 0, ARM_INST_SIZE * 8, 1, &(inst.word)) == 0)    {        /*         * Unable to read this address, probably an invalid address.         * Don't set a breakpoint here, as it will likely cause a bus error         */#if DEBUG_SINGLESTEP        bsp_printf("Setting BP at <0x%08lx>: Error\n", pc);#endif /* DEBUG_SINGLESTEP */        return;    }    if (inst.word != BREAKPOINT_INSN)    {        /*         * Only insert a breakpoint if we haven't done so already         *         * We may try to insert 2 breakpoints if we to a branch to         * the immediately following instruction.         */#if DEBUG_SINGLESTEP        bsp_printf("Setting BP at <0x%08lx>: inst <0x%08lx>\n", pc, inst.word);#endif /* DEBUG_SINGLESTEP */        p->addr = pc;        p->opcode = inst.word;        inst.word = BREAKPOINT_INSN;        if (bsp_memory_write(pc, 0, ARM_INST_SIZE * 8, 1, &(inst.word)) == 0)        {            /*             * Unable to write this address, probably an invalid address.             * Don't set a breakpoint here, as it will likely cause a bus error             */#if DEBUG_SINGLESTEP            bsp_printf("Setting BP at <0x%08lx>: Error\n", pc);#endif /* DEBUG_SINGLESTEP */            return;        }        /* flush icache and dcache, now */        bsp_flush_dcache((void *)pc, ARM_INST_SIZE);        bsp_flush_icache((void *)pc, ARM_INST_SIZE);#if DEBUG_SINGLESTEP_VERBOSE        bsp_printf("Done setting BP at <0x%08lx>: inst <0x%08lx>\n", pc, *pc);#endif /* DEBUG_SINGLESTEP_VERBOSE */    }}/* *  Cleanup after a singlestep. */voidbsp_singlestep_cleanup(void *registers){    struct _bp_save *p = _breaks;    int i;        for (i = 0; i < NUM_BREAKS_SAVED; i++, p++)    {        if (p->addr)        {            unsigned long *old_addr = p->addr;#if DEBUG_SINGLESTEP_VERBOSE            bsp_printf("Remove BP at <0x%08lx>: inst <0x%08lx>\n", old_addr, *old_addr);#endif /* DEBUG_SINGLESTEP */            *(p->addr) = p->opcode;            p->addr = NULL;            /* flush icache and dcache, now */            bsp_flush_dcache((void *)old_addr, ARM_INST_SIZE);            bsp_flush_icache((void *)old_addr, ARM_INST_SIZE);#if DEBUG_SINGLESTEP_VERBOSE            bsp_printf("Done removing BP at <0x%08lx>: inst <0x%08lx>\n", old_addr, *old_addr);#endif /* DEBUG_SINGLESTEP_VERBOSE */        }    }}/* * Rotate right a value by count */static unsigned long ror(unsigned long value, unsigned count){    while (count-- > 0)    {        if (value & 0x1)            value = (value >> 1) | 0x80000000;        else            value = (value >> 1);    }    return(value);}/* * Rotate right a value by 1 with extend */static unsigned long rrx(union arm_psr sr, unsigned long value){    if (sr.psr.c_bit)        value = (value >> 1) | 0x80000000;    else        value = (value >> 1);    return(value);}/* * Logical shift left by count */static unsigned long lsl(unsigned long value, unsigned count){    value <<= count;    return(value);}/* * Logical shift right by count */static unsigned long lsr(unsigned long value, unsigned count){    value >>= count;    return(value); }/* * Arithmetic shift right by count */static unsigned long asr(unsigned long value, unsigned count){    unsigned long sign_ext_mask = 0;    if (value & 0x80000000)    {        if (count >= sizeof(value)*8)            sign_ext_mask = ~0;        else            sign_ext_mask = (~0 << (sizeof(value)*8 - count));    }    value = (value >> count) | sign_ext_mask;    return(value); }/* * Calculate an immediate shift operand based on input shift operand,  * shift value and register address. */static unsigned long immediate_shift_operand(ex_regs_t *regs, unsigned shift_immediate,                                              unsigned shift, unsigned Rm){    unsigned char *regs_array = (unsigned char *)regs;    unsigned char *reg_ptr = &regs_array[bsp_regbyte(Rm)];    unsigned long reg_value = *((unsigned long *)(reg_ptr));    unsigned long rc = 0;    BSP_ASSERT((shift_immediate >= 0) && (shift_immediate <= 0x1f));    BSP_ASSERT((shift >= 0) && (shift <= 0x3));    BSP_ASSERT((Rm >= 0) && (Rm <= 0xf));    BSP_ASSERT(bsp_regsize(Rm) == sizeof(unsigned long));    /*     * According to the ARM(R) Manual, if Rm is PC then,     * the value used is the address of the current instruction     * plus 8     */    if (Rm == REG_PC)        reg_value += 8;    switch (shift)    {    case SHIFT_LSL:        rc = lsl(reg_value, shift_immediate);        break;    case SHIFT_LSR:        if (shift_immediate == 0)        {            /*             * Special Case: LSR IMM(0) == 0             */            rc = 0;        } else {            rc = lsr(reg_value, shift_immediate);        }        break;    case SHIFT_ASR:        if (shift_immediate == 0)        {            /*             * Special Case: ASR IMM(0)             */            if (reg_value & 0x80000000)            {                rc = 0xFFFFFFFF;            } else {                rc = 0;            }        } else {            rc = asr(reg_value, shift_immediate);        }        break;    case SHIFT_ROR:        if (shift_immediate == 0)        {            /*             * SHIFT_RRX             * Special case: ROR(0) implies RRX             */            rc = rrx((union arm_psr)(unsigned long)regs->_cpsr, reg_value);        } else {            rc = ror(reg_value, shift_immediate);        }        break;    default:        BSP_ASSERT(0);        break;    }    return (rc);}/* * Calculate a register shift operand based on input shift operand,  * and target registers. */static unsigned long register_shift_operand(ex_regs_t *regs, unsigned Rs,                                            unsigned shift, unsigned Rm){    unsigned char *regs_array = (unsigned char *)regs;    unsigned char *Rs_ptr = &regs_array[bsp_regbyte(Rs)];    unsigned char *Rm_ptr = &regs_array[bsp_regbyte(Rm)];    unsigned long Rs_val = *((unsigned long *)(Rs_ptr));    unsigned long Rm_val = *((unsigned long *)(Rm_ptr));    unsigned long rc = 0;    /*     * Use only the least significant byte of Rs     */    Rs_val &= 0xFF;    BSP_ASSERT((Rs >= 0) && (Rs <= 0xf));    BSP_ASSERT((shift >= 0) && (shift <= 0x3));    BSP_ASSERT((Rm >= 0) && (Rm <= 0xf));    BSP_ASSERT(bsp_regsize(Rs) == sizeof(unsigned long));    BSP_ASSERT(bsp_regsize(Rm) == sizeof(unsigned long));    BSP_ASSERT((Rs_val >=0) && (Rs_val <= 0xff));    /*     * According to the ARM(R) Manual, if Rm is PC then,     * the value used is the address of the current instruction     * plus 8     */    if (Rm == REG_PC)        Rm_val += 8;    switch (shift)    {    case SHIFT_LSL: rc = lsl(Rm_val, Rs_val); break;    case SHIFT_LSR: rc = lsr(Rm_val, Rs_val); break;    case SHIFT_ASR: rc = asr(Rm_val, Rs_val); break;    case SHIFT_ROR: rc = ror(Rm_val, Rs_val); break;    default:        BSP_ASSERT(0);            break;    }    return (rc);}/* * Calculate a branch exchange operand based on input destination register */static unsigned long branch_exchange_operand(ex_regs_t *regs, unsigned Rm){    unsigned char *regs_array = (unsigned char *)regs;    unsigned char *reg_ptr = &regs_array[bsp_regbyte(Rm)];    unsigned long reg_value = *((unsigned long *)(reg_ptr));    BSP_ASSERT((Rm >= 0) && (Rm <= 0xf));    BSP_ASSERT(bsp_regsize(Rm) == sizeof(unsigned long));    /*     * Clear the low-order bit     */    return (reg_value & ~0x1);}/* * Handle a load to the PC */static void handle_pc_load(unsigned size, unsigned long operand){    unsigned long mem_value = 0;    if (size == LS_SIZE_WORD)    {        if (bsp_memory_read((void*)(operand & ~0x3), 0, 32, 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 */        }        /*         * Handle rotations if required         */        switch (operand & 0x3)        {        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;        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -