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

📄 mipsuwnd.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++

Module Name:
    mipsuwnd.c

Abstract:
    This module implements the unwinding of procedure call frames for
    exception processing on MIPS processors.
--*/

#include "kernel.h"

// Define stack register and zero register numbers.
#define RA 0x1f                         // integer register 31
#define SP 0x1d                         // integer register 29
#define ZERO 0x0                        // integer register 0
#define NOREG -1                        // invalid register number


extern PRUNTIME_FUNCTION NKLookupFunctionEntry(PPROCESS, ULONG, PRUNTIME_FUNCTION);

// Maximum number of instructions encoded by block with given start and end addresses
#define BYTES_TO_OPCOUNT(_begin, _end)  (((_end) - (_begin)) >> (2 >> ((_end) & 1)))

// Op count of longest prologue helper function called from the current mode
#define MIPS_PROLHELPER_OPCOUNT(_pc) 14 // store 9 callee-saved regs, store RA, subtract saved-reg and arg area
                                        // size from SP, subtract local var area size from SP, return, and return 
                                        // delay slot = 14 instructions.

// Address of instruction adjacent to _pc: +/- 4 for MIPS32, +/- 2 for MIPS16
#define MIPS_PREV_INSTR(_pc)  (ULONG)((_pc) - (4 >> ((_pc) & 1)))
#define MIPS_NEXT_INSTR(_pc)  (ULONG)((_pc) + (4 >> ((_pc) & 1)))

// MIPS16->MIPS32 register encoding conversion
#define FIX_MIPS16_REG(r)     (((r) < 2) ? (r)+16 : (r))

// MIPS16 MOV32R register encoding
#define FIX_MOV32R_REG(r)     (((r) >> 2) | (((r) & 0x3) << 3))
#define UNFIX_MOV32R_REG(r)   (((r) << 2) | (((r) & 0x18) >> 3))

// MIPS16 instruction tests
#define IS_MIPS16_MOV32RSP(i) (((i) & 0xfff8) == ((I8_OP16 << 11) | (MOV32R_OP16 << 8) | (UNFIX_MOV32R_REG (SP) << 3)))
#define IS_MIPS16_ADDIUSP(i)  (((i) & 0xff00) == ((I8_OP16 << 11) | (ADJSP_OP16 << 8)))
#define IS_MIPS16_JR(i)       (((i) & 0xf8ff) == ((RR_OP16 << 11) | JR_OP16))
#define IS_MIPS16_JRRA(i)     ((i) == ((RR_OP16 << 11) | (0x1 << 5) | JR_OP16))
#define IS_MIPS16_RETURN(i)   (IS_MIPS16_JR(i) || IS_MIPS16_JRRA(i))
                
// MIPS32 instruction tests
#define IS_MIPS32_ADDIUSP(i) (((i) & 0xffff0000) == ((ADDIU_OP << 26) | (SP << 16) | (SP << 21)))
#define IS_MIPS32_ADDUSP(i) (((i) & 0xffe0ffff) == ((SPEC_OP << 26) | ADDU_OP | (SP << 11) | (SP << 21)))
#define IS_MIPS32_RETURN(i) ((i) == JUMP_RA)

// Interpreter opcodes
typedef enum Opcode {
    OP_NOP = 0,
    OP_ADD,
    OP_ADDI,
    OP_SUB,
    OP_OR,
    OP_MOVE,
    OP_IMM,
    OP_STORE,
    OP_STORE64,
    OP_FSTORE,
    OP_DSTORE,
} OPCODE;

// Register names
typedef enum RegName {
    none = NOREG,
    zero = ZERO,
    at,
    v0, v1,
    a0, a1, a2, a3,
    t0, t1, t2, t3, t4, t5, t6, t7,
    s0, s1, s2, s3, s4, s5, s6, s7,
    t8, t9,
    k0, k1,
    gp,
    sp,
    s8,
    ra
} REGNAME;

// Interpreter operation structure
typedef struct Operation {
    OPCODE Opcode:CHAR_BIT;
    REGNAME Rd:CHAR_BIT;
    REGNAME Rs:CHAR_BIT;
    REGNAME Rt:CHAR_BIT;
    REG_TYPE Imm;
} OPERATION, *POPERATION;

static BOOL
IsScratchReg (
    IN REGNAME regName)
/*++
Routine Description
    Returns TRUE if the given register is used as a scratch register in the
    prologue.

Arguments
    regName - register index in question.
--*/
{
    switch (regName)
    {
        case at:
        case v0:
        case v1:
        case t0:
        case t1:
        case t2:
        case t3:
        case t4:
        case t5:
        case t6:
        case t7:
        case t8:
        case t9:
            return TRUE;
    }

    return FALSE;
}

static POPERATION
BuildSimpleOp16 (
    IN OUT POPERATION Op,
    IN ULONG Address,
    IN ULONG PCAddress,
    IN ULONG Extend)
/*++
Routine Description
    This function converts a MIPS16 instruction at the specified address into the
    equivalent interpreter instruction.

Arguments
    Op - A pointer to an interpreter operation structure to receive the translated
        opcode.

    Address - The address of the MIPS16 instruction.

    PCAddress - The PC value at execution time (PCAddress != Address when the
        instruction is being executed in a delay slot).

    Extend - The value of a previous EXTEND opcode immediate field.  Set to -1
        if the instruction is not extended.
--*/
{
    MIPS16_INSTRUCTION Instruction;
    ULONG UImm8, UImm5, SImm8;

    Instruction.Short = *(PUSHORT) Address;
    // Replace any break instruction introduced in the prolog
    // by the debugger with its original instruction
    if (Instruction.rr_format.Function == BREAK_OP16 &&
        Instruction.rr_format.Opcode == RR_OP16) {
        (*KDSanitize)((BYTE *)&Instruction.Short, (void *)(Address), 
                   sizeof(Instruction.Short), FALSE);
    }
    UImm8 = Instruction.ri_format.Immediate << 2;
    UImm5 = Instruction.rri_format.Immediate << 2;
    SImm8 = Instruction.rsi_format.Simmediate;
    if (Extend != (ULONG) -1) {
        SImm8 = UImm8 = UImm5 = Extend | Instruction.rri_format.Immediate;
    }
    Op->Opcode = OP_NOP;
    Op->Rt = Op->Rs = Op->Rd = NOREG;
    switch (Instruction.i_format.Opcode) {
    case LI_OP16:
        Op->Opcode = OP_IMM;
        Op->Rd = FIX_MIPS16_REG (Instruction.ri_format.Rx);
        Op->Imm = Instruction.ri_format.Immediate;
        if (Extend != (ULONG) -1) {
            Op->Imm = (Extend | Instruction.rri_format.Immediate) & 0xFFFF;
        }
        break;
    case SW_OP16:
        Op->Opcode = OP_STORE;
        Op->Rs = FIX_MIPS16_REG (Instruction.rri_format.Rx);
        Op->Rt = FIX_MIPS16_REG (Instruction.rri_format.Ry);
        Op->Imm = UImm5;
        break;
    case SWSP_OP16:
        Op->Opcode = OP_STORE;
        Op->Rs = SP;
        Op->Rt = FIX_MIPS16_REG (Instruction.ri_format.Rx);
        Op->Imm = UImm8;
        break;
    case LWPC_OP16:
        Op->Opcode = OP_IMM;
        Op->Rd = FIX_MIPS16_REG (Instruction.ri_format.Rx);
        Op->Imm = *(PULONG) ((PCAddress & ~3) + UImm8);
        break;
    case ADDIU8_OP16:
        Op->Opcode = OP_ADDI;
        Op->Rs = Op->Rd = FIX_MIPS16_REG (Instruction.ri_format.Rx);
        Op->Imm = SImm8;
        break;
    case ADDIUSP_OP16:
        Op->Opcode = OP_ADDI;
        Op->Rd = FIX_MIPS16_REG (Instruction.ri_format.Rx);
        Op->Rs = SP;
        Op->Imm = UImm8;
        break;
    case RRR_OP16:
        Op->Rd = FIX_MIPS16_REG (Instruction.rrr_format.Rz);
        Op->Rs = FIX_MIPS16_REG (Instruction.rrr_format.Rx);
        Op->Rt = FIX_MIPS16_REG (Instruction.rrr_format.Ry);
        if (Op->Rs != Op->Rd) break;
        switch (Instruction.rrr_format.Function) {
        case SUBU_OP16:
            Op->Opcode = OP_SUB;
            break;
        case ADDU_OP16:
            Op->Opcode = OP_ADD;
            break;
        }
        break;
    case I8_OP16:
        switch (Instruction.i8_format.Function) {
        case SWRASP_OP16:
            Op->Opcode = OP_STORE;
            Op->Rs = SP;
            Op->Rt = RA;
            Op->Imm = UImm8;
            break;
        case ADJSP_OP16:
            Op->Opcode = OP_ADDI;
            Op->Rs = Op->Rd = SP;
            Op->Imm = SImm8;
            if (Extend == (ULONG) -1) {
                Op->Imm = SImm8 << 3;
            }
            break;
        case MOV32R_OP16:
            Op->Opcode = OP_MOVE;
            Op->Rd = FIX_MOV32R_REG (Instruction.mov32r_format.R32);
            Op->Rs = FIX_MIPS16_REG (Instruction.mov32r_format.Rz);
            break;
        case MOVR32_OP16:
            Op->Opcode = OP_MOVE;
            Op->Rd = FIX_MIPS16_REG (Instruction.movr32_format.Ry);
            Op->Rs = (BYTE) Instruction.movr32_format.R32;
            break;
        }
        break;
    default:
        break;
    }
    return Op + (Op->Opcode != OP_NOP);
}

static POPERATION
BuildSimpleOp32 (
    IN OUT POPERATION Op,
    IN ULONG Address,
    IN BOOLEAN NotFirst)
/*++
Routine Description
    This function converts a MIPS32 instruction at the specified address into the
    equivalent interpreter instruction.  It will attempt to compress LUI-ORI pairs
    into a single OP_IMM operation.

Arguments
    Op - A pointer to an interpreter operation structure to receive the translated
        opcode.

    Address - The address of the MIPS32 instruction.

    NotFirst - True if this is not the first Op in the list, to tell LUI-ORI
        compression to look at the previous operation at Op-1. 
--*/
{
    MIPS_INSTRUCTION I32;

    I32.Long = *(PULONG) Address;
    // Replace any break instruction introduced in the prolog
    // by the debugger with its original instruction
    if (I32.r_format.Function == BREAK_OP &&
        I32.r_format.Opcode == SPEC_OP) {
        (*KDSanitize)((BYTE *)&I32.Long, (void *)Address, sizeof(I32.Long), FALSE);
    }
    Op->Rs = (BYTE) I32.i_format.Rs;
    Op->Rt = (BYTE) I32.i_format.Rt;
    Op->Rd = (BYTE) I32.r_format.Rd;
    Op->Imm = I32.i_format.Simmediate;
    switch (I32.i_format.Opcode) {
    case SD_OP:
        Op->Opcode = OP_STORE64;
        goto store;
    case SW_OP:
        Op->Opcode = OP_STORE;
        goto store;
    case SWC1_OP:
        Op->Opcode = OP_FSTORE;
        goto store;
    case SDC1_OP:
        Op->Opcode = OP_DSTORE;
    store:
        if (Op->Rs == SP) {

⌨️ 快捷键说明

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