Author: aandrejevic
Date: Sun Oct 13 21:15:01 2013
New Revision: 60645
URL:
http://svn.reactos.org/svn/reactos?rev=60645&view=rev
Log:
[SOFT386]
Implement the REP prefix for MOVS.
Fix the REP prefix in INS, OUTS and STOS to simulate the DI
wrap-around even if DF is set.
Modified:
branches/ntvdm/lib/soft386/opcodes.c
Modified: branches/ntvdm/lib/soft386/opcodes.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/soft386/opcodes.c?rev…
==============================================================================
--- branches/ntvdm/lib/soft386/opcodes.c [iso-8859-1] (original)
+++ branches/ntvdm/lib/soft386/opcodes.c [iso-8859-1] Sun Oct 13 21:15:01 2013
@@ -5929,68 +5929,163 @@
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 == 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))
- {
- /* 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;
+ if (State->PrefixFlags & SOFT386_PREFIX_REP)
+ {
+ UCHAR Block[STRING_BLOCK_SIZE];
+ ULONG Count = OperandSize ? State->GeneralRegs[SOFT386_REG_ECX].Long
+ : State->GeneralRegs[SOFT386_REG_ECX].LowWord;
+
+ /* 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 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);
+
+
+ Processed = min(Processed, min(MaxBytesSrc, MaxBytesDest) / DataSize);
+ if (Processed == 0) Processed = 1;
+ }
+
+ 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,
+ SOFT386_REG_DS,
+ 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
{
- 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;
+ 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;
+ }
}
}
@@ -6171,7 +6266,9 @@
/* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
if (!AddressSize)
{
- ULONG MaxBytes = 0x10000 -
(ULONG)State->GeneralRegs[SOFT386_REG_EDI].LowWord;
+ 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;
@@ -6449,7 +6546,9 @@
/* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
if (!AddressSize)
{
- ULONG MaxBytes = 0x10000 -
(ULONG)State->GeneralRegs[SOFT386_REG_EDI].LowWord;
+ 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;
@@ -6595,7 +6694,9 @@
/* Simulate the 16-bit wrap-around of DI in 16-bit address mode */
if (!AddressSize)
{
- ULONG MaxBytes = 0x10000 -
(ULONG)State->GeneralRegs[SOFT386_REG_EDI].LowWord;
+ 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;