diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/x86new/shiftops.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/nthals/x86new/shiftops.c')
-rw-r--r-- | private/ntos/nthals/x86new/shiftops.c | 580 |
1 files changed, 580 insertions, 0 deletions
diff --git a/private/ntos/nthals/x86new/shiftops.c b/private/ntos/nthals/x86new/shiftops.c new file mode 100644 index 000000000..2e4a61745 --- /dev/null +++ b/private/ntos/nthals/x86new/shiftops.c @@ -0,0 +1,580 @@ +/*++ + +Copyright (c) 1994 Microsoft Corporation + +Module Name: + + mulops.c + +Abstract: + + This module implements the code to emulate the shift opcodes. + +Author: + + David N. Cutler (davec) 21-Sep-1994 + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "nthal.h" +#include "emulate.h" + +VOID +XmRolOp ( + IN PRXM_CONTEXT P + ) + +/*++ + +Routine Description: + + This function emulates a rol opcode. + +Arguments: + + P - Supplies a pointer to the emulation context structure. + +Return Value: + + None. + +--*/ + +{ + + ULONG Carry; + ULONG Count; + ULONG Mask; + ULONG Shift; + ULONG Value; + + // + // Rotate destination left and store result. + // + + Shift = ((P->DataType + 1) << 3) - 1; + Mask = ((1 << Shift) - 1) | (1 << Shift); + Value = P->DstValue.Long; + Count = P->SrcValue.Long & Shift; + if (Count != 0) { + if (Count == 1) { + P->Eflags.OF = (Value >> Shift) ^ (Value >> (Shift - 1)); + } + + do { + Carry = Value >> Shift; + Value = Carry | ((Value << 1) & Mask); + Count -= 1; + } while (Count != 0); + + P->Eflags.CF = Carry; + } + + XmStoreResult(P, Value); + return; +} + +VOID +XmRorOp ( + IN PRXM_CONTEXT P + ) + +/*++ + +Routine Description: + + This function emulates a ror opcode. + +Arguments: + + P - Supplies a pointer to the emulation context structure. + +Return Value: + + None. + +--*/ + +{ + + ULONG Carry; + ULONG Count; + ULONG Shift; + ULONG Value; + + // + // Rotate destination right and store result. + // + + Shift = ((P->DataType + 1) << 3) - 1; + Value = P->DstValue.Long; + Count = P->SrcValue.Long & Shift; + if (Count != 0) { + if (Count == 1) { + P->Eflags.OF = (Value >> Shift) ^ (Value & 0x1); + } + + do { + Carry = Value & 1; + Value = (Carry << Shift) | (Value >> 1); + Count -= 1; + } while (Count != 0 ); + + P->Eflags.CF = Carry; + } + + XmStoreResult(P, Value); + return; +} + +VOID +XmRclOp ( + IN PRXM_CONTEXT P + ) + +/*++ + +Routine Description: + + This function emulates a rcl opcode. + +Arguments: + + P - Supplies a pointer to the emulation context structure. + +Return Value: + + None. + +--*/ + +{ + + ULONG Carry; + ULONG Count; + ULONG Mask; + ULONG Shift; + ULONG Temp; + ULONG Value; + + // + // Rotate destination left through carry and store result. + // + + Shift = ((P->DataType + 1) << 3) - 1; + Mask = ((1 << Shift) - 1) | (1 << Shift); + Value = P->DstValue.Long; + Count = P->SrcValue.Long & Shift; + Carry = P->Eflags.CF; + if (Count != 0) { + if (Count == 1) { + P->Eflags.OF = (Value >> Shift) ^ (Value >> (Shift - 1)); + } + + do { + Temp = Value >> Shift; + Value = ((Value << 1) & Mask) | Carry; + Carry = Temp; + Count -= 1; + } while (Count != 0); + } + + XmStoreResult(P, Value); + P->Eflags.CF = Carry; + return; +} + +VOID +XmRcrOp ( + IN PRXM_CONTEXT P + ) + +/*++ + +Routine Description: + + This function emulates a rcr opcode. + +Arguments: + + P - Supplies a pointer to the emulation context structure. + +Return Value: + + None. + +--*/ + +{ + + ULONG Carry; + ULONG Count; + ULONG Shift; + ULONG Temp; + ULONG Value; + + // + // Rotate destination right through carry and store result. + // + + Shift = ((P->DataType + 1) << 3) - 1; + Value = P->DstValue.Long; + Count = P->SrcValue.Long & Shift; + Carry = P->Eflags.CF; + if (Count != 0) { + if (Count == 1) { + P->Eflags.OF = (Value >> Shift) ^ Carry; + } + + do { + Temp = Value & 1; + Value = (Carry << Shift) | (Value >> 1); + Carry = Temp; + Count -= 1; + } while (Count != 0); + } + + XmStoreResult(P, Value); + P->Eflags.CF = Carry; + return; +} + +VOID +XmShlOp ( + IN PRXM_CONTEXT P + ) + +/*++ + +Routine Description: + + This function emulates a shl opcode. + +Arguments: + + P - Supplies a pointer to the emulation context structure. + +Return Value: + + None. + +--*/ + +{ + + ULONG Carry; + ULONG Count; + ULONG Overflow; + ULONG Shift; + ULONG Value; + + // + // Shift destination left logical and store result. + // + + Shift = ((P->DataType + 1) << 3) - 1; + Value = P->DstValue.Long; + Count = P->SrcValue.Long; + if (Count != 0) { + if (P->DataType == LONG_DATA) { + Overflow = (Value ^ (Value << 1)) >> 31; + Carry = Value >> (32 - Count); + Value <<= Count; + + } else if (P->DataType == WORD_DATA) { + Overflow = (Value ^ (Value << 1)) >> 15; + Carry = Value >> (16 - Count); + Value = (Value << Count) & 0xffff; + + } else { + Overflow = (Value ^ (Value << 1)) >> 7; + Carry = Value >> (8 - Count); + Value = (Value << Count) & 0xff; + } + + P->Eflags.CF = Carry; + P->Eflags.OF = Overflow; + P->Eflags.PF = XmComputeParity(Value); + P->Eflags.ZF = (Value == 0); + P->Eflags.SF = Value >> Shift; + } + + XmStoreResult(P, Value); + return; +} + +VOID +XmShrOp ( + IN PRXM_CONTEXT P + ) + +/*++ + +Routine Description: + + This function emulates a shr opcode. + +Arguments: + + P - Supplies a pointer to the emulation context structure. + +Return Value: + + None. + +--*/ + +{ + + ULONG Carry; + ULONG Count; + ULONG Overflow; + ULONG Shift; + ULONG Value; + + // + // Shift destination right logical and store result. + // + + Shift = ((P->DataType + 1) << 3) - 1; + Value = P->DstValue.Long; + Count = P->SrcValue.Long; + if (Count != 0) { + if (P->DataType == LONG_DATA) { + Overflow = Value >> 31; + Carry = Value >> (Count - 1); + Value >>= Count; + + } else if (P->DataType == WORD_DATA) { + Overflow = Value >> 15; + Carry = Value >> (Count - 1); + Value >>= Count; + + } else { + Overflow = Value >> 7; + Carry = Value >> (Count - 1); + Value >>= Count; + } + + P->Eflags.CF = Carry; + P->Eflags.OF = Overflow; + P->Eflags.PF = XmComputeParity(Value); + P->Eflags.ZF = (Value == 0); + P->Eflags.SF = Value >> Shift; + } + + XmStoreResult(P, Value); + return; +} + +VOID +XmSarOp ( + IN PRXM_CONTEXT P + ) + +/*++ + +Routine Description: + + This function emulates a sar opcode. + +Arguments: + + P - Supplies a pointer to the emulation context structure. + +Return Value: + + None. + +--*/ + +{ + + ULONG Carry; + ULONG Count; + ULONG Shift; + LONG Value; + + // + // Shift destination right arithmetic and store result. + // + + Shift = ((P->DataType + 1) << 3) - 1; + Value = (LONG)P->DstValue.Long; + Count = P->SrcValue.Long; + if (Count != 0) { + if (P->DataType == LONG_DATA) { + Carry = Value >> (Count - 1); + Value >>= Count; + + } else if (P->DataType == WORD_DATA) { + Carry = Value >> (Count - 1); + Value = ((Value << 16) >> (Count + 16)) & 0xffff; + + } else { + Carry = Value >> (Count - 1); + Value = ((Value << 24) >> (Count + 24)) & 0xff; + } + + P->Eflags.CF = Carry; + P->Eflags.OF = 0; + P->Eflags.PF = XmComputeParity(Value); + P->Eflags.ZF = (Value == 0); + P->Eflags.SF = Value >> Shift; + } + + XmStoreResult(P, (ULONG)Value); + return; +} + +VOID +XmShldOp ( + IN PRXM_CONTEXT P + ) + +/*++ + +Routine Description: + + This function emulates a shld opcode. + +Arguments: + + P - Supplies a pointer to the emulation context structure. + +Return Value: + + None. + +--*/ + +{ + + ULONG Carry; + ULONG Count; + ULONG High; + ULONG Low; + ULONG Sign; + + // + // Double shift left logical and store result. + // + // The low 32-bits of the shift are the source. + // The high 32-bits of the shift are the destination. + // The shift count has been masked modulo the datatype. + // + // This shift is equivalent to extracting the high 32-bits of the left + // shifted result. + // + + Low = P->SrcValue.Long; + High = P->DstValue.Long; + Count = P->Shift; + if (Count != 0) { + if (P->DataType == LONG_DATA) { + if (Count == 1) { + P->Eflags.OF = (High ^ (High << 1)) >> 31; + } + + Carry = High >> (32 - Count); + High = (High << Count) | (Low >> (32 - Count)); + Sign = High >> 31; + + } else { + if (Count == 1) { + P->Eflags.OF = (High ^ (High << 1)) >> 15; + } + + Carry = High >> (16 - Count); + High = ((High << Count) | (Low >> (16 - Count))) & 0xffff; + Sign = High >> 15; + } + + P->Eflags.CF = Carry; + P->Eflags.PF = XmComputeParity(High); + P->Eflags.ZF = (High == 0); + P->Eflags.SF = Sign; + } + + XmStoreResult(P, High); + return; +} + +VOID +XmShrdOp ( + IN PRXM_CONTEXT P + ) + +/*++ + +Routine Description: + + This function emulates a shrd opcode. + +Arguments: + + P - Supplies a pointer to the emulation context structure. + +Return Value: + + None. + +--*/ + +{ + + ULONG Carry; + ULONG Count; + ULONG High; + ULONG Low; + ULONG Sign; + + // + // Double shift right logical and store result. + // + // The high 32-bits of the shift are the source. + // The low 32-bits of the shift are the destination. + // The shift count has been masked modulo the datatype. + // + // This shift is equivalent to extracting the low 32-bits of the right + // shifted result. + // + + High = P->SrcValue.Long; + Low = P->DstValue.Long; + Count = P->Shift; + if (Count != 0) { + if (P->DataType == LONG_DATA) { + if (Count == 1) { + P->Eflags.OF = High ^ (Low >> 31); + } + + Carry = Low >> (Count - 1); + Low = (High << (32 - Count)) | (Low >> Count); + Sign = Low >> 31; + + } else { + if (Count == 1) { + P->Eflags.OF = High ^ (Low >> 15); + } + + Carry = Low >> (Count - 1); + Low = ((High << (16 - Count)) | (Low >> Count)) & 0xffff; + Sign = Low >> 15; + } + + P->Eflags.CF = Carry; + P->Eflags.PF = XmComputeParity(Low); + P->Eflags.ZF = (Low == 0); + P->Eflags.SF = Sign; + } + + XmStoreResult(P, Low); + return; +} |