xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] x86emul: correct CF output of SHLD/SHRD
@ 2017-06-23 14:38 Jan Beulich
  2017-06-23 15:14 ` Andrew Cooper
  0 siblings, 1 reply; 2+ messages in thread
From: Jan Beulich @ 2017-06-23 14:38 UTC (permalink / raw)
  To: xen-devel; +Cc: Andrew Cooper

[-- Attachment #1: Type: text/plain, Size: 2070 bytes --]

CF reflects the last bit shifted out, i.e. can't possibly be derived
from the result value.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v2: Fix 64-bit testcase build.

--- a/tools/tests/x86_emulator/test_x86_emulator.c
+++ b/tools/tests/x86_emulator/test_x86_emulator.c
@@ -783,6 +783,31 @@ int main(int argc, char **argv)
     printf("okay\n");
 #endif
 
+    printf("%-40s", "Testing shld $1,%ecx,(%edx)...");
+    res[0]      = 0x12345678;
+    regs.edx    = (unsigned long)res;
+    regs.ecx    = 0x9abcdef0;
+    instr[0] = 0x0f; instr[1] = 0xa4; instr[2] = 0x0a; instr[3] = 0x01;
+    for ( i = 0; i < 0x20; ++i )
+    {
+        uint32_t r = res[0];
+        const uint32_t m = X86_EFLAGS_ARITH_MASK & ~X86_EFLAGS_AF;
+        unsigned long f;
+
+        asm ( "shld $1,%2,%0; pushf; pop %1"
+              : "+rm" (r), "=rm" (f) : "r" ((uint32_t)regs.ecx) );
+        regs.eflags = f ^ m;
+        regs.eip    = (unsigned long)&instr[0];
+        rc = x86_emulate(&ctxt, &emulops);
+        if ( (rc != X86EMUL_OKAY) ||
+             (regs.eip != (unsigned long)&instr[4]) ||
+             (res[0] != r) ||
+             ((regs.eflags ^ f) & m) )
+            goto fail;
+        regs.ecx <<= 1;
+    }
+    printf("okay\n");
+
     printf("%-40s", "Testing movbe (%ecx),%eax...");
     instr[0] = 0x0f; instr[1] = 0x38; instr[2] = 0xf0; instr[3] = 0x01;
     regs.eflags = 0x200;
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -6424,7 +6424,7 @@ x86_emulate(
                    (src.val >> (width - shift)));
         _regs.eflags &= ~(X86_EFLAGS_OF | X86_EFLAGS_SF | X86_EFLAGS_ZF |
                           X86_EFLAGS_PF | X86_EFLAGS_CF);
-        if ( (dst.val >> ((b & 8) ? (shift - 1) : (width - shift))) & 1 )
+        if ( (dst.orig_val >> ((b & 8) ? (shift - 1) : (width - shift))) & 1 )
             _regs.eflags |= X86_EFLAGS_CF;
         if ( ((dst.val ^ dst.orig_val) >> (width - 1)) & 1 )
             _regs.eflags |= X86_EFLAGS_OF;




[-- Attachment #2: x86emul-shld-CF.patch --]
[-- Type: text/plain, Size: 2107 bytes --]

x86emul: correct CF output of SHLD/SHRD

CF reflects the last bit shifted out, i.e. can't possibly be derived
from the result value.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v2: Fix 64-bit testcase build.

--- a/tools/tests/x86_emulator/test_x86_emulator.c
+++ b/tools/tests/x86_emulator/test_x86_emulator.c
@@ -783,6 +783,31 @@ int main(int argc, char **argv)
     printf("okay\n");
 #endif
 
+    printf("%-40s", "Testing shld $1,%ecx,(%edx)...");
+    res[0]      = 0x12345678;
+    regs.edx    = (unsigned long)res;
+    regs.ecx    = 0x9abcdef0;
+    instr[0] = 0x0f; instr[1] = 0xa4; instr[2] = 0x0a; instr[3] = 0x01;
+    for ( i = 0; i < 0x20; ++i )
+    {
+        uint32_t r = res[0];
+        const uint32_t m = X86_EFLAGS_ARITH_MASK & ~X86_EFLAGS_AF;
+        unsigned long f;
+
+        asm ( "shld $1,%2,%0; pushf; pop %1"
+              : "+rm" (r), "=rm" (f) : "r" ((uint32_t)regs.ecx) );
+        regs.eflags = f ^ m;
+        regs.eip    = (unsigned long)&instr[0];
+        rc = x86_emulate(&ctxt, &emulops);
+        if ( (rc != X86EMUL_OKAY) ||
+             (regs.eip != (unsigned long)&instr[4]) ||
+             (res[0] != r) ||
+             ((regs.eflags ^ f) & m) )
+            goto fail;
+        regs.ecx <<= 1;
+    }
+    printf("okay\n");
+
     printf("%-40s", "Testing movbe (%ecx),%eax...");
     instr[0] = 0x0f; instr[1] = 0x38; instr[2] = 0xf0; instr[3] = 0x01;
     regs.eflags = 0x200;
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -6424,7 +6424,7 @@ x86_emulate(
                    (src.val >> (width - shift)));
         _regs.eflags &= ~(X86_EFLAGS_OF | X86_EFLAGS_SF | X86_EFLAGS_ZF |
                           X86_EFLAGS_PF | X86_EFLAGS_CF);
-        if ( (dst.val >> ((b & 8) ? (shift - 1) : (width - shift))) & 1 )
+        if ( (dst.orig_val >> ((b & 8) ? (shift - 1) : (width - shift))) & 1 )
             _regs.eflags |= X86_EFLAGS_CF;
         if ( ((dst.val ^ dst.orig_val) >> (width - 1)) & 1 )
             _regs.eflags |= X86_EFLAGS_OF;

[-- Attachment #3: Type: text/plain, Size: 127 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] x86emul: correct CF output of SHLD/SHRD
  2017-06-23 14:38 [PATCH v2] x86emul: correct CF output of SHLD/SHRD Jan Beulich
@ 2017-06-23 15:14 ` Andrew Cooper
  0 siblings, 0 replies; 2+ messages in thread
From: Andrew Cooper @ 2017-06-23 15:14 UTC (permalink / raw)
  To: Jan Beulich, xen-devel

On 23/06/17 15:38, Jan Beulich wrote:
> CF reflects the last bit shifted out, i.e. can't possibly be derived
> from the result value.
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>

Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2017-06-23 15:14 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-06-23 14:38 [PATCH v2] x86emul: correct CF output of SHLD/SHRD Jan Beulich
2017-06-23 15:14 ` Andrew Cooper

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).