about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-10 20:44:00 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-10 20:44:00 +0100
commit5a244911cc9e6066962b75fbbf7ba310d79af524 (patch)
tree539c5034d28f3e146e11a4b5adc9df2fb7a9ad63 /src
parent02161dc4d761cf209095b614534db908a140384a (diff)
downloadbox64-5a244911cc9e6066962b75fbbf7ba310d79af524.tar.gz
box64-5a244911cc9e6066962b75fbbf7ba310d79af524.zip
Added and fixed many opcodes
Diffstat (limited to 'src')
-rwxr-xr-xsrc/emu/x64primop.c32
-rwxr-xr-xsrc/emu/x64primop.h2
-rwxr-xr-xsrc/emu/x64run.c38
-rw-r--r--src/emu/x64run0f.c187
-rw-r--r--src/emu/x64run66.c54
-rw-r--r--src/emu/x64run660f.c167
-rwxr-xr-xsrc/emu/x64run_private.c54
7 files changed, 471 insertions, 63 deletions
diff --git a/src/emu/x64primop.c b/src/emu/x64primop.c
index 9b6fffb8..cc9422e7 100755
--- a/src/emu/x64primop.c
+++ b/src/emu/x64primop.c
@@ -310,7 +310,7 @@ uint64_t adc64(x64emu_t *emu, uint64_t d, uint64_t s)
 
 	CONDITIONAL_SET_FLAG(hi & 0x100000000L, F_CF);
 	CONDITIONAL_SET_FLAG(!res, F_ZF);
-	CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF);
+	CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF);
 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 
 	/* calculate the carry chain  SEE NOTE AT TOP. */
@@ -393,13 +393,13 @@ uint64_t cmp64(x64emu_t *emu, uint64_t d, uint64_t s)
 	RESET_FLAGS(emu);
 
 	res = d - s;
-	CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF);
+	CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF);
 	CONDITIONAL_SET_FLAG(!res, F_ZF);
 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 
 	/* calculate the borrow chain.  See note at top */
 	bc = (res & (~d | s)) | (~d & s);
-	CONDITIONAL_SET_FLAG(bc & 0x8000000000000000L, F_CF);
+	CONDITIONAL_SET_FLAG(bc & 0x8000000000000000LL, F_CF);
 	CONDITIONAL_SET_FLAG(XOR2(bc >> 62), F_OF);
 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 	return d;
@@ -573,7 +573,7 @@ uint32_t rcl32(x64emu_t *emu, uint32_t d, uint8_t s)
 	return res;
 }
 
-uint32_t rcl64(x64emu_t *emu, uint64_t d, uint8_t s)
+uint64_t rcl64(x64emu_t *emu, uint64_t d, uint8_t s)
 {
 	uint64_t res, cnt, mask, cf;
 	CHECK_FLAGS(emu);
@@ -583,10 +583,10 @@ uint32_t rcl64(x64emu_t *emu, uint64_t d, uint8_t s)
 	if ((cnt = s % 65) != 0) {
 		cf = (d >> (64 - cnt)) & 0x1;
 		res = (d << cnt);
-		mask = (1 << (cnt - 1)) - 1;
+		mask = (1LL << (cnt - 1)) - 1;
 		res |= (d >> (65 - cnt)) & mask;
 		if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
-			res |= 1 << (cnt - 1);
+			res |= 1LL << (cnt - 1);
 		}
 		CONDITIONAL_SET_FLAG(cf, F_CF);
 		CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 62) & 0x2)),
@@ -756,12 +756,12 @@ uint64_t rcr64(x64emu_t *emu, uint64_t d, uint8_t s)
 			ocf = ACCESS_FLAG(F_CF) != 0;
 		} else
 			cf = (d >> (cnt - 1)) & 0x1;
-		mask = (1 << (64 - cnt)) - 1;
+		mask = (1LL << (64 - cnt)) - 1;
 		res = (d >> cnt) & mask;
 		if (cnt != 1)
 			res |= (d << (65 - cnt));
 		if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
-			res |= 1 << (64 - cnt);
+			res |= 1LL << (64 - cnt);
 		}
 		CONDITIONAL_SET_FLAG(cf, F_CF);
 		if (cnt == 1) {
@@ -1033,17 +1033,17 @@ uint32_t shld32 (x64emu_t *emu, uint32_t d, uint32_t fill, uint8_t s)
 
 uint64_t shld64 (x64emu_t *emu, uint64_t d, uint64_t fill, uint8_t s)
 {
-	unsigned int cnt, res, cf;
+	uint64_t cnt, res, cf;
 	RESET_FLAGS(emu);
 
 	s = s&0x3f;
 	cnt = s % 64;
 	if (cnt > 0) {
 		res = (d << cnt) | (fill >> (64-cnt));
-		cf = d & (1 << (64 - cnt));
+		cf = d & (1LL << (64 - cnt));
 		CONDITIONAL_SET_FLAG(cf, F_CF);
 		CONDITIONAL_SET_FLAG(!res, F_ZF);
-		CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF);
+		CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF);
 		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 	} else {
 		res = d;
@@ -1139,11 +1139,11 @@ uint64_t shrd64 (x64emu_t *emu, uint64_t d, uint64_t fill, uint8_t s)
 	s = s&0x3f;
 	cnt = s % 64;
 	if (cnt > 0) {
-		cf = d & (1 << (cnt - 1));
+		cf = d & (1LL << (cnt - 1));
 		res = (d >> cnt) | (fill << (64 - cnt));
 		CONDITIONAL_SET_FLAG(cf, F_CF);
 		CONDITIONAL_SET_FLAG(!res, F_ZF);
-		CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF);
+		CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF);
 		CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 	} else {
 		res = d;
@@ -1235,13 +1235,13 @@ uint64_t sbb64(x64emu_t *emu, uint64_t d, uint64_t s)
         res = d - s - 1;
     else
         res = d - s;
-	CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF);
+	CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF);
 	CONDITIONAL_SET_FLAG(!res, F_ZF);
 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 
 	/* calculate the borrow chain.  See note at top */
 	bc = (res & (~d | s)) | (~d & s);
-	CONDITIONAL_SET_FLAG(bc & 0x8000000000000000L, F_CF);
+	CONDITIONAL_SET_FLAG(bc & 0x8000000000000000LL, F_CF);
 	CONDITIONAL_SET_FLAG(XOR2(bc >> 62), F_OF);
 	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
 	return res;
@@ -1304,7 +1304,7 @@ void test64(x64emu_t *emu, uint64_t d, uint64_t s)
 	res = d & s;
 
 	CLEAR_FLAG(F_OF);
-	CONDITIONAL_SET_FLAG(res & 0x8000000000000000L, F_SF);
+	CONDITIONAL_SET_FLAG(res & 0x8000000000000000LL, F_SF);
 	CONDITIONAL_SET_FLAG(res == 0, F_ZF);
 	CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
 	/* AF == dont care */
diff --git a/src/emu/x64primop.h b/src/emu/x64primop.h
index df32d2c4..f27c8cc0 100755
--- a/src/emu/x64primop.h
+++ b/src/emu/x64primop.h
@@ -34,7 +34,7 @@ static inline uint16_t add16(x64emu_t *emu, uint16_t d, uint16_t s)
 
 static inline uint32_t add32(x64emu_t *emu, uint32_t d, uint32_t s)
 {
-	emu->res = d + s;
+	emu->res = (uint64_t)d + s;
 	emu->op1 = d;
 	emu->op2 = s;
 	emu->df = d_add32;
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index dbf257c6..32778044 100755
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -466,6 +466,15 @@ x64emurun:
                 R_RDX=(R_EAX & 0x80000000)?0xFFFFFFFFFFFFFFFFL:0x0000000000000000L;
             break;
 
+        case 0x9C:                      /* PUSHF */
+            CHECK_FLAGS(emu);
+            Push(emu, emu->eflags.x64);
+            break;
+        case 0x9D:                      /* POPF */
+            emu->eflags.x64 = ((Pop(emu) & 0x3F7FD7)/* & (0xffff-40)*/ ) | 0x2; // mask off res2 and res3 and on res1
+            RESET_FLAGS(emu);
+            break;
+
         case 0xA5:              /* (REP) MOVSD */
             tmp8s = ACCESS_FLAG(F_DF)?-1:+1;
             tmp64u = (rep)?R_RCX:1L;
@@ -913,27 +922,48 @@ x64emurun:
                         test32(emu, ED->dword[0], tmp32u);
                         break;
                     case 2:                 /* NOT Ed */
-                        ED->dword[0] = not32(emu, ED->dword[0]);
+                        ED->q[0] = not32(emu, ED->dword[0]);
                         break;
                     case 3:                 /* NEG Ed */
-                        ED->dword[0] = neg32(emu, ED->dword[0]);
+                        ED->q[0] = neg32(emu, ED->dword[0]);
                         break;
                     case 4:                 /* MUL EAX,Ed */
                         mul32_eax(emu, ED->dword[0]);
+                        emu->regs[_AX].dword[1] = 0;
                         break;
                     case 5:                 /* IMUL EAX,Ed */
                         imul32_eax(emu, ED->dword[0]);
+                        emu->regs[_AX].dword[1] = 0;
                         break;
                     case 6:                 /* DIV Ed */
                         div32(emu, ED->dword[0]);
+                        emu->regs[_AX].dword[1] = 0;
+                        emu->regs[_DX].dword[1] = 0;
                         break;
                     case 7:                 /* IDIV Ed */
                         idiv32(emu, ED->dword[0]);
+                        emu->regs[_AX].dword[1] = 0;
+                        emu->regs[_DX].dword[1] = 0;
                         break;
                 }
             }
             break;
 
+        case 0xFE:                      /* GRP 5 Eb */
+            nextop = F8;
+            GETEB(0);
+            switch((nextop>>3)&7) {
+                case 0:                 /* INC Eb */
+                    ED->byte[0] = inc8(emu, ED->byte[0]);
+                    break;
+                case 1:                 /* DEC Ed */
+                    ED->byte[0] = dec8(emu, ED->byte[0]);
+                    break;
+                default:
+                    unimp = 1;
+                    goto fini;
+            }
+            break;
         case 0xFF:                      /* GRP 5 Ed */
             nextop = F8;
             GETED(0);
@@ -942,13 +972,13 @@ x64emurun:
                     if(rex.w)
                         ED->q[0] = inc64(emu, ED->q[0]);
                     else
-                        ED->dword[0] = inc32(emu, ED->dword[0]);
+                        ED->q[0] = inc32(emu, ED->dword[0]);
                     break;
                 case 1:                 /* DEC Ed */
                     if(rex.w)
                         ED->q[0] = dec64(emu, ED->q[0]);
                     else
-                        ED->dword[0] = dec32(emu, ED->dword[0]);
+                        ED->q[0] = dec32(emu, ED->dword[0]);
                     break;
                 case 2:                 /* CALL NEAR Ed */
                     tmp64u = (uintptr_t)getAlternate((void*)ED->q[0]);
diff --git a/src/emu/x64run0f.c b/src/emu/x64run0f.c
index ec055fb2..a58ed582 100644
--- a/src/emu/x64run0f.c
+++ b/src/emu/x64run0f.c
@@ -143,8 +143,8 @@ int Run0F(x64emu_t *emu, rex_t rex)
             GETED(0);

             GETGD;

             CHECK_FLAGS(emu);

-            , if(rex.w) {GD->q[0] = ED->q[0]; } else {GD->dword[0] = ED->dword[0];}

-            ,

+            , if(rex.w) {GD->q[0] = ED->q[0]; } else {GD->q[0] = ED->dword[0];}

+            , if(!rex.w) GD->dword[1] = 0;

         )                               /* 0x40 -> 0x4F CMOVxx Gd,Ed */ // conditional move, no sign

         

         case 0x51:                      /* SQRTPS Gx, Ex */

@@ -452,7 +452,86 @@ int Run0F(x64emu_t *emu, rex_t rex)
             tmp32u = R_EAX;

             my_cpuid(emu, tmp32u);

             break;

+        case 0xA3:                      /* BT Ed,Gd */

+            CHECK_FLAGS(emu);

+            nextop = F8;

+            GETED(0);

+            GETGD;

+            tmp8u = GD->byte[0];

+            if(!MODREG)

+            {

+                ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));

+            }

+            if(rex.w) {

+                tmp8u&=63;

+                if(ED->q[0] & (1LL<<tmp8u))

+                    SET_FLAG(F_CF);

+                else

+                    CLEAR_FLAG(F_CF);

+            } else {

+                tmp8u&=31;

+                if(ED->dword[0] & (1<<tmp8u))

+                    SET_FLAG(F_CF);

+                else

+                    CLEAR_FLAG(F_CF);

+            }

+            break;

+        case 0xA4:                      /* SHLD Ed,Gd,Ib */

+        case 0xA5:                      /* SHLD Ed,Gd,CL */

+            nextop = F8;

+            GETED((nextop==0xA4)?1:0);

+            GETGD;

+            if(opcode==0xA4)

+                tmp8u = F8;

+            else

+                tmp8u = R_CL;

+            if(rex.w)

+                ED->q[0] = shld64(emu, ED->q[0], GD->q[0], tmp8u);

+            else

+                ED->q[0] = shld32(emu, ED->dword[0], GD->dword[0], tmp8u);

+            break;

 

+        case 0xAB:                      /* BTS Ed,Gd */

+            CHECK_FLAGS(emu);

+            nextop = F8;

+            GETED(0);

+            GETGD;

+            tmp8u = GD->byte[0];

+            if(!MODREG)

+            {

+                ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));

+            }

+            if(rex.w) {

+                tmp8u&=63;

+                if(ED->q[0] & (1LL<<tmp8u))

+                    SET_FLAG(F_CF);

+                else {

+                    ED->q[0] |= (1LL<<tmp8u);

+                    CLEAR_FLAG(F_CF);

+                }

+            } else {

+                tmp8u&=31;

+                if(ED->dword[0] & (1<<tmp8u))

+                    SET_FLAG(F_CF);

+                else {

+                    ED->dword[0] |= (1<<tmp8u);

+                    CLEAR_FLAG(F_CF);

+                }

+                if(MODREG)

+                    ED->dword[1] = 0;

+            }

+            break;

+        case 0xAC:                      /* SHRD Ed,Gd,Ib */

+        case 0xAD:                      /* SHRD Ed,Gd,CL */

+            nextop = F8;

+            GETED((nextop==0xAC)?1:0);

+            GETGD;

+            tmp8u = (opcode==0xAC)?(F8):R_CL;

+            if(rex.w)

+                ED->q[0] = shrd64(emu, ED->q[0], GD->q[0], tmp8u);

+            else

+                ED->q[0] = shrd32(emu, ED->dword[0], GD->dword[0], tmp8u);

+            break;

         case 0xAE:                      /* Grp Ed (SSE) */

             nextop = F8;

             if((nextop&0xF8)==0xE8) {

@@ -486,6 +565,35 @@ int Run0F(x64emu_t *emu, rex_t rex)
                 GD->dword[0] = imul32(emu, GD->dword[0], ED->dword[0]);

             break;

 

+        case 0xB3:                      /* BTR Ed,Gd */

+            CHECK_FLAGS(emu);

+            nextop = F8;

+            GETED(0);

+            GETGD;

+            tmp8u = GD->byte[0];

+            if(!MODREG)

+            {

+                ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));

+            }

+            if(rex.w) {

+                tmp8u&=63;

+                if(ED->q[0] & (1LL<<tmp8u)) {

+                    SET_FLAG(F_CF);

+                    ED->q[0] ^= (1LL<<tmp8u);

+                } else

+                    CLEAR_FLAG(F_CF);

+            } else {

+                tmp8u&=31;

+                if(ED->dword[0] & (1<<tmp8u)) {

+                    SET_FLAG(F_CF);

+                    ED->dword[0] ^= (1<<tmp8u);

+                } else

+                    CLEAR_FLAG(F_CF);

+                if(MODREG)

+                    ED->dword[1] = 0;

+            }

+            break;

+

         case 0xB6:                      /* MOVZX Gd,Eb */

             nextop = F8;

             GETEB(0);

@@ -510,7 +618,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
                         ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));

                     if(rex.w) {

                         tmp8u&=63;

-                        if(ED->q[0] & (1L<<tmp8u))

+                        if(ED->q[0] & (1LL<<tmp8u))

                             SET_FLAG(F_CF);

                         else

                             CLEAR_FLAG(F_CF);

@@ -530,10 +638,10 @@ int Run0F(x64emu_t *emu, rex_t rex)
                         ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));

                     if(rex.w) {

                         tmp8u&=63;

-                        if(ED->q[0] & (1L<<tmp8u)) {

+                        if(ED->q[0] & (1LL<<tmp8u)) {

                             SET_FLAG(F_CF);

                         } else {

-                            ED->q[0] ^= (1L<<tmp8u);

+                            ED->q[0] ^= (1LL<<tmp8u);

                             CLEAR_FLAG(F_CF);

                         }

                     } else {

@@ -554,9 +662,9 @@ int Run0F(x64emu_t *emu, rex_t rex)
                         ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));

                     if(rex.w) {

                         tmp8u&=63;

-                        if(ED->q[0] & (1L<<tmp8u)) {

+                        if(ED->q[0] & (1LL<<tmp8u)) {

                             SET_FLAG(F_CF);

-                            ED->q[0] ^= (1L<<tmp8u);

+                            ED->q[0] ^= (1LL<<tmp8u);

                         } else

                             CLEAR_FLAG(F_CF);

                     } else {

@@ -576,11 +684,11 @@ int Run0F(x64emu_t *emu, rex_t rex)
                         ED=(reg64_t*)(((uintptr_t*)(ED))+(tmp8u>>5));

                     if(rex.w) {

                         tmp8u&=63;

-                        if(ED->q[0] & (1L<<tmp8u))

+                        if(ED->q[0] & (1LL<<tmp8u))

                             SET_FLAG(F_CF);

                         else

                             CLEAR_FLAG(F_CF);

-                        ED->q[0] ^= (1L<<tmp8u);

+                        ED->q[0] ^= (1LL<<tmp8u);

                     } else {

                         tmp8u&=31;

                         if(ED->dword[0] & (1<<tmp8u))

@@ -595,7 +703,64 @@ int Run0F(x64emu_t *emu, rex_t rex)
                     return 1;

             }

             break;

-

+        case 0xBB:                      /* BTC Ed,Gd */

+            CHECK_FLAGS(emu);

+            nextop = F8;

+            GETED(0);

+            GETGD;

+            tmp8u = GD->byte[0];

+            if(!MODREG)

+            {

+                if(rex.w)

+                    ED=(reg64_t*)(((uint64_t*)(ED))+(tmp8u>>6));

+                else

+                    ED=(reg64_t*)(((uint32_t*)(ED))+(tmp8u>>5));

+            }

+            if(rex.w) {

+                tmp8u&=63;

+                if(ED->q[0] & (1LL<<tmp8u))

+                    SET_FLAG(F_CF);

+                else

+                    CLEAR_FLAG(F_CF);

+                ED->q[0] ^= (1LL<<tmp8u);

+            } else {

+                tmp8u&=31;

+                if(ED->dword[0] & (1<<tmp8u))

+                    SET_FLAG(F_CF);

+                else

+                    CLEAR_FLAG(F_CF);

+                ED->dword[0] ^= (1<<tmp8u);

+                if(MODREG)

+                    ED->dword[1] = 0;

+            }

+            break;

+        case 0xBC:                      /* BSF Ed,Gd */

+            CHECK_FLAGS(emu);

+            nextop = F8;

+            GETED(0);

+            GETGD;

+            if(rex.w) {

+                tmp64u = ED->q[0];

+                if(tmp64u) {

+                    CLEAR_FLAG(F_ZF);

+                    tmp8u = 0;

+                    while(!(tmp64u&(1LL<<tmp8u))) ++tmp8u;

+                    GD->q[0] = tmp8u;

+                } else {

+                    SET_FLAG(F_ZF);

+                }

+            } else {

+                tmp32u = ED->dword[0];

+                if(tmp32u) {

+                    CLEAR_FLAG(F_ZF);

+                    tmp8u = 0;

+                    while(!(tmp32u&(1<<tmp8u))) ++tmp8u;

+                    GD->q[0] = tmp8u;

+                } else {

+                    SET_FLAG(F_ZF);

+                }

+            }

+            break;

         case 0xBD:                      /* BSR Ed,Gd */

             CHECK_FLAGS(emu);

             nextop = F8;

@@ -606,7 +771,7 @@ int Run0F(x64emu_t *emu, rex_t rex)
                 if(tmp64u) {

                     CLEAR_FLAG(F_ZF);

                     tmp8u = 63;

-                    while(!(tmp64u&(1L<<tmp8u))) --tmp8u;

+                    while(!(tmp64u&(1LL<<tmp8u))) --tmp8u;

                     GD->q[0] = tmp8u;

                 } else {

                     SET_FLAG(F_ZF);

diff --git a/src/emu/x64run66.c b/src/emu/x64run66.c
index 822d91df..c2e8a5a0 100644
--- a/src/emu/x64run66.c
+++ b/src/emu/x64run66.c
@@ -33,6 +33,7 @@ int Run66(x64emu_t *emu, rex_t rex)
     uint8_t tmp8u;

     int16_t tmp16s;

     uint16_t tmp16u;

+    int64_t tmp64s;

     uint64_t tmp64u;

     reg64_t *oped, *opgd;

 

@@ -129,6 +130,32 @@ int Run66(x64emu_t *emu, rex_t rex)
     case 0x64:                              /* FS: */

         return Run6664(emu, rex);

 

+    case 0x69:                      /* IMUL Gw,Ew,Iw */

+        nextop = F8;

+        GETEW(rex.w?4:2);

+        GETGW;

+        if(rex.w) {

+            tmp64u = F32S64;

+            GW->q[0] = imul64(emu, EW->q[0], tmp64u);

+        } else {

+            tmp16u = F16;

+            GW->word[0] = imul16(emu, EW->word[0], tmp16u);

+        }

+        break;

+

+    case 0x6B:                      /* IMUL Gw,Ew,Ib */

+        nextop = F8;

+        GETEW(1);

+        GETGW;

+        if(rex.w) {

+            tmp64s = F8S;

+            GW->q[0] = imul64(emu, EW->q[0], (uint64_t)tmp64s);

+        } else {

+            tmp16s = F8S;

+            GW->word[0] = imul16(emu, EW->word[0], (uint16_t)tmp16s);

+        }

+        break;

+

     case 0x81:                              /* GRP3 Ew,Iw */

     case 0x83:                              /* GRP3 Ew,Ib */

         nextop = F8;

@@ -300,8 +327,31 @@ int Run66(x64emu_t *emu, rex_t rex)
         }

         break;

 

-        default:

-            return 1;

+    case 0xFF:                      /* GRP 5 Ew */

+        nextop = F8;

+        GETEW(0);

+        GETGW;

+        switch((nextop>>3)&7) {

+            case 0:                 /* INC Ed */

+                EW->word[0] = inc16(emu, EW->word[0]);

+                break;

+            case 1:                 /* DEC Ed */

+                EW->word[0] = dec16(emu, EW->word[0]);

+                break;

+            /*case 6:

+                Push16(emu, EW->word[0]);

+                break;*/

+            default:

+                    R_RIP = emu->old_ip;

+                    printf_log(LOG_NONE, "Illegal Opcode %p: 66 %02X %02X %02X %02X %02X %02X\n",(void*)R_RIP, opcode, nextop, PK(2), PK(3), PK(4), PK(5));

+                    emu->quit=1;

+                    emu->error |= ERR_ILLEGAL;

+                    return 0;

+        }

+        break;

+

+    default:

+        return 1;

     }

     return 0;

 }
\ No newline at end of file
diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c
index 660ac028..434fd81e 100644
--- a/src/emu/x64run660f.c
+++ b/src/emu/x64run660f.c
@@ -30,7 +30,9 @@ int Run660F(x64emu_t *emu, rex_t rex)
 {

     uint8_t opcode;

     uint8_t nextop;

-    int32_t tmp32s;

+    uint8_t tmp8u;

+    uint16_t tmp16u;

+    uint64_t tmp64u;

     reg64_t *oped, *opgd;

     sse_regs_t *opex, *opgx;

     mmx87_regs_t *opem;

@@ -386,6 +388,169 @@ int Run660F(x64emu_t *emu, rex_t rex)
         EX->q[1] = GX->q[1];

         break;

 

+    case 0xA3:                      /* BT Ew,Gw */

+        CHECK_FLAGS(emu);

+        nextop = F8;

+        GETEW(0);

+        GETGW;

+        if(rex.w) {

+            if(EW->q[0] & (1LL<<(GW->q[0]&63)))

+                SET_FLAG(F_CF);

+            else

+                CLEAR_FLAG(F_CF);

+        } else {

+            if(EW->word[0] & (1<<(GW->word[0]&15)))

+                SET_FLAG(F_CF);

+            else

+                CLEAR_FLAG(F_CF);

+        }

+        break;

+    case 0xA4:                      /* SHLD Ew,Gw,Ib */

+    case 0xA5:                      /* SHLD Ew,Gw,CL */

+        nextop = F8;

+        GETEW((nextop==0xA4)?1:0);

+        GETGW;

+        if(opcode==0xA4)

+            tmp8u = F8;

+        else

+            tmp8u = R_CL;

+        if(rex.w)

+            EW->q[0] = shld64(emu, EW->q[0], GW->q[0], tmp8u);

+        else

+            EW->word[0] = shld16(emu, EW->word[0], GW->word[0], tmp8u);

+        break;

+

+    case 0xAB:                      /* BTS Ew,Gw */

+        CHECK_FLAGS(emu);

+        nextop = F8;

+        GETEW(0);

+        GETGW;

+        if(rex.w) {

+            if(EW->q[0] & (1LL<<(GW->q[0]&63)))

+                SET_FLAG(F_CF);

+            else {

+                EW->q[0] |= (1LL<<(GW->q[0]&63));

+                CLEAR_FLAG(F_CF);

+            }

+        } else {

+            if(EW->word[0] & (1<<(GW->word[0]&15)))

+                SET_FLAG(F_CF);

+            else {

+                EW->word[0] |= (1<<(GW->word[0]&15));

+                CLEAR_FLAG(F_CF);

+            }

+        }

+        break;

+    case 0xAC:                      /* SHRD Ew,Gw,Ib */

+    case 0xAD:                      /* SHRD Ew,Gw,CL */

+        nextop = F8;

+        GETEW((nextop==0xAC)?1:0);

+        GETGW;

+        if(opcode==0xAC)

+            tmp8u = F8;

+        else

+            tmp8u = R_CL;

+        if(rex.w)

+            EW->q[0] = shrd64(emu, EW->q[0], GW->q[0], tmp8u);

+        else

+            EW->word[0] = shrd16(emu, EW->word[0], GW->word[0], tmp8u);

+        break;

+

+    case 0xAF:                      /* IMUL Gw,Ew */

+        nextop = F8;

+        GETEW(0);

+        GETGW;

+        if(rex.w)

+            GW->q[0] = imul64(emu, GW->q[0], EW->q[0]);

+        else

+            GW->word[0] = imul16(emu, GW->word[0], EW->word[0]);

+        break;

+

+    case 0xB3:                      /* BTR Ew,Gw */

+        CHECK_FLAGS(emu);

+        nextop = F8;

+        GETEW(0);

+        GETGW;

+        if(rex.w) {

+            if(EW->q[0] & (1LL<<(GW->q[0]&63))) {

+                SET_FLAG(F_CF);

+                EW->q[0] ^= (1LL<<(GW->q[0]&63));

+            } else

+                CLEAR_FLAG(F_CF);

+        } else {

+            if(EW->word[0] & (1<<(GW->word[0]&15))) {

+                SET_FLAG(F_CF);

+                EW->word[0] ^= (1<<(GW->word[0]&15));

+            } else

+                CLEAR_FLAG(F_CF);

+        }

+        break;

+

+    case 0xBB:                      /* BTC Ew,Gw */

+        CHECK_FLAGS(emu);

+        nextop = F8;

+        GETEW(0);

+        GETGW;

+        if(EW->word[0] & (1<<(GW->word[0]&15)))

+            SET_FLAG(F_CF);

+        else

+            CLEAR_FLAG(F_CF);

+        EW->word[0] ^= (1<<(GW->word[0]&15));

+        break;

+    case 0xBC:                      /* BSF Ew,Gw */

+        CHECK_FLAGS(emu);

+        nextop = F8;

+        GETEW(0);

+        GETGW;

+        if(rex.w) {

+            tmp64u = EW->q[0];

+            if(tmp64u) {

+                CLEAR_FLAG(F_ZF);

+                tmp8u = 0;

+                while(!(tmp64u&(1LL<<tmp8u))) ++tmp8u;

+                GW->q[0] = tmp8u;

+            } else {

+                SET_FLAG(F_ZF);

+            }

+        } else {

+            tmp16u = EW->word[0];

+            if(tmp16u) {

+                CLEAR_FLAG(F_ZF);

+                tmp8u = 0;

+                while(!(tmp16u&(1<<tmp8u))) ++tmp8u;

+                GW->word[0] = tmp8u;

+            } else {

+                SET_FLAG(F_ZF);

+            }

+        }

+        break;

+    case 0xBD:                      /* BSR Ew,Gw */

+        CHECK_FLAGS(emu);

+        nextop = F8;

+        GETEW(0);

+        GETGW;

+        if(rex.w) {

+            tmp64u = EW->q[0];

+            if(tmp64u) {

+                CLEAR_FLAG(F_ZF);

+                tmp8u = 63;

+                while(!(tmp64u&(1LL<<tmp8u))) --tmp8u;

+                GW->q[0] = tmp8u;

+            } else {

+                SET_FLAG(F_ZF);

+            }

+        } else {

+            tmp16u = EW->word[0];

+            if(tmp16u) {

+                CLEAR_FLAG(F_ZF);

+                tmp8u = 15;

+                while(!(tmp16u&(1<<tmp8u))) --tmp8u;

+                GW->word[0] = tmp8u;

+            } else {

+                SET_FLAG(F_ZF);

+            }

+        }

+        break;

     case 0xBE:                      /* MOVSX Gw,Eb */

         nextop = F8;

         GETEB(0);

diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c
index 9e012d1f..b3f21421 100755
--- a/src/emu/x64run_private.c
+++ b/src/emu/x64run_private.c
@@ -115,7 +115,7 @@ void UpdateFlags(x64emu_t *emu)
             CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
             break;
         case d_add32:
-            CONDITIONAL_SET_FLAG(emu->res & 0x100000000, F_CF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x100000000LL, F_CF);
             CONDITIONAL_SET_FLAG((emu->res & 0xffffffff) == 0, F_ZF);
             CONDITIONAL_SET_FLAG(emu->res & 0x80000000, F_SF);
             CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
@@ -128,7 +128,7 @@ void UpdateFlags(x64emu_t *emu)
             hi = (lo >> 32) + (emu->op2 >> 32) + (emu->op1 >> 32);
             CONDITIONAL_SET_FLAG(hi & 0x100000000, F_CF);
             CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
-            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF);
             CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
             cc = (emu->op1 & emu->op2) | ((~emu->res) & (emu->op1 | emu->op2));
             CONDITIONAL_SET_FLAG(XOR2(cc >> 62), F_OF);
@@ -162,7 +162,7 @@ void UpdateFlags(x64emu_t *emu)
             CLEAR_FLAG(F_OF);
             CLEAR_FLAG(F_CF);
             CLEAR_FLAG(F_AF);
-            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF);
             CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
             CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
             break;
@@ -191,7 +191,7 @@ void UpdateFlags(x64emu_t *emu)
             CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
             break;
         case d_dec64:
-            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF);
             CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
             CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
             bc = (emu->res & (~emu->op1 | 1)) | (~emu->op1 & 1);
@@ -224,7 +224,7 @@ void UpdateFlags(x64emu_t *emu)
             break;
         case d_inc64:
             CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
-            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF);
             CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
             cc = (1 & emu->op1) | ((~emu->res) & (1 | emu->op1));
             CONDITIONAL_SET_FLAG(XOR2(cc >> 62), F_OF);
@@ -268,8 +268,8 @@ void UpdateFlags(x64emu_t *emu)
             CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
             break;
         case d_imul64:
-            if (((emu->res & 0x8000000000000000L) == 0 && emu->op1 == 0x00) ||
-                ((emu->res & 0x8000000000000000L) != 0 && emu->op1 == 0xFFFFFFFFFFFFFFFFL)) {
+            if (((emu->res & 0x8000000000000000LL) == 0 && emu->op1 == 0x00) ||
+                ((emu->res & 0x8000000000000000LL) != 0 && emu->op1 == 0xFFFFFFFFFFFFFFFFLL)) {
                 CLEAR_FLAG(F_CF);
                 CLEAR_FLAG(F_OF);
             } else {
@@ -303,9 +303,7 @@ void UpdateFlags(x64emu_t *emu)
             CONDITIONAL_SET_FLAG(PARITY(lo & 0xff), F_PF);
             break;
         case d_mul32:
-            lo = (uint32_t)emu->res;
-            hi = (uint32_t)(emu->res >> 32);
-            if (hi == 0) {
+            if (emu->op1 == 0) {
                 CLEAR_FLAG(F_CF);
                 CLEAR_FLAG(F_OF);
             } else {
@@ -352,7 +350,7 @@ void UpdateFlags(x64emu_t *emu)
             CLEAR_FLAG(F_OF);
             CLEAR_FLAG(F_CF);
             CLEAR_FLAG(F_AF);
-            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF);
             CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
             CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
             break;
@@ -386,7 +384,7 @@ void UpdateFlags(x64emu_t *emu)
         case d_neg64:
             CONDITIONAL_SET_FLAG(emu->op1 != 0, F_CF);
             CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
-            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF);
             CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
             bc = emu->res | emu->op1;
             CONDITIONAL_SET_FLAG(XOR2(bc >> 62), F_OF);
@@ -464,14 +462,14 @@ void UpdateFlags(x64emu_t *emu)
             break;
         case d_shl64:
             if (emu->op2 > 0) {
-                cc = emu->op1 & (1 << (64 - emu->op2));
+                cc = emu->op1 & (1LL << (64 - emu->op2));
                 CONDITIONAL_SET_FLAG(cc, F_CF);
                 CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
-                CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF);
+                CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF);
                 CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
             }
             if (emu->op2 == 1) {
-                CONDITIONAL_SET_FLAG(((!!(emu->res & 0x8000000000000000L)) ^
+                CONDITIONAL_SET_FLAG(((!!(emu->res & 0x8000000000000000LL)) ^
                                         (ACCESS_FLAG(F_CF) != 0)), F_OF);
             } else {
                 CLEAR_FLAG(F_OF);
@@ -548,10 +546,10 @@ void UpdateFlags(x64emu_t *emu)
             break;
         case d_sar64:
             if(emu->op2) {
-                cc = emu->op1 & (1 << (emu->op2 - 1));
+                cc = emu->op1 & (1LL << (emu->op2 - 1));
                 CONDITIONAL_SET_FLAG(cc, F_CF);
                 CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
-                CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF);
+                CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF);
                 CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
             }
             break;
@@ -618,10 +616,10 @@ void UpdateFlags(x64emu_t *emu)
         case d_shr64:
             cnt = emu->op2;
             if (cnt > 0) {
-                cc = emu->op1 & (1 << (cnt - 1));
+                cc = emu->op1 & (1LL << (cnt - 1));
                 CONDITIONAL_SET_FLAG(cc, F_CF);
                 CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
-                CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF);
+                CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF);
                 CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
             }
             if (cnt == 1) {
@@ -656,11 +654,11 @@ void UpdateFlags(x64emu_t *emu)
             CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
             break;
         case d_sub64:
-            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF);
             CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
             CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
             bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
-            CONDITIONAL_SET_FLAG(bc & 0x8000000000000000L, F_CF);
+            CONDITIONAL_SET_FLAG(bc & 0x8000000000000000LL, F_CF);
             CONDITIONAL_SET_FLAG(XOR2(bc >> 62), F_OF);
             CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
             break;
@@ -690,7 +688,7 @@ void UpdateFlags(x64emu_t *emu)
             break;
         case d_xor64:
             CLEAR_FLAG(F_OF);
-            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF);
             CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
             CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
             CLEAR_FLAG(F_CF);
@@ -725,11 +723,11 @@ void UpdateFlags(x64emu_t *emu)
         	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
             break;
         case d_cmp64:
-        	CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF);
+        	CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF);
         	CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
         	CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
         	bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
-        	CONDITIONAL_SET_FLAG(bc & 0x8000000000000000L, F_CF);
+        	CONDITIONAL_SET_FLAG(bc & 0x8000000000000000LL, F_CF);
         	CONDITIONAL_SET_FLAG(XOR2(bc >> 62), F_OF);
         	CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
             break;
@@ -756,7 +754,7 @@ void UpdateFlags(x64emu_t *emu)
             break;
         case d_tst64:
         	CLEAR_FLAG(F_OF);
-        	CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF);
+        	CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF);
         	CONDITIONAL_SET_FLAG(emu->res == 0, F_ZF);
         	CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
         	CLEAR_FLAG(F_CF);
@@ -797,7 +795,7 @@ void UpdateFlags(x64emu_t *emu)
             hi = (lo >> 32) + (emu->op1 >> 32) + (emu->op2 >> 32);
             CONDITIONAL_SET_FLAG(hi & 0x1000000000000L, F_CF);
             CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
-            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF);
             CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
             cc = (emu->op2 & emu->op1) | ((~emu->res) & (emu->op2 | emu->op1));
             CONDITIONAL_SET_FLAG(XOR2(cc >> 62), F_OF);
@@ -831,11 +829,11 @@ void UpdateFlags(x64emu_t *emu)
             CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
             break;
         case d_sbb64:
-            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000L, F_SF);
+            CONDITIONAL_SET_FLAG(emu->res & 0x8000000000000000LL, F_SF);
             CONDITIONAL_SET_FLAG(!emu->res, F_ZF);
             CONDITIONAL_SET_FLAG(PARITY(emu->res & 0xff), F_PF);
             bc = (emu->res & (~emu->op1 | emu->op2)) | (~emu->op1 & emu->op2);
-            CONDITIONAL_SET_FLAG(bc & 0x8000000000000000L, F_CF);
+            CONDITIONAL_SET_FLAG(bc & 0x8000000000000000LL, F_CF);
             CONDITIONAL_SET_FLAG(XOR2(bc >> 62), F_OF);
             CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
             break;