mirror of
https://github.com/reactos/reactos.git
synced 2025-06-27 14:39:43 +00:00
[SOFT386]
Implement the REP prefix for OUTS, LODS and STOS. svn path=/branches/ntvdm/; revision=60616
This commit is contained in:
parent
20486fd1b7
commit
caf9a0a671
1 changed files with 213 additions and 65 deletions
|
@ -6122,40 +6122,106 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeStos)
|
||||||
AddressSize = !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 */
|
/* Calculate the size */
|
||||||
if (Opcode == 0xAA) DataSize = sizeof(UCHAR);
|
if (Opcode == 0xAA) DataSize = sizeof(UCHAR);
|
||||||
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
|
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
|
||||||
|
|
||||||
/* Write to the destination operand */
|
if (State->PrefixFlags & SOFT386_PREFIX_REP)
|
||||||
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 */
|
UCHAR Block[STRING_BLOCK_SIZE];
|
||||||
return FALSE;
|
ULONG Count = OperandSize ? State->GeneralRegs[SOFT386_REG_ECX].Long
|
||||||
}
|
: State->GeneralRegs[SOFT386_REG_ECX].LowWord;
|
||||||
|
|
||||||
/* Increment/decrement EDI */
|
/* Fill the memory block with the data */
|
||||||
if (OperandSize)
|
if (DataSize == sizeof(UCHAR))
|
||||||
{
|
{
|
||||||
if (State->Flags.Df) State->GeneralRegs[SOFT386_REG_EDI].Long += DataSize;
|
RtlFillMemory(Block, State->GeneralRegs[SOFT386_REG_EAX].LowByte, sizeof(Block));
|
||||||
else State->GeneralRegs[SOFT386_REG_EDI].Long -= DataSize;
|
}
|
||||||
|
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);
|
||||||
|
|
||||||
|
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
|
else
|
||||||
{
|
{
|
||||||
if (State->Flags.Df) State->GeneralRegs[SOFT386_REG_EDI].LowWord += DataSize;
|
/* Write to the destination operand */
|
||||||
else State->GeneralRegs[SOFT386_REG_EDI].LowWord -= DataSize;
|
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 */
|
/* Return success */
|
||||||
|
@ -6184,18 +6250,31 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeLods)
|
||||||
AddressSize = !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 */
|
/* Calculate the size */
|
||||||
if (Opcode == 0xAC) DataSize = sizeof(UCHAR);
|
if (Opcode == 0xAC) DataSize = sizeof(UCHAR);
|
||||||
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
|
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 */
|
/* Read from the source operand */
|
||||||
if (!Soft386ReadMemory(State,
|
if (!Soft386ReadMemory(State,
|
||||||
SOFT386_REG_DS,
|
SOFT386_REG_DS,
|
||||||
|
@ -6448,7 +6527,6 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeIns)
|
||||||
|
|
||||||
SOFT386_OPCODE_HANDLER(Soft386OpcodeOuts)
|
SOFT386_OPCODE_HANDLER(Soft386OpcodeOuts)
|
||||||
{
|
{
|
||||||
ULONG Data = 0;
|
|
||||||
ULONG DataSize;
|
ULONG DataSize;
|
||||||
BOOLEAN OperandSize, AddressSize;
|
BOOLEAN OperandSize, AddressSize;
|
||||||
|
|
||||||
|
@ -6469,47 +6547,117 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeOuts)
|
||||||
AddressSize = !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 */
|
/* Calculate the size */
|
||||||
if (Opcode == 0x6E) DataSize = sizeof(UCHAR);
|
if (Opcode == 0x6E) DataSize = sizeof(UCHAR);
|
||||||
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
|
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
|
||||||
|
|
||||||
/* Read from the source operand */
|
if (State->PrefixFlags & SOFT386_PREFIX_REP)
|
||||||
if (!Soft386ReadMemory(State,
|
|
||||||
SOFT386_REG_DS,
|
|
||||||
AddressSize ? State->GeneralRegs[SOFT386_REG_ESI].Long
|
|
||||||
: State->GeneralRegs[SOFT386_REG_ESI].LowWord,
|
|
||||||
FALSE,
|
|
||||||
&Data,
|
|
||||||
DataSize))
|
|
||||||
{
|
{
|
||||||
/* Exception occurred */
|
UCHAR Block[STRING_BLOCK_SIZE];
|
||||||
return FALSE;
|
ULONG Count = OperandSize ? State->GeneralRegs[SOFT386_REG_ECX].Long
|
||||||
}
|
: State->GeneralRegs[SOFT386_REG_ECX].LowWord;
|
||||||
|
|
||||||
/* Write to the I/O port */
|
/* Clear the memory block */
|
||||||
State->IoWriteCallback(State,
|
RtlZeroMemory(Block, sizeof(Block));
|
||||||
State->GeneralRegs[SOFT386_REG_EDX].LowWord,
|
|
||||||
&Data,
|
|
||||||
DataSize);
|
|
||||||
|
|
||||||
/* Increment/decrement ESI */
|
/* Transfer until finished */
|
||||||
if (OperandSize)
|
while (Count)
|
||||||
{
|
{
|
||||||
if (State->Flags.Df) State->GeneralRegs[SOFT386_REG_ESI].Long += DataSize;
|
ULONG Processed = min(Count, STRING_BLOCK_SIZE / DataSize);
|
||||||
else State->GeneralRegs[SOFT386_REG_ESI].Long -= DataSize;
|
|
||||||
|
/* 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
|
else
|
||||||
{
|
{
|
||||||
if (State->Flags.Df) State->GeneralRegs[SOFT386_REG_ESI].LowWord += DataSize;
|
ULONG Data = 0;
|
||||||
else State->GeneralRegs[SOFT386_REG_ESI].LowWord -= DataSize;
|
|
||||||
|
/* 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 */
|
/* Return success */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue