about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorwannacu <wannacu2049@gmail.com>2023-08-15 18:02:23 +0800
committerwannacu <wannacu2049@gmail.com>2023-08-18 18:22:53 +0800
commitb4cd6f27baa7b5087ea81f52de26616c0a1194db (patch)
treef83746e62016219ed39071470a30e1496f46dcf2
parent7f775b7662c888f831995bd0e82daa9689e94635 (diff)
downloadbox64-b4cd6f27baa7b5087ea81f52de26616c0a1194db.tar.gz
box64-b4cd6f27baa7b5087ea81f52de26616c0a1194db.zip
[RV64_DYNAREC] Added 10/11/12/13/14 opcodes
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_0.c49
-rw-r--r--src/dynarec/rv64/dynarec_rv64_66.c37
-rw-r--r--src/dynarec/rv64/dynarec_rv64_66f0.c66
-rw-r--r--src/dynarec/rv64/dynarec_rv64_f0.c98
4 files changed, 248 insertions, 2 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_0.c b/src/dynarec/rv64/dynarec_rv64_00_0.c
index a0ff3746..4971849c 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_0.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_0.c
@@ -167,7 +167,16 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 DEFAULT;
             }
             break;
-
+        case 0x10:
+            INST_NAME("ADC Eb, Gb");
+            READFLAGS(X_CF);
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETEB(x1, 0);
+            GETGB(x2);
+            emit_adc8(dyn, ninst, x1, x2, x4, x5, x3);
+            EBBACK(x5, 0);
+            break;
         case 0x11:
             INST_NAME("ADC Ed, Gd");
             READFLAGS(X_CF);
@@ -178,7 +187,43 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             emit_adc32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6);
             WBACK;
             break;
-
+        case 0x12:
+            INST_NAME("ADC Gb, Eb");
+            READFLAGS(X_CF);
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETEB(x2, 0);
+            GETGB(x1);
+            emit_adc8(dyn, ninst, x1, x2, x4, x3, x5);
+            GBBACK(x5);
+            break;
+        case 0x13:
+            INST_NAME("ADC Gd, Ed");
+            READFLAGS(X_CF);
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETGD;
+            GETED(0);
+            emit_adc32(dyn, ninst, rex, gd, ed, x3, x4, x5, x6);
+            break;
+        case 0x14:
+            INST_NAME("ADC AL, Ib");
+            READFLAGS(X_CF);
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            u8 = F8;
+            ANDI(x1, xRAX, 0xff);
+            emit_adc8c(dyn, ninst, x1, u8, x3, x4, x5, x6);
+            ANDI(xRAX, xRAX, -256);
+            OR(xRAX, xRAX, x1);
+            break;
+        case 0x15:
+            INST_NAME("ADC EAX, Id");
+            READFLAGS(X_CF);
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            i64 = F32S;
+            MOV64xw(x1, i64);
+            emit_adc32(dyn, ninst, rex, xRAX, x1, x3, x4, x5, x6);
+            break;
         case 0x18:
             INST_NAME("SBB Eb, Gb");
             READFLAGS(X_CF);
diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c
index 66a9f1c1..3e11d45f 100644
--- a/src/dynarec/rv64/dynarec_rv64_66.c
+++ b/src/dynarec/rv64/dynarec_rv64_66.c
@@ -117,6 +117,43 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         case 0x0F:
             addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog);
             break;
+        case 0x11:
+            INST_NAME("ADC Ew, Gw");
+            READFLAGS(X_CF);
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETGW(x2);
+            GETEW(x1, 0);
+            emit_adc16(dyn, ninst, x1, x2, x4, x3, x5);
+            EWBACK;
+            break;
+        case 0x13:
+            INST_NAME("ADC Gw, Ew");
+            READFLAGS(X_CF);
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETGW(x1);
+            GETEW(x2, 0);
+            emit_adc16(dyn, ninst, x1, x2, x4, x3, x5);
+            GWBACK;
+            break;
+        case 0x15:
+            INST_NAME("ADC AX, Iw");
+            READFLAGS(X_CF);
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            i16 = F16;
+            SRLI(x6, xMASK, 16);
+            AND(x1, xRAX, x6);
+            MOV32w(x2, i16);
+            emit_adc16(dyn, ninst, x1, x2, x3, x4, x5);
+            if (rv64_zbb) {
+                ANDN(xRAX, xRAX, x6);
+            } else {
+                NOT(x6, x6);
+                AND(xRAX, xRAX, x6);
+            }
+            OR(xRAX, xRAX, x1);
+            break;
         case 0x19:
             INST_NAME("SBB Ew, Gw");
             READFLAGS(X_CF);
diff --git a/src/dynarec/rv64/dynarec_rv64_66f0.c b/src/dynarec/rv64/dynarec_rv64_66f0.c
index 863e535d..84164227 100644
--- a/src/dynarec/rv64/dynarec_rv64_66f0.c
+++ b/src/dynarec/rv64/dynarec_rv64_66f0.c
@@ -8,6 +8,7 @@
 #include "dynarec.h"
 #include "emu/x64emu_private.h"
 #include "emu/x64run_private.h"
+#include "rv64_emitter.h"
 #include "x64run.h"
 #include "x64emu.h"
 #include "box64stack.h"
@@ -48,6 +49,71 @@ uintptr_t dynarec64_66F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
     GETREX();
 
     switch(opcode) {
+        case 0x11:
+            INST_NAME("LOCK ADC Ew, Gw");
+            READFLAGS(X_CF);
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETGW(x1);
+            SMDMB();
+            if(MODREG) {
+                ed = xRAX+(nextop&7)+(rex.b<<3);
+                MOV32w(x6, 0xFFFF);
+                AND(x2, ed, x6);
+                emit_adc16(dyn, ninst, x1, x2, x3, x4, x5);
+                if (rv64_zbb) {
+                    ANDN(ed, ed, x6);
+                } else {
+                    NOT(x6, x6);
+                    AND(ed, ed, x6);
+                }
+                OR(ed, ed, x2);
+            } else {
+                addr = geted(dyn, addr, ninst, nextop, &wback, x2, x3, &fixedaddress, rex, LOCK_LOCK, 0, 0);
+                ANDI(x3, wback, 0b10);
+                MOV32w(x4, 0xffff); // x4 = mask
+                BNEZ_MARK(x3);
+                // lower 16bits
+                MARKLOCK;
+                LR_W(x5, wback, 1, 1);
+                AND(x6, x5, x4);        // x6 = Ed.h[0]
+                SRLIW(x5, x5, 16);
+                SLLIW(x5, x5, 16);      // x5 = clear Ed.h[0]
+                ADDW(x2, x1, x6);       // x2 = Gw + Ew
+                ANDI(x9, xFlags, 1 << F_CF);
+                ADDW(x2, x2, x9);       // x2 = adc
+                AND(x2, x2, x4);
+                OR(x5, x5, x2);
+                SC_W(x2, x5, wback, 1, 1);
+                BNEZ_MARKLOCK(x2);
+                B_MARK3_nocond;
+                MARK;
+                // upper 16bits
+                SLLIW(x3, x4, 16);     // x3 = mask
+                SUBI(wback, wback, 2); // aligning address
+                SLLI(x1, x1, 16);      // x1 = extended Gw
+                MARK2;
+                LR_W(x6, wback, 1, 1); // x6 = Ed
+                AND(x5, x6, x3);       // x5 = Ed.h[1] << 16
+                ADDW(x5,x5, x1);
+                ANDI(x9, xFlags, 1 << F_CF);
+                SLLIW(x9, x9, 16);
+                ADDW(x5, x5, x9);      // x5 = adc << 16
+                AND(x9, x6, x4);       // x9 = Ed.h[0]
+                OR(x5, x5, x9);
+                SC_W(x9, x5, wback, 1, 1);
+                BNEZ_MARK2(x9);
+                IFX(X_ALL|X_PEND) {
+                    SRLIW(x6, x6, 16);
+                    SRLIW(x1, x1, 16);
+                }
+                MARK3;
+                IFX(X_ALL|X_PEND) {
+                    emit_adc16(dyn, ninst, x1, x6, x3, x4, x5);
+                }
+            }
+            SMDMB();
+            break;
         case 0x81:
         case 0x83:
             nextop = F8;
diff --git a/src/dynarec/rv64/dynarec_rv64_f0.c b/src/dynarec/rv64/dynarec_rv64_f0.c
index 348f2905..bb5c78c5 100644
--- a/src/dynarec/rv64/dynarec_rv64_f0.c
+++ b/src/dynarec/rv64/dynarec_rv64_f0.c
@@ -339,6 +339,101 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     DEFAULT;
             }
             break;
+        case 0x10:
+            INST_NAME("LOCK ADC Eb, Gb");
+            READFLAGS(X_CF);
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETGB(x2);
+            SMDMB();
+            if((nextop&0xC0)==0xC0) {
+                if(rex.rex) {
+                    wback = xRAX + (nextop&7) + (rex.b<<3);
+                    wb2 = 0;
+                } else {
+                    wback = (nextop&7);
+                    wb2 = (wback>>2);
+                    wback = xRAX+(wback&3);
+                }
+                SRLIW(x1, wback, wb2*8);
+                ANDI(x1, x1, 0xFF);
+                emit_adc8(dyn, ninst, x1, x2, x3, x4, x5);
+                SLLI(x1, x1, wb2*8);
+                MOV_U12(x3, 0xFF);
+                SLLI(x3, x3, wb2*8);
+                NOT(x3, x3);
+                AND(wback, wback, x3);
+                OR(wback, wback, x1);
+            } else {
+                addr = geted(dyn, addr, ninst, nextop, &wback, x1, x3, &fixedaddress, rex, LOCK_LOCK, 0, 0);
+                ANDI(x3, wback, 0b11);
+                BNEZ_MARK(x3);
+                MARKLOCK;
+                LR_W(x5, wback, 1, 1);
+                ANDI(x4, x5, 0xff); // x4 = Ed.b[0]
+                ANDI(x5, x5, -256); // x5 = clear Ed.b[0]
+                ADDW(x6, x4, x2);
+                ANDI(x9, xFlags, 1 << F_CF);
+                ADDW(x6, x6, x9);   // x6 = adc
+                ANDI(x6, x6, 0xff);
+                OR(x5, x5, x6);
+                SC_W(x9, x5, wback, 1, 1);
+                BNEZ_MARKLOCK(x9);
+                B_MARK3_nocond;
+                MARK;
+                SLLI(x3, x3, 3);
+                MOV_U12(x4, 0xff);
+                ANDI(wback, wback, ~3); // aligning address
+                SLLI(x4, x4, x3);       // x4 = byte mask
+                NOT(x5, x4);            // x5 = ~mask
+                SLL(x2, x2, x3);        // x2 = extented Gb
+                MARK2;
+                LR_W(x6, wback, 1, 1);  // x6 = Ed
+                AND(x9, x6, x4);        // x9 = extended Ed.b[dest]
+                AND(x6, x6, x5);        // x6 = clear Ed.b[dest]
+                ADDW(x5, x9, x2);
+                ANDI(x4, xFlags, 1 << F_CF);
+                SLL(x4, x4, x3);        // extented
+                ADDW(x5, x5, x4);       // x5 = adc
+                OR(x5, x5, x6);
+                SC_W(x4, x5, wback, 1, 1);
+                BNEZ_MARK2(x4);
+                IFX(X_ALL|X_PEND) {
+                    SRLI(x2, x2, x3);  // Gb
+                    SRLI(x4, x9, x3);  // Eb
+                }
+                MARK3;
+                IFX(X_ALL|X_PEND) {
+                    emit_adc8(dyn, ninst, x4, x2, x3, x5, x6);
+                }
+            }
+            SMDMB();
+            break;
+        case 0x11:
+            INST_NAME("LOCK ADC Ed, Gd");
+            READFLAGS(X_CF);
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop = F8;
+            GETGD;
+            SMDMB();
+            if(MODREG) {
+                ed = xRAX+(nextop&7)+(rex.b<<3);
+                emit_adc32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6);
+            } else {
+                addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
+                MARKLOCK;
+                LRxw(x1, wback, 1, 1);
+                ADDxw(x3, x1, gd);
+                ANDI(x4, xFlags, 1 << F_CF);
+                ADDxw(x3, x3, x4);
+                SCxw(x4, x3, wback, 1, 1);
+                BNEZ_MARKLOCK(x4);
+                IFX(X_ALL|X_PEND) {
+                    emit_adc32(dyn, ninst, rex, x1, gd, x3, x4, x5, x6);
+                }
+            }
+            SMDMB();
+            break;
         case 0x21:
             INST_NAME("LOCK AND Ed, Gd");
             SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -381,6 +476,9 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             }
             SMDMB();
             break;
+        case 0x66:
+            return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
+
         case 0x80:
             nextop = F8;
             SMDMB();