Author: aandrejevic
Date: Mon Oct 7 20:38:01 2013
New Revision: 60582
URL:
http://svn.reactos.org/svn/reactos?rev=60582&view=rev
Log:
[SOFT386]
Implement opcode group 0xF7.
Modified:
branches/ntvdm/lib/soft386/opgroups.c
Modified: branches/ntvdm/lib/soft386/opgroups.c
URL:
http://svn.reactos.org/svn/reactos/branches/ntvdm/lib/soft386/opgroups.c?re…
==============================================================================
--- branches/ntvdm/lib/soft386/opgroups.c [iso-8859-1] (original)
+++ branches/ntvdm/lib/soft386/opgroups.c [iso-8859-1] Mon Oct 7 20:38:01 2013
@@ -1070,7 +1070,7 @@
USHORT Result = (USHORT)Value *
(USHORT)State->GeneralRegs[SOFT386_REG_EAX].LowByte;
/* Update the flags */
- State->Flags.Cf = State->Flags.Of = (Result & 0xFF00) ? TRUE :
FALSE;
+ State->Flags.Cf = State->Flags.Of = HIBYTE(Result) ? TRUE : FALSE;
/* Write back the result */
State->GeneralRegs[SOFT386_REG_EAX].LowWord = Result;
@@ -1084,7 +1084,8 @@
SHORT Result = (SHORT)Value *
(SHORT)State->GeneralRegs[SOFT386_REG_EAX].LowByte;
/* Update the flags */
- State->Flags.Cf = State->Flags.Of = ((Result > 255) || (Result <
256)) ? TRUE : FALSE;
+ State->Flags.Cf = State->Flags.Of =
+ ((Result < -128) || (Result > 127)) ? TRUE : FALSE;
/* Write back the result */
State->GeneralRegs[SOFT386_REG_EAX].LowWord = (USHORT)Result;
@@ -1124,8 +1125,259 @@
SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupF7)
{
- UNIMPLEMENTED;
- return FALSE; // TODO: NOT IMPLEMENTED
+ ULONG Dummy, Value, SignFlag;
+ SOFT386_MOD_REG_RM ModRegRm;
+ BOOLEAN OperandSize, AddressSize;
+
+ OperandSize = AddressSize = State->SegmentRegs[SOFT386_REG_CS].Size;
+
+ if (State->PrefixFlags & SOFT386_PREFIX_OPSIZE)
+ {
+ /* The OPSIZE prefix toggles the size */
+ OperandSize = !OperandSize;
+ }
+
+ if (State->PrefixFlags & SOFT386_PREFIX_ADSIZE)
+ {
+ /* The ADSIZE prefix toggles the size */
+ AddressSize = !AddressSize;
+ }
+
+ if (!Soft386ParseModRegRm(State, AddressSize, &ModRegRm))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+
+ /* Set the sign flag */
+ if (OperandSize) SignFlag = SIGN_FLAG_LONG;
+ else SignFlag = SIGN_FLAG_WORD;
+
+ /* Read the operand */
+ if (OperandSize)
+ {
+ /* 32-bit */
+ if (!Soft386ReadModrmDwordOperands(State, &ModRegRm, &Dummy,
&Value))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* 16-bit */
+ if (!Soft386ReadModrmWordOperands(State, &ModRegRm, (PUSHORT)&Dummy,
(PUSHORT)&Value))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
+
+ switch (ModRegRm.Register)
+ {
+ /* TEST */
+ case 0:
+ case 1:
+ {
+ ULONG Immediate = 0, Result = 0;
+
+ if (OperandSize)
+ {
+ /* Fetch the immediate dword */
+ if (!Soft386FetchDword(State, &Immediate))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* Fetch the immediate word */
+ if (!Soft386FetchWord(State, (PUSHORT)&Immediate))
+ {
+ /* Exception occurred */
+ return FALSE;
+ }
+ }
+
+ /* Calculate the result */
+ Result = Value & Immediate;
+
+ /* Update the flags */
+ State->Flags.Cf = FALSE;
+ State->Flags.Of = FALSE;
+ State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
+ State->Flags.Sf = (Result & SignFlag) ? TRUE : FALSE;
+ State->Flags.Pf = Soft386CalculateParity(Result);
+
+ break;
+ }
+
+ /* NOT */
+ case 2:
+ {
+ /* Write back the result */
+ if (OperandSize)
+ {
+ /* 32-bit */
+ return Soft386WriteModrmDwordOperands(State, &ModRegRm, FALSE,
~Value);
+ }
+ else
+ {
+ /* 16-bit */
+ return Soft386WriteModrmWordOperands(State, &ModRegRm, FALSE,
LOWORD(~Value));
+ }
+ }
+
+ /* NEG */
+ case 3:
+ {
+ /* Calculate the result */
+ ULONG Result = -Value;
+ if (!OperandSize) Result &= 0xFFFF;
+
+ /* Update the flags */
+ State->Flags.Cf = (Value != 0) ? TRUE : FALSE;
+ State->Flags.Of = (Value & SignFlag) && (Result &
SignFlag);
+ State->Flags.Af = ((Value & 0x0F) != 0) ? TRUE : FALSE;
+ State->Flags.Zf = (Result == 0) ? TRUE : FALSE;
+ State->Flags.Sf = (Result & SignFlag) ? TRUE : FALSE;
+ State->Flags.Pf = Soft386CalculateParity(Result);
+
+ /* Write back the result */
+ if (OperandSize)
+ {
+ /* 32-bit */
+ return Soft386WriteModrmDwordOperands(State, &ModRegRm, FALSE,
Result);
+ }
+ else
+ {
+ /* 16-bit */
+ return Soft386WriteModrmWordOperands(State, &ModRegRm, FALSE,
LOWORD(Result));
+ }
+ }
+
+ /* MUL */
+ case 4:
+ {
+ if (OperandSize)
+ {
+ ULONGLONG Result = (ULONGLONG)Value *
(ULONGLONG)State->GeneralRegs[SOFT386_REG_EAX].Long;
+
+ /* Update the flags */
+ State->Flags.Cf = State->Flags.Of =
+ (Result & 0xFFFFFFFF00000000ULL) ? TRUE : FALSE;
+
+ /* Write back the result */
+ State->GeneralRegs[SOFT386_REG_EAX].Long = Result &
0xFFFFFFFFULL;
+ State->GeneralRegs[SOFT386_REG_EDX].Long = Result >> 32;
+ }
+ else
+ {
+ ULONG Result = (ULONG)Value *
(ULONG)State->GeneralRegs[SOFT386_REG_EAX].LowWord;
+
+ /* Update the flags */
+ State->Flags.Cf = State->Flags.Of = HIWORD(Result) ? TRUE : FALSE;
+
+ /* Write back the result */
+ State->GeneralRegs[SOFT386_REG_EAX].LowWord = LOWORD(Result);
+ State->GeneralRegs[SOFT386_REG_EDX].LowWord = HIWORD(Result);
+ }
+
+ break;
+ }
+
+ /* IMUL */
+ case 5:
+ {
+ if (OperandSize)
+ {
+ LONGLONG Result = (LONGLONG)Value *
(LONGLONG)State->GeneralRegs[SOFT386_REG_EAX].Long;
+
+ /* Update the flags */
+ State->Flags.Cf = State->Flags.Of =
+ ((Result < -2147483648LL) || (Result > 2147483647LL)) ? TRUE :
FALSE;
+
+ /* Write back the result */
+ State->GeneralRegs[SOFT386_REG_EAX].Long = Result &
0xFFFFFFFFULL;
+ State->GeneralRegs[SOFT386_REG_EDX].Long = Result >> 32;
+ }
+ else
+ {
+ LONG Result = (LONG)Value *
(LONG)State->GeneralRegs[SOFT386_REG_EAX].LowWord;
+
+ /* Update the flags */
+ State->Flags.Cf = State->Flags.Of =
+ ((Result < -32768) || (Result > 32767)) ? TRUE : FALSE;
+
+ /* Write back the result */
+ State->GeneralRegs[SOFT386_REG_EAX].LowWord = LOWORD(Result);
+ State->GeneralRegs[SOFT386_REG_EDX].LowWord = HIWORD(Result);
+ }
+
+ break;
+ }
+
+ /* DIV */
+ case 6:
+ {
+ if (OperandSize)
+ {
+ ULONGLONG Dividend =
(ULONGLONG)State->GeneralRegs[SOFT386_REG_EAX].Long
+ |
((ULONGLONG)State->GeneralRegs[SOFT386_REG_EDX].Long << 32);
+ ULONG Quotient = Dividend / Value;
+ ULONG Remainder = Dividend % Value;
+
+ /* Write back the results */
+ State->GeneralRegs[SOFT386_REG_EAX].Long = Quotient;
+ State->GeneralRegs[SOFT386_REG_EDX].Long = Remainder;
+ }
+ else
+ {
+ ULONG Dividend = (ULONG)State->GeneralRegs[SOFT386_REG_EAX].LowWord
+ | ((ULONG)State->GeneralRegs[SOFT386_REG_EDX].LowWord
<< 16);
+ USHORT Quotient = Dividend / Value;
+ USHORT Remainder = Dividend % Value;
+
+ /* Write back the results */
+ State->GeneralRegs[SOFT386_REG_EAX].LowWord = Quotient;
+ State->GeneralRegs[SOFT386_REG_EDX].LowWord = Remainder;
+ }
+
+ break;
+ }
+
+ /* IDIV */
+ case 7:
+ {
+ if (OperandSize)
+ {
+ LONGLONG Dividend =
(LONGLONG)State->GeneralRegs[SOFT386_REG_EAX].Long
+ |
((LONGLONG)State->GeneralRegs[SOFT386_REG_EDX].Long << 32);
+ LONG Quotient = Dividend / (LONG)Value;
+ LONG Remainder = Dividend % (LONG)Value;
+
+ /* Write back the results */
+ State->GeneralRegs[SOFT386_REG_EAX].Long = (ULONG)Quotient;
+ State->GeneralRegs[SOFT386_REG_EDX].Long = (ULONG)Remainder;
+ }
+ else
+ {
+ LONG Dividend = (LONG)State->GeneralRegs[SOFT386_REG_EAX].LowWord
+ | ((LONG)State->GeneralRegs[SOFT386_REG_EDX].LowWord
<< 16);
+ SHORT Quotient = Dividend / (SHORT)Value;
+ SHORT Remainder = Dividend % (SHORT)Value;
+
+ /* Write back the results */
+ State->GeneralRegs[SOFT386_REG_EAX].LowWord = (USHORT)Quotient;
+ State->GeneralRegs[SOFT386_REG_EDX].LowWord = (USHORT)Remainder;
+ }
+
+ break;
+ }
+ }
+
+ return TRUE;
}
SOFT386_OPCODE_HANDLER(Soft386OpcodeGroupFE)