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

📄 unwind.c

📁 wince下的源代码集合打包
💻 C
📖 第 1 页 / 共 2 页
字号:
            // We know that as of this instruction, r11 is a valid frame            // pointer.  Therefore, it contains the stack value immediately            // before the STM that set up the stack frame.  So, we scan            // backward to find the STM, pretend it was a STM using r11 as the            // base register with no update, and reverse-execute it.            j = i - 1;            while (j >= 0 && (Prolog[j].instruction & STM_MASK) != STM_INSTR)                j--;            if ( j >= 0 ){                // Tweak the instruction so it will be reverse-executed                // correctly.  A convenient side-effect of this is that it                // prevents it from being recognized as a STM when we continue                // reverse-executing, which is good because we don't want to do it                // again.                Prolog[j].ldm.l = TRUE;                Prolog[j].ldm.rn = 11;                Prolog[j].ldm.w = FALSE;                if (!UnwindLoadMultiple(Prolog[j], Register))                    return ControlPc;            }        }    }        // The continuation address is contained in the link register.        *EstablisherFrame = Register[13];    if (!HaveExceptionPc)        NextPc = Register[14] - 4;    return NextPc;}VOIDUnwindDataProcess(ARMI instr, PULONG Register)/*++Routine Description:    This function executes an ARM data processing instruction using the    current register set. It automatically updates the destination register.Arguments:    instr      The ARM 32-bit instruction    Register   Pointer to the ARM integer registers.Return Value:    None.--*/{    ULONG Op1, Op2;    ULONG Cflag = (Register[16] & 0x20000000L) == 0x20000000L; // CPSR    ULONG shift;    // We are checking for all addressing modes and op codes, even though    // the prolog and epilog don't use them all right now.  In the future,    // more instructions and addressing modes may be added.    //    // Figure out the addressing mode (there are 11 of them), and get the    // operands.    Op1 = Register[instr.dataproc.rn];    if (instr.dataproc.bits == 0x1) {        // Immediate addressing - Type 1        Op2 = _lrotr(instr.dpi.immediate, instr.dpi.rotate * 2);    } else {        // Register addressing - start by getting the value of Rm.        Op2 = Register[instr.dpshi.rm];        if (instr.dprre.bits == 0x6) {            // Rotate right with extended - Type 11            Op2 = (Cflag << 31) | (Op2 >> 1);        } else if (instr.dataproc.operand2 & 0x10) {            // Register shifts. Types 4, 6, 8, and 10            //            // Get the shift value from the least-significant byte of the            // shift register.            shift = Register[instr.dpshr.rs] & 0xFF;            switch(instr.dpshr.bits) {            case 0x1: //  4 Logical shift left by register                if (shift >= 32)                    Op2 = 0;                else                    Op2 = Op2 << shift;                break;            case 0x3: //  6 Logical shift right by register                if (shift >= 32)                    Op2 = 0;                else                    Op2 = Op2 >> shift;                break;            case 0x5: //  8 Arithmetic shift right by register                if (shift >= 32) {                    if (Op2 & 0x80000000)                        Op2 = 0xffffffff;                    else                        Op2 = 0;                } else                    Op2 = (LONG)Op2 >> shift;                break;            case 0x7: // 10 Rotate right by register                if ((shift & 0xf) != 0)                    Op2 = _lrotl(Op2, shift);            default:                break;            }        } else {            // Immediate shifts. Types 2, 3, 5, 7, and 9            //            // Get the shift value from the instruction.            shift = instr.dpshi.shift;            switch(instr.dpshi.bits) {            case 0x0: // 2,3 Register, Logical shift left by immediate                if (shift != 0)                    Op2 = Op2 << shift;                break;            case 0x2: // 5 Logical shift right by immediate                if (shift == 0)                    Op2 = 0;                else                    Op2 = Op2 >> shift;                break;            case 0x4: // 7 Arithmetic shift right by immediate                if (shift == 0)                    Op2 = 0;                else                    Op2 = (LONG)Op2 >> shift;                break;            case 0x6: // 9 Rotate right by immediate                Op2 = _lrotl(Op2, shift);                break;            default:                break;            }        }    }    // Determine the result (the new PC), based on the opcode.    switch(instr.dataproc.opcode) {    case OP_AND:        Register[instr.dataproc.rd] = Op1 & Op2;        break;    case OP_EOR:        Register[instr.dataproc.rd] = Op1 ^ Op2;        break;    case OP_SUB:        Register[instr.dataproc.rd] = Op1 - Op2;        break;    case OP_RSB:        Register[instr.dataproc.rd] = Op2 - Op1;        break;    case OP_ADD:        Register[instr.dataproc.rd] = Op1 + Op2;        break;    case OP_ADC:        Register[instr.dataproc.rd] = (Op1 + Op2) + Cflag;        break;    case OP_SBC:        Register[instr.dataproc.rd] = (Op1 - Op2) - ~Cflag;        break;    case OP_RSC:        Register[instr.dataproc.rd] = (Op2 - Op1) - ~Cflag;        break;    case OP_ORR:        Register[instr.dataproc.rd] = Op1 | Op2;        break;    case OP_MOV:        Register[instr.dataproc.rd] = Op2;        break;    case OP_BIC:        Register[instr.dataproc.rd] = Op1 & ~Op2;        break;    case OP_MVN:        Register[instr.dataproc.rd] = ~Op2;        break;    case OP_TST:    case OP_TEQ:    case OP_CMP:    case OP_CMN:    default:        // These instructions do not have a destination register.        // There is nothing to do.        break;    }}BOOLUnwindLoadMultiple(ARMI instr, PULONG Register)/*++Routine Description:    This function executes an ARM load multiple instruction.Arguments:    instr           The ARM 32-bit instruction    Register        Pointer to the ARM integer registers.Return Value:    TRUE if successful, FALSE otherwise.--*/{    LONG i;    ULONG RegList;    PULONG Rn;    // Load multiple with the PC bit set.  We are currently checking for all    // four addressing modes, even though decrement before and increment    // after are the only modes currently used in the epilog and prolog.    //    // Rn is the address at which to begin, and RegList is the bit map of which    // registers to read.    Rn = (PULONG)Register[instr.ldm.rn];    RegList = instr.ldm.reglist;    if (instr.ldm.p) {        if (instr.ldm.u) {            // Increment before            for(i = 0; i <= 15; i++) {                if (RegList & 0x1) {                    Rn++;                    if (!ReadMemory(Rn, &Register[i], 4))                        return FALSE;                }                RegList = RegList >> 1;            }        } else {            // Decrement before            for(i = 15; i >= 0; i--) {                if (RegList & 0x8000) {                    Rn--;                    if (!ReadMemory(Rn, &Register[i], 4))                        return FALSE;                }                RegList = RegList << 1;            }        }    } else {        if (instr.ldm.u) {            // Increment after            for(i = 0; i <= 15; i++) {                if (RegList & 0x1) {                    if (!ReadMemory(Rn, &Register[i], 4))                        return FALSE;                    Rn++;                }                RegList = RegList >> 1;            }        } else {            // Decrement after            for(i = 15; i >= 0; i--) {                if (RegList & 0x8000) {                    if (!ReadMemory(Rn, &Register[i], 4))                        return FALSE;                    Rn--;                }                RegList = RegList << 1;            }        }    }    if (instr.ldm.w)        Register[instr.ldm.rn] = (ULONG)Rn; // Update the base register.    return TRUE;}BOOLUnwindLoadI(ARMI instr, PULONG Register)/*++Routine Description:    This function executes an ARM load instruction with an immediat offset.Arguments:    instr           The ARM 32-bit instruction    Register        Pointer to the ARM integer registers.Return Value:    TRUE if successful, FALSE otherwise.--*/{    LONG offset;    LONG size;    PULONG Rn;    Rn = (PULONG)Register[instr.ldr.rn];    offset = instr.ldr.offset;    if (instr.ldr.u == 0)        offset = -offset;    if (instr.ldr.b == 0)        size = 4;    else        size = 1;    if (instr.ldm.p) { // add offset before transfer        if (!ReadMemory(Rn + offset, &Register[instr.ldr.rd], size))            return FALSE;        if (instr.ldr.w)            Register[instr.ldr.rn] += offset;    } else {        if (!ReadMemory(Rn, &Register[instr.ldr.rd], size))            return FALSE;        if (instr.ldr.w)            Register[instr.ldr.rn] += offset;    }    return TRUE;}BOOLCheckConditionCodes(ULONG CPSR, DWORD instr)/*++Routine Description:    Checks the condition codes of the instruction and the values of the    condition flags in the current program status register, and determines    whether or not the instruction will be executed.Arguments:    CPSR    -   The value of the Current Program Status Register.    instr   -   The instruction to analyze.Return Value:    TRUE if the instruction will be executed, FALSE otherwise.--*/{    BOOL Execute = FALSE;    BOOL Nset = (CPSR & 0x80000000L) == 0x80000000L;    BOOL Zset = (CPSR & 0x40000000L) == 0x40000000L;    BOOL Cset = (CPSR & 0x20000000L) == 0x20000000L;    BOOL Vset = (CPSR & 0x10000000L) == 0x10000000L;    switch(instr & COND_MASK) {    case COND_EQ:   // Z set        if (Zset) Execute = TRUE;        break;    case COND_NE:   // Z clear        if (!Zset) Execute = TRUE;        break;    case COND_CS:   // C set        if (Cset) Execute = TRUE;        break;    case COND_CC:   // C clear        if (!Cset) Execute = TRUE;        break;    case COND_MI:   // N set        if (Nset) Execute = TRUE;        break;    case COND_PL:   // N clear        if (!Nset) Execute = TRUE;        break;    case COND_VS:   // V set        if (Vset) Execute = TRUE;        break;    case COND_VC:   // V clear        if (!Vset) Execute = TRUE;        break;    case COND_HI:   // C set and Z clear        if (Cset && !Zset) Execute = TRUE;        break;    case COND_LS:   // C clear or Z set        if (!Cset || Zset) Execute = TRUE;        break;    case COND_GE:   // N == V        if ((Nset && Vset) || (!Nset && !Vset)) Execute = TRUE;        break;    case COND_LT:   // N != V        if ((Nset && !Vset) || (!Nset && Vset)) Execute = TRUE;        break;    case COND_GT:   // Z clear, and N == V        if (!Zset &&          ((Nset && Vset) || (!Nset && !Vset))) Execute = TRUE;        break;    case COND_LE:   // Z set, and N != V        if (Zset &&          ((Nset && !Vset) || (!Nset && Vset))) Execute = TRUE;        break;    case COND_AL:   // Always execute        Execute = TRUE;        break;    default:    case COND_NV:   // Never - undefined.        Execute = FALSE;        break;    }    return Execute;}

⌨️ 快捷键说明

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