[FAST486]
[reactos.git] / lib / fast486 / opcodes.c
index 4eb2e6b..a3e1664 100644 (file)
@@ -3595,7 +3595,6 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeImulModrmImm)
     BOOLEAN OperandSize, AddressSize;
     FAST486_MOD_REG_RM ModRegRm;
     LONG Multiplier;
-    LONGLONG Product;
 
     /* Make sure this is the right instruction */
     ASSERT((Opcode & 0xFD) == 0x69);
@@ -3658,6 +3657,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeImulModrmImm)
     if (OperandSize)
     {
         LONG RegValue, Multiplicand;
+        LONGLONG Product;
 
         /* Read the operands */
         if (!Fast486ReadModrmDwordOperands(State,
@@ -3671,10 +3671,20 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeImulModrmImm)
 
         /* Multiply */
         Product = (LONGLONG)Multiplicand * (LONGLONG)Multiplier;
+
+        /* Check for carry/overflow */
+        State->Flags.Cf = State->Flags.Of = ((Product < MINLONG) || (Product > MAXLONG));
+
+        /* Write-back the result */
+        return Fast486WriteModrmDwordOperands(State,
+                                              &ModRegRm,
+                                              TRUE,
+                                              (ULONG)((LONG)Product));
     }
     else
     {
         SHORT RegValue, Multiplicand;
+        LONG Product;
 
         /* Read the operands */
         if (!Fast486ReadModrmWordOperands(State,
@@ -3687,17 +3697,17 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeImulModrmImm)
         }
 
         /* Multiply */
-        Product = (LONGLONG)Multiplicand * (LONGLONG)Multiplier;
-    }
+        Product = (LONG)Multiplicand * (LONG)Multiplier;
 
-    /* Check for carry/overflow */
-    State->Flags.Cf = State->Flags.Of = ((Product < MINLONG) || (Product > MAXLONG));
+        /* Check for carry/overflow */
+        State->Flags.Cf = State->Flags.Of = ((Product < MINSHORT) || (Product > MAXSHORT));
 
-    /* Write-back the result */
-    return Fast486WriteModrmDwordOperands(State,
-                                          &ModRegRm,
-                                          TRUE,
-                                          (ULONG)((LONG)Product));
+        /* Write-back the result */
+        return Fast486WriteModrmWordOperands(State,
+                                             &ModRegRm,
+                                             TRUE,
+                                             (USHORT)((SHORT)Product));
+    }
 }
 
 FAST486_OPCODE_HANDLER(Fast486OpcodePushByteImm)
@@ -4314,6 +4324,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeLdsLes)
 
     OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
+    TOGGLE_OPSIZE(OperandSize);
     TOGGLE_ADSIZE(AddressSize);
 
     /* Get the operands */
@@ -4918,7 +4929,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeLoop)
     ASSERT((Opcode >= 0xE0) && (Opcode <= 0xE2));
 
     NO_LOCK_PREFIX();
-    TOGGLE_OPSIZE(Size);
+    TOGGLE_ADSIZE(Size);
 
     if (Size) Condition = ((--State->GeneralRegs[FAST486_REG_ECX].Long) != 0);
     else Condition = ((--State->GeneralRegs[FAST486_REG_ECX].LowWord) != 0);
@@ -4945,7 +4956,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeLoop)
     if (Condition)
     {
         /* Move the instruction pointer */
-        State->InstPtr.Long += Offset;
+        if (Size) State->InstPtr.Long += Offset;
+        else State->InstPtr.LowWord += Offset;
     }
 
     return TRUE;
@@ -4961,7 +4973,7 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeJecxz)
     ASSERT(Opcode == 0xE3);
 
     NO_LOCK_PREFIX();
-    TOGGLE_OPSIZE(Size);
+    TOGGLE_ADSIZE(Size);
 
     if (Size) Condition = (State->GeneralRegs[FAST486_REG_ECX].Long == 0);
     else Condition = (State->GeneralRegs[FAST486_REG_ECX].LowWord == 0);
@@ -4976,7 +4988,8 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeJecxz)
     if (Condition)
     {
         /* Move the instruction pointer */
-        State->InstPtr.Long += Offset;
+        if (Size) State->InstPtr.Long += Offset;
+        else State->InstPtr.LowWord += Offset;
     }
 
     return TRUE;
@@ -5133,15 +5146,15 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeJmpAbs)
 
 FAST486_OPCODE_HANDLER(Fast486OpcodeMovAlOffset)
 {
-    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+    BOOLEAN AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
     ULONG Offset;
 
     /* Make sure this is the right instruction */
     ASSERT(Opcode == 0xA0);
 
-    TOGGLE_OPSIZE(Size);
+    TOGGLE_ADSIZE(AddressSize);
 
-    if (Size)
+    if (AddressSize)
     {
         if (!Fast486FetchDword(State, &Offset))
         {
@@ -5174,14 +5187,17 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovAlOffset)
 
 FAST486_OPCODE_HANDLER(Fast486OpcodeMovEaxOffset)
 {
-    BOOLEAN Size = State->SegmentRegs[FAST486_REG_CS].Size;
+    BOOLEAN OperandSize, AddressSize;
+
+    OperandSize = AddressSize = State->SegmentRegs[FAST486_REG_CS].Size;
 
     /* Make sure this is the right instruction */
     ASSERT(Opcode == 0xA1);
 
-    TOGGLE_OPSIZE(Size);
+    TOGGLE_OPSIZE(OperandSize);
+    TOGGLE_ADSIZE(AddressSize);
 
-    if (Size)
+    if (AddressSize)
     {
         ULONG Offset;
 
@@ -5192,13 +5208,26 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovEaxOffset)
         }
 
         /* Read from memory */
-        return Fast486ReadMemory(State,
-                                 (State->PrefixFlags & FAST486_PREFIX_SEG) ?
-                                 State->SegmentOverride : FAST486_REG_DS,
-                                 Offset,
-                                 FALSE,
-                                 &State->GeneralRegs[FAST486_REG_EAX].Long,
-                                 sizeof(ULONG));
+        if (OperandSize)
+        {
+            return Fast486ReadMemory(State,
+                                     (State->PrefixFlags & FAST486_PREFIX_SEG) ?
+                                     State->SegmentOverride : FAST486_REG_DS,
+                                     Offset,
+                                     FALSE,
+                                     &State->GeneralRegs[FAST486_REG_EAX].Long,
+                                     sizeof(ULONG));
+        }
+        else
+        {
+            return Fast486ReadMemory(State,
+                                     (State->PrefixFlags & FAST486_PREFIX_SEG) ?
+                                     State->SegmentOverride : FAST486_REG_DS,
+                                     Offset,
+                                     FALSE,
+                                     &State->GeneralRegs[FAST486_REG_EAX].LowWord,
+                                     sizeof(USHORT));
+        }
     }
     else
     {
@@ -5211,13 +5240,26 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeMovEaxOffset)
         }
 
         /* Read from memory */
-        return Fast486ReadMemory(State,
-                                 (State->PrefixFlags & FAST486_PREFIX_SEG) ?
-                                 State->SegmentOverride : FAST486_REG_DS,
-                                 Offset,
-                                 FALSE,
-                                 &State->GeneralRegs[FAST486_REG_EAX].LowWord,
-                                 sizeof(USHORT));
+        if (OperandSize)
+        {
+            return Fast486ReadMemory(State,
+                                     (State->PrefixFlags & FAST486_PREFIX_SEG) ?
+                                     State->SegmentOverride : FAST486_REG_DS,
+                                     Offset,
+                                     FALSE,
+                                     &State->GeneralRegs[FAST486_REG_EAX].Long,
+                                     sizeof(ULONG));
+        }
+        else
+        {
+            return Fast486ReadMemory(State,
+                                     (State->PrefixFlags & FAST486_PREFIX_SEG) ?
+                                     State->SegmentOverride : FAST486_REG_DS,
+                                     Offset,
+                                     FALSE,
+                                     &State->GeneralRegs[FAST486_REG_EAX].LowWord,
+                                     sizeof(USHORT));
+        }
     }
 }
 
@@ -5843,6 +5885,18 @@ FAST486_OPCODE_HANDLER(Fast486OpcodeLods)
             if (AddressSize) State->GeneralRegs[FAST486_REG_ESI].Long -= (Count - 1) * DataSize;
             else State->GeneralRegs[FAST486_REG_ESI].LowWord -= (Count - 1) * DataSize;
         }
+
+        /* Update registers */
+        if (OperandSize)
+        {
+            State->GeneralRegs[FAST486_REG_ECX].Long = 0;
+            State->GeneralRegs[FAST486_REG_ESI].Long += Count - 1;
+        }
+        else
+        {
+            State->GeneralRegs[FAST486_REG_ECX].LowWord = 0;
+            State->GeneralRegs[FAST486_REG_ESI].LowWord += Count - 1;
+        }
     }
 
     /* Read from the source operand */