mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 03:12:59 +00:00
[FAST486]
The current "fast" method used in MOVS gives incorrect results. It has been temporarily replaced with a slow method that works correctly. The string functions do nothing when CX is 0 on entry, fix CMPS and SCAS. svn path=/branches/ntvdm/; revision=61203
This commit is contained in:
parent
84662d3de9
commit
e7a6deb93f
1 changed files with 81 additions and 145 deletions
|
@ -5363,176 +5363,90 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovs)
|
||||||
Segment = State->SegmentOverride;
|
Segment = State->SegmentOverride;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (State->PrefixFlags & FAST486_PREFIX_REP)
|
||||||
|
{
|
||||||
|
if ((AddressSize && (State->GeneralRegs[FAST486_REG_ECX].Long == 0))
|
||||||
|
|| (!AddressSize && (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0)))
|
||||||
|
{
|
||||||
|
/* Do nothing */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate the size */
|
/* Calculate the size */
|
||||||
if (Opcode == 0xA4) DataSize = sizeof(UCHAR);
|
if (Opcode == 0xA4) DataSize = sizeof(UCHAR);
|
||||||
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
|
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
|
||||||
|
|
||||||
if (State->PrefixFlags & FAST486_PREFIX_REP)
|
/* Read from the source operand */
|
||||||
|
if (!Fast486ReadMemory(State,
|
||||||
|
Segment,
|
||||||
|
AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long
|
||||||
|
: State->GeneralRegs[FAST486_REG_ESI].LowWord,
|
||||||
|
FALSE,
|
||||||
|
&Data,
|
||||||
|
DataSize))
|
||||||
{
|
{
|
||||||
UCHAR Block[STRING_BLOCK_SIZE];
|
/* Exception occurred */
|
||||||
ULONG Count = AddressSize ? State->GeneralRegs[FAST486_REG_ECX].Long
|
return FALSE;
|
||||||
: State->GeneralRegs[FAST486_REG_ECX].LowWord;
|
}
|
||||||
|
|
||||||
/* Clear the memory block */
|
/* Write to the destination operand */
|
||||||
RtlZeroMemory(Block, sizeof(Block));
|
if (!Fast486WriteMemory(State,
|
||||||
|
FAST486_REG_ES,
|
||||||
|
AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
|
||||||
|
: State->GeneralRegs[FAST486_REG_EDI].LowWord,
|
||||||
|
&Data,
|
||||||
|
DataSize))
|
||||||
|
{
|
||||||
|
/* Exception occurred */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Transfer until finished */
|
/* Increment/decrement ESI and EDI */
|
||||||
while (Count)
|
if (AddressSize)
|
||||||
|
{
|
||||||
|
if (!State->Flags.Df)
|
||||||
{
|
{
|
||||||
ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
|
State->GeneralRegs[FAST486_REG_ESI].Long += DataSize;
|
||||||
|
State->GeneralRegs[FAST486_REG_EDI].Long += DataSize;
|
||||||
/* Simulate the 16-bit wrap-around of SI and DI in 16-bit address mode */
|
}
|
||||||
if (!AddressSize)
|
else
|
||||||
{
|
{
|
||||||
ULONG MaxBytesSrc = State->Flags.Df
|
State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize;
|
||||||
? (ULONG)State->GeneralRegs[FAST486_REG_ESI].LowWord
|
State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
|
||||||
: (0x10000 - (ULONG)State->GeneralRegs[FAST486_REG_ESI].LowWord);
|
|
||||||
ULONG MaxBytesDest = State->Flags.Df
|
|
||||||
? (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord
|
|
||||||
: (0x10000 - (ULONG)State->GeneralRegs[FAST486_REG_EDI].LowWord);
|
|
||||||
|
|
||||||
|
|
||||||
Processed = min(Processed, min(MaxBytesSrc, MaxBytesDest) / DataSize);
|
|
||||||
if (Processed == 0) Processed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (State->Flags.Df)
|
|
||||||
{
|
|
||||||
/* Move ESI and EDI to the start of the block */
|
|
||||||
if (AddressSize)
|
|
||||||
{
|
|
||||||
State->GeneralRegs[FAST486_REG_ESI].Long -= (Processed - 1) * DataSize;
|
|
||||||
State->GeneralRegs[FAST486_REG_EDI].Long -= (Processed - 1) * DataSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
State->GeneralRegs[FAST486_REG_ESI].LowWord -= (Processed - 1) * DataSize;
|
|
||||||
State->GeneralRegs[FAST486_REG_EDI].LowWord -= (Processed - 1) * DataSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read from memory */
|
|
||||||
if (!Fast486ReadMemory(State,
|
|
||||||
Segment,
|
|
||||||
AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long
|
|
||||||
: State->GeneralRegs[FAST486_REG_ESI].LowWord,
|
|
||||||
FALSE,
|
|
||||||
Block,
|
|
||||||
Processed * DataSize))
|
|
||||||
{
|
|
||||||
/* Set ECX */
|
|
||||||
if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
|
|
||||||
else State->GeneralRegs[FAST486_REG_ECX].LowWord = LOWORD(Count);
|
|
||||||
|
|
||||||
/* Exception occurred */
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write to memory */
|
|
||||||
if (!Fast486WriteMemory(State,
|
|
||||||
FAST486_REG_ES,
|
|
||||||
AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
|
|
||||||
: State->GeneralRegs[FAST486_REG_EDI].LowWord,
|
|
||||||
Block,
|
|
||||||
Processed * DataSize))
|
|
||||||
{
|
|
||||||
/* Set ECX */
|
|
||||||
if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = Count;
|
|
||||||
else State->GeneralRegs[FAST486_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[FAST486_REG_ESI].Long += Processed * DataSize;
|
|
||||||
State->GeneralRegs[FAST486_REG_EDI].Long += Processed * DataSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
State->GeneralRegs[FAST486_REG_ESI].LowWord += Processed * DataSize;
|
|
||||||
State->GeneralRegs[FAST486_REG_EDI].LowWord += Processed * DataSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Reduce ESI and EDI */
|
|
||||||
if (AddressSize)
|
|
||||||
{
|
|
||||||
State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize;
|
|
||||||
State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
State->GeneralRegs[FAST486_REG_ESI].LowWord -= DataSize;
|
|
||||||
State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reduce the total count by the number processed in this run */
|
|
||||||
Count -= Processed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear ECX */
|
|
||||||
if (AddressSize) State->GeneralRegs[FAST486_REG_ECX].Long = 0;
|
|
||||||
else State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Read from the source operand */
|
if (!State->Flags.Df)
|
||||||
if (!Fast486ReadMemory(State,
|
|
||||||
FAST486_REG_DS,
|
|
||||||
AddressSize ? State->GeneralRegs[FAST486_REG_ESI].Long
|
|
||||||
: State->GeneralRegs[FAST486_REG_ESI].LowWord,
|
|
||||||
FALSE,
|
|
||||||
&Data,
|
|
||||||
DataSize))
|
|
||||||
{
|
{
|
||||||
/* Exception occurred */
|
State->GeneralRegs[FAST486_REG_ESI].LowWord += DataSize;
|
||||||
return FALSE;
|
State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/* Write to the destination operand */
|
|
||||||
if (!Fast486WriteMemory(State,
|
|
||||||
FAST486_REG_ES,
|
|
||||||
AddressSize ? State->GeneralRegs[FAST486_REG_EDI].Long
|
|
||||||
: State->GeneralRegs[FAST486_REG_EDI].LowWord,
|
|
||||||
&Data,
|
|
||||||
DataSize))
|
|
||||||
{
|
{
|
||||||
/* Exception occurred */
|
State->GeneralRegs[FAST486_REG_ESI].LowWord -= DataSize;
|
||||||
return FALSE;
|
State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Increment/decrement ESI and EDI */
|
// FIXME: This method is slow!
|
||||||
|
if (State->PrefixFlags & FAST486_PREFIX_REP)
|
||||||
|
{
|
||||||
if (AddressSize)
|
if (AddressSize)
|
||||||
{
|
{
|
||||||
if (!State->Flags.Df)
|
if (--State->GeneralRegs[FAST486_REG_ECX].Long)
|
||||||
{
|
{
|
||||||
State->GeneralRegs[FAST486_REG_ESI].Long += DataSize;
|
/* Repeat the instruction */
|
||||||
State->GeneralRegs[FAST486_REG_EDI].Long += DataSize;
|
State->InstPtr = State->SavedInstPtr;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
State->GeneralRegs[FAST486_REG_ESI].Long -= DataSize;
|
|
||||||
State->GeneralRegs[FAST486_REG_EDI].Long -= DataSize;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!State->Flags.Df)
|
if (--State->GeneralRegs[FAST486_REG_ECX].LowWord)
|
||||||
{
|
{
|
||||||
State->GeneralRegs[FAST486_REG_ESI].LowWord += DataSize;
|
/* Repeat the instruction */
|
||||||
State->GeneralRegs[FAST486_REG_EDI].LowWord += DataSize;
|
State->InstPtr = State->SavedInstPtr;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
State->GeneralRegs[FAST486_REG_ESI].LowWord -= DataSize;
|
|
||||||
State->GeneralRegs[FAST486_REG_EDI].LowWord -= DataSize;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5562,6 +5476,17 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeCmps)
|
||||||
Segment = State->SegmentOverride;
|
Segment = State->SegmentOverride;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((State->PrefixFlags & FAST486_PREFIX_REP)
|
||||||
|
|| (State->PrefixFlags & FAST486_PREFIX_REPNZ))
|
||||||
|
{
|
||||||
|
if ((AddressSize && (State->GeneralRegs[FAST486_REG_ECX].Long == 0))
|
||||||
|
|| (!AddressSize && (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0)))
|
||||||
|
{
|
||||||
|
/* Do nothing */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate the size */
|
/* Calculate the size */
|
||||||
if (Opcode == 0xA6) DataSize = sizeof(UCHAR);
|
if (Opcode == 0xA6) DataSize = sizeof(UCHAR);
|
||||||
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
|
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
|
||||||
|
@ -5909,6 +5834,17 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeScas)
|
||||||
TOGGLE_OPSIZE(OperandSize);
|
TOGGLE_OPSIZE(OperandSize);
|
||||||
TOGGLE_ADSIZE(AddressSize);
|
TOGGLE_ADSIZE(AddressSize);
|
||||||
|
|
||||||
|
if ((State->PrefixFlags & FAST486_PREFIX_REP)
|
||||||
|
|| (State->PrefixFlags & FAST486_PREFIX_REPNZ))
|
||||||
|
{
|
||||||
|
if ((AddressSize && (State->GeneralRegs[FAST486_REG_ECX].Long == 0))
|
||||||
|
|| (!AddressSize && (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0)))
|
||||||
|
{
|
||||||
|
/* Do nothing */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate the size */
|
/* Calculate the size */
|
||||||
if (Opcode == 0xAE) DataSize = sizeof(UCHAR);
|
if (Opcode == 0xAE) DataSize = sizeof(UCHAR);
|
||||||
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
|
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue