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

📄 arm_stub.c

📁 eCos1.31版
💻 C
📖 第 1 页 / 共 2 页
字号:
//========================================================================////      arm_stub.c////      Helper functions for stub, generic to all ARM processors////========================================================================//####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):     Red Hat, gthomas// Contributors:  Red Hat, gthomas, jskov// Date:          1998-11-26// Purpose:       // Description:   Helper functions for stub, generic to all ARM processors// Usage:         ////####DESCRIPTIONEND####////========================================================================#include <stddef.h>#include <pkgconf/hal.h>#ifdef CYGPKG_CYGMON#include <pkgconf/cygmon.h>#endif#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS#ifdef CYGPKG_HAL_ARM_SIM#error "GDB Stub support not implemented for ARM SIM"#endif#include <cyg/hal/hal_stub.h>#include <cyg/hal/hal_arch.h>#include <cyg/hal/hal_intr.h>#ifndef FALSE#define FALSE 0#define TRUE  1#endif// Use bit 0 as a thumb-mode flag for next address to be executed.// Alternative would be to keep track of it using a C variable, but// since bit 0 is used by the BX instruction, we might as well do the// same thing and thus avoid checking two different flags.#define IS_THUMB_ADDR(addr)     ((addr) & 1)#define MAKE_THUMB_ADDR(addr) ((addr) | 1)#define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1)#ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT#include <cyg/hal/dbg-threads-api.h>    // dbg_currthread_id#endif/* Given a trap value TRAP, return the corresponding signal. */int __computeSignal (unsigned int trap_number){    // should also catch CYGNUM_HAL_VECTOR_UNDEF_INSTRUCTION here but we    // can't tell the different between a real one and a breakpoint :-(    switch (trap_number) {    case CYGNUM_HAL_VECTOR_ABORT_PREFETCH:      // Fall through    case CYGNUM_HAL_VECTOR_ABORT_DATA:          // Fall through    case CYGNUM_HAL_VECTOR_reserved:        return SIGBUS;    case CYGNUM_HAL_VECTOR_IRQ:    case CYGNUM_HAL_VECTOR_FIQ:        return SIGINT;    default:        return SIGTRAP;    }}/* Return the trap number corresponding to the last-taken trap. */int __get_trap_number (void){    // The vector is not not part of the GDB register set so get it    // directly from the save context.    return _hal_registers->vector;}/* Set the currently-saved pc register value to PC. */void set_pc (target_register_t pc){    put_register (PC, pc);}/*---------------------------------------------------------------------- * Single-step support *//* Set things up so that the next user resume will execute one instruction.   This may be done by setting breakpoints or setting a single step flag   in the saved user registers, for example. */static unsigned long  ss_saved_pc = 0;static unsigned long  ss_saved_instr;static unsigned short ss_saved_thumb_instr;#define FIXME() {diag_printf("FIXME - %s\n", __FUNCTION__); }static intins_will_execute(unsigned long ins){    unsigned long psr = get_register(PS);  // condition codes    int res = 0;    switch ((ins & 0xF0000000) >> 28) {    case 0x0: // EQ        res = (psr & PS_Z) != 0;        break;    case 0x1: // NE        res = (psr & PS_Z) == 0;        break;    case 0x2: // CS        res = (psr & PS_C) != 0;        break;    case 0x3: // CC        res = (psr & PS_C) == 0;        break;    case 0x4: // MI        res = (psr & PS_N) != 0;        break;    case 0x5: // PL        res = (psr & PS_N) == 0;        break;    case 0x6: // VS        res = (psr & PS_V) != 0;        break;    case 0x7: // VC        res = (psr & PS_V) == 0;        break;    case 0x8: // HI        res = ((psr & PS_C) != 0) && ((psr & PS_Z) == 0);        break;    case 0x9: // LS        res = ((psr & PS_C) == 0) || ((psr & PS_Z) != 0);        break;    case 0xA: // GE        res = ((psr & (PS_N|PS_V)) == (PS_N|PS_V)) ||            ((psr & (PS_N|PS_V)) == 0);        break;    case 0xB: // LT        res = ((psr & (PS_N|PS_V)) == PS_N) ||            ((psr & (PS_N|PS_V)) == PS_V);        break;    case 0xC: // GT        res = ((psr & (PS_N|PS_V)) == (PS_N|PS_V)) ||            ((psr & (PS_N|PS_V)) == 0);        res = ((psr & PS_Z) == 0) && res;        break;    case 0xD: // LE        res = ((psr & (PS_N|PS_V)) == PS_N) ||            ((psr & (PS_N|PS_V)) == PS_V);        res = ((psr & PS_Z) == PS_Z) || res;        break;    case 0xE: // AL        res = TRUE;        break;    case 0xF: // NV        res = FALSE;        break;    }    return res;}static unsigned longRmShifted(int shift){    unsigned long Rm = get_register(shift & 0x00F);    int shift_count;    if ((shift & 0x010) == 0) {        shift_count = (shift & 0xF80) >> 7;    } else {        shift_count = get_register((shift & 0xF00) >> 8);    }    switch ((shift & 0x060) >> 5) {    case 0x0: // Logical left        Rm <<= shift_count;        break;    case 0x1: // Logical right        Rm >>= shift_count;        break;    case 0x2: // Arithmetic right        Rm = (unsigned long)((long)Rm >> shift_count);        break;    case 0x3: // Rotate right        if (shift_count == 0) {            // Special case, RORx            Rm >>= 1;            if (get_register(PS) & PS_C) Rm |= 0x80000000;        } else {            Rm = (Rm >> shift_count) | (Rm << (32-shift_count));        }        break;    }    return Rm;}// Decide the next instruction to be executed for a given instructionstatic unsigned long *target_ins(unsigned long *pc, unsigned long ins){    unsigned long new_pc, offset, op2;    unsigned long Rn;    int i, reg_count, c;    switch ((ins & 0x0C000000) >> 26) {    case 0x0:        // BX        if ((ins & 0x0FFFFFF0) == 0x012FFF10) {            new_pc = (unsigned long)get_register(ins & 0x0000000F);            return ((unsigned long *)new_pc);        }        // Data processing        new_pc = (unsigned long)(pc+1);        if ((ins & 0x0000F000) == 0x0000F000) {            // Destination register is PC            if ((ins & 0x0FBF0000) != 0x010F0000) {                Rn = (unsigned long)get_register((ins & 0x000F0000) >> 16);                if ((ins & 0x02000000) == 0) {                    op2 = RmShifted(ins & 0x00000FFF);                } else {                    op2 = ins & 0x000000FF;                    i = (ins & 0x00000F00) >> 8;  // Rotate count                                    op2 = (op2 >> (i*2)) | (op2 << (32-(i*2)));                }                switch ((ins & 0x01E00000) >> 21) {                case 0x0: // AND                    new_pc = Rn & op2;                    break;                case 0x1: // EOR                    new_pc = Rn ^ op2;                    break;                case 0x2: // SUB                    new_pc = Rn - op2;                    break;                case 0x3: // RSB                    new_pc = op2 - Rn;                    break;                case 0x4: // ADD                    new_pc = Rn + op2;                    break;                case 0x5: // ADC                    c = (get_register(PS) & PS_C) != 0;                    new_pc = Rn + op2 + c;                    break;                case 0x6: // SBC                    c = (get_register(PS) & PS_C) != 0;                    new_pc = Rn - op2 + c - 1;                    break;                case 0x7: // RSC                    c = (get_register(PS) & PS_C) != 0;                    new_pc = op2 - Rn +c - 1;                    break;                case 0x8: // TST                case 0x9: // TEQ                case 0xA: // CMP                case 0xB: // CMN                    break; // PC doesn't change                case 0xC: // ORR                    new_pc = Rn | op2;                    break;                case 0xD: // MOV                    new_pc = op2;                    break;                case 0xE: // BIC                    new_pc = Rn & ~op2;                    break;                case 0xF: // MVN                    new_pc = ~op2;                    break;                }            }        }        return ((unsigned long *)new_pc);    case 0x1:        if ((ins & 0x02000010) == 0x02000010) {            // Undefined!            return (pc+1);        } else {            if ((ins & 0x00100000) == 0) {                // STR                return (pc+1);            } else {                // LDR                if ((ins & 0x0000F000) != 0x0000F000) {                    // Rd not PC                    return (pc+1);                } else {

⌨️ 快捷键说明

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