[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v2 1/2] x86emul: consolidate loop counter handling



Rename _get_rep_prefix() to make it more visibly fit other use cases
and introduce a companion "put". Use them for repeated string insn
handling as well as LOOP/J?CXZ instead of open coding the same logic a
couple of times.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---
v2: s/int_regs/regs/ in {get,put}_loop_count(). Defer subtraction of 1
    in LOOP handling.

--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -913,19 +913,30 @@ do {
     put_stub(stub);                                                     \
 } while (0)
 
-static unsigned long _get_rep_prefix(
-    const struct cpu_user_regs *int_regs,
+static inline unsigned long get_loop_count(
+    const struct cpu_user_regs *regs,
     int ad_bytes)
 {
-    return (ad_bytes == 2) ? (uint16_t)int_regs->ecx :
-           (ad_bytes == 4) ? (uint32_t)int_regs->ecx :
-           int_regs->ecx;
+    return (ad_bytes == 2) ? (uint16_t)regs->ecx :
+           (ad_bytes == 4) ? (uint32_t)regs->ecx :
+           regs->ecx;
+}
+
+static inline void put_loop_count(
+    struct cpu_user_regs *regs,
+    int ad_bytes,
+    unsigned long count)
+{
+    if ( ad_bytes == 2 )
+        *(uint16_t *)&regs->ecx = count;
+    else
+        regs->ecx = ad_bytes == 4 ? (uint32_t)count : count;
 }
 
 #define get_rep_prefix() ({                                             \
     unsigned long max_reps = 1;                                         \
     if ( rep_prefix() )                                                 \
-        max_reps = _get_rep_prefix(&_regs, ad_bytes);                   \
+        max_reps = get_loop_count(&_regs, ad_bytes);                    \
     if ( max_reps == 0 )                                                \
     {                                                                   \
         /* Skip the instruction if no repetitions are required. */      \
@@ -941,21 +952,14 @@ static void __put_rep_prefix(
     int ad_bytes,
     unsigned long reps_completed)
 {
-    unsigned long ecx = ((ad_bytes == 2) ? (uint16_t)int_regs->ecx :
-                         (ad_bytes == 4) ? (uint32_t)int_regs->ecx :
-                         int_regs->ecx);
+    unsigned long ecx = get_loop_count(int_regs, ad_bytes);
 
     /* Reduce counter appropriately, and repeat instruction if non-zero. */
     ecx -= reps_completed;
     if ( ecx != 0 )
         int_regs->eip = ext_regs->eip;
 
-    if ( ad_bytes == 2 )
-        *(uint16_t *)&int_regs->ecx = ecx;
-    else if ( ad_bytes == 4 )
-        int_regs->ecx = (uint32_t)ecx;
-    else
-        int_regs->ecx = ecx;
+    put_loop_count(int_regs, ad_bytes, ecx);
 }
 
 #define put_rep_prefix(reps_completed) ({                               \
@@ -4007,33 +4011,21 @@ x86_emulate(
         break;
 
     case 0xe0 ... 0xe2: /* loop{,z,nz} */ {
+        unsigned long count = get_loop_count(&_regs, ad_bytes);
         int do_jmp = !(_regs.eflags & EFLG_ZF); /* loopnz */
 
         if ( b == 0xe1 )
             do_jmp = !do_jmp; /* loopz */
         else if ( b == 0xe2 )
             do_jmp = 1; /* loop */
-        switch ( ad_bytes )
-        {
-        case 2:
-            do_jmp &= --(*(uint16_t *)&_regs.ecx) != 0;
-            break;
-        case 4:
-            do_jmp &= --(*(uint32_t *)&_regs.ecx) != 0;
-            _regs.ecx = (uint32_t)_regs.ecx; /* zero extend in x86/64 mode */
-            break;
-        default: /* case 8: */
-            do_jmp &= --_regs.ecx != 0;
-            break;
-        }
-        if ( do_jmp )
+        if ( count != 1 && do_jmp )
             jmp_rel((int32_t)src.val);
+        put_loop_count(&_regs, ad_bytes, count - 1);
         break;
     }
 
     case 0xe3: /* jcxz/jecxz (short) */
-        if ( (ad_bytes == 2) ? !(uint16_t)_regs.ecx :
-             (ad_bytes == 4) ? !(uint32_t)_regs.ecx : !_regs.ecx )
+        if ( !get_loop_count(&_regs, ad_bytes) )
             jmp_rel((int32_t)src.val);
         break;
 



Attachment: x86emul-loop-count.patch
Description: Text document

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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.