about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorxctan <xctan@cirno.icu>2023-06-02 14:19:45 +0800
committerGitHub <noreply@github.com>2023-06-02 08:19:45 +0200
commit5e19c8f142a11bca2613c1e54004bb848e08ac6a (patch)
tree832c79ff66d28e5b8c36a128fea80a47c2434d13 /src
parenta6737720f4abca8794fffbff1ba0dfbd9ef9b22b (diff)
downloadbox64-5e19c8f142a11bca2613c1e54004bb848e08ac6a.tar.gz
box64-5e19c8f142a11bca2613c1e54004bb848e08ac6a.zip
[RV64_DYNAREC] Added more opcodes for ICEY (#816)
* [RV64_DYNAREC] Added 66 AF SCASW opcode

* [RV64_DYNAREC] Added DD /7 FNSTSW opcode

* [RV64_DYNAREC] Added {D0,D2} /0 ROL opcode

* [RV64_DYNAREC] Added {D0,D2} /{4,6} SHL opcode
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_3.c35
-rw-r--r--src/dynarec/rv64/dynarec_rv64_66.c48
-rw-r--r--src/dynarec/rv64/dynarec_rv64_dd.c17
3 files changed, 100 insertions, 0 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c
index 00de07fe..9d6fa74e 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_3.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_3.c
@@ -358,6 +358,24 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
         case 0xD2:  // TODO: Jump if CL is 0
             nextop = F8;
             switch((nextop>>3)&7) {
+                case 0:
+                    if(opcode==0xD0) {
+                        INST_NAME("ROL Eb, 1");
+                        MOV32w(x2, 1);
+                    } else {
+                        INST_NAME("ROL Eb, CL");
+                        ANDI(x2, xRCX, 7);
+                    }
+                    SETFLAGS(X_OF|X_CF, SF_PENDING);
+                    GETEB(x1, 0);
+                    UFLAG_OP12(ed, x2);
+                    SLL(x3, ed, x2);
+                    SRLI(x4, x3, 8);
+                    OR(ed, x3, x4);
+                    EBBACK(x5, 1);
+                    UFLAG_RES(ed);
+                    UFLAG_DF(x3, d_rol8);
+                    break;
                 case 1:
                     if(opcode==0xD0) {
                         INST_NAME("ROR Eb, 1");
@@ -377,6 +395,23 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     UFLAG_RES(ed);
                     UFLAG_DF(x3, d_ror8);
                     break;
+                case 4:
+                case 6:
+                    if(opcode==0xD0) {
+                        INST_NAME("SHL Eb, 1");
+                        MOV32w(x2, 1);
+                    } else {
+                        INST_NAME("SHL Eb, CL");
+                        ANDI(x2, xRCX, 7);
+                    }
+                    SETFLAGS(X_ALL, SF_PENDING);
+                    GETEB(x1, 0);
+                    UFLAG_OP12(ed, x2)
+                    SLL(ed, ed, x2);
+                    EBBACK(x5, 1);
+                    UFLAG_RES(ed);
+                    UFLAG_DF(x3, d_shl8);
+                    break;
                 case 5:
                     if(opcode==0xD0) {
                         INST_NAME("SHR Eb, 1");
diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c
index 36359a20..ddf79b51 100644
--- a/src/dynarec/rv64/dynarec_rv64_66.c
+++ b/src/dynarec/rv64/dynarec_rv64_66.c
@@ -538,6 +538,54 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 ADD(xRDI, xRDI, x3);
             }
             break;
+
+        case 0xAF:
+            switch (rep) {
+                case 1:
+                case 2:
+                    if(rep==1) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");}
+                    MAYSETFLAGS();
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    CBZ_NEXT(xRCX);
+                    GETDIR(x3, x1, rex.w?8:2);
+                    if (rex.w) {
+                        MARK;
+                        LD(x2, xRDI, 0);
+                        ADD(xRDI, xRDI, x3);
+                        ADDI(xRCX, xRCX, -1);
+                        if (rep==1) {BEQ_MARK3(xRAX, x2);} else {BNE_MARK3(xRAX, x2);}
+                        BNE_MARK(xRCX, xZR);
+                        MARK3;
+                        emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5, x6);
+                    } else {
+                        ZEXTH(x1, xRAX);
+                        MARK;
+                        LHU(x2, xRDI, 0);
+                        ADD(xRDI, xRDI, x3);
+                        ADDI(xRCX, xRCX, -1);
+                        if (rep==1) {BEQ_MARK3(x1, x2);} else {BNE_MARK3(x1, x2);}
+                        BNE_MARK(xRCX, xZR);
+                        MARK3;
+                        emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
+                    }
+                    break;
+                default:
+                    INST_NAME("SCASW");
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETDIR(x3, x1, rex.w?8:2);
+                    if (rex.w) {
+                        LD(x2, xRDI, 0);
+                        emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5, x6);
+                    } else {
+                        ZEXTH(x1, xRAX);
+                        LHU(x2, xRDI, 0);
+                        emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6);
+                    }
+                    ADD(xRDI, xRDI, x3);
+                    break;
+            }
+            break;
+
         case 0xB8:
         case 0xB9:
         case 0xBA:
diff --git a/src/dynarec/rv64/dynarec_rv64_dd.c b/src/dynarec/rv64/dynarec_rv64_dd.c
index fa1a6a13..c6151196 100644
--- a/src/dynarec/rv64/dynarec_rv64_dd.c
+++ b/src/dynarec/rv64/dynarec_rv64_dd.c
@@ -155,6 +155,23 @@ uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     FSD(v1, wback, fixedaddress);
                     x87_do_pop(dyn, ninst, x3);
                     break;
+                case 7:
+                    INST_NAME("FNSTSW m2byte");
+                    fpu_purgecache(dyn, ninst, 0, x1, x2, x3);
+                    addr = geted(dyn, addr, ninst, nextop, &ed, x4, x6, &fixedaddress, rex, NULL, 0, 0);
+                    LWU(x2, xEmu, offsetof(x64emu_t, top));
+                    LHU(x3, xEmu, offsetof(x64emu_t, sw));
+                    if(dyn->e.x87stack) {
+                        // update top
+                        ADDI(x2, x2, -dyn->e.x87stack);
+                        ANDI(x2, x2, 7);
+                    }
+                    MOV32w(x5, ~0x3800);
+                    AND(x3, x3, x5);    // mask out TOP
+                    SLLI(x2, x2, 11);   // shift TOP to bit 11
+                    OR(x3, x3, x2);     // inject TOP
+                    SH(x3, ed, fixedaddress);   // store whole sw flags
+                    break;
                 default:
                     DEFAULT;
             }