/*++ Copyright (c) 1995 Microsoft Corporation Module Name: decoder.c Abstract: Public Decoder APIs and helper functions use in decoding instructions Author: 27-Jun-1995 BarryBo Revision History: 24-Aug-1999 [askhalid] copied from 32-bit wx86 directory and make work for 64bit. --*/ #include #include #include #include #include #include "cpuassrt.h" #include "threadst.h" #include "instr.h" #include "decoder.h" #include "decoderp.h" ASSERTNAME; ULONG DecoderExceptionFilter( PINSTRUCTION Instruction, struct _EXCEPTION_POINTERS *ExInfo ) /*++ Routine Description: Handles any exception thrown while decoding an instruction. Creates an OP_Fault instruction with operand2 being the exception code and operand1 being the address where the exception occurred. Arguments: Instruction - Structure to be filled in with the decoding ExInfo - Information about the exception. Return Value: ULONG - always EXCEPTION_EXECUTE_HANDLER. --*/ { Instruction->Operation = OP_Fault; Instruction->Operand1.Type = OPND_IMM; Instruction->Operand2.Immed = (ULONG)(ULONGLONG)ExInfo->ExceptionRecord->ExceptionAddress; Instruction->Operand2.Type = OPND_IMM; Instruction->Operand1.Immed = ExInfo->ExceptionRecord->ExceptionCode; Instruction->Size = 1; return EXCEPTION_EXECUTE_HANDLER; } VOID DecodeInstruction( DWORD InstructionAddress, PINSTRUCTION Instruction ) /*++ Routine Description: Decodes a single Intel instruction beginning at InstructionAddress, filling in the INSTRUCTION structure. Arguments: InstructionAddress - Address of first byte of the Intel Instruction Instruction - Structure to be filled in with the decoding Return Value: None - always succeeds. --*/ { DECODERSTATE DecoderState; // // Initialize the Instruction structure. Instruction structures are // zero-filled by the analysis phase, so only non-zero fields need // to be filled in here. // Instruction->Size = 1; Instruction->Operand1.Reg = NO_REG; Instruction->Operand1.IndexReg = NO_REG; Instruction->Operand2.Reg = NO_REG; Instruction->Operand2.IndexReg = NO_REG; Instruction->Operand3.Reg = NO_REG; Instruction->Operand3.IndexReg = NO_REG; Instruction->IntelAddress = InstructionAddress; // Initialize the decoder state info DecoderState.InstructionAddress = InstructionAddress; DecoderState.RepPrefix = PREFIX_NONE; DecoderState.AdrPrefix = FALSE; DecoderState.OperationOverride = OP_MAX; try { // Decode the instruction, filling in the Instruction structure (Dispatch32[GET_BYTE(InstructionAddress)])(&DecoderState, Instruction); } except(DecoderExceptionFilter(Instruction, GetExceptionInformation())) { } // Handle illegal instructions if (DecoderState.OperationOverride != OP_MAX) { Instruction->Size = 1; Instruction->Operation = DecoderState.OperationOverride; Instruction->Operand1.Type = OPND_NONE; Instruction->Operand2.Type = OPND_NONE; } // If Operand2 is filled-in, then Operand1 must also be filled in. CPUASSERT(Instruction->Operand2.Type == OPND_NONE || Instruction->Operand1.Type != OPND_NONE); } void get_segreg(PDECODERSTATE State, POPERAND op) { BYTE Reg = ((*(PBYTE)(eipTemp+1)) >> 3) & 0x07; op->Type = OPND_REGVALUE; op->Reg = REG_ES + Reg; if (Reg > 5) { BAD_INSTR; } } int scaled_index(PBYTE pmodrm, POPERAND op) { BYTE sib = *(pmodrm+1); INT IndexReg = GP_EAX + (sib >> 3) & 0x07; BYTE base = GP_EAX + sib & 0x07; op->Type = OPND_ADDRREF; op->Scale = sib >> 6; if (IndexReg != GP_ESP) { op->IndexReg = IndexReg; } // else op->IndexReg = NO_REG, which is the default value if (base == GP_EBP && ((*pmodrm) >> 6) == 0) { op->Immed = GET_LONG(pmodrm+2); return 5; // account for sib+DWORD } op->Reg = base; return 1; // account for sib }