about summary refs log tree commit diff stats
path: root/src/dynarec/rv64/dynarec_rv64_00_2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dynarec/rv64/dynarec_rv64_00_2.c')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_2.c192
1 files changed, 163 insertions, 29 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_2.c b/src/dynarec/rv64/dynarec_rv64_00_2.c
index 6f0ef03e..20333f96 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_2.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_2.c
@@ -1,7 +1,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
-#include <pthread.h>
 #include <errno.h>
 #include <signal.h>
 #include <assert.h>
@@ -26,8 +25,6 @@
 #include "dynarec_rv64_functions.h"
 #include "dynarec_rv64_helper.h"
 
-int isSimpleWrapper(wrapper_t fun);
-
 uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog)
 {
     uint8_t nextop, opcode;
@@ -72,6 +69,15 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     emit_or8c(dyn, ninst, x1, u8, x2, x4, x5);
                     EBBACK(x5, 0);
                     break;
+                case 2: // ADC
+                    INST_NAME("ADC Eb, Ib");
+                    READFLAGS(X_CF);
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETEB(x1, 1);
+                    u8 = F8;
+                    emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5, x6);
+                    EBBACK(x5, 0);
+                    break;
                 case 3: // SBB
                     INST_NAME("SBB Eb, Ib");
                     READFLAGS(X_CF);
@@ -148,7 +154,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     GETED((opcode==0x81)?4:1);
                     if(opcode==0x81) i64 = F32S; else i64 = F8S;
                     MOV64xw(x5, i64);
-                    emit_adc32(dyn, ninst, rex, ed, x5, x3, x4, x6);
+                    emit_adc32(dyn, ninst, rex, ed, x5, x3, x4, x6, x9);
                     WBACK;
                     break;
                 case 3: // SBB
@@ -297,7 +303,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 ANDI(gd, gb1, 0xff);
                 if(eb2) {
                     MOV64x(x1, 0xffffffffffff00ffLL);
-                    ANDI(x1, eb1, x1);
+                    AND(x1, eb1, x1);
                     SLLI(gd, gd, 8);
                     OR(eb1, x1, gd);
                 } else {
@@ -316,7 +322,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             GETGD;
             if(MODREG) {   // reg <= reg
                 MVxw(xRAX+(nextop&7)+(rex.b<<3), gd);
-            } else {                    // mem <= reg
+            } else {       // mem <= reg
                 addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
                 SDxw(gd, ed, fixedaddress);
                 SMWRITELOCK(lock);
@@ -391,15 +397,13 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             INST_NAME("LEA Gd, Ed");
             nextop=F8;
             GETGD;
-            if(MODREG) {   // reg <= reg? that's an invalid operation
+            if(MODREG) { // reg <= reg? that's an invalid operation
                 DEFAULT;
-            } else {                    // mem <= reg
-                addr = geted(dyn, addr, ninst, nextop, &ed, gd, x1, &fixedaddress, rex, NULL, 0, 0);
-                if(gd!=ed) {    // it's sometimes used as a 3 bytes NOP
-                    MV(gd, ed);
-                }
-                if(!rex.w) {
-                    ZEROUP(gd);   //truncate the higher 32bits as asked
+            } else {     // mem <= reg
+                addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 0, 0);
+                MV(gd, ed);
+                if(!rex.w || rex.is32bits) {
+                    ZEROUP(gd); // truncate the higher 32bits as asked
                 }
             }
             break;
@@ -421,17 +425,17 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             INST_NAME("POP Ed");
             nextop = F8;
             if(MODREG) {
-                POP1(xRAX+(nextop&7)+(rex.b<<3));
+                POP1z(xRAX+(nextop&7)+(rex.b<<3));
             } else {
-                POP1(x2); // so this can handle POP [ESP] and maybe some variant too
-                addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0);
+                POP1z(x2); // so this can handle POP [ESP] and maybe some variant too
+                addr = geted(dyn, addr, ninst, nextop, &ed, x3, x1, &fixedaddress, rex, &lock, 1, 0);
                 if(ed==xRSP) {
-                    SD(x2, ed, fixedaddress);
+                    SDz(x2, ed, fixedaddress);
                 } else {
                     // complicated to just allow a segfault that can be recovered correctly
-                    SUB(xRSP, xRSP, 8);
-                    SD(x2, ed, fixedaddress);
-                    ADD(xRSP, xRSP, 8);
+                    ADDIz(xRSP, xRSP, rex.is32bits?-4:-8);
+                    SDz(x2, ed, fixedaddress);
+                    ADDIz(xRSP, xRSP, rex.is32bits?4:8);
                 }
             }
             break;
@@ -473,39 +477,68 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 ZEROUP(xRDX);
             }
             break;
+        case 0x9B:
+            INST_NAME("FWAIT");
+            break;
         case 0x9C:
             INST_NAME("PUSHF");
+            NOTEST(x1);
             READFLAGS(X_ALL);
             FLAGS_ADJUST_TO11(x3, xFlags, x2);
-            PUSH1(x3);
+            PUSH1z(x3);
             break;
         case 0x9D:
             INST_NAME("POPF");
             SETFLAGS(X_ALL, SF_SET);
-            POP1(xFlags);
+            POP1z(xFlags);
             FLAGS_ADJUST_FROM11(xFlags, x2);
             MOV32w(x1, 0x3F7FD7);
             AND(xFlags, xFlags, x1);
             ORI(xFlags, xFlags, 0x2);
             SET_DFNONE();
+            if(box64_wine) {    // should this be done all the time?
+                ANDI(x1, xFlags, 1 << F_TF);
+                CBZ_NEXT(x1);
+                MOV64x(xRIP, addr);
+                STORE_XEMU_CALL();
+                CALL(native_singlestep, -1);
+                ANDI(xFlags, xFlags, ~(1 << F_TF));
+            }
+            break;
+        case 0x9F:
+            INST_NAME("LAHF");
+            READFLAGS(X_CF|X_PF|X_AF|X_ZF|X_SF);
+            ANDI(x1, xFlags, 0xFF);
+            SLLI(x1, x1, 8);
+            MOV64x(x2, 0xffffffffffff00ffLL);
+            AND(xRAX, xRAX, x2);
+            OR(xRAX, xRAX, x1);
+            break;
+        case 0xA0:
+            INST_NAME("MOV AL,Ob");
+            if(rex.is32bits) u64 = F32; else u64 = F64;
+            MOV64z(x1, u64);
+            LBU(x1, x1, 0);
+            ANDI(xRAX, xRAX, ~0xff);
+            OR(xRAX, xRAX, x1);
             break;
         case 0xA1:
             INST_NAME("MOV EAX,Od");
-            u64 = F64;
-            MOV64x(x1, u64);
+            if(rex.is32bits) u64 = F32; else u64 = F64;
+            MOV64z(x1, u64);
             LDxw(xRAX, x1, 0);
             break;
         case 0xA2:
             INST_NAME("MOV Ob,AL");
-            u64 = F64;
-            MOV64x(x1, u64);
+            if(rex.is32bits) u64 = F32; else u64 = F64;
+            MOV64z(x1, u64);
             SB(xRAX, x1, 0);
             SMWRITE();
             break;
         case 0xA3:
             INST_NAME("MOV Od,EAX");
-            u64 = F64;
-            MOV64x(x1, u64);
+            if(rex.is32bits) u64 = F32; else u64 = F64;
+            MOV64z(x1, u64);
             SDxw(xRAX, x1, 0);
             SMWRITE();
             break;
@@ -628,6 +661,31 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
             MOV64xw(x2, i64);
             emit_test32(dyn, ninst, rex, xRAX, x2, x3, x4, x5);
             break;
+        case 0xAA:
+            if(rep) {
+                INST_NAME("REP STOSB");
+                CBZ_NEXT(xRCX);
+                ANDI(x1, xFlags, 1<<F_DF);
+                BNEZ_MARK2(x1);
+                MARK;   // Part with DF==0
+                SB(xRAX, xRDI, 0);
+                ADDI(xRDI, xRDI, 1);
+                ADDI(xRCX, xRCX, -1);
+                BNEZ_MARK(xRCX);
+                B_NEXT_nocond;
+                MARK2;  // Part with DF==1
+                SB(xRAX, xRDI, 0);
+                ADDI(xRDI, xRDI, -1);
+                ADDI(xRCX, xRCX, -1);
+                BNEZ_MARK2(xRCX);
+                // done
+            } else {
+                INST_NAME("STOSB");
+                GETDIR(x3, x1, 1);
+                SB(xRAX, xRDI, 0);
+                ADD(xRDI, xRDI, x3);
+            }
+            break;
         case 0xAB:
             if(rep) {
                 INST_NAME("REP STOSD");
@@ -653,6 +711,82 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                 ADD(xRDI, xRDI, x3);
             }
             break;
+        case 0xAE:
+            switch (rep) {
+            case 1:
+            case 2:
+                if (rep==1) {INST_NAME("REPNZ SCASB");} else {INST_NAME("REPZ SCASB");}
+                MAYSETFLAGS();
+                SETFLAGS(X_ALL, SF_SET_PENDING);
+                CBZ_NEXT(xRCX);
+                ANDI(x1, xRAX, 0xff);
+                ANDI(x2, xFlags, 1<<F_DF);
+                BNEZ_MARK2(x2);
+                MARK;   // Part with DF==0
+                LBU(x2, xRDI, 0);
+                ADDI(xRDI, xRDI, 1);
+                SUBI(xRCX, xRCX, 1);
+                if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);}
+                BNE_MARK(xRCX, xZR);
+                B_MARK3_nocond;
+                MARK2;  // Part with DF==1
+                LBU(x2, xRDI, 0);
+                SUBI(xRDI, xRDI, 1);
+                SUBI(xRCX, xRCX, 1);
+                if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);}
+                BNE_MARK2(xRCX, xZR);
+                MARK3; // end
+                emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6);
+                break;
+            default:
+                INST_NAME("SCASB");
+                SETFLAGS(X_ALL, SF_SET_PENDING);
+                GETDIR(x3, x1, 1);
+                ANDI(x1, xRAX, 0xff);
+                LBU(x2, xRDI, 0);
+                ADD(xRDI, xRDI, x3);
+                emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6);
+                break;
+            }
+            break;
+        case 0xAF:
+            switch (rep) {
+            case 1:
+            case 2:
+                if (rep==1) {INST_NAME("REPNZ SCASD");} else {INST_NAME("REPZ SCASD");}
+                MAYSETFLAGS();
+                SETFLAGS(X_ALL, SF_SET_PENDING);
+                CBZ_NEXT(xRCX);
+                if (rex.w) {MV(x1, xRAX);} else {AND(x1, xRAX, xMASK);}
+                ANDI(x2, xFlags, 1<<F_DF);
+                BNEZ_MARK2(x2);
+                MARK;   // Part with DF==0
+                LDxw(x2, xRDI, 0);
+                ADDI(xRDI, xRDI, rex.w?8:4);
+                SUBI(xRCX, xRCX, 1);
+                if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);}
+                BNE_MARK(xRCX, xZR);
+                B_MARK3_nocond;
+                MARK2;  // Part with DF==1
+                LDxw(x2, xRDI, 0);
+                SUBI(xRDI, xRDI, rex.w?8:4);
+                SUBI(xRCX, xRCX, 1);
+                if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);}
+                BNE_MARK2(xRCX, xZR);
+                MARK3; // end
+                emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5, x6);
+                break;
+            default:
+                INST_NAME("SCASD");
+                SETFLAGS(X_ALL, SF_SET_PENDING);
+                GETDIR(x3, x1, rex.w?8:4);
+                AND(x1, xRAX, xMASK);
+                LDxw(x2, xRDI, 0);
+                ADD(xRDI, xRDI, x3);
+                emit_cmp32(dyn, ninst, rex, x1, x2, x3, x4, x5, x6);
+                break;
+            }
+            break;
         case 0xB0:
         case 0xB1:
         case 0xB2: