306 lines
7.2 KiB
C
306 lines
7.2 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1995 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
shr1632a.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Instruction fragments with common (shared) WORD, and DWORD flavors
|
||
|
(but not BYTE).
|
||
|
|
||
|
Compiled twice per flavor, once with UNALIGNED and once with ALIGNED
|
||
|
pointers.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
05-Nov-1995 BarryBo
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include "shr1632a.h"
|
||
|
|
||
|
FRAGCOMMON2(BtMemFrag)
|
||
|
{
|
||
|
UTYPE bit = 1<<(op2&LMB);
|
||
|
|
||
|
op2 /= LMB+1; // compute offset of the correct WORD/DWORD
|
||
|
SET_CFLAG_IND(GET_VAL(pop1+op2) & bit);
|
||
|
}
|
||
|
FRAGCOMMON2(BtsMemFrag)
|
||
|
{
|
||
|
DWORD NewCFlag;
|
||
|
UTYPE bit = 1<<(op2&LMB);
|
||
|
UTYPE op1;
|
||
|
|
||
|
op2 /= LMB+1; // compute offset of the correct WORD/DWORD
|
||
|
pop1 += op2;
|
||
|
op1 = GET_VAL(pop1);
|
||
|
|
||
|
NewCFlag = op1 & bit;
|
||
|
// Intel docs indicate that we can safely overwrite all 2/4 bytes
|
||
|
// when writing the value back out. (pg. 26/43)
|
||
|
PUT_VAL(pop1, (op1|bit));
|
||
|
SET_CFLAG_IND(NewCFlag);
|
||
|
}
|
||
|
FRAGCOMMON2(BtcMemFrag)
|
||
|
{
|
||
|
DWORD NewCFlag;
|
||
|
UTYPE bit = 1<<(op2&LMB);
|
||
|
UTYPE op1;
|
||
|
|
||
|
op2 /= LMB+1; // compute offset of the correct WORD/DWORD
|
||
|
pop1 += op2;
|
||
|
op1 = GET_VAL(pop1);
|
||
|
|
||
|
NewCFlag = op1 & bit;
|
||
|
// Intel docs indicate that we can safely overwrite all 2/4 bytes
|
||
|
// when writing the value back out. (pg. 26/43)
|
||
|
PUT_VAL(pop1, op1 ^ bit);
|
||
|
SET_CFLAG_IND(NewCFlag);
|
||
|
}
|
||
|
FRAGCOMMON2(BtrMemFrag)
|
||
|
{
|
||
|
DWORD NewCFlag;
|
||
|
UTYPE bit = 1<<(op2&LMB);
|
||
|
UTYPE op1;
|
||
|
|
||
|
op2 /= LMB+1; // compute offset of the correct WORD/DWORD
|
||
|
pop1 += op2;
|
||
|
op1 = GET_VAL(pop1);
|
||
|
|
||
|
NewCFlag = op1 & bit;
|
||
|
// Intel docs indicate that we can safely overwrite all 2/4 bytes
|
||
|
// when writing the value back out. (pg. 26/43)
|
||
|
PUT_VAL(pop1, (op1&(~bit)));
|
||
|
SET_CFLAG_IND(NewCFlag);
|
||
|
}
|
||
|
FRAGCOMMON2(BtRegFrag)
|
||
|
{
|
||
|
UTYPE bit = 1<<(op2&LMB);
|
||
|
|
||
|
SET_CFLAG_IND(GET_VAL(pop1) & bit);
|
||
|
}
|
||
|
FRAGCOMMON2(BtsRegFrag)
|
||
|
{
|
||
|
DWORD NewCFlag;
|
||
|
UTYPE bit = 1<<(op2&LMB);
|
||
|
UTYPE op1;
|
||
|
|
||
|
op1 = GET_VAL(pop1);
|
||
|
|
||
|
NewCFlag = op1 & bit;
|
||
|
// Intel docs indicate that we can safely overwrite all 2/4 bytes
|
||
|
// when writing the value back out. (pg. 26/43)
|
||
|
PUT_VAL(pop1, (op1|bit));
|
||
|
SET_CFLAG_IND(NewCFlag);
|
||
|
}
|
||
|
FRAGCOMMON2(BtcRegFrag)
|
||
|
{
|
||
|
DWORD NewCFlag;
|
||
|
UTYPE bit = 1<<(op2&LMB);
|
||
|
UTYPE op1;
|
||
|
|
||
|
op1 = GET_VAL(pop1);
|
||
|
|
||
|
NewCFlag = op1 & bit;
|
||
|
// Intel docs indicate that we can safely overwrite all 2/4 bytes
|
||
|
// when writing the value back out. (pg. 26/43)
|
||
|
PUT_VAL(pop1, (op1 ^ bit));
|
||
|
SET_CFLAG_IND(NewCFlag);
|
||
|
}
|
||
|
FRAGCOMMON2(BtrRegFrag)
|
||
|
{
|
||
|
DWORD NewCFlag;
|
||
|
UTYPE bit = 1<<(op2&LMB);
|
||
|
UTYPE op1;
|
||
|
|
||
|
op1 = GET_VAL(pop1);
|
||
|
|
||
|
NewCFlag = op1 & bit;
|
||
|
// Intel docs indicate that we can safely overwrite all 2/4 bytes
|
||
|
// when writing the value back out. (pg. 26/43)
|
||
|
PUT_VAL(pop1, (op1&(~bit)));
|
||
|
SET_CFLAG_IND(NewCFlag);
|
||
|
}
|
||
|
|
||
|
FRAGCOMMON3(ShldFrag)
|
||
|
{
|
||
|
// pop1 = Base -- ptr to dest reg/mem
|
||
|
// op2 = inBits -- value of register containing bits to shift into Base
|
||
|
// op3 = count -- number of bits to shift
|
||
|
|
||
|
|
||
|
DWORD NewCFlag;
|
||
|
UTYPE Base;
|
||
|
|
||
|
if (op3 == 0) {
|
||
|
return; // nothing to do - nop with all flags preserved
|
||
|
}
|
||
|
op3 &= 0x1f; // make the count MOD 32 (now op3 = ShiftAmt)
|
||
|
#if MSB == 0x8000
|
||
|
if (op3 > 16) {
|
||
|
// Bad parameters - *pop1 UNDEFINED!
|
||
|
// - CF,OF,SF,ZF,AF,PF UNDEFINED!
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
Base = GET_VAL(pop1);
|
||
|
NewCFlag = Base & (1<<(LMB+1-op3)); // Get the new CF value
|
||
|
|
||
|
Base <<= op3; // shift Base left
|
||
|
op2 >>= LMB+1-op3; // shift the top op3 bits of op2 right
|
||
|
Base |= op2; // merge the two together
|
||
|
PUT_VAL(pop1, Base);
|
||
|
SET_CFLAG_IND(NewCFlag);
|
||
|
SET_ZFLAG(Base);
|
||
|
SET_PFLAG(Base);
|
||
|
SET_SFLAG(Base << (31-LMB));
|
||
|
}
|
||
|
FRAGCOMMON3(ShldNoFlagsFrag)
|
||
|
{
|
||
|
// pop1 = Base -- ptr to dest reg/mem
|
||
|
// op2 = inBits -- value of register containing bits to shift into Base
|
||
|
// op3 = count -- number of bits to shift
|
||
|
|
||
|
|
||
|
UTYPE Base;
|
||
|
|
||
|
if (op3 == 0) {
|
||
|
return; // nothing to do - nop with all flags preserved
|
||
|
}
|
||
|
op3 &= 0x1f; // make the count MOD 32 (now op3 = ShiftAmt)
|
||
|
#if MSB == 0x8000
|
||
|
if (op3 > 16) {
|
||
|
// Bad parameters - *pop1 UNDEFINED!
|
||
|
// - CF,OF,SF,ZF,AF,PF UNDEFINED!
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
Base = GET_VAL(pop1);
|
||
|
|
||
|
Base <<= op3; // shift Base left
|
||
|
op2 >>= LMB+1-op3; // shift the top op3 bits of op2 right
|
||
|
Base |= op2; // merge the two together
|
||
|
PUT_VAL(pop1, Base);
|
||
|
}
|
||
|
FRAGCOMMON3(ShrdFrag)
|
||
|
{
|
||
|
// pop1 = Base -- ptr to dest reg/mem
|
||
|
// op2 = inBits -- value of register containing bits to shift into Base
|
||
|
// op3 = count -- number of bits to shift
|
||
|
|
||
|
|
||
|
DWORD NewCFlag;
|
||
|
UTYPE Base;
|
||
|
int i;
|
||
|
|
||
|
if (op3 == 0) {
|
||
|
return; // nothing to do - nop with all flags preserved
|
||
|
}
|
||
|
op3 &= 0x1f; // make the count MOD 32 (now op3 = ShiftAmt)
|
||
|
#if MSB == 0x8000
|
||
|
if (op3 > 16) {
|
||
|
// Bad parameters - *pop1 UNDEFINED!
|
||
|
// - CF,OF,SF,ZF,AF,PF UNDEFINED!
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
Base = GET_VAL(pop1);
|
||
|
NewCFlag = Base & (1<<(op3-1)); // Get the new CF value
|
||
|
|
||
|
Base >>= op3; // shift Base right
|
||
|
op2 <<= LMB+1-op3; // shift the low op3 bits of op2
|
||
|
Base |= op2; // merge the two together
|
||
|
PUT_VAL(pop1, Base);
|
||
|
SET_CFLAG_IND(NewCFlag);
|
||
|
SET_ZFLAG(Base);
|
||
|
SET_PFLAG(Base);
|
||
|
SET_SFLAG(Base << (31-LMB));
|
||
|
}
|
||
|
FRAGCOMMON3(ShrdNoFlagsFrag)
|
||
|
{
|
||
|
// pop1 = Base -- ptr to dest reg/mem
|
||
|
// op2 = inBits -- value of register containing bits to shift into Base
|
||
|
// op3 = count -- number of bits to shift
|
||
|
|
||
|
|
||
|
UTYPE Base;
|
||
|
int i;
|
||
|
|
||
|
if (op3 == 0) {
|
||
|
return; // nothing to do - nop with all flags preserved
|
||
|
}
|
||
|
op3 &= 0x1f; // make the count MOD 32 (now op3 = ShiftAmt)
|
||
|
#if MSB == 0x8000
|
||
|
if (op3 > 16) {
|
||
|
// Bad parameters - *pop1 UNDEFINED!
|
||
|
// - CF,OF,SF,ZF,AF,PF UNDEFINED!
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
Base = GET_VAL(pop1);
|
||
|
|
||
|
Base >>= op3; // shift Base right
|
||
|
op2 <<= LMB+1-op3; // shift the low op3 bits of op2
|
||
|
Base |= op2; // merge the two together
|
||
|
PUT_VAL(pop1, Base);
|
||
|
}
|
||
|
FRAGCOMMON2(BsfFrag)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
if (op2 == 0) {
|
||
|
// value is 0 - set ZFLAG and return
|
||
|
SET_ZFLAG(0);
|
||
|
// *pop1 = UNDEFINED
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// scan from bit 0 forward, looking for the index of '1' bit
|
||
|
for (i=0; (op2 & 1) == 0; ++i) {
|
||
|
op2 >>= 1;
|
||
|
}
|
||
|
|
||
|
// write the index of the '1' bit and clear the ZFLAG
|
||
|
PUT_VAL(pop1, i);
|
||
|
SET_ZFLAG(op2);
|
||
|
}
|
||
|
FRAGCOMMON2(BsrFrag)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
if (op2 == 0) {
|
||
|
// value is 0 - set ZFLAG and return
|
||
|
SET_ZFLAG(0);
|
||
|
// *pop1 = UNDEFINED
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// scan from bit 31/15 downward, looking for the index of '1' bit
|
||
|
for (i=LMB; (op2 & MSB) == 0; --i) {
|
||
|
op2 <<= 1;
|
||
|
}
|
||
|
|
||
|
// write the index of the '1' bit and clear the ZFLAG
|
||
|
PUT_VAL(pop1, i);
|
||
|
SET_ZFLAG(op2);
|
||
|
}
|
||
|
FRAGCOMMON1(PopFrag)
|
||
|
{
|
||
|
POP_VAL(GET_VAL(pop1));
|
||
|
}
|