summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/x86new/stringop.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/x86new/stringop.c
downloadNT4.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/stringop.c')
-rw-r--r--private/ntos/nthals/x86new/stringop.c496
1 files changed, 496 insertions, 0 deletions
diff --git a/private/ntos/nthals/x86new/stringop.c b/private/ntos/nthals/x86new/stringop.c
new file mode 100644
index 000000000..61fc6998a
--- /dev/null
+++ b/private/ntos/nthals/x86new/stringop.c
@@ -0,0 +1,496 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ stringop.c
+
+Abstract:
+
+ This module implements the code to emulate the string opcodes.
+
+Author:
+
+ David N. Cutler (davec) 7-Nov-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+
+//
+// Define forward referenced prototypes.
+//
+
+VOID
+XmCompareOperands (
+ IN PRXM_CONTEXT P
+ );
+
+VOID
+XmCmpsOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a cmpsb/w/d opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Count;
+
+ //
+ // If a repeat prefix is active, then the loop count is specified
+ // by eCX. Otherwise, the loop count is one.
+ //
+
+ Count = 1;
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ Count = P->Gpr[ECX].Exx;
+
+ } else {
+ Count = P->Gpr[CX].Xx;
+ }
+ }
+
+ //
+ // Compare items from source and destination.
+ //
+
+ while (Count != 0) {
+
+ //
+ // Set source and destination values.
+ //
+
+ XmSetSourceValue(P, XmGetStringAddress(P, P->DataSegment, ESI));
+ XmSetDestinationValue(P, XmGetStringAddress(P, ES, EDI));
+
+ //
+ // Compare source with destination operand and decrement loop count.
+ // If ZF is not equal to the repeat Z flag condition, then terminate
+ // the loop.
+ //
+
+ XmCompareOperands(P);
+ Count -= 1;
+ if (P->Eflags.ZF != P->RepeatZflag) {
+ break;
+ }
+ }
+
+ //
+ // If a repeat prefix is active, then set the final count value.
+ //
+
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ P->Gpr[ECX].Exx = Count;
+
+ } else {
+ P->Gpr[CX].Xx = (USHORT)Count;
+ }
+ }
+
+ return;
+}
+
+VOID
+XmLodsOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a lodsb/w/d opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Count;
+
+ //
+ // If a repeat prefix is active, then the loop count is specified
+ // by eCX. Otherwise, the loop count is one.
+ //
+
+ Count = 1;
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ Count = P->Gpr[ECX].Exx;
+ P->Gpr[ECX].Exx = 0;
+
+ } else {
+ Count = P->Gpr[CX].Xx;
+ P->Gpr[CX].Xx = 0;
+ }
+ }
+
+ //
+ // Set destination address.
+ //
+
+ P->DstLong = (ULONG UNALIGNED *)&P->Gpr[EAX].Exx;
+
+ //
+ // Move items from source to destination.
+ //
+
+ while (Count != 0) {
+
+ //
+ // Set source value and store result.
+ //
+
+ XmSetSourceValue(P, XmGetStringAddress(P, P->DataSegment, ESI));
+ XmStoreResult(P, P->SrcValue.Long);
+ Count -= 1;
+ }
+
+ return;
+}
+
+VOID
+XmMovsOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a movsb/w/d opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Count;
+
+ //
+ // If a repeat prefix is active, then the loop count is specified
+ // by eCX. Otherwise, the loop count is one.
+ //
+
+ Count = 1;
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ Count = P->Gpr[ECX].Exx;
+ P->Gpr[ECX].Exx = 0;
+
+ } else {
+ Count = P->Gpr[CX].Xx;
+ P->Gpr[CX].Xx = 0;
+ }
+ }
+
+ //
+ // Move items from source to destination.
+ //
+
+ while (Count != 0) {
+
+ //
+ // Set source value, set destination address, and store result.
+ //
+
+ XmSetSourceValue(P, XmGetStringAddress(P, P->DataSegment, ESI));
+ P->DstLong = (ULONG UNALIGNED *)XmGetStringAddress(P, ES, EDI);
+ XmStoreResult(P, P->SrcValue.Long);
+ Count -= 1;
+ }
+
+ return;
+}
+
+VOID
+XmScasOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a scasb/w/d opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Count;
+
+ //
+ // If a repeat prefix is active, then the loop count is specified
+ // by eCX. Otherwise, the loop count is one.
+ //
+
+ Count = 1;
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ Count = P->Gpr[ECX].Exx;
+
+ } else {
+ Count = P->Gpr[CX].Xx;
+ }
+ }
+
+ //
+ // Set source value.
+ //
+
+ XmSetSourceValue(P, (PVOID)&P->Gpr[EAX].Exx);
+
+ //
+ // Compare items from source and destination.
+ //
+
+ while (Count != 0) {
+
+ //
+ // Set destination value.
+ //
+
+ XmSetDestinationValue(P, XmGetStringAddress(P, ES, EDI));
+
+ //
+ // Compare source with destination operand and decrement loop count.
+ // If ZF is not equal to the repeat Z flag condition, then terminate
+ // the loop.
+ //
+
+ XmCompareOperands(P);
+ Count -= 1;
+ if (P->Eflags.ZF != P->RepeatZflag) {
+ break;
+ }
+ }
+
+ //
+ // If a repeat prefix is active, then set the final count value.
+ //
+
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ P->Gpr[ECX].Exx = Count;
+
+ } else {
+ P->Gpr[CX].Xx = (USHORT)Count;
+ }
+ }
+
+ return;
+}
+
+VOID
+XmStosOp (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a stosb/w/d opcode.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Count;
+
+ //
+ // If a repeat prefix is active, then the loop count is specified
+ // by eCX. Otherwise, the loop count is one.
+ //
+
+ Count = 1;
+ if (P->RepeatPrefixActive != FALSE) {
+ if (P->OpaddrPrefixActive != FALSE) {
+ Count = P->Gpr[ECX].Exx;
+ P->Gpr[ECX].Exx = 0;
+
+ } else {
+ Count = P->Gpr[CX].Xx;
+ P->Gpr[CX].Xx = 0;
+ }
+ }
+
+ //
+ // Set source value.
+ //
+
+ XmSetSourceValue(P, (PVOID)&P->Gpr[EAX].Exx);
+
+ //
+ // Move items from source to destination.
+ //
+
+ while (Count != 0) {
+
+ //
+ // Set destination address and store result.
+ //
+
+ P->DstLong = (ULONG UNALIGNED *)XmGetStringAddress(P, ES, EDI);
+ XmStoreResult(P, P->SrcValue.Long);
+ Count -= 1;
+ }
+
+ return;
+}
+
+VOID
+XmCompareOperands (
+ IN PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function compares two operands and computes the resulting condition
+ codes.
+
+Arguments:
+
+ P - Supplies a pointer to the emulation context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG CarryFlag;
+ ULONG OverflowFlag;
+ ULONG SignFlag;
+ ULONG ZeroFlag;
+ union {
+ UCHAR ResultByte;
+ ULONG ResultLong;
+ USHORT ResultWord;
+ } u;
+
+ //
+ // Switch on data type.
+ //
+
+ switch (P->DataType) {
+
+ //
+ // The operation datatype is byte.
+ //
+
+ case BYTE_DATA:
+ CarryFlag = (P->SrcValue.Byte < P->DstValue.Byte);
+ u.ResultByte = P->SrcValue.Byte - P->DstValue.Byte;
+ OverflowFlag = (((u.ResultByte ^ P->SrcValue.Byte) &
+ (u.ResultByte ^ P->DstValue.Byte)) >> 7) & 0x1;
+
+ SignFlag = (u.ResultByte >> 7) & 0x1;
+ ZeroFlag = (u.ResultByte == 0);
+ u.ResultLong = u.ResultByte;
+ break;
+
+ //
+ // The operation datatype is word.
+ //
+
+ case WORD_DATA:
+ CarryFlag = (P->SrcValue.Word < P->DstValue.Word);
+ u.ResultWord = P->SrcValue.Word - P->DstValue.Word;
+ OverflowFlag = (((u.ResultWord ^ P->SrcValue.Word) &
+ (u.ResultWord ^ P->DstValue.Word)) >> 15) & 0x1;
+
+ SignFlag = (u.ResultWord >> 15) & 0x1;
+ ZeroFlag = (u.ResultWord == 0);
+ u.ResultLong = u.ResultWord;
+ break;
+
+ //
+ // The operation datatype is long.
+ //
+
+ case LONG_DATA:
+ CarryFlag = (P->SrcValue.Long < P->DstValue.Long);
+ u.ResultLong = P->SrcValue.Long - P->DstValue.Long;
+ OverflowFlag = (((u.ResultLong ^ P->SrcValue.Long) &
+ (u.ResultLong ^ P->DstValue.Long)) >> 31) & 0x1;
+
+ SignFlag = (u.ResultLong >> 31) & 0x1;
+ ZeroFlag = (u.ResultLong == 0);
+ break;
+ }
+
+ //
+ // Compute auxilary carry flag, parity flag, and store all flags in
+ // the flags register.
+ //
+
+ P->Eflags.CF = CarryFlag;
+ P->Eflags.PF = XmComputeParity(u.ResultLong);
+ P->Eflags.AF = ((P->DstValue.Byte & 0xf) + (P->SrcValue.Byte & 0xf)) >> 4;
+ P->Eflags.ZF = ZeroFlag;
+ P->Eflags.SF = SignFlag;
+ P->Eflags.OF = OverflowFlag;
+ return;
+}