about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-05 14:38:55 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-05 14:38:55 +0100
commitcafbaa1e239994ee0ef694e2650cb224ce15a7a9 (patch)
tree01a2cb599d4f54d6b5107cf3f7bf6f920c03003f /src
parentb13273be0536d5ecf5b70f9935208540e82f1d05 (diff)
downloadbox64-cafbaa1e239994ee0ef694e2650cb224ce15a7a9.tar.gz
box64-cafbaa1e239994ee0ef694e2650cb224ce15a7a9.zip
Added REX F7 opcodes
Diffstat (limited to 'src')
-rwxr-xr-xsrc/emu/x64primop.c56
-rwxr-xr-xsrc/emu/x64primop.h12
-rwxr-xr-xsrc/emu/x64run.c58
3 files changed, 123 insertions, 3 deletions
diff --git a/src/emu/x64primop.c b/src/emu/x64primop.c
index 0c040f1d..9b6fffb8 100755
--- a/src/emu/x64primop.c
+++ b/src/emu/x64primop.c
@@ -1371,10 +1371,10 @@ void idiv32(x64emu_t *emu, uint32_t s)
 		INTR_RAISE_DIV0(emu);
 		return;
 	}
-	lldiv_t p = lldiv(dvd, (int32_t)s);
+	ldiv_t p = ldiv(dvd, (int32_t)s);
 	quot = p.quot;
 	mod = p.rem;
-	if (llabs(quot) > 0x7fffffff) {
+	if (labs(quot) > 0x7fffffff) {
 		INTR_RAISE_DIV0(emu);
 		return;
 	}
@@ -1388,6 +1388,32 @@ void idiv32(x64emu_t *emu, uint32_t s)
 	R_EDX = (uint32_t)mod;
 }
 
+void idiv64(x64emu_t *emu, uint64_t s)
+{
+	__int128 dvd, quot, mod;
+	RESET_FLAGS(emu);
+
+	dvd = (((__int128)R_RDX) << 64) | R_RAX;
+	if (s == 0) {
+		INTR_RAISE_DIV0(emu);
+		return;
+	}
+	quot = dvd/(int64_t)s;
+	mod = dvd%(int64_t)s;
+	if (llabs(quot) > 0x7fffffffffffffffL) {
+		INTR_RAISE_DIV0(emu);
+		return;
+	}
+	CLEAR_FLAG(F_CF);
+	CLEAR_FLAG(F_AF);
+	CLEAR_FLAG(F_SF);
+	SET_FLAG(F_ZF);
+	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
+
+	R_RAX = (uint64_t)quot;
+	R_RDX = (uint64_t)mod;
+}
+
 /****************************************************************************
 REMARKS:
 Implements the DIV instruction and side effects.
@@ -1462,3 +1488,29 @@ void div32(x64emu_t *emu, uint32_t s)
 	R_EAX = (uint32_t)div;
 	R_EDX = (uint32_t)mod;
 }
+
+void div64(x64emu_t *emu, uint64_t s)
+{
+	__int128 dvd, div, mod;
+	RESET_FLAGS(emu);
+
+	dvd = (((__int128)R_RDX) << 64) | R_RAX;
+	if (s == 0) {
+		INTR_RAISE_DIV0(emu);
+		return;
+	}
+	div = dvd / (unsigned __int128)s;
+	mod = dvd % (unsigned __int128)s;
+	if (div > 0xffffffffffffffffL) {
+		INTR_RAISE_DIV0(emu);
+		return;
+	}
+	CLEAR_FLAG(F_CF);
+	CLEAR_FLAG(F_AF);
+	CLEAR_FLAG(F_SF);
+	SET_FLAG(F_ZF);
+	CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
+
+	R_RAX = (uint64_t)div;
+	R_RDX = (uint64_t)mod;
+}
diff --git a/src/emu/x64primop.h b/src/emu/x64primop.h
index 2b018548..df32d2c4 100755
--- a/src/emu/x64primop.h
+++ b/src/emu/x64primop.h
@@ -559,7 +559,7 @@ static inline uint64_t imul64(x64emu_t *emu, uint64_t op1, uint64_t op2)
 	return emu->res;
 }
 
-static inline void imul64_eax(x64emu_t *emu, uint64_t s)
+static inline void imul64_rax(x64emu_t *emu, uint64_t s)
 {
 	emu->df = d_imul64;
 	imul64_direct(&R_RAX,&R_RDX,R_RAX,s);
@@ -589,11 +589,21 @@ static inline void mul32_eax(x64emu_t *emu, uint32_t s)
 	emu->op1 = R_EDX = (uint32_t)(res >> 32);
 }
 
+static inline void mul64_rax(x64emu_t *emu, uint64_t s)
+{
+	emu->df = d_mul64;
+	__int128 res = (__int128)R_RAX * s;
+	emu->res = R_RAX = (uint64_t)res;
+	emu->op1 = R_RDX = (uint64_t)(res >> 64);
+}
+
 void         idiv8  (x64emu_t *emu, uint8_t s);
 void         idiv16 (x64emu_t *emu, uint16_t s);
 void         idiv32 (x64emu_t *emu, uint32_t s);
+void         idiv64 (x64emu_t *emu, uint64_t s);
 void         div8  (x64emu_t *emu, uint8_t s);
 void         div16 (x64emu_t *emu, uint16_t s);
 void         div32 (x64emu_t *emu, uint32_t s);
+void         div64 (x64emu_t *emu, uint64_t s);
 
 #endif //__X64PRIMOP_H_
diff --git a/src/emu/x64run.c b/src/emu/x64run.c
index 2a6c3585..4f3b9986 100755
--- a/src/emu/x64run.c
+++ b/src/emu/x64run.c
@@ -473,6 +473,64 @@ x64emurun:
             STEP
             break;
 
+        case 0xF7:                      /* GRP3 Ed(,Id) */
+            nextop = F8;
+            GETED;
+            if(rex.w) {
+                switch((nextop>>3)&7) {
+                    case 0: 
+                    case 1:                 /* TEST Ed,Id */
+                        tmp64u = F32S64;
+                        test64(emu, ED->q[0], tmp64u);
+                        break;
+                    case 2:                 /* NOT Ed */
+                        ED->q[0] = not64(emu, ED->q[0]);
+                        break;
+                    case 3:                 /* NEG Ed */
+                        ED->q[0] = neg64(emu, ED->q[0]);
+                        break;
+                    case 4:                 /* MUL RAX,Ed */
+                        mul64_rax(emu, ED->q[0]);
+                        break;
+                    case 5:                 /* IMUL RAX,Ed */
+                        imul64_rax(emu, ED->q[0]);
+                        break;
+                    case 6:                 /* DIV Ed */
+                        div64(emu, ED->q[0]);
+                        break;
+                    case 7:                 /* IDIV Ed */
+                        idiv64(emu, ED->q[0]);
+                        break;
+                }
+            } else {
+                switch((nextop>>3)&7) {
+                    case 0: 
+                    case 1:                 /* TEST Ed,Id */
+                        tmp32u = F32;
+                        test32(emu, ED->dword[0], tmp32u);
+                        break;
+                    case 2:                 /* NOT Ed */
+                        ED->dword[0] = not32(emu, ED->dword[0]);
+                        break;
+                    case 3:                 /* NEG Ed */
+                        ED->dword[0] = neg32(emu, ED->dword[0]);
+                        break;
+                    case 4:                 /* MUL EAX,Ed */
+                        mul32_eax(emu, ED->dword[0]);
+                        break;
+                    case 5:                 /* IMUL EAX,Ed */
+                        imul32_eax(emu, ED->dword[0]);
+                        break;
+                    case 6:                 /* DIV Ed */
+                        div32(emu, ED->dword[0]);
+                        break;
+                    case 7:                 /* IDIV Ed */
+                        idiv32(emu, ED->dword[0]);
+                        break;
+                }
+            }
+            break;
+
         case 0xFF:                      /* GRP 5 Ed */
             nextop = F8;
             GETED;