windows-nt/Source/XPSP1/NT/base/wow64/mscpu/decoder/decoder.c
2020-09-26 16:20:57 +08:00

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
}