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=6... ============================================================================== --- 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 */