171 lines
4.1 KiB
C
171 lines
4.1 KiB
C
/*++
|
|
|
|
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 <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#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
|
|
}
|