diff mbox

x86emul: fold almost identical code

Message ID 56C1CC0602000078000D20EE@prv-mh.provo.novell.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jan Beulich Feb. 15, 2016, noon UTC
AAM/AAD as well as DAA/DAS emulation code is respectively almost
identical. Fold each pair, following what's already the case for
AAA/AAS.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
x86emul: fold almost identical code

AAM/AAD as well as DAA/DAS emulation code is respectively almost
identical. Fold each pair, following what's already the case for
AAA/AAS.

Signed-off-by: Jan Beulich <jbeulich@suse.com>

--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -2053,46 +2053,25 @@ x86_emulate(
         src.val = x86_seg_ds;
         goto pop_seg;
 
-    case 0x27: /* daa */ {
-        uint8_t al = _regs.eax;
-        unsigned long eflags = _regs.eflags;
-        generate_exception_if(mode_64bit(), EXC_UD, -1);
-        _regs.eflags &= ~(EFLG_CF|EFLG_AF);
-        if ( ((al & 0x0f) > 9) || (eflags & EFLG_AF) )
-        {
-            *(uint8_t *)&_regs.eax += 6;
-            _regs.eflags |= EFLG_AF;
-        }
-        if ( (al > 0x99) || (eflags & EFLG_CF) )
-        {
-            *(uint8_t *)&_regs.eax += 0x60;
-            _regs.eflags |= EFLG_CF;
-        }
-        _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
-        _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
-        _regs.eflags |= (( int8_t)_regs.eax <  0) ? EFLG_SF : 0;
-        _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0;
-        break;
-    }
-
+    case 0x27: /* daa */
     case 0x2f: /* das */ {
         uint8_t al = _regs.eax;
         unsigned long eflags = _regs.eflags;
+
         generate_exception_if(mode_64bit(), EXC_UD, -1);
-        _regs.eflags &= ~(EFLG_CF|EFLG_AF);
+        _regs.eflags &= ~(EFLG_CF|EFLG_AF|EFLG_SF|EFLG_ZF|EFLG_PF);
         if ( ((al & 0x0f) > 9) || (eflags & EFLG_AF) )
         {
             _regs.eflags |= EFLG_AF;
-            if ( (al < 6) || (eflags & EFLG_CF) )
+            if ( b == 0x2f && (al < 6 || (eflags & EFLG_CF)) )
                 _regs.eflags |= EFLG_CF;
-            *(uint8_t *)&_regs.eax -= 6;
+            *(uint8_t *)&_regs.eax += (b == 0x27) ? 6 : -6;
         }
         if ( (al > 0x99) || (eflags & EFLG_CF) )
         {
-            *(uint8_t *)&_regs.eax -= 0x60;
+            *(uint8_t *)&_regs.eax += (b == 0x27) ? 0x60 : -0x60;
             _regs.eflags |= EFLG_CF;
         }
-        _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
         _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
         _regs.eflags |= (( int8_t)_regs.eax <  0) ? EFLG_SF : 0;
         _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0;
@@ -2833,24 +2812,24 @@ x86_emulate(
         src.val = _regs.ecx;
         goto grp2;
 
-    case 0xd4: /* aam */ {
-        unsigned int base = insn_fetch_type(uint8_t);
-        uint8_t al = _regs.eax;
-        generate_exception_if(mode_64bit(), EXC_UD, -1);
-        generate_exception_if(base == 0, EXC_DE, -1);
-        *(uint16_t *)&_regs.eax = ((al / base) << 8) | (al % base);
-        _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
-        _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
-        _regs.eflags |= (( int8_t)_regs.eax <  0) ? EFLG_SF : 0;
-        _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0;
-        break;
-    }
-
+    case 0xd4: /* aam */
     case 0xd5: /* aad */ {
         unsigned int base = insn_fetch_type(uint8_t);
-        uint16_t ax = _regs.eax;
+
         generate_exception_if(mode_64bit(), EXC_UD, -1);
-        *(uint16_t *)&_regs.eax = (uint8_t)(ax + ((ax >> 8) * base));
+        if ( b & 0x01 )
+        {
+            uint16_t ax = _regs.eax;
+
+            *(uint16_t *)&_regs.eax = (uint8_t)(ax + ((ax >> 8) * base));
+        }
+        else
+        {
+            uint8_t al = _regs.eax;
+
+            generate_exception_if(!base, EXC_DE, -1);
+            *(uint16_t *)&_regs.eax = ((al / base) << 8) | (al % base);
+        }
         _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
         _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
         _regs.eflags |= (( int8_t)_regs.eax <  0) ? EFLG_SF : 0;

Comments

Andrew Cooper Feb. 15, 2016, 1:31 p.m. UTC | #1
On 15/02/16 12:00, Jan Beulich wrote:
> AAM/AAD as well as DAA/DAS emulation code is respectively almost
> identical. Fold each pair, following what's already the case for
> AAA/AAS.
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>

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

Patch

--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -2053,46 +2053,25 @@  x86_emulate(
         src.val = x86_seg_ds;
         goto pop_seg;
 
-    case 0x27: /* daa */ {
-        uint8_t al = _regs.eax;
-        unsigned long eflags = _regs.eflags;
-        generate_exception_if(mode_64bit(), EXC_UD, -1);
-        _regs.eflags &= ~(EFLG_CF|EFLG_AF);
-        if ( ((al & 0x0f) > 9) || (eflags & EFLG_AF) )
-        {
-            *(uint8_t *)&_regs.eax += 6;
-            _regs.eflags |= EFLG_AF;
-        }
-        if ( (al > 0x99) || (eflags & EFLG_CF) )
-        {
-            *(uint8_t *)&_regs.eax += 0x60;
-            _regs.eflags |= EFLG_CF;
-        }
-        _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
-        _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
-        _regs.eflags |= (( int8_t)_regs.eax <  0) ? EFLG_SF : 0;
-        _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0;
-        break;
-    }
-
+    case 0x27: /* daa */
     case 0x2f: /* das */ {
         uint8_t al = _regs.eax;
         unsigned long eflags = _regs.eflags;
+
         generate_exception_if(mode_64bit(), EXC_UD, -1);
-        _regs.eflags &= ~(EFLG_CF|EFLG_AF);
+        _regs.eflags &= ~(EFLG_CF|EFLG_AF|EFLG_SF|EFLG_ZF|EFLG_PF);
         if ( ((al & 0x0f) > 9) || (eflags & EFLG_AF) )
         {
             _regs.eflags |= EFLG_AF;
-            if ( (al < 6) || (eflags & EFLG_CF) )
+            if ( b == 0x2f && (al < 6 || (eflags & EFLG_CF)) )
                 _regs.eflags |= EFLG_CF;
-            *(uint8_t *)&_regs.eax -= 6;
+            *(uint8_t *)&_regs.eax += (b == 0x27) ? 6 : -6;
         }
         if ( (al > 0x99) || (eflags & EFLG_CF) )
         {
-            *(uint8_t *)&_regs.eax -= 0x60;
+            *(uint8_t *)&_regs.eax += (b == 0x27) ? 0x60 : -0x60;
             _regs.eflags |= EFLG_CF;
         }
-        _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
         _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
         _regs.eflags |= (( int8_t)_regs.eax <  0) ? EFLG_SF : 0;
         _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0;
@@ -2833,24 +2812,24 @@  x86_emulate(
         src.val = _regs.ecx;
         goto grp2;
 
-    case 0xd4: /* aam */ {
-        unsigned int base = insn_fetch_type(uint8_t);
-        uint8_t al = _regs.eax;
-        generate_exception_if(mode_64bit(), EXC_UD, -1);
-        generate_exception_if(base == 0, EXC_DE, -1);
-        *(uint16_t *)&_regs.eax = ((al / base) << 8) | (al % base);
-        _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
-        _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
-        _regs.eflags |= (( int8_t)_regs.eax <  0) ? EFLG_SF : 0;
-        _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0;
-        break;
-    }
-
+    case 0xd4: /* aam */
     case 0xd5: /* aad */ {
         unsigned int base = insn_fetch_type(uint8_t);
-        uint16_t ax = _regs.eax;
+
         generate_exception_if(mode_64bit(), EXC_UD, -1);
-        *(uint16_t *)&_regs.eax = (uint8_t)(ax + ((ax >> 8) * base));
+        if ( b & 0x01 )
+        {
+            uint16_t ax = _regs.eax;
+
+            *(uint16_t *)&_regs.eax = (uint8_t)(ax + ((ax >> 8) * base));
+        }
+        else
+        {
+            uint8_t al = _regs.eax;
+
+            generate_exception_if(!base, EXC_DE, -1);
+            *(uint16_t *)&_regs.eax = ((al / base) << 8) | (al % base);
+        }
         _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
         _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
         _regs.eflags |= (( int8_t)_regs.eax <  0) ? EFLG_SF : 0;