windows-nt/Source/XPSP1/NT/base/wow64/mscpu/inc/threadst.h

265 lines
7.9 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1992-1998 Microsoft Corporation
Module Name:
threadst.h
Abstract:
This module defines the structures and constant for describing a
thread's state.
Author:
Dave Hastings (daveh) creation-date 20-May-1995
Revision History:
--*/
#ifndef _THREADST_H_
#define _THREADST_H_
#define EIPLOGSIZE 32 // keep track of the last N instructions run
#define CSSIZE 512 // Size of call stack (512*8 = 2048 bytes = 1 page)
typedef union _REG32 { // definition of a 32-bit x86 register
struct {
BYTE i1;
BYTE hb;
};
USHORT i2;
ULONG i4;
} REG32;
#if defined(_ALPHA_)
typedef DWORD FPTAG; // bytes are too slow on AXP
#else
typedef BYTE FPTAG;
#endif
typedef struct _FPREG { // definition of an x86 floating-point register
union {
double r64;
DWORD rdw[2];
BYTE rb[8];
};
FPTAG Tag;
FPTAG TagSpecial;
} FPREG, *PFPREG;
//
// CALLSTACK is an optimization for CALL/RET pairs, so that an expensive
// NativeAddressFromEip() call can be avoided when determining the RISC
// address of an x86 return address.
//
typedef struct _callStack {
ULONG intelAddr;
ULONG nativeAddr;
} CALLSTACK, *PCALLSTACK;
// Indices into CPUSTATE.Regs[]. get_reg32() depends on EAX through
// EDI being contiguous and ordered the same as they are in the mod/rm and
// reg instruction encodings (ie. EAX=0,ECX=1,EDX=2,EBX=3,ESP=4,EBP=5,ESI=6,
// EDI=7)
#define GP_EAX 0x00
#define GP_ECX 0x01
#define GP_EDX 0x02
#define GP_EBX 0x03
#define GP_ESP 0x04
#define GP_EBP 0x05
#define GP_ESI 0x06
#define GP_EDI 0x07
// Segment registers. get_segreg() depends on the order.
#define REG_ES 0x08
#define REG_CS 0x09
#define REG_SS 0x0a
#define REG_DS 0x0b
#define REG_FS 0x0c
#define REG_GS 0x0d
// Identifiers for components of registers. get_reg16() depends on the order.
#define GP_AX 0x0e
#define GP_CX 0x0f
#define GP_DX 0x10
#define GP_BX 0x11
#define GP_SP 0x12
#define GP_BP 0x13
#define GP_SI 0x14
#define GP_DI 0x15
// PlaceOperandFragments() depends on GP_AH and beyond, and that no registers
// are past GP_BH.
#define GP_AL 0x16
#define GP_CL 0x17
#define GP_DL 0x18
#define GP_BL 0x19
#define GP_AH 0x1a
#define GP_CH 0x1b
#define GP_DH 0x1c
#define GP_BH 0x1d
#define NO_REG 0xffffffff
typedef struct _CPU_SUSPEND_MSG
{
// Owned by local thread
HANDLE StartSuspendCallEvent;
HANDLE EndSuspendCallEvent;
} CPU_SUSPEND_MSG, *PCPU_SUSPEND_MSG;
// all information related to a particular thread of the CPU belongs here
typedef struct _ThreadState {
//
// General-purpose and segment registers
// accessible as an array of REG32 or by Register Name
// NOTE: the name orders must match the GP_XXX defines for registers
//
union {
REG32 GpRegs[14];
struct _RegisterByName {
REG32 Eax;
REG32 Ecx;
REG32 Edx;
REG32 Ebx;
REG32 Esp;
REG32 Ebp;
REG32 Esi;
REG32 Edi;
REG32 Es;
REG32 Cs;
REG32 Ss;
REG32 Ds;
REG32 Fs;
REG32 Gs;
};
};
REG32 eipReg; // Pointer to start of current instruction (never
// points into the middle of an instruction)
DWORD flag_cf; // 0 = carry
DWORD flag_pf; // 2 = parity
DWORD flag_aux; // 4 = aux carry
DWORD flag_zf; // 6 = zero
DWORD flag_sf; // 7 = sign
DWORD flag_tf; // 8 = trap
DWORD flag_if; // 9 = interrupt enable
DWORD flag_df; // 10 = direction (1 = clear, -1 = set)
DWORD flag_of; // 11 = overflow
DWORD flag_nt; // 14 = nested task
DWORD flag_rf; // 16 = resume flag
DWORD flag_vm; // 17 = virtual mode
DWORD flag_ac; // 18 = alignment check
// Floating-point registers
FPREG FpStack[8];
PFPREG FpST0;
INT FpTop;
INT FpStatusC3;
INT FpStatusC2;
INT FpStatusC1;
INT FpStatusC0;
INT FpStatusSF;
INT FpStatusES; // Error Summary Status
INT FpControlInfinity;
INT FpControlRounding;
INT FpControlPrecision;
DWORD FpStatusExceptions;
DWORD FpControlMask;
DWORD FpEip; // EIP for the current FP instruction
PVOID FpData; // Effective address for current FP instruction
PVOID FpAddTable; // ptr to table of function pointers for FADD
PVOID FpSubTable; // ptr to table of function pointers for FSUB
PVOID FpMulTable; // ptr to table of function pointers for FMUL
PVOID FpDivTable; // ptr to table of function pointers for FDIV
ULONG CpuNotify;
PVOID TraceAddress; // Used by debugger extensions
DWORD fTCUnlocked; // FALSE means TC must be unlocked after exception
// SuspendThread/ResumeThread support
PCPU_SUSPEND_MSG SuspendMsg;
int eipLogIndex; // Index of next entry to write into in the log
DWORD eipLog[EIPLOGSIZE]; // log of last EIPLOGSIZE instructions run
ULONG CSIndex; // Index into the stack (offset of current location)
DWORD CSTimestamp;// Value of TranslationCacheTimestamp corresponding to the callstack cache
CALLSTACK callStack[CSSIZE]; // callstack optimization
int ErrnoVal; // CRT errno value
DWORD flag_id; // 21 = ID (CPUID present if this can be toggled)
} THREADSTATE, *PTHREADSTATE, CPUCONTEXT, *PCPUCONTEXT;
// Bit offsets in cpu->FpControlMask. Same as the x86 bit positions
#define FPCONTROL_IM 1 // Invalid operation
#define FPCONTROL_DM 2 // Denormalized operation
#define FPCONTROL_ZM 4 // Zero divide
#define FPCONTROL_OM 8 // Overflow
#define FPCONTROL_UM 16 // Underflow
#define FPCONTROL_PM 32 // Precision
// This macro allows one to access the cpu state via the local variable cpu
#define DECLARE_CPU \
PCPUCONTEXT cpu=(PCPUCONTEXT)Wow64TlsGetValue(WOW64_TLS_CPURESERVED);
//
// The following macros allow one to push and pop values from the
// call stack
//
#define ISTOPOF_CALLSTACK(iAddr) \
(cpu->callStack[(cpu->CSIndex)].intelAddr == iAddr)
#define PUSH_CALLSTACK(iAddr,nAddr) \
{ \
PCALLSTACK pCallStack; \
\
cpu->CSIndex = (cpu->CSIndex+1) % CSSIZE; \
pCallStack = &cpu->callStack[cpu->CSIndex]; \
pCallStack->intelAddr = iAddr; \
pCallStack->nativeAddr = nAddr; \
}
#define POP_CALLSTACK(iAddr,nAddr) \
{ \
PCALLSTACK pCallStack; \
extern ULONG TranslationCacheTimestamp; \
\
CPUASSERTMSG( \
(cpu->CSTimestamp == TranslationCacheTimestamp), \
"POP_CALLSTACK: About to return and invalid value\n"\
); \
\
pCallStack = &cpu->callStack[cpu->CSIndex]; \
if (iAddr == pCallStack->intelAddr) { \
nAddr = pCallStack->nativeAddr; \
} else { \
nAddr = 0; \
} \
cpu->CSIndex = (cpu->CSIndex-1) % CSSIZE; \
}
PCPUCONTEXT GetCpuContext (); //has been implemented in wowproxy
NTSTATUS
CpupSuspendCurrentThread(
VOID);
#endif //_THREADST_H_