218 lines
5.8 KiB
C
218 lines
5.8 KiB
C
/*++
|
|
|
|
Copyright (c) 1995-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
shr1632.c
|
|
|
|
Abstract:
|
|
|
|
Instruction fragments with common (shared) WORD, and DWORD flavors
|
|
(but not BYTE).
|
|
|
|
Author:
|
|
|
|
12-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 "wx86.h"
|
|
#include "wx86nt.h"
|
|
#include "shr1632.h"
|
|
|
|
FRAGCOMMON0(PushfFrag)
|
|
{
|
|
UTYPE dw;
|
|
|
|
dw = ((GET_CFLAG) ? FLAG_CF : 0)
|
|
| 2
|
|
| ((GET_AUXFLAG) ? FLAG_AUX : 0) // The auxflag is special
|
|
| ((GET_PFLAG) ? FLAG_PF : 0)
|
|
| ((cpu->flag_zf) ? 0 : FLAG_ZF) // zf has inverse logic
|
|
| ((GET_SFLAG) ? FLAG_SF : 0)
|
|
| ((cpu->flag_tf) ? FLAG_TF : 0)
|
|
| FLAG_IF
|
|
| ((cpu->flag_df == -1) ? FLAG_DF : 0)
|
|
| ((GET_OFLAG) ? FLAG_OF : 0)
|
|
#if MSB==0x80000000
|
|
| cpu->flag_ac
|
|
| cpu->flag_id
|
|
// VM and RF bits are both 0
|
|
#endif
|
|
;
|
|
PUSH_VAL(dw);
|
|
}
|
|
FRAGCOMMON0(PopfFrag)
|
|
{
|
|
UTYPE dw;
|
|
|
|
POP_VAL(dw);
|
|
// ignore: FLAG_NT, FLAG_RF, FLAG_VM, IOPL
|
|
SET_CFLAG_IND (dw & FLAG_CF);
|
|
cpu->flag_pf = (dw & FLAG_PF) ? 0 : 1; // pf is an index into the ParityBit[] array
|
|
cpu->flag_aux= (dw & FLAG_AUX) ? AUX_VAL : 0;
|
|
cpu->flag_zf = (dw & FLAG_ZF) ? 0 : 1; // zf has inverse logic
|
|
SET_SFLAG_IND (dw & FLAG_SF);
|
|
cpu->flag_tf = (dw & FLAG_TF) ? 1 : 0;
|
|
cpu->flag_df = (dw & FLAG_DF) ? -1 : 1;
|
|
SET_OFLAG_IND (dw & FLAG_OF);
|
|
#if MSB==0x80000000
|
|
cpu->flag_ac = (dw & FLAG_AC);
|
|
cpu->flag_id = (dw & FLAG_ID);
|
|
#endif
|
|
}
|
|
FRAGCOMMON0(PushAFrag)
|
|
{
|
|
// can't use PUSH_VAL() as ESP cannot be updated until after we're sure
|
|
// things can't fault
|
|
*(UTYPE *)(esp-sizeof(UTYPE)) = AREG;
|
|
*(UTYPE *)(esp-2*sizeof(UTYPE)) = CREG;
|
|
*(UTYPE *)(esp-3*sizeof(UTYPE)) = DREG;
|
|
*(UTYPE *)(esp-4*sizeof(UTYPE)) = BREG;
|
|
*(UTYPE *)(esp-5*sizeof(UTYPE)) = SPREG;
|
|
*(UTYPE *)(esp-6*sizeof(UTYPE)) = BPREG;
|
|
*(UTYPE *)(esp-7*sizeof(UTYPE)) = SIREG;
|
|
*(UTYPE *)(esp-8*sizeof(UTYPE)) = DIREG;
|
|
esp -= 8*sizeof(UTYPE);
|
|
}
|
|
FRAGCOMMON0(PopAFrag)
|
|
{
|
|
// can't use POP_VAL() as ESP cannot be updated untile after we're sure
|
|
// things can't fault
|
|
DIREG = *(UTYPE *)(esp);
|
|
SIREG = *(UTYPE *)(esp+sizeof(UTYPE));
|
|
BPREG = *(UTYPE *)(esp+2*sizeof(UTYPE));
|
|
// ignore [E]SP register image on the stack
|
|
BREG = *(UTYPE *)(esp+4*sizeof(UTYPE));
|
|
DREG = *(UTYPE *)(esp+5*sizeof(UTYPE));
|
|
CREG = *(UTYPE *)(esp+6*sizeof(UTYPE));
|
|
AREG = *(UTYPE *)(esp+7*sizeof(UTYPE));
|
|
esp += 8*sizeof(UTYPE);
|
|
}
|
|
FRAGCOMMON1IMM(PushFrag)
|
|
{
|
|
PUSH_VAL(op1);
|
|
}
|
|
FRAGCOMMON0(CwdFrag)
|
|
{
|
|
DREG = (AREG & MSB) ? (UTYPE)0xffffffff : 0;
|
|
}
|
|
FRAGCOMMON2(BoundFrag)
|
|
{
|
|
if ((op2 < GET_VAL(pop1)) ||
|
|
(op2 > (GET_VAL( (ULONG)(ULONGLONG)(pop1) + sizeof(UTYPE))))) {
|
|
|
|
Int5(); // raise BOUND exception
|
|
}
|
|
}
|
|
FRAGCOMMON2IMM(EnterFrag)
|
|
{
|
|
BYTE level;
|
|
DWORD frameptr;
|
|
DWORD espTemp;
|
|
|
|
level = (BYTE)(op1 % 32);
|
|
espTemp = esp - sizeof(UTYPE);
|
|
*(UTYPE *)(espTemp) = BPREG; // can't use PUSH_VAL because esp can't be changed
|
|
frameptr = espTemp;
|
|
if (level) {
|
|
BYTE i;
|
|
DWORD ebpTemp = ebp;
|
|
for (i=1; i<= level-1; ++i) {
|
|
ebpTemp -= sizeof(UTYPE);
|
|
espTemp -= sizeof(UTYPE);
|
|
*(UTYPE *)espTemp = (UTYPE)ebpTemp;
|
|
}
|
|
espTemp-=sizeof(UTYPE);
|
|
*(DWORD *)espTemp = frameptr;
|
|
}
|
|
ebp = frameptr;
|
|
esp = espTemp-op2;
|
|
}
|
|
FRAGCOMMON0(LeaveFrag)
|
|
{
|
|
DWORD espTemp;
|
|
|
|
espTemp = ebp;
|
|
BPREG = *(UTYPE *)espTemp;
|
|
esp = espTemp + sizeof(UTYPE);
|
|
}
|
|
FRAGCOMMON2(LesFrag)
|
|
{
|
|
*pop1 = GET_VAL(op2); // pop1 is always a ptr to a register
|
|
ES = GET_SHORT(op2+sizeof(UTYPE));
|
|
//UNDONE: fault if segment register not loaded with correct value?
|
|
}
|
|
FRAGCOMMON2(LdsFrag)
|
|
{
|
|
*pop1 = GET_VAL(op2); // pop1 is always a ptr to a register
|
|
DS = GET_SHORT(op2+sizeof(UTYPE));
|
|
//UNDONE: fault if segment register not loaded with correct value?
|
|
}
|
|
FRAGCOMMON2(LssFrag)
|
|
{
|
|
*pop1 = GET_VAL(op2); // pop1 is always a ptr to a register
|
|
SS = GET_SHORT(op2+sizeof(UTYPE));
|
|
//UNDONE: fault if segment register not loaded with correct value?
|
|
}
|
|
FRAGCOMMON2(LfsFrag)
|
|
{
|
|
*pop1 = GET_VAL(op2); // pop1 is always a ptr to a register
|
|
FS = GET_SHORT(op2+sizeof(UTYPE));
|
|
//UNDONE: fault if segment register not loaded with correct value?
|
|
//UNDONE: what about the selector base for FS?
|
|
}
|
|
FRAGCOMMON2(LgsFrag)
|
|
{
|
|
*pop1 = GET_VAL(op2); // pop1 is always a ptr to a register
|
|
GS = GET_SHORT(op2+sizeof(UTYPE));
|
|
//UNDONE: fault if segment register not loaded with correct value?
|
|
}
|
|
FRAGCOMMON2(LslFrag)
|
|
{
|
|
//
|
|
// pop1 is a pointer to a register, so can use aligned code
|
|
//
|
|
|
|
op2 &= ~3; // mask off RPL bits
|
|
if (op2 == KGDT_R3_CODE || // CS: selector
|
|
op2 == KGDT_R3_DATA // DS:, SS:, ES: selector
|
|
) {
|
|
*pop1 = (UTYPE)-1; // limit=0xffffffff
|
|
SET_ZFLAG(0); // ZF=1
|
|
} else if (op2 == KGDT_R3_TEB) {
|
|
*pop1 = 0xfff; // limit=0xfff (1 x86 page)
|
|
SET_ZFLAG(0); // ZF=1
|
|
} else {
|
|
SET_ZFLAG(1); // ZF=0
|
|
}
|
|
}
|
|
FRAGCOMMON2(LarFrag)
|
|
{
|
|
//
|
|
// pop1 is a pointer to a register, so can use aligned code
|
|
//
|
|
|
|
op2 &= ~3; // mask off RPL bits
|
|
if (op2 == KGDT_R3_CODE) {
|
|
*pop1 = (UTYPE)0xcffb00;
|
|
SET_ZFLAG(0); // ZF=1
|
|
} else if (op2 == KGDT_R3_DATA) {
|
|
*pop1 = (UTYPE)0xcff300;
|
|
SET_ZFLAG(0); // ZF=1
|
|
} else if (op2 == KGDT_R3_TEB) {
|
|
*pop1 = (UTYPE)0x40f300;
|
|
SET_ZFLAG(0); // ZF=1
|
|
} else {
|
|
SET_ZFLAG(1); // ZF=0
|
|
}
|
|
}
|