Author: aandrejevic
Date: Thu Oct 10 19:01:41 2013
New Revision: 60600
URL:
http://svn.reactos.org/svn/reactos?rev=60600&view=rev
Log:
[SOFT386]
Implement the REP prefix for the INS instruction.
Modified:
branches/ntvdm/lib/soft386/common.h
branches/ntvdm/lib/soft386/opcodes.c
Modified: branches/ntvdm/lib/soft386/common.h
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/soft386/common.h?rev=…
==============================================================================
--- branches/ntvdm/lib/soft386/common.h [iso-8859-1] (original)
+++ branches/ntvdm/lib/soft386/common.h [iso-8859-1] Thu Oct 10 19:01:41 2013
@@ -33,6 +33,9 @@
#define SIGN_FLAG_LONG 0x80000000
#define REAL_MODE_FLAGS_MASK 0x17FD5
#define PROT_MODE_FLAGS_MASK 0x10DD5
+
+/* Block size for string operations */
+#define STRING_BLOCK_SIZE 4096
#define GET_SEGMENT_RPL(s) ((s) & 3)
#define GET_SEGMENT_INDEX(s) ((s) & 0xFFF8)
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] Thu Oct 10 19:01:41 2013
@@ -6311,7 +6311,6 @@
SOFT386_OPCODE_HANDLER(Soft386OpcodeIns)
{
- ULONG Data = 0;
ULONG DataSize;
BOOLEAN OperandSize, AddressSize;
@@ -6330,48 +6329,114 @@
{
/* The ADSIZE prefix toggles the size */
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))
- {
- /* 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;
+ 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;
+
+ /* Transfer until finished */
+ while (Count)
+ {
+ ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
+
+ /* 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 */