[FAST486]
[reactos.git] / reactos / lib / fast486 / opgroups.c
index 2c99e47..60e778d 100644 (file)
@@ -70,6 +70,7 @@ Fast486ArithmeticOperation(PFAST486_STATE State,
         case 1:
         {
             Result = FirstValue | SecondValue;
+            State->Flags.Cf = State->Flags.Of = FALSE;
             break;
         }
 
@@ -112,6 +113,7 @@ Fast486ArithmeticOperation(PFAST486_STATE State,
         case 4:
         {
             Result = FirstValue & SecondValue;
+            State->Flags.Cf = State->Flags.Of = FALSE;
             break;
         }
 
@@ -134,6 +136,7 @@ Fast486ArithmeticOperation(PFAST486_STATE State,
         case 6:
         {
             Result = FirstValue ^ SecondValue;
+            State->Flags.Cf = State->Flags.Of = FALSE;
             break;
         }
 
@@ -209,7 +212,7 @@ Fast486RotateOperation(PFAST486_STATE State,
         case 2:
         {
             Result = (Value << Count) | (State->Flags.Cf << (Count - 1));
-            
+
             /* Complete the calculation, but make sure we don't shift by too much */
             if ((Bits - Count) < 31) Result |= Value >> (Bits - Count + 1);
 
@@ -980,7 +983,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
         /* DIV */
         case 6:
         {
-            UCHAR Quotient, Remainder;
+            USHORT Quotient;
+            UCHAR Remainder;
 
             if (Value == 0)
             {
@@ -992,8 +996,15 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
             Quotient = State->GeneralRegs[FAST486_REG_EAX].LowWord / Value;
             Remainder = State->GeneralRegs[FAST486_REG_EAX].LowWord % Value;
 
+            if (Quotient > 0xFF)
+            {
+                /* Divide error */
+                Fast486Exception(State, FAST486_EXCEPTION_DE);
+                return;
+            }
+
             /* Write back the results */
-            State->GeneralRegs[FAST486_REG_EAX].LowByte = Quotient;
+            State->GeneralRegs[FAST486_REG_EAX].LowByte = (UCHAR)Quotient;
             State->GeneralRegs[FAST486_REG_EAX].HighByte = Remainder;
 
             break;
@@ -1002,7 +1013,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
         /* IDIV */
         case 7:
         {
-            CHAR Quotient, Remainder;
+            SHORT Quotient;
+            CHAR Remainder;
 
             if (Value == 0)
             {
@@ -1014,8 +1026,15 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF6)
             Quotient = (SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord / (CHAR)Value;
             Remainder = (SHORT)State->GeneralRegs[FAST486_REG_EAX].LowWord % (CHAR)Value;
 
+            if (Quotient > 127 || Quotient < -128)
+            {
+                /* Divide error */
+                Fast486Exception(State, FAST486_EXCEPTION_DE);
+                return;
+            }
+
             /* Write back the results */
-            State->GeneralRegs[FAST486_REG_EAX].LowByte = (UCHAR)Quotient;
+            State->GeneralRegs[FAST486_REG_EAX].LowByte = (UCHAR)((CHAR)Quotient);
             State->GeneralRegs[FAST486_REG_EAX].HighByte = (UCHAR)Remainder;
 
             break;
@@ -1126,7 +1145,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
         case 3:
         {
             /* Calculate the result */
-            ULONG Result = -Value;
+            ULONG Result = -(LONG)Value;
             if (!OperandSize) Result &= 0xFFFF;
 
             /* Update the flags */
@@ -1224,22 +1243,36 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
             {
                 ULONGLONG Dividend = (ULONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long
                                      | ((ULONGLONG)State->GeneralRegs[FAST486_REG_EDX].Long << 32);
-                ULONG Quotient = Dividend / Value;
+                ULONGLONG Quotient = Dividend / Value;
                 ULONG Remainder = Dividend % Value;
 
+                if (Quotient > 0xFFFFFFFFULL)
+                {
+                    /* Divide error */
+                    Fast486Exception(State, FAST486_EXCEPTION_DE);
+                    return;
+                }
+
                 /* Write back the results */
-                State->GeneralRegs[FAST486_REG_EAX].Long = Quotient;
+                State->GeneralRegs[FAST486_REG_EAX].Long = (ULONG)Quotient;
                 State->GeneralRegs[FAST486_REG_EDX].Long = Remainder;
             }
             else
             {
                 ULONG Dividend = (ULONG)State->GeneralRegs[FAST486_REG_EAX].LowWord
                                  | ((ULONG)State->GeneralRegs[FAST486_REG_EDX].LowWord << 16);
-                USHORT Quotient = Dividend / Value;
+                ULONG Quotient = Dividend / Value;
                 USHORT Remainder = Dividend % Value;
 
+                if (Quotient > 0xFFFF)
+                {
+                    /* Divide error */
+                    Fast486Exception(State, FAST486_EXCEPTION_DE);
+                    return;
+                }
+
                 /* Write back the results */
-                State->GeneralRegs[FAST486_REG_EAX].LowWord = Quotient;
+                State->GeneralRegs[FAST486_REG_EAX].LowWord = (USHORT)Quotient;
                 State->GeneralRegs[FAST486_REG_EDX].LowWord = Remainder;
             }
 
@@ -1260,22 +1293,36 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeGroupF7)
             {
                 LONGLONG Dividend = (LONGLONG)State->GeneralRegs[FAST486_REG_EAX].Long
                                      | ((LONGLONG)State->GeneralRegs[FAST486_REG_EDX].Long << 32);
-                LONG Quotient = Dividend / (LONG)Value;
+                LONGLONG Quotient = Dividend / (LONG)Value;
                 LONG Remainder = Dividend % (LONG)Value;
 
+                if (Quotient > 2147483647LL || Quotient < -2147483648LL)
+                {
+                    /* Divide error */
+                    Fast486Exception(State, FAST486_EXCEPTION_DE);
+                    return;
+                }
+
                 /* Write back the results */
-                State->GeneralRegs[FAST486_REG_EAX].Long = (ULONG)Quotient;
+                State->GeneralRegs[FAST486_REG_EAX].Long = (ULONG)((LONG)Quotient);
                 State->GeneralRegs[FAST486_REG_EDX].Long = (ULONG)Remainder;
             }
             else
             {
                 LONG Dividend = (LONG)State->GeneralRegs[FAST486_REG_EAX].LowWord
                                  | ((LONG)State->GeneralRegs[FAST486_REG_EDX].LowWord << 16);
-                SHORT Quotient = Dividend / (SHORT)LOWORD(Value);
+                LONG Quotient = Dividend / (SHORT)LOWORD(Value);
                 SHORT Remainder = Dividend % (SHORT)LOWORD(Value);
 
+                if (Quotient > 32767 || Quotient < -32768)
+                {
+                    /* Divide error */
+                    Fast486Exception(State, FAST486_EXCEPTION_DE);
+                    return;
+                }
+
                 /* Write back the results */
-                State->GeneralRegs[FAST486_REG_EAX].LowWord = (USHORT)Quotient;
+                State->GeneralRegs[FAST486_REG_EAX].LowWord = (USHORT)((SHORT)Quotient);
                 State->GeneralRegs[FAST486_REG_EDX].LowWord = (USHORT)Remainder;
             }
 
@@ -1765,10 +1812,10 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00)
                 return;
             }
 
-            if (Fast486ReadDescriptorEntry(State,
-                                           Selector,
-                                           &Valid,
-                                           (PFAST486_GDT_ENTRY)&GdtEntry))
+            if (!Fast486ReadDescriptorEntry(State,
+                                            Selector,
+                                            &Valid,
+                                            (PFAST486_GDT_ENTRY)&GdtEntry))
             {
                 /* Exception occurred */
                 return;
@@ -1804,7 +1851,12 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00)
             State->Ldtr.Selector = Selector;
             State->Ldtr.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24);
             State->Ldtr.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
-            if (GdtEntry.Granularity) State->Ldtr.Limit <<= 12;
+
+            if (GdtEntry.Granularity)
+            {
+                State->Ldtr.Limit <<= 12;
+                State->Ldtr.Limit |= 0x00000FFF;
+            }
 
             break;
         }
@@ -1847,10 +1899,10 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00)
                 return;
             }
 
-            if (Fast486ReadDescriptorEntry(State,
-                                           Selector,
-                                           &Valid,
-                                           (PFAST486_GDT_ENTRY)&GdtEntry))
+            if (!Fast486ReadDescriptorEntry(State,
+                                            Selector,
+                                            &Valid,
+                                            (PFAST486_GDT_ENTRY)&GdtEntry))
             {
                 /* Exception occurred */
                 return;
@@ -1886,7 +1938,12 @@ FAST486_OPCODE_HANDLER(Fast486ExtOpcodeGroup0F00)
             State->TaskReg.Selector = Selector;
             State->TaskReg.Base = GdtEntry.Base | (GdtEntry.BaseMid << 16) | (GdtEntry.BaseHigh << 24);
             State->TaskReg.Limit = GdtEntry.Limit | (GdtEntry.LimitHigh << 16);
-            if (GdtEntry.Granularity) State->TaskReg.Limit <<= 12;
+
+            if (GdtEntry.Granularity)
+            {
+                State->TaskReg.Limit <<= 12;
+                State->TaskReg.Limit |= 0x00000FFF;
+            }
 
             break;
         }