📄 mipsuwnd.c
字号:
/*++ Copyright (c) 1997-2000 Microsoft Corporation. All rights reserved.Module Name: mipsuwnd.cAbstract: 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#if defined(MIPS16SUPPORT)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) 13 // store 9 callee-saved regs, store RA, subtract saved-reg and arg area // size from SP, subtract local var area size from SP, and return // = 13 instructions.// Address of instruction adjacent to _pc: +/- 4 for MIPS32, +/- 2 for MIPS16#define MIPS_PREV_INSTR(_pc) ((_pc) - (4 >> ((_pc) & 1)))#define MIPS_NEXT_INSTR(_pc) ((_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 opcodesenum { OP_NOP = 0, OP_ADD, OP_ADDI, OP_SUB, OP_OR, OP_MOVE, OP_IMM, OP_STORE, OP_FSTORE, OP_DSTORE,};// Interpreter operation structuretypedef struct Operation { BYTE Opcode; BYTE Rd; BYTE Rs; BYTE Rt; ULONG Imm;} OPERATION, *POPERATION;POPERATIONBuildSimpleOp16 ( 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; 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; } 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 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);}POPERATIONBuildSimpleOp32 ( 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; 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 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) { Op->Rd = NOREG; Op++; } break; case ADDIU_OP: Op->Rd = Op->Rt; if (Op->Rs == Op->Rt) { Op->Opcode = OP_ADDI; Op++; } else if (Op->Rs == ZERO) { Op->Opcode = OP_IMM; Op++; } break; case ORI_OP: Op->Opcode = OP_IMM; Op->Imm &= 0xffff; Op->Rd = Op->Rt; if (Op->Rs == Op->Rt) { // Look for matching LUI if (NotFirst && (Op-1)->Opcode == OP_IMM && (Op-1)->Rd == Op->Rd) { (Op-1)->Imm |= Op->Imm; } else { Op++; } } else if (Op->Rs == ZERO) { Op++; } break; case SPEC_OP: switch (I32.r_format.Function) { case OR_OP: Op->Opcode = OP_OR; goto spec; case ADDU_OP: Op->Opcode = OP_ADD; spec: if (Op->Rs == ZERO) { Op->Opcode = OP_MOVE; Op->Rs = Op->Rt; Op++; } else if (Op->Rt == ZERO) { Op->Opcode = OP_MOVE; Op++; } else if (Op->Rs == Op->Rd) { Op++; } else if (Op->Rt == Op->Rd) { Op->Rt = Op->Rs; Op++; } break; case SUBU_OP: if (Op->Rs == Op->Rd) { Op->Opcode = OP_SUB; Op++; } break; } break; case LUI_OP: Op->Opcode = OP_IMM; Op->Imm <<= 16; Op->Rd = Op->Rt; Op++; break; } return Op;} INTBuildOps ( IN OUT POPERATION Operations, IN INT Max, IN ULONG Address, IN ULONG EndAddress)/*++Routine Description This function constructs an interpreter operation list based upon the machine instructions found between a start and end address. The code is smart enough to handle a single level of calls, this is required if prolog helpers are being used.Arguments Operations - A pointer to an interpreter operation array to receive the translated instructions. Max - Size of the operation array. Address - The address of the first instruction. EndAddress - The address of the last instruction.Return Value: The number of operations generated.--*/{ MIPS16_INSTRUCTION I16; MIPS_INSTRUCTION I32; ULONG RetAddress = (ULONG) -1; ULONG Extend = (ULONG) -1; ULONG PCAddress = Address; POPERATION Op = Operations; POPERATION LastOp = Operations + Max; while (Address != EndAddress && Op < LastOp) { if (Address & 1) { // Get MIPS16 instruction
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -