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

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
}
}