mirror of
https://github.com/reactos/reactos.git
synced 2025-01-03 21:09:19 +00:00
[FAST486]
Implement CMPXCHG. svn path=/branches/ntvdm/; revision=60712
This commit is contained in:
parent
a98544e517
commit
75a0ca07a1
2 changed files with 160 additions and 2 deletions
|
@ -214,8 +214,8 @@ Fast486ExtendedHandlers[FAST486_NUM_OPCODE_HANDLERS] =
|
|||
NULL, // TODO: OPCODE 0xAD NOT IMPLEMENTED
|
||||
NULL, // TODO: OPCODE 0xAE NOT IMPLEMENTED
|
||||
NULL, // TODO: OPCODE 0xAF NOT IMPLEMENTED
|
||||
NULL, // TODO: OPCODE 0xB0 NOT IMPLEMENTED
|
||||
NULL, // TODO: OPCODE 0xB1 NOT IMPLEMENTED
|
||||
Fast486ExtOpcodeCmpXchgByte,
|
||||
Fast486ExtOpcodeCmpXchg,
|
||||
NULL, // TODO: OPCODE 0xB2 NOT IMPLEMENTED
|
||||
NULL, // TODO: OPCODE 0xB3 NOT IMPLEMENTED
|
||||
NULL, // TODO: OPCODE 0xB4 NOT IMPLEMENTED
|
||||
|
@ -338,6 +338,162 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopGs)
|
|||
return Fast486LoadSegment(State, FAST486_REG_GS, LOWORD(NewSelector));
|
||||
}
|
||||
|
||||
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchgByte)
|
||||
{
|
||||
FAST486_MOD_REG_RM ModRegRm;
|
||||
UCHAR Accumulator = State->GeneralRegs[FAST486_REG_EAX].LowByte;
|
||||
UCHAR Source, Destination, Result;
|
||||
BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;;
|
||||
|
||||
if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
|
||||
{
|
||||
/* The ADSIZE prefix toggles the size */
|
||||
AddressSize = !AddressSize;
|
||||
}
|
||||
|
||||
/* Get the operands */
|
||||
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
|
||||
{
|
||||
/* Exception occurred */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Read the operands */
|
||||
if (!Fast486ReadModrmByteOperands(State, &ModRegRm, &Source, &Destination))
|
||||
{
|
||||
/* Exception occurred */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Compare AL with the destination */
|
||||
Result = Accumulator - Destination;
|
||||
|
||||
/* Update the flags */
|
||||
State->Flags.Cf = Accumulator < Destination;
|
||||
State->Flags.Of = ((Accumulator & SIGN_FLAG_BYTE) != (Destination & SIGN_FLAG_BYTE))
|
||||
&& ((Accumulator & SIGN_FLAG_BYTE) != (Result & SIGN_FLAG_BYTE));
|
||||
State->Flags.Af = (Accumulator & 0x0F) < (Destination & 0x0F);
|
||||
State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
|
||||
State->Flags.Sf = (Result & SIGN_FLAG_BYTE) ? TRUE : FALSE;
|
||||
State->Flags.Pf = Fast486CalculateParity(Result);
|
||||
|
||||
if (State->Flags.Zf)
|
||||
{
|
||||
/* Load the source operand into the destination */
|
||||
return Fast486WriteModrmByteOperands(State, &ModRegRm, FALSE, Source);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Load the destination into AL */
|
||||
State->GeneralRegs[FAST486_REG_EAX].LowByte = Destination;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchg)
|
||||
{
|
||||
FAST486_MOD_REG_RM ModRegRm;
|
||||
BOOLEAN OperandSize, AddressSize;
|
||||
|
||||
OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
|
||||
|
||||
if (State->PrefixFlags & FAST486_PREFIX_OPSIZE)
|
||||
{
|
||||
/* The OPSIZE prefix toggles the size */
|
||||
OperandSize = !OperandSize;
|
||||
}
|
||||
|
||||
if (State->PrefixFlags & FAST486_PREFIX_ADSIZE)
|
||||
{
|
||||
/* The ADSIZE prefix toggles the size */
|
||||
AddressSize = !AddressSize;
|
||||
}
|
||||
|
||||
/* Get the operands */
|
||||
if (!Fast486ParseModRegRm(State, AddressSize, &ModRegRm))
|
||||
{
|
||||
/* Exception occurred */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (OperandSize)
|
||||
{
|
||||
ULONG Source, Destination, Result;
|
||||
ULONG Accumulator = State->GeneralRegs[FAST486_REG_EAX].Long;
|
||||
|
||||
/* Read the operands */
|
||||
if (!Fast486ReadModrmDwordOperands(State, &ModRegRm, &Source, &Destination))
|
||||
{
|
||||
/* Exception occurred */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Compare EAX with the destination */
|
||||
Result = Accumulator - Destination;
|
||||
|
||||
/* Update the flags */
|
||||
State->Flags.Cf = Accumulator < Destination;
|
||||
State->Flags.Of = ((Accumulator & SIGN_FLAG_LONG) != (Destination & SIGN_FLAG_LONG))
|
||||
&& ((Accumulator & SIGN_FLAG_LONG) != (Result & SIGN_FLAG_LONG));
|
||||
State->Flags.Af = (Accumulator & 0x0F) < (Destination & 0x0F);
|
||||
State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
|
||||
State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
|
||||
State->Flags.Pf = Fast486CalculateParity(Result);
|
||||
|
||||
if (State->Flags.Zf)
|
||||
{
|
||||
/* Load the source operand into the destination */
|
||||
return Fast486WriteModrmDwordOperands(State, &ModRegRm, FALSE, Source);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Load the destination into EAX */
|
||||
State->GeneralRegs[FAST486_REG_EAX].Long = Destination;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
USHORT Source, Destination, Result;
|
||||
USHORT Accumulator = State->GeneralRegs[FAST486_REG_EAX].LowWord;
|
||||
|
||||
/* Read the operands */
|
||||
if (!Fast486ReadModrmWordOperands(State, &ModRegRm, &Source, &Destination))
|
||||
{
|
||||
/* Exception occurred */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Compare AX with the destination */
|
||||
Result = Accumulator - Destination;
|
||||
|
||||
/* Update the flags */
|
||||
State->Flags.Cf = Accumulator < Destination;
|
||||
State->Flags.Of = ((Accumulator & SIGN_FLAG_WORD) != (Destination & SIGN_FLAG_WORD))
|
||||
&& ((Accumulator & SIGN_FLAG_WORD) != (Result & SIGN_FLAG_WORD));
|
||||
State->Flags.Af = (Accumulator & 0x0F) < (Destination & 0x0F);
|
||||
State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
|
||||
State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
|
||||
State->Flags.Pf = Fast486CalculateParity(Result);
|
||||
|
||||
if (State->Flags.Zf)
|
||||
{
|
||||
/* Load the source operand into the destination */
|
||||
return Fast486WriteModrmWordOperands(State, &ModRegRm, FALSE, Source);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Load the destination into AX */
|
||||
State->GeneralRegs[FAST486_REG_EAX].LowWord = Destination;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalJmp)
|
||||
{
|
||||
BOOLEAN Jump = FALSE;
|
||||
|
|
|
@ -27,6 +27,8 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushFs);
|
|||
FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopFs);
|
||||
FAST486_OPCODE_HANDLER(Fast486ExtOpcodePushGs);
|
||||
FAST486_OPCODE_HANDLER(Fast486ExtOpcodePopGs);
|
||||
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchgByte);
|
||||
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeCmpXchg);
|
||||
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalJmp);
|
||||
FAST486_OPCODE_HANDLER(Fast486ExtOpcodeConditionalSet);
|
||||
FAST486_OPCODE_HANDLER(Fast486OpcodeExtended);
|
||||
|
|
Loading…
Reference in a new issue