about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorYang Liu <liuyang22@iscas.ac.cn>2025-08-06 16:34:37 +0800
committerGitHub <noreply@github.com>2025-08-06 10:34:37 +0200
commit676efe40327a8324889a736110ffea897b03736d (patch)
tree7813154233fd3ee8ea2674670810ba16e8269c82 /src
parentdd7b99ffd1445d824bd351488c6f7b976f77fc9e (diff)
downloadbox64-676efe40327a8324889a736110ffea897b03736d.tar.gz
box64-676efe40327a8324889a736110ffea897b03736d.zip
[LA64_DYNAREC] Added more opcodes (#2902)
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/la64/dynarec_la64_00.c3
-rw-r--r--src/dynarec/la64/dynarec_la64_64.c29
-rw-r--r--src/dynarec/la64/dynarec_la64_66.c5
-rw-r--r--src/dynarec/la64/dynarec_la64_67.c187
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.h13
-rw-r--r--src/dynarec/la64/la64_emitter.h12
6 files changed, 248 insertions, 1 deletions
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c
index 556ccd34..b8464a2e 100644
--- a/src/dynarec/la64/dynarec_la64_00.c
+++ b/src/dynarec/la64/dynarec_la64_00.c
@@ -377,6 +377,9 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             i64 = F32S;
             emit_sub32c(dyn, ninst, rex, xRAX, i64, x2, x3, x4, x5);
             break;
+        case 0x2E:
+            INST_NAME("CS:");
+            break;
         case 0x30:
             INST_NAME("XOR Eb, Gb");
             SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
diff --git a/src/dynarec/la64/dynarec_la64_64.c b/src/dynarec/la64/dynarec_la64_64.c
index 906e8fe7..62de36e1 100644
--- a/src/dynarec/la64/dynarec_la64_64.c
+++ b/src/dynarec/la64/dynarec_la64_64.c
@@ -444,6 +444,22 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             } else
                 LDXxw(xRAX, x4, x1);
             break;
+        case 0xA3:
+            INST_NAME("MOV FS:Od, EAX");
+            grab_segdata(dyn, addr, ninst, x4, seg, 0);
+            if (rex.is32bits)
+                u64 = F32;
+            else
+                u64 = F64;
+            if (u64 < 0x800) {
+                ADDIz(x1, x4, u64);
+            } else {
+                MOV64z(x1, u64);
+                ADDz(x1, x1, x4);
+            }
+            SDxw(xRAX, x1, 0);
+            SMWRITE2();
+            break;
         case 0xC6:
             INST_NAME("MOV Seg:Eb, Ib");
             nextop = F8;
@@ -502,6 +518,19 @@ uintptr_t dynarec64_64(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 SMWRITE2();
             }
             break;
+        case 0xFF:
+            nextop = F8;
+            switch ((nextop >> 3) & 7) {
+                case 6: // Push Ed
+                    INST_NAME("PUSH Ed");
+                    grab_segdata(dyn, addr, ninst, x6, seg, (MODREG));
+                    GETEDOz(x6, 0, x3);
+                    PUSH1z(ed);
+                    break;
+                default:
+                    DEFAULT;
+            }
+            break;
         default:
             DEFAULT;
     }
diff --git a/src/dynarec/la64/dynarec_la64_66.c b/src/dynarec/la64/dynarec_la64_66.c
index 109683d3..cc29e3bc 100644
--- a/src/dynarec/la64/dynarec_la64_66.c
+++ b/src/dynarec/la64/dynarec_la64_66.c
@@ -1026,6 +1026,11 @@ uintptr_t dynarec64_66(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     emit_dec16(dyn, ninst, x1, x2, x4, x5, x6);
                     EWBACK;
                     break;
+                case 6: // Push Ew
+                    INST_NAME("PUSH Ew");
+                    GETEW(x1, 0);
+                    PUSH1_16(ed);
+                    break;
                 default:
                     DEFAULT;
             }
diff --git a/src/dynarec/la64/dynarec_la64_67.c b/src/dynarec/la64/dynarec_la64_67.c
index 908ec378..70cb6536 100644
--- a/src/dynarec/la64/dynarec_la64_67.c
+++ b/src/dynarec/la64/dynarec_la64_67.c
@@ -60,6 +60,47 @@ uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
     }
 
     switch(opcode) {
+        case 0x0F:
+            opcode = F8;
+            switch (opcode) {
+                case 0xB6:
+                    INST_NAME("MOVZX Gd, Eb");
+                    nextop = F8;
+                    GETGD;
+                    if (MODREG) {
+                        ed = (nextop & 7) + (rex.b << 3);
+                        if (rex.rex) {
+                            eb1 = TO_NAT(ed);
+                            eb2 = 0;
+                        } else {
+                            eb1 = TO_NAT(ed & 3);  // Ax, Cx, Dx or Bx
+                            eb2 = ((ed & 4) << 1); // L or H
+                        }
+                        BSTRPICK_D(gd, eb1, eb2 + 7, eb2);
+                    } else {
+                        SMREAD();
+                        addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
+                        LD_BU(gd, ed, fixedaddress);
+                    }
+                    break;
+                case 0xB7:
+                    INST_NAME("MOVZX Gd, Ew");
+                    nextop = F8;
+                    GETGD;
+                    if (MODREG) {
+                        ed = TO_NAT((nextop & 7) + (rex.b << 3));
+                        BSTRPICK_D(gd, ed, 15, 0);
+                    } else {
+                        SMREAD();
+                        addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0);
+                        LD_HU(gd, ed, fixedaddress);
+                    }
+                    break;
+                default:
+                    DEFAULT;
+            }
+            break;
+
         case 0x19:
             INST_NAME("SBB Ed, Gd");
             READFLAGS(X_CF);
@@ -97,6 +138,140 @@ uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             MOV64xw(x2, i64);
             emit_sbb32(dyn, ninst, rex, xRAX, x2, x3, x4, x5);
             break;
+
+        case 0x81:
+        case 0x83:
+            nextop = F8;
+            switch ((nextop >> 3) & 7) {
+                case 0: // ADD
+                    if (opcode == 0x81) {
+                        INST_NAME("ADD Ed, Id");
+                    } else {
+                        INST_NAME("ADD Ed, Ib");
+                    }
+                    SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
+                    GETED32((opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6);
+                    WBACK;
+                    break;
+                case 1: // OR
+                    if (opcode == 0x81) {
+                        INST_NAME("OR Ed, Id");
+                    } else {
+                        INST_NAME("OR Ed, Ib");
+                    }
+                    SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
+                    GETED32((opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
+                    WBACK;
+                    break;
+                case 2: // ADC
+                    if (opcode == 0x81) {
+                        INST_NAME("ADC Ed, Id");
+                    } else {
+                        INST_NAME("ADC Ed, Ib");
+                    }
+                    READFLAGS(X_CF);
+                    SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
+                    GETED32((opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    MOV64xw(x5, i64);
+                    emit_adc32(dyn, ninst, rex, ed, x5, x3, x4, x5, x6);
+                    WBACK;
+                    break;
+                case 3: // SBB
+                    if (opcode == 0x81) {
+                        INST_NAME("SBB Ed, Id");
+                    } else {
+                        INST_NAME("SBB Ed, Ib");
+                    }
+                    READFLAGS(X_CF);
+                    SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
+                    GETED32((opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    MOV64xw(x5, i64);
+                    emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4, x5);
+                    WBACK;
+                    break;
+                case 4: // AND
+                    if (opcode == 0x81) {
+                        INST_NAME("AND Ed, Id");
+                    } else {
+                        INST_NAME("AND Ed, Ib");
+                    }
+                    SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
+                    GETED32((opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    emit_and32c(dyn, ninst, rex, ed, i64, x3, x4);
+                    WBACK;
+                    break;
+                case 5: // SUB
+                    if (opcode == 0x81) {
+                        INST_NAME("SUB Ed, Id");
+                    } else {
+                        INST_NAME("SUB Ed, Ib");
+                    }
+                    SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
+                    GETED32((opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6);
+                    WBACK;
+                    break;
+                case 6: // XOR
+                    if (opcode == 0x81) {
+                        INST_NAME("XOR Ed, Id");
+                    } else {
+                        INST_NAME("XOR Ed, Ib");
+                    }
+                    SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
+                    GETED32((opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    emit_xor32c(dyn, ninst, rex, ed, i64, x3, x4);
+                    WBACK;
+                    break;
+                case 7: // CMP
+                    if (opcode == 0x81) {
+                        INST_NAME("CMP Ed, Id");
+                    } else {
+                        INST_NAME("CMP Ed, Ib");
+                    }
+                    SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION);
+                    GETED32((opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81)
+                        i64 = F32S;
+                    else
+                        i64 = F8S;
+                    if (i64) {
+                        MOV64x(x2, i64);
+                        emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6);
+                    } else
+                        emit_cmp32_0(dyn, ninst, rex, nextop, ed, x3, x4, x5);
+                    break;
+            }
+            break;
         case 0x88:
             INST_NAME("MOV Eb, Gb");
             nextop = F8;
@@ -142,6 +317,18 @@ uintptr_t dynarec64_67(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 SMWRITELOCK(lock);
             }
             break;
+        case 0x8B:
+            INST_NAME("MOV Gd, Ed");
+            nextop = F8;
+            GETGD;
+            if (MODREG) {
+                MVxw(gd, TO_NAT((nextop & 7) + (rex.b << 3)));
+            } else {
+                addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
+                SMREADLOCK(lock);
+                LDxw(gd, ed, fixedaddress);
+            }
+            break;
         case 0x8D:
             INST_NAME("LEA Gd, Ed");
             nextop = F8;
diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h
index 92f271bf..0121004c 100644
--- a/src/dynarec/la64/dynarec_la64_helper.h
+++ b/src/dynarec/la64/dynarec_la64_helper.h
@@ -136,7 +136,18 @@
         }                                                                                           \
         ed = x1;                                                                                    \
     }
-
+// GETEDOz can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI
+#define GETEDOz(O, D, S)                                                                       \
+    if (MODREG) {                                                                              \
+        ed = TO_NAT((nextop & 7) + (rex.b << 3));                                              \
+        wback = 0;                                                                             \
+    } else {                                                                                   \
+        SMREAD();                                                                              \
+        addr = geted(dyn, addr, ninst, nextop, &wback, x2, S, &fixedaddress, rex, NULL, 1, D); \
+        ADDz(S, wback, O);                                                                     \
+        LDz(x1, S, fixedaddress);                                                              \
+        ed = x1;                                                                               \
+    }
 // GETSED can use r1 for ed, and r2 for wback. ed will be sign extended!
 #define GETSED(D)                                                                               \
     if (MODREG) {                                                                               \
diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h
index 44c35e05..466180f7 100644
--- a/src/dynarec/la64/la64_emitter.h
+++ b/src/dynarec/la64/la64_emitter.h
@@ -2528,6 +2528,18 @@ LSX instruction starts with V, LASX instruction starts with XV.
         if (reg != xRSP) ADDI_D(xRSP, xRSP, 4); \
     } while (0);
 
+#define PUSH1_16(reg)           \
+    do {                        \
+        ST_H(reg, xRSP, -2);    \
+        ADDI_D(xRSP, xRSP, -2); \
+    } while (0)
+
+#define POP1_16(reg)                            \
+    do {                                        \
+        LD_HU(reg, xRSP, 0);                    \
+        if (reg != xRSP) ADDI_D(xRSP, xRSP, 2); \
+    } while (0)
+
 // POP reg
 #define POP1z(reg)          \
     do {                    \