/*++ 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 #include #include #include #include #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)); }