[SOFT386]
authorAleksandar Andrejevic <aandrejevic@reactos.org>
Sun, 13 Oct 2013 23:59:52 +0000 (23:59 +0000)
committerAleksandar Andrejevic <aandrejevic@reactos.org>
Sun, 13 Oct 2013 23:59:52 +0000 (23:59 +0000)
Halfplement REPZ/REPNZ for CMPS and SCAS.

svn path=/branches/ntvdm/; revision=60658

lib/soft386/opcodes.c

index e93a429..dad7182 100644 (file)
@@ -6200,6 +6200,43 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeCmps)
         }
     }
 
+    // FIXME: This method is slow!
+    if ((State->PrefixFlags & SOFT386_PREFIX_REP)
+        || (State->PrefixFlags & SOFT386_PREFIX_REPNZ))
+    {
+        BOOLEAN Repeat = TRUE;
+        
+        if (OperandSize)
+        {
+            if ((--State->GeneralRegs[SOFT386_REG_ECX].Long) == 0)
+            {
+                /* ECX is 0 */
+                Repeat = FALSE;
+            }
+        }
+        else
+        {
+            if ((--State->GeneralRegs[SOFT386_REG_ECX].LowWord) == 0)
+            {
+                /* CX is 0 */
+                Repeat = FALSE;
+            }
+        }
+
+        if (((State->PrefixFlags & SOFT386_PREFIX_REP) && !State->Flags.Zf)
+            || ((State->PrefixFlags & SOFT386_PREFIX_REPNZ) && State->Flags.Zf))
+        {
+            /* REPZ with ZF = 0 or REPNZ with ZF = 1 */
+            Repeat = FALSE;
+        }
+
+        if (Repeat)
+        {
+            /* Repeat the instruction */
+            State->InstPtr = State->SavedInstPtr;
+        }
+    }
+
     /* Return success */
     return TRUE;
 }
@@ -6444,16 +6481,8 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeScas)
         AddressSize = !AddressSize;
     }
 
-    if ((State->PrefixFlags & SOFT386_PREFIX_REP)
-        || (State->PrefixFlags & SOFT386_PREFIX_REPNZ))
-    {
-        // TODO: The REP/REPZ/REPNZ prefixes need to be implemented!
-        Soft386Exception(State, SOFT386_EXCEPTION_UD);
-        return FALSE;
-    }
-
     /* Calculate the size */
-    if (Opcode == 0xA6) DataSize = sizeof(UCHAR);
+    if (Opcode == 0xAE) DataSize = sizeof(UCHAR);
     else DataSize = OperandSize ? sizeof(ULONG) : sizeof(USHORT);
 
     /* Calculate the mask and sign flag */
@@ -6499,6 +6528,43 @@ SOFT386_OPCODE_HANDLER(Soft386OpcodeScas)
         else State->GeneralRegs[SOFT386_REG_EDI].LowWord -= DataSize;
     }
 
+    // FIXME: This method is slow!
+    if ((State->PrefixFlags & SOFT386_PREFIX_REP)
+        || (State->PrefixFlags & SOFT386_PREFIX_REPNZ))
+    {
+        BOOLEAN Repeat = TRUE;
+        
+        if (OperandSize)
+        {
+            if ((--State->GeneralRegs[SOFT386_REG_ECX].Long) == 0)
+            {
+                /* ECX is 0 */
+                Repeat = FALSE;
+            }
+        }
+        else
+        {
+            if ((--State->GeneralRegs[SOFT386_REG_ECX].LowWord) == 0)
+            {
+                /* CX is 0 */
+                Repeat = FALSE;
+            }
+        }
+
+        if (((State->PrefixFlags & SOFT386_PREFIX_REP) && !State->Flags.Zf)
+            || ((State->PrefixFlags & SOFT386_PREFIX_REPNZ) && State->Flags.Zf))
+        {
+            /* REPZ with ZF = 0 or REPNZ with ZF = 1 */
+            Repeat = FALSE;
+        }
+
+        if (Repeat)
+        {
+            /* Repeat the instruction */
+            State->InstPtr = State->SavedInstPtr;
+        }
+    }
+
     /* Return success */
     return TRUE;
 }