Soft386OpcodeGroupC7,
Soft386OpcodeEnter,
Soft386OpcodeLeave,
- Soft386OpcodeRetFarImm,
+ Soft386OpcodeRetFar,
Soft386OpcodeRetFar,
Soft386OpcodeInt,
Soft386OpcodeInt,
ULONG Value;
BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
- if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
}
- else if (State->PrefixFlags != 0)
+
+ if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
{
/* Invalid prefix */
Soft386Exception(State, SOFT386_EXCEPTION_UD);
ULONG Value;
BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
- if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
}
- else if (State->PrefixFlags != 0)
+
+ if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
{
/* Invalid prefix */
Soft386Exception(State, SOFT386_EXCEPTION_UD);
INT Reg = Opcode & 0x07;
BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
- if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
}
- else if (State->PrefixFlags != 0)
+
+ if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
{
/* Invalid prefix */
Soft386Exception(State, SOFT386_EXCEPTION_UD);
/* Make sure this is the right instruction */
ASSERT((Opcode & 0xF7) == 0xE5);
- if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
}
- else if (State->PrefixFlags != 0)
+
+ if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
{
/* Invalid prefix */
Soft386Exception(State, SOFT386_EXCEPTION_UD);
/* Make sure this is the right instruction */
ASSERT((Opcode & 0xF7) == 0xE7);
- if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
}
- else if (State->PrefixFlags != 0)
+
+ if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
{
/* Invalid prefix */
Soft386Exception(State, SOFT386_EXCEPTION_UD);
State->Flags.Cf = FALSE;
State->Flags.Of = FALSE;
State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
- State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
+ State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
State->Flags.Pf = Soft386CalculateParity(Result);
/* Write back the result */
State->Flags.Cf = FALSE;
State->Flags.Of = FALSE;
State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
- State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
+ State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
State->Flags.Pf = Soft386CalculateParity(Result);
/* Write back the result */
State->Flags.Cf = FALSE;
State->Flags.Of = FALSE;
State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
- State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
+ State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
State->Flags.Pf = Soft386CalculateParity(Result);
/* Write back the result */
State->Flags.Cf = FALSE;
State->Flags.Of = FALSE;
State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
- State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
+ State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
State->Flags.Pf = Soft386CalculateParity(Result);
}
/* Make sure this is the right instruction */
ASSERT(Opcode == 0x98);
- if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
}
- else if (State->PrefixFlags != 0)
+
+ if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
{
/* Invalid prefix */
Soft386Exception(State, SOFT386_EXCEPTION_UD);
/* Make sure this is the right instruction */
ASSERT(Opcode == 0x99);
- if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
}
- else if (State->PrefixFlags != 0)
+
+ if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
{
/* Invalid prefix */
Soft386Exception(State, SOFT386_EXCEPTION_UD);
SOFT386_OPCODE_HANDLER(Soft386OpcodeCallAbs)
{
- // TODO: NOT IMPLEMENTED
- UNIMPLEMENTED;
+ USHORT Segment = 0;
+ ULONG Offset = 0;
+ BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
- return FALSE;
+ /* Make sure this is the right instruction */
+ ASSERT(Opcode == 0x9A);
+
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
+ {
+ /* The OPSIZE prefix toggles the size */
+ Size = !Size;
+ }
+
+ if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
+ {
+ /* Invalid prefix */
+ Soft386Exception(State, SOFT386_EXCEPTION_UD);
+ return FALSE;
+ }
+
+ /* Fetch the offset */
+ if (Size)
+ {
+ if (!Soft386FetchDword(State, &Offset))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!Soft386FetchWord(State, (PUSHORT)&Offset))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
+
+ /* Fetch the segment */
+ if (!Soft386FetchWord(State, &Segment))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Push the current code segment selector */
+ if (!Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_CS].Selector))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Push the current value of the instruction pointer */
+ if (!Soft386StackPush(State, State->InstPtr.Long))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Load the new CS */
+ if (!Soft386LoadSegment(State, SOFT386_REG_CS, Segment))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Load new (E)IP */
+ if (Size) State->InstPtr.Long = Offset;
+ else State->InstPtr.LowWord = LOWORD(Offset);
+
+ return TRUE;
}
SOFT386_OPCODE_HANDLER(Soft386OpcodeWait)
return FALSE;
}
- if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
}
}
-SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFarImm)
+SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFar)
{
- // TODO: NOT IMPLEMENTED
- UNIMPLEMENTED;
+ ULONG Segment = 0;
+ ULONG Offset = 0;
+ USHORT BytesToPop = 0;
+ BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
- return FALSE;
-}
+ /* Make sure this is the right instruction */
+ ASSERT((Opcode & 0xFE) == 0xCA);
-SOFT386_OPCODE_HANDLER(Soft386OpcodeRetFar)
-{
- // TODO: NOT IMPLEMENTED
- UNIMPLEMENTED;
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
+ {
+ /* The OPSIZE prefix toggles the size */
+ Size = !Size;
+ }
- return FALSE;
+ if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
+ {
+ /* Invalid prefix */
+ Soft386Exception(State, SOFT386_EXCEPTION_UD);
+ return FALSE;
+ }
+
+ if (Opcode == 0xCA)
+ {
+ /* Fetch the number of bytes to pop after the return */
+ if (!Soft386FetchWord(State, &BytesToPop)) return FALSE;
+ }
+
+ /* Pop the offset */
+ if (!Soft386StackPop(State, &Offset))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Pop the segment */
+ if (!Soft386StackPop(State, &Segment))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Load the new CS */
+ if (!Soft386LoadSegment(State, SOFT386_REG_CS, Segment))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Load new (E)IP, and if necessary, pop the parameters */
+ if (Size)
+ {
+ State->InstPtr.Long = Offset;
+ State->GeneralRegs[SOFT386_REG_ESP].Long += BytesToPop;
+ }
+ else
+ {
+ State->InstPtr.LowWord = LOWORD(Offset);
+ State->GeneralRegs[SOFT386_REG_ESP].LowWord += BytesToPop;
+ }
+
+ return TRUE;
}
SOFT386_OPCODE_HANDLER(Soft386OpcodeInt)
return FALSE;
}
- if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
/* Make sure this is the right instruction */
ASSERT(Opcode == 0xE8);
- if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
}
- else if (State->PrefixFlags != 0)
+
+ if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
{
/* Invalid prefix */
Soft386Exception(State, SOFT386_EXCEPTION_UD);
/* Make sure this is the right instruction */
ASSERT(Opcode == 0xE9);
- if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
{
/* The OPSIZE prefix toggles the size */
Size = !Size;
}
- else if (State->PrefixFlags != 0)
+
+ if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
{
/* Invalid prefix */
Soft386Exception(State, SOFT386_EXCEPTION_UD);
SOFT386_OPCODE_HANDLER(Soft386OpcodeJmpAbs)
{
- // TODO: NOT IMPLEMENTED
- UNIMPLEMENTED;
+ USHORT Segment = 0;
+ ULONG Offset = 0;
+ BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
- return FALSE;
+ /* Make sure this is the right instruction */
+ ASSERT(Opcode == 0xEA);
+
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
+ {
+ /* The OPSIZE prefix toggles the size */
+ Size = !Size;
+ }
+
+ if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
+ {
+ /* Invalid prefix */
+ Soft386Exception(State, SOFT386_EXCEPTION_UD);
+ return FALSE;
+ }
+
+ /* Fetch the offset */
+ if (Size)
+ {
+ if (!Soft386FetchDword(State, &Offset))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!Soft386FetchWord(State, (PUSHORT)&Offset))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
+
+ /* Fetch the segment */
+ if (!Soft386FetchWord(State, &Segment))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Load the new CS */
+ if (!Soft386LoadSegment(State, SOFT386_REG_CS, Segment))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Load new (E)IP */
+ if (Size) State->InstPtr.Long = Offset;
+ else State->InstPtr.LowWord = LOWORD(Offset);
+
+ return TRUE;
}
SOFT386_OPCODE_HANDLER(Soft386OpcodeMovAlOffset)
{
ULONG Data, DataSize;
BOOLEAN OperandSize, AddressSize;
+ SOFT386_SEG_REGS Segment = SOFT386_REG_DS;
OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
AddressSize = !AddressSize;
}
- if ((State->PrefixFlags & SOFT386_PREFIX_REP)
- || (State->PrefixFlags & SOFT386_PREFIX_REPNZ))
+ if (State->PrefixFlags & SOFT386_PREFIX_SEG)
{
- // TODO: The REP/REPZ/REPNZ prefixes need to be implemented!
- Soft386Exception(State, SOFT386_EXCEPTION_UD);
- return FALSE;
+ /* Use the override segment instead of DS */
+ Segment = State->SegmentOverride;
}
/* Calculate the size */
if (Opcode == 0xA4) DataSize = sizeof(UCHAR);
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
- /* Read from the source operand */
- if (!Soft386ReadMemory(State,
- SOFT386_REG_DS,
- AddressSize ? State->GeneralRegs[SOFT386_REG_ESI].Long
- : State->GeneralRegs[SOFT386_REG_ESI].LowWord,
- FALSE,
- &Data,
- DataSize))
+ if (State->PrefixFlags & SOFT386_PREFIX_REP)
{
- /* Exception occurred */
- return FALSE;
- }
+ UCHAR Block[STRING_BLOCK_SIZE];
+ ULONG Count = OperandSize ? State->GeneralRegs[SOFT386_REG_ECX].Long
+ : State->GeneralRegs[SOFT386_REG_ECX].LowWord;
- /* Write to the destination operand */
- if (!Soft386WriteMemory(State,
- SOFT386_REG_ES,
- AddressSize ? State->GeneralRegs[SOFT386_REG_EDI].Long
- : State->GeneralRegs[SOFT386_REG_EDI].LowWord,
- &Data,
- DataSize))
- {
- /* Exception occurred */
- return FALSE;
- }
+ /* Clear the memory block */
+ RtlZeroMemory(Block, sizeof(Block));
- /* Increment/decrement ESI and EDI */
- if (OperandSize)
- {
- if (State->Flags.Df)
- {
- State->GeneralRegs[SOFT386_REG_ESI].Long += DataSize;
- State->GeneralRegs[SOFT386_REG_EDI].Long += DataSize;
- }
- else
- {
- State->GeneralRegs[SOFT386_REG_ESI].Long -= DataSize;
- State->GeneralRegs[SOFT386_REG_EDI].Long -= DataSize;
- }
- }
- else
- {
- if (State->Flags.Df)
- {
- State->GeneralRegs[SOFT386_REG_ESI].LowWord += DataSize;
- State->GeneralRegs[SOFT386_REG_EDI].LowWord += DataSize;
- }
- else
+ /* Transfer until finished */
+ while (Count)
{
- State->GeneralRegs[SOFT386_REG_ESI].LowWord -= DataSize;
- State->GeneralRegs[SOFT386_REG_EDI].LowWord -= DataSize;
- }
- }
+ ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
- /* Return success */
- return TRUE;
-}
+ /* Simulate the 16-bit wrap-around of SI and DI in 16-bit address mode */
+ if (!AddressSize)
+ {
+ ULONG MaxBytesSrc = State->Flags.Df
+ ? (ULONG)State->GeneralRegs[SOFT386_REG_ESI].LowWord
+ : (0x10000 - (ULONG)State->GeneralRegs[SOFT386_REG_ESI].LowWord);
+ ULONG MaxBytesDest = State->Flags.Df
+ ? (ULONG)State->GeneralRegs[SOFT386_REG_EDI].LowWord
+ : (0x10000 - (ULONG)State->GeneralRegs[SOFT386_REG_EDI].LowWord);
-SOFT386_OPCODE_HANDLER(Soft386OpcodeCmps)
-{
- ULONG FirstValue = 0, SecondValue = 0, Result;
- ULONG DataSize, DataMask, SignFlag;
- BOOLEAN OperandSize, AddressSize;
- OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
+ Processed = min(Processed, min(MaxBytesSrc, MaxBytesDest) / DataSize);
+ if (Processed == 0) Processed = 1;
+ }
- /* Make sure this is the right instruction */
+ if (State->Flags.Df)
+ {
+ /* Reduce ESI and EDI by the number of bytes to transfer */
+ if (AddressSize)
+ {
+ State->GeneralRegs[SOFT386_REG_ESI].Long -= Processed * DataSize;
+ State->GeneralRegs[SOFT386_REG_EDI].Long -= Processed * DataSize;
+ }
+ else
+ {
+ State->GeneralRegs[SOFT386_REG_ESI].LowWord -= Processed * DataSize;
+ State->GeneralRegs[SOFT386_REG_EDI].LowWord -= Processed * DataSize;
+ }
+ }
+
+ /* Read from memory */
+ if (!Soft386ReadMemory(State,
+ Segment,
+ AddressSize ? State->GeneralRegs[SOFT386_REG_ESI].Long
+ : State->GeneralRegs[SOFT386_REG_ESI].LowWord,
+ FALSE,
+ Block,
+ Processed * DataSize))
+ {
+ /* Set ECX */
+ if (OperandSize) State->GeneralRegs[SOFT386_REG_ECX].Long = Count;
+ else State->GeneralRegs[SOFT386_REG_ECX].LowWord = LOWORD(Count);
+
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Write to memory */
+ if (!Soft386WriteMemory(State,
+ SOFT386_REG_ES,
+ AddressSize ? State->GeneralRegs[SOFT386_REG_EDI].Long
+ : State->GeneralRegs[SOFT386_REG_EDI].LowWord,
+ Block,
+ Processed * DataSize))
+ {
+ /* Set ECX */
+ if (OperandSize) State->GeneralRegs[SOFT386_REG_ECX].Long = Count;
+ else State->GeneralRegs[SOFT386_REG_ECX].LowWord = LOWORD(Count);
+
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ if (!State->Flags.Df)
+ {
+ /* Increase ESI and EDI by the number of bytes transfered */
+ if (AddressSize)
+ {
+ State->GeneralRegs[SOFT386_REG_ESI].Long += Processed * DataSize;
+ State->GeneralRegs[SOFT386_REG_EDI].Long += Processed * DataSize;
+ }
+ else
+ {
+ State->GeneralRegs[SOFT386_REG_ESI].LowWord += Processed * DataSize;
+ State->GeneralRegs[SOFT386_REG_EDI].LowWord += Processed * DataSize;
+ }
+ }
+
+ /* Reduce the total count by the number processed in this run */
+ Count -= Processed;
+ }
+
+ /* Clear ECX */
+ if (OperandSize) State->GeneralRegs[SOFT386_REG_ECX].Long = 0;
+ else State->GeneralRegs[SOFT386_REG_ECX].LowWord = 0;
+ }
+ else
+ {
+ /* Read from the source operand */
+ if (!Soft386ReadMemory(State,
+ SOFT386_REG_DS,
+ AddressSize ? State->GeneralRegs[SOFT386_REG_ESI].Long
+ : State->GeneralRegs[SOFT386_REG_ESI].LowWord,
+ FALSE,
+ &Data,
+ DataSize))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Write to the destination operand */
+ if (!Soft386WriteMemory(State,
+ SOFT386_REG_ES,
+ AddressSize ? State->GeneralRegs[SOFT386_REG_EDI].Long
+ : State->GeneralRegs[SOFT386_REG_EDI].LowWord,
+ &Data,
+ DataSize))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Increment/decrement ESI and EDI */
+ if (OperandSize)
+ {
+ if (!State->Flags.Df)
+ {
+ State->GeneralRegs[SOFT386_REG_ESI].Long += DataSize;
+ State->GeneralRegs[SOFT386_REG_EDI].Long += DataSize;
+ }
+ else
+ {
+ State->GeneralRegs[SOFT386_REG_ESI].Long -= DataSize;
+ State->GeneralRegs[SOFT386_REG_EDI].Long -= DataSize;
+ }
+ }
+ else
+ {
+ if (!State->Flags.Df)
+ {
+ State->GeneralRegs[SOFT386_REG_ESI].LowWord += DataSize;
+ State->GeneralRegs[SOFT386_REG_EDI].LowWord += DataSize;
+ }
+ else
+ {
+ State->GeneralRegs[SOFT386_REG_ESI].LowWord -= DataSize;
+ State->GeneralRegs[SOFT386_REG_EDI].LowWord -= DataSize;
+ }
+ }
+ }
+
+ /* Return success */
+ return TRUE;
+}
+
+SOFT386_OPCODE_HANDLER(Soft386OpcodeCmps)
+{
+ ULONG FirstValue = 0, SecondValue = 0, Result;
+ ULONG DataSize, DataMask, SignFlag;
+ BOOLEAN OperandSize, AddressSize;
+ SOFT386_SEG_REGS Segment = SOFT386_REG_DS;
+
+ OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
+
+ /* Make sure this is the right instruction */
ASSERT((Opcode & 0xFE) == 0xA6);
if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
AddressSize = !AddressSize;
}
- if ((State->PrefixFlags & SOFT386_PREFIX_REP)
- || (State->PrefixFlags & SOFT386_PREFIX_REPNZ))
+ if (State->PrefixFlags & SOFT386_PREFIX_SEG)
{
- // TODO: The REP/REPZ/REPNZ prefixes need to be implemented!
- Soft386Exception(State, SOFT386_EXCEPTION_UD);
- return FALSE;
+ /* Use the override segment instead of DS */
+ Segment = State->SegmentOverride;
}
/* Calculate the size */
/* Read from the first source operand */
if (!Soft386ReadMemory(State,
- SOFT386_REG_DS,
+ Segment,
AddressSize ? State->GeneralRegs[SOFT386_REG_ESI].Long
: State->GeneralRegs[SOFT386_REG_ESI].LowWord,
FALSE,
/* Increment/decrement ESI and EDI */
if (OperandSize)
{
- if (State->Flags.Df)
+ if (!State->Flags.Df)
{
State->GeneralRegs[SOFT386_REG_ESI].Long += DataSize;
State->GeneralRegs[SOFT386_REG_EDI].Long += DataSize;
}
else
{
- if (State->Flags.Df)
+ if (!State->Flags.Df)
{
State->GeneralRegs[SOFT386_REG_ESI].LowWord += DataSize;
State->GeneralRegs[SOFT386_REG_EDI].LowWord += DataSize;
}
}
+ // FIXME: This method is slow!
+ if ((State->PrefixFlags & SOFT386_PREFIX_REP)
+ || (State->PrefixFlags & SOFT386_PREFIX_REPNZ))
+ {
+ BOOLEAN Repeat = TRUE;
+
+ if (OperandSize)
+ {
+ if ((--State->GeneralRegs[SOFT386_REG_ECX].Long) == 0)
+ {
+ /* ECX is 0 */
+ Repeat = FALSE;
+ }
+ }
+ else
+ {
+ if ((--State->GeneralRegs[SOFT386_REG_ECX].LowWord) == 0)
+ {
+ /* CX is 0 */
+ Repeat = FALSE;
+ }
+ }
+
+ if (((State->PrefixFlags & SOFT386_PREFIX_REP) && !State->Flags.Zf)
+ || ((State->PrefixFlags & SOFT386_PREFIX_REPNZ) && State->Flags.Zf))
+ {
+ /* REPZ with ZF = 0 or REPNZ with ZF = 1 */
+ Repeat = FALSE;
+ }
+
+ if (Repeat)
+ {
+ /* Repeat the instruction */
+ State->InstPtr = State->SavedInstPtr;
+ }
+ }
+
/* Return success */
return TRUE;
}
AddressSize = !AddressSize;
}
- if ((State->PrefixFlags & SOFT386_PREFIX_REP)
- || (State->PrefixFlags & SOFT386_PREFIX_REPNZ))
- {
- // TODO: The REP/REPZ/REPNZ prefixes need to be implemented!
- Soft386Exception(State, SOFT386_EXCEPTION_UD);
- return FALSE;
- }
-
/* Calculate the size */
if (Opcode == 0xAA) DataSize = sizeof(UCHAR);
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
- /* Write to the destination operand */
- if (!Soft386WriteMemory(State,
- SOFT386_REG_ES,
- AddressSize ? State->GeneralRegs[SOFT386_REG_EDI].Long
- : State->GeneralRegs[SOFT386_REG_EDI].LowWord,
- &State->GeneralRegs[SOFT386_REG_EAX].Long,
- DataSize))
+ if (State->PrefixFlags & SOFT386_PREFIX_REP)
{
- /* Exception occurred */
- return FALSE;
- }
+ UCHAR Block[STRING_BLOCK_SIZE];
+ ULONG Count = OperandSize ? State->GeneralRegs[SOFT386_REG_ECX].Long
+ : State->GeneralRegs[SOFT386_REG_ECX].LowWord;
- /* Increment/decrement EDI */
- if (OperandSize)
- {
- if (State->Flags.Df) State->GeneralRegs[SOFT386_REG_EDI].Long += DataSize;
- else State->GeneralRegs[SOFT386_REG_EDI].Long -= DataSize;
+ /* Fill the memory block with the data */
+ if (DataSize == sizeof(UCHAR))
+ {
+ RtlFillMemory(Block, sizeof(Block), State->GeneralRegs[SOFT386_REG_EAX].LowByte);
+ }
+ else
+ {
+ ULONG i;
+
+ for (i = 0; i < STRING_BLOCK_SIZE / DataSize; i++)
+ {
+ if (DataSize == sizeof(USHORT))
+ {
+ ((PUSHORT)Block)[i] = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
+ }
+ else
+ {
+ ((PULONG)Block)[i] = State->GeneralRegs[SOFT386_REG_EAX].Long;
+ }
+ }
+ }
+
+ /* Transfer until finished */
+ while (Count)
+ {
+ ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
+
+ /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
+ if (!AddressSize)
+ {
+ ULONG MaxBytes = State->Flags.Df
+ ? (ULONG)State->GeneralRegs[SOFT386_REG_EDI].LowWord
+ : (0x10000 - (ULONG)State->GeneralRegs[SOFT386_REG_EDI].LowWord);
+
+ Processed = min(Processed, MaxBytes / DataSize);
+ if (Processed == 0) Processed = 1;
+ }
+
+ if (State->Flags.Df)
+ {
+ /* Reduce EDI by the number of bytes to transfer */
+ if (AddressSize) State->GeneralRegs[SOFT386_REG_EDI].Long -= Processed * DataSize;
+ else State->GeneralRegs[SOFT386_REG_EDI].LowWord -= Processed * DataSize;
+ }
+
+ /* Write to memory */
+ if (!Soft386WriteMemory(State,
+ SOFT386_REG_ES,
+ AddressSize ? State->GeneralRegs[SOFT386_REG_EDI].Long
+ : State->GeneralRegs[SOFT386_REG_EDI].LowWord,
+ Block,
+ Processed * DataSize))
+ {
+ /* Set ECX */
+ if (OperandSize) State->GeneralRegs[SOFT386_REG_ECX].Long = Count;
+ else State->GeneralRegs[SOFT386_REG_ECX].LowWord = LOWORD(Count);
+
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ if (!State->Flags.Df)
+ {
+ /* Increase EDI by the number of bytes transfered */
+ if (AddressSize) State->GeneralRegs[SOFT386_REG_EDI].Long += Processed * DataSize;
+ else State->GeneralRegs[SOFT386_REG_EDI].LowWord += Processed * DataSize;
+ }
+
+ /* Reduce the total count by the number processed in this run */
+ Count -= Processed;
+ }
+
+ /* Clear ECX */
+ if (OperandSize) State->GeneralRegs[SOFT386_REG_ECX].Long = 0;
+ else State->GeneralRegs[SOFT386_REG_ECX].LowWord = 0;
}
else
{
- if (State->Flags.Df) State->GeneralRegs[SOFT386_REG_EDI].LowWord += DataSize;
- else State->GeneralRegs[SOFT386_REG_EDI].LowWord -= DataSize;
+ /* Write to the destination operand */
+ if (!Soft386WriteMemory(State,
+ SOFT386_REG_ES,
+ AddressSize ? State->GeneralRegs[SOFT386_REG_EDI].Long
+ : State->GeneralRegs[SOFT386_REG_EDI].LowWord,
+ &State->GeneralRegs[SOFT386_REG_EAX].Long,
+ DataSize))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Increment/decrement EDI */
+ if (OperandSize)
+ {
+ if (!State->Flags.Df) State->GeneralRegs[SOFT386_REG_EDI].Long += DataSize;
+ else State->GeneralRegs[SOFT386_REG_EDI].Long -= DataSize;
+ }
+ else
+ {
+ if (!State->Flags.Df) State->GeneralRegs[SOFT386_REG_EDI].LowWord += DataSize;
+ else State->GeneralRegs[SOFT386_REG_EDI].LowWord -= DataSize;
+ }
}
/* Return success */
{
ULONG DataSize;
BOOLEAN OperandSize, AddressSize;
+ SOFT386_SEG_REGS Segment = SOFT386_REG_DS;
OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
AddressSize = !AddressSize;
}
- if ((State->PrefixFlags & SOFT386_PREFIX_REP)
- || (State->PrefixFlags & SOFT386_PREFIX_REPNZ))
+ if (State->PrefixFlags & SOFT386_PREFIX_SEG)
{
- // TODO: The REP/REPZ/REPNZ prefixes need to be implemented!
- Soft386Exception(State, SOFT386_EXCEPTION_UD);
- return FALSE;
+ /* Use the override segment instead of DS */
+ Segment = State->SegmentOverride;
}
/* Calculate the size */
if (Opcode == 0xAC) DataSize = sizeof(UCHAR);
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
+ if (State->PrefixFlags & SOFT386_PREFIX_REP)
+ {
+ ULONG Count = OperandSize ? State->GeneralRegs[SOFT386_REG_ECX].Long
+ : State->GeneralRegs[SOFT386_REG_ECX].LowWord;
+
+ /* If the count is 0, do nothing */
+ if (Count == 0) return TRUE;
+
+ /* Only the last entry will be loaded */
+ if (!State->Flags.Df)
+ {
+ if (AddressSize) State->GeneralRegs[SOFT386_REG_ESI].Long += (Count - 1) * DataSize;
+ else State->GeneralRegs[SOFT386_REG_ESI].LowWord += (Count - 1) * DataSize;
+ }
+ else
+ {
+ if (AddressSize) State->GeneralRegs[SOFT386_REG_ESI].Long -= (Count - 1) * DataSize;
+ else State->GeneralRegs[SOFT386_REG_ESI].LowWord -= (Count - 1) * DataSize;
+ }
+ }
+
/* Read from the source operand */
if (!Soft386ReadMemory(State,
- SOFT386_REG_DS,
+ Segment,
AddressSize ? State->GeneralRegs[SOFT386_REG_ESI].Long
: State->GeneralRegs[SOFT386_REG_ESI].LowWord,
FALSE,
/* Increment/decrement ESI */
if (OperandSize)
{
- if (State->Flags.Df) State->GeneralRegs[SOFT386_REG_ESI].Long += DataSize;
+ if (!State->Flags.Df) State->GeneralRegs[SOFT386_REG_ESI].Long += DataSize;
else State->GeneralRegs[SOFT386_REG_ESI].Long -= DataSize;
}
else
{
- if (State->Flags.Df) State->GeneralRegs[SOFT386_REG_ESI].LowWord += DataSize;
+ if (!State->Flags.Df) State->GeneralRegs[SOFT386_REG_ESI].LowWord += DataSize;
else State->GeneralRegs[SOFT386_REG_ESI].LowWord -= DataSize;
}
AddressSize = !AddressSize;
}
- if ((State->PrefixFlags & SOFT386_PREFIX_REP)
- || (State->PrefixFlags & SOFT386_PREFIX_REPNZ))
- {
- // TODO: The REP/REPZ/REPNZ prefixes need to be implemented!
- Soft386Exception(State, SOFT386_EXCEPTION_UD);
- return FALSE;
- }
-
/* Calculate the size */
- if (Opcode == 0xA6) DataSize = sizeof(UCHAR);
+ if (Opcode == 0xAE) DataSize = sizeof(UCHAR);
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
/* Calculate the mask and sign flag */
/* Increment/decrement EDI */
if (OperandSize)
{
- if (State->Flags.Df) State->GeneralRegs[SOFT386_REG_EDI].Long += DataSize;
+ if (!State->Flags.Df) State->GeneralRegs[SOFT386_REG_EDI].Long += DataSize;
else State->GeneralRegs[SOFT386_REG_EDI].Long -= DataSize;
}
else
{
- if (State->Flags.Df) State->GeneralRegs[SOFT386_REG_EDI].LowWord += DataSize;
+ if (!State->Flags.Df) State->GeneralRegs[SOFT386_REG_EDI].LowWord += DataSize;
else State->GeneralRegs[SOFT386_REG_EDI].LowWord -= DataSize;
}
+ // FIXME: This method is slow!
+ if ((State->PrefixFlags & SOFT386_PREFIX_REP)
+ || (State->PrefixFlags & SOFT386_PREFIX_REPNZ))
+ {
+ BOOLEAN Repeat = TRUE;
+
+ if (OperandSize)
+ {
+ if ((--State->GeneralRegs[SOFT386_REG_ECX].Long) == 0)
+ {
+ /* ECX is 0 */
+ Repeat = FALSE;
+ }
+ }
+ else
+ {
+ if ((--State->GeneralRegs[SOFT386_REG_ECX].LowWord) == 0)
+ {
+ /* CX is 0 */
+ Repeat = FALSE;
+ }
+ }
+
+ if (((State->PrefixFlags & SOFT386_PREFIX_REP) && !State->Flags.Zf)
+ || ((State->PrefixFlags & SOFT386_PREFIX_REPNZ) && State->Flags.Zf))
+ {
+ /* REPZ with ZF = 0 or REPNZ with ZF = 1 */
+ Repeat = FALSE;
+ }
+
+ if (Repeat)
+ {
+ /* Repeat the instruction */
+ State->InstPtr = State->SavedInstPtr;
+ }
+ }
+
/* Return success */
return TRUE;
}
SOFT386_OPCODE_HANDLER(Soft386OpcodeIns)
{
- ULONG Data = 0;
ULONG DataSize;
BOOLEAN OperandSize, AddressSize;
AddressSize = !AddressSize;
}
- if ((State->PrefixFlags & SOFT386_PREFIX_REP)
- || (State->PrefixFlags & SOFT386_PREFIX_REPNZ))
- {
- // TODO: The REP/REPZ/REPNZ prefixes need to be implemented!
- Soft386Exception(State, SOFT386_EXCEPTION_UD);
- return FALSE;
- }
-
/* Calculate the size */
if (Opcode == 0x6C) DataSize = sizeof(UCHAR);
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
- /* Read from the I/O port */
- State->IoReadCallback(State,
- State->GeneralRegs[SOFT386_REG_EDX].LowWord,
- &Data,
- DataSize);
-
- /* Write to the destination operand */
- if (!Soft386WriteMemory(State,
- SOFT386_REG_ES,
- AddressSize ? State->GeneralRegs[SOFT386_REG_EDI].Long
- : State->GeneralRegs[SOFT386_REG_EDI].LowWord,
- &Data,
- DataSize))
+ if (State->PrefixFlags & SOFT386_PREFIX_REP)
{
- /* Exception occurred */
- return FALSE;
- }
+ UCHAR Block[STRING_BLOCK_SIZE];
+ ULONG Count = OperandSize ? State->GeneralRegs[SOFT386_REG_ECX].Long
+ : State->GeneralRegs[SOFT386_REG_ECX].LowWord;
- /* Increment/decrement EDI */
- if (OperandSize)
- {
- if (State->Flags.Df) State->GeneralRegs[SOFT386_REG_EDI].Long += DataSize;
- else State->GeneralRegs[SOFT386_REG_EDI].Long -= DataSize;
+ /* Clear the memory block */
+ RtlZeroMemory(Block, sizeof(Block));
+
+ /* Transfer until finished */
+ while (Count)
+ {
+ ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
+
+ /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
+ if (!AddressSize)
+ {
+ ULONG MaxBytes = State->Flags.Df
+ ? (ULONG)State->GeneralRegs[SOFT386_REG_EDI].LowWord
+ : (0x10000 - (ULONG)State->GeneralRegs[SOFT386_REG_EDI].LowWord);
+
+ Processed = min(Processed, MaxBytes / DataSize);
+ if (Processed == 0) Processed = 1;
+ }
+
+ /* Read from the I/O port */
+ State->IoReadCallback(State,
+ State->GeneralRegs[SOFT386_REG_EDX].LowWord,
+ Block,
+ Processed * DataSize);
+
+ if (State->Flags.Df)
+ {
+ ULONG i, j;
+
+ /* Reduce EDI by the number of bytes to transfer */
+ if (AddressSize) State->GeneralRegs[SOFT386_REG_EDI].Long -= Processed * DataSize;
+ else State->GeneralRegs[SOFT386_REG_EDI].LowWord -= Processed * DataSize;
+
+ /* Reverse the block data */
+ for (i = 0; i < Processed / 2; i++)
+ {
+ /* Swap the values */
+ for (j = 0; j < DataSize; j++)
+ {
+ UCHAR Temp = Block[i * DataSize + j];
+ Block[i * DataSize + j] = Block[(Processed - i - 1) * DataSize + j];
+ Block[(Processed - i - 1) * DataSize + j] = Temp;
+ }
+ }
+ }
+
+ /* Write to memory */
+ if (!Soft386WriteMemory(State,
+ SOFT386_REG_ES,
+ AddressSize ? State->GeneralRegs[SOFT386_REG_EDI].Long
+ : State->GeneralRegs[SOFT386_REG_EDI].LowWord,
+ Block,
+ Processed * DataSize))
+ {
+ /* Set ECX */
+ if (OperandSize) State->GeneralRegs[SOFT386_REG_ECX].Long = Count;
+ else State->GeneralRegs[SOFT386_REG_ECX].LowWord = LOWORD(Count);
+
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ if (!State->Flags.Df)
+ {
+ /* Increase EDI by the number of bytes transfered */
+ if (AddressSize) State->GeneralRegs[SOFT386_REG_EDI].Long += Processed * DataSize;
+ else State->GeneralRegs[SOFT386_REG_EDI].LowWord += Processed * DataSize;
+ }
+
+ /* Reduce the total count by the number processed in this run */
+ Count -= Processed;
+ }
+
+ /* Clear ECX */
+ if (OperandSize) State->GeneralRegs[SOFT386_REG_ECX].Long = 0;
+ else State->GeneralRegs[SOFT386_REG_ECX].LowWord = 0;
}
else
{
- if (State->Flags.Df) State->GeneralRegs[SOFT386_REG_EDI].LowWord += DataSize;
- else State->GeneralRegs[SOFT386_REG_EDI].LowWord -= DataSize;
+ ULONG Data = 0;
+
+ /* Read from the I/O port */
+ State->IoReadCallback(State,
+ State->GeneralRegs[SOFT386_REG_EDX].LowWord,
+ &Data,
+ DataSize);
+
+ /* Write to the destination operand */
+ if (!Soft386WriteMemory(State,
+ SOFT386_REG_ES,
+ AddressSize ? State->GeneralRegs[SOFT386_REG_EDI].Long
+ : State->GeneralRegs[SOFT386_REG_EDI].LowWord,
+ &Data,
+ DataSize))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Increment/decrement EDI */
+ if (OperandSize)
+ {
+ if (!State->Flags.Df) State->GeneralRegs[SOFT386_REG_EDI].Long += DataSize;
+ else State->GeneralRegs[SOFT386_REG_EDI].Long -= DataSize;
+ }
+ else
+ {
+ if (!State->Flags.Df) State->GeneralRegs[SOFT386_REG_EDI].LowWord += DataSize;
+ else State->GeneralRegs[SOFT386_REG_EDI].LowWord -= DataSize;
+ }
}
/* Return success */
SOFT386_OPCODE_HANDLER(Soft386OpcodeOuts)
{
- ULONG Data = 0;
ULONG DataSize;
BOOLEAN OperandSize, AddressSize;
AddressSize = !AddressSize;
}
- if ((State->PrefixFlags & SOFT386_PREFIX_REP)
- || (State->PrefixFlags & SOFT386_PREFIX_REPNZ))
- {
- // TODO: The REP/REPZ/REPNZ prefixes need to be implemented!
- Soft386Exception(State, SOFT386_EXCEPTION_UD);
- return FALSE;
- }
-
/* Calculate the size */
if (Opcode == 0x6E) DataSize = sizeof(UCHAR);
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
- /* Read from the source operand */
- if (!Soft386ReadMemory(State,
- SOFT386_REG_DS,
- AddressSize ? State->GeneralRegs[SOFT386_REG_ESI].Long
- : State->GeneralRegs[SOFT386_REG_ESI].LowWord,
- FALSE,
- &Data,
- DataSize))
+ if (State->PrefixFlags & SOFT386_PREFIX_REP)
{
- /* Exception occurred */
- return FALSE;
- }
+ UCHAR Block[STRING_BLOCK_SIZE];
+ ULONG Count = OperandSize ? State->GeneralRegs[SOFT386_REG_ECX].Long
+ : State->GeneralRegs[SOFT386_REG_ECX].LowWord;
- /* Write to the I/O port */
- State->IoWriteCallback(State,
- State->GeneralRegs[SOFT386_REG_EDX].LowWord,
- &Data,
- DataSize);
+ /* Clear the memory block */
+ RtlZeroMemory(Block, sizeof(Block));
- /* Increment/decrement ESI */
- if (OperandSize)
- {
- if (State->Flags.Df) State->GeneralRegs[SOFT386_REG_ESI].Long += DataSize;
- else State->GeneralRegs[SOFT386_REG_ESI].Long -= DataSize;
+ /* Transfer until finished */
+ while (Count)
+ {
+ ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
+
+ /* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
+ if (!AddressSize)
+ {
+ ULONG MaxBytes = State->Flags.Df
+ ? (ULONG)State->GeneralRegs[SOFT386_REG_EDI].LowWord
+ : (0x10000 - (ULONG)State->GeneralRegs[SOFT386_REG_EDI].LowWord);
+
+ Processed = min(Processed, MaxBytes / DataSize);
+ if (Processed == 0) Processed = 1;
+ }
+
+ /* Read from memory */
+ if (!Soft386ReadMemory(State,
+ SOFT386_REG_ES,
+ AddressSize ? State->GeneralRegs[SOFT386_REG_EDI].Long
+ : State->GeneralRegs[SOFT386_REG_EDI].LowWord,
+ FALSE,
+ Block,
+ Processed * DataSize))
+ {
+ /* Set ECX */
+ if (OperandSize) State->GeneralRegs[SOFT386_REG_ECX].Long = Count;
+ else State->GeneralRegs[SOFT386_REG_ECX].LowWord = LOWORD(Count);
+
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ if (State->Flags.Df)
+ {
+ ULONG i, j;
+
+ /* Reduce EDI by the number of bytes to transfer */
+ if (AddressSize) State->GeneralRegs[SOFT386_REG_EDI].Long -= Processed * DataSize;
+ else State->GeneralRegs[SOFT386_REG_EDI].LowWord -= Processed * DataSize;
+
+ /* Reverse the block data */
+ for (i = 0; i < Processed / 2; i++)
+ {
+ /* Swap the values */
+ for (j = 0; j < DataSize; j++)
+ {
+ UCHAR Temp = Block[i * DataSize + j];
+ Block[i * DataSize + j] = Block[(Processed - i - 1) * DataSize + j];
+ Block[(Processed - i - 1) * DataSize + j] = Temp;
+ }
+ }
+ }
+
+ /* Write to the I/O port */
+ State->IoWriteCallback(State,
+ State->GeneralRegs[SOFT386_REG_EDX].LowWord,
+ Block,
+ Processed * DataSize);
+
+ if (!State->Flags.Df)
+ {
+ /* Increase EDI by the number of bytes transfered */
+ if (AddressSize) State->GeneralRegs[SOFT386_REG_EDI].Long += Processed * DataSize;
+ else State->GeneralRegs[SOFT386_REG_EDI].LowWord += Processed * DataSize;
+ }
+
+ /* Reduce the total count by the number processed in this run */
+ Count -= Processed;
+ }
+
+ /* Clear ECX */
+ if (OperandSize) State->GeneralRegs[SOFT386_REG_ECX].Long = 0;
+ else State->GeneralRegs[SOFT386_REG_ECX].LowWord = 0;
}
else
{
- if (State->Flags.Df) State->GeneralRegs[SOFT386_REG_ESI].LowWord += DataSize;
- else State->GeneralRegs[SOFT386_REG_ESI].LowWord -= DataSize;
+ ULONG Data = 0;
+
+ /* Read from the source operand */
+ if (!Soft386ReadMemory(State,
+ SOFT386_REG_DS,
+ AddressSize ? State->GeneralRegs[SOFT386_REG_ESI].Long
+ : State->GeneralRegs[SOFT386_REG_ESI].LowWord,
+ FALSE,
+ &Data,
+ DataSize))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Write to the I/O port */
+ State->IoWriteCallback(State,
+ State->GeneralRegs[SOFT386_REG_EDX].LowWord,
+ &Data,
+ DataSize);
+
+ /* Increment/decrement ESI */
+ if (OperandSize)
+ {
+ if (!State->Flags.Df) State->GeneralRegs[SOFT386_REG_ESI].Long += DataSize;
+ else State->GeneralRegs[SOFT386_REG_ESI].Long -= DataSize;
+ }
+ else
+ {
+ if (!State->Flags.Df) State->GeneralRegs[SOFT386_REG_ESI].LowWord += DataSize;
+ else State->GeneralRegs[SOFT386_REG_ESI].LowWord -= DataSize;
+ }
}
/* Return success */