State->Flags.Cf = FALSE;
State->Flags.Of = FALSE;
State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
- State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
+ State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
State->Flags.Pf = Soft386CalculateParity(Result);
/* Write back the result */
State->Flags.Cf = FALSE;
State->Flags.Of = FALSE;
State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
- State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
+ State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
State->Flags.Pf = Soft386CalculateParity(Result);
/* Write back the result */
State->Flags.Cf = FALSE;
State->Flags.Of = FALSE;
State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
- State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
+ State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
State->Flags.Pf = Soft386CalculateParity(Result);
/* Write back the result */
State->Flags.Cf = FALSE;
State->Flags.Of = FALSE;
State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
- State->Flags.Sf = (Result & SIGN_FLAG_LONG) ? TRUE : FALSE;
+ State->Flags.Sf = (Result & SIGN_FLAG_WORD) ? TRUE : FALSE;
State->Flags.Pf = Soft386CalculateParity(Result);
}
SOFT386_OPCODE_HANDLER(Soft386OpcodeCallAbs)
{
- // TODO: NOT IMPLEMENTED
- UNIMPLEMENTED;
+ USHORT Segment = 0;
+ ULONG Offset = 0;
+ BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
- return FALSE;
+ /* Make sure this is the right instruction */
+ ASSERT(Opcode == 0x9A);
+
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
+ {
+ /* The OPSIZE prefix toggles the size */
+ Size = !Size;
+ }
+
+ if (State->PrefixFlags & SOFT386_PREFIX_LOCK)
+ {
+ /* Invalid prefix */
+ Soft386Exception(State, SOFT386_EXCEPTION_UD);
+ return FALSE;
+ }
+
+ /* Fetch the offset */
+ if (Size)
+ {
+ if (!Soft386FetchDword(State, &Offset))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!Soft386FetchWord(State, (PUSHORT)&Offset))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
+
+ /* Fetch the segment */
+ if (!Soft386FetchWord(State, &Segment))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Push the current code segment selector */
+ if (!Soft386StackPush(State, State->SegmentRegs[SOFT386_REG_CS].Selector))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Push the current value of the instruction pointer */
+ if (!Soft386StackPush(State, State->InstPtr.Long))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Load the new CS */
+ if (!Soft386LoadSegment(State, SOFT386_REG_CS, Segment))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Load new (E)IP */
+ if (Size) State->InstPtr.Long = Offset;
+ else State->InstPtr.LowWord = LOWORD(Offset);
+
+ return TRUE;
}
SOFT386_OPCODE_HANDLER(Soft386OpcodeWait)
{
ULONG Data, DataSize;
BOOLEAN OperandSize, AddressSize;
+ SOFT386_SEG_REGS Segment = SOFT386_REG_DS;
OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
AddressSize = !AddressSize;
}
+ if (State->PrefixFlags & SOFT386_PREFIX_SEG)
+ {
+ /* Use the override segment instead of DS */
+ Segment = State->SegmentOverride;
+ }
+
/* Calculate the size */
if (Opcode == 0xA4) DataSize = sizeof(UCHAR);
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
/* Read from memory */
if (!Soft386ReadMemory(State,
- SOFT386_REG_DS,
+ Segment,
AddressSize ? State->GeneralRegs[SOFT386_REG_ESI].Long
: State->GeneralRegs[SOFT386_REG_ESI].LowWord,
FALSE,
ULONG FirstValue = 0, SecondValue = 0, Result;
ULONG DataSize, DataMask, SignFlag;
BOOLEAN OperandSize, AddressSize;
+ SOFT386_SEG_REGS Segment = SOFT386_REG_DS;
OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
AddressSize = !AddressSize;
}
- if ((State->PrefixFlags & SOFT386_PREFIX_REP)
- || (State->PrefixFlags & SOFT386_PREFIX_REPNZ))
+ if (State->PrefixFlags & SOFT386_PREFIX_SEG)
{
- // TODO: The REP/REPZ/REPNZ prefixes need to be implemented!
- Soft386Exception(State, SOFT386_EXCEPTION_UD);
- return FALSE;
+ /* Use the override segment instead of DS */
+ Segment = State->SegmentOverride;
}
/* Calculate the size */
/* Read from the first source operand */
if (!Soft386ReadMemory(State,
- SOFT386_REG_DS,
+ Segment,
AddressSize ? State->GeneralRegs[SOFT386_REG_ESI].Long
: State->GeneralRegs[SOFT386_REG_ESI].LowWord,
FALSE,
{
ULONG DataSize;
BOOLEAN OperandSize, AddressSize;
+ SOFT386_SEG_REGS Segment = SOFT386_REG_DS;
OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
AddressSize = !AddressSize;
}
+ if (State->PrefixFlags & SOFT386_PREFIX_SEG)
+ {
+ /* Use the override segment instead of DS */
+ Segment = State->SegmentOverride;
+ }
+
/* Calculate the size */
if (Opcode == 0xAC) DataSize = sizeof(UCHAR);
else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
/* Read from the source operand */
if (!Soft386ReadMemory(State,
- SOFT386_REG_DS,
+ Segment,
AddressSize ? State->GeneralRegs[SOFT386_REG_ESI].Long
: State->GeneralRegs[SOFT386_REG_ESI].LowWord,
FALSE,