about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorYang Liu <numbksco@gmail.com>2024-03-05 02:35:37 +0800
committerGitHub <noreply@github.com>2024-03-04 19:35:37 +0100
commita242a8e2778f8256d3f5d49419fece86ac6435f4 (patch)
treee71fb6842f772d3b8119759d64a863e11bfb6c5f
parentcc86e94cd5636b1b83fde08a6a82842d182684d7 (diff)
downloadbox64-a242a8e2778f8256d3f5d49419fece86ac6435f4.tar.gz
box64-a242a8e2778f8256d3f5d49419fece86ac6435f4.zip
[LA64_DYNAREC] Added more and more opcodes (#1326)
* [LA64_DYNAREC] Added 81/83 /1 OR opcode

* [LA64_DYNAREC] Added F6 /0 /1 TEST opcode

* Added A9 TEST opcode

* Added A8 TEST opcode

* [LA64_DYNAREC] Added 80 /4 AND opcode

* [LA64_DYNAREC] Added 0F 90..9F SETcc opcodes

* [LA64_DYNAREC] Added 84 TEST opcode

* [LA64_DYNAREC] Added 0F 01 XGETBV opcode

* [LA64_DYNAREC] Added E0..E3 opcodes
-rw-r--r--src/dynarec/la64/dynarec_la64_00.c116
-rw-r--r--src/dynarec/la64/dynarec_la64_0f.c67
-rw-r--r--src/dynarec/la64/dynarec_la64_emit_logic.c91
-rw-r--r--src/dynarec/la64/dynarec_la64_emit_tests.c44
-rw-r--r--src/dynarec/la64/dynarec_la64_helper.h10
-rw-r--r--src/dynarec/la64/la64_emitter.h16
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_3.c2
7 files changed, 339 insertions, 7 deletions
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c
index 87c6a989..cdc3d621 100644
--- a/src/dynarec/la64/dynarec_la64_00.c
+++ b/src/dynarec/la64/dynarec_la64_00.c
@@ -291,6 +291,14 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
         case 0x80:
             nextop = F8;
             switch((nextop>>3)&7) {
+                case 4: // AND
+                    INST_NAME("AND Eb, Ib");
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETEB(x1, 1);
+                    u8 = F8;
+                    emit_and8c(dyn, ninst, x1, u8, x2, x4);
+                    EBBACK(x5, 0);
+                    break;
                 case 7: // CMP
                     INST_NAME("CMP Eb, Ib");
                     SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -323,6 +331,14 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     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);
+                    GETED((opcode == 0x81) ? 4 : 1);
+                    if (opcode == 0x81) i64 = F32S; else i64 = F8S;
+                    emit_or32c(dyn, ninst, rex, ed, i64, x3, x4);
+                    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);
@@ -370,6 +386,14 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     DEFAULT;
             }
             break;
+        case 0x84:
+            INST_NAME("TEST Eb, Gb");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            nextop=F8;
+            GETEB(x1, 0);
+            GETGB(x2);
+            emit_test8(dyn, ninst, x1, x2, x3, x4, x5);
+            break;
         case 0x85:
             INST_NAME("TEST Ed, Gd");
             SETFLAGS(X_ALL, SF_SET_PENDING);
@@ -420,6 +444,21 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 }
             }
             break;
+        case 0xA8:
+            INST_NAME("TEST AL, Ib");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            ANDI(x1, xRAX, 0xff);
+            u8 = F8;
+            MOV32w(x2, u8);
+            emit_test8(dyn, ninst, x1, x2, x3, x4, x5);
+            break;
+        case 0xA9:
+            INST_NAME("TEST EAX, Id");
+            SETFLAGS(X_ALL, SF_SET_PENDING);
+            i64 = F32S;
+            MOV64xw(x2, i64);
+            emit_test32(dyn, ninst, rex, xRAX, x2, x3, x4, x5);
+            break;
         case 0xB8:
         case 0xB9:
         case 0xBA:
@@ -594,6 +633,65 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     DEFAULT;
             }
             break;
+        #define GO(Z)                                                                               \
+            BARRIER(BARRIER_MAYBE);                                                                 \
+            JUMP(addr + i8, 1);                                                                     \
+            if (dyn->insts[ninst].x64.jmp_insts == -1 || CHECK_CACHE()) {                           \
+                /* out of the block */                                                              \
+                i32 = dyn->insts[ninst].epilog - (dyn->native_size);                                \
+                if (Z) {                                                                            \
+                    BNE(xRCX, xZR, i32);                                                            \
+                } else {                                                                            \
+                    BEQ(xRCX, xZR, i32);                                                            \
+                }                                                                                   \
+                if (dyn->insts[ninst].x64.jmp_insts == -1) {                                        \
+                    if (!(dyn->insts[ninst].x64.barrier & BARRIER_FLOAT))                           \
+                        fpu_purgecache(dyn, ninst, 1, x1, x2, x3);                                  \
+                    jump_to_next(dyn, addr + i8, 0, ninst, rex.is32bits);                           \
+                } else {                                                                            \
+                    CacheTransform(dyn, ninst, cacheupd, x1, x2, x3);                               \
+                    i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address - (dyn->native_size); \
+                    B(i32);                                                                         \
+                }                                                                                   \
+            } else {                                                                                \
+                /* inside the block */                                                              \
+                i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address - (dyn->native_size);     \
+                if (Z) {                                                                            \
+                    BEQ(xRCX, xZR, i32);                                                            \
+                } else {                                                                            \
+                    BNE(xRCX, xZR, i32);                                                            \
+                };                                                                                  \
+            }
+        case 0xE0:
+            INST_NAME("LOOPNZ");
+            READFLAGS(X_ZF);
+            i8 = F8S;
+            ADDI_D(xRCX, xRCX, -1);
+            ANDI(x1, xFlags, 1 << F_ZF);
+            CBNZ_NEXT(x1);
+            GO(0);
+            break;
+        case 0xE1:
+            INST_NAME("LOOPZ");
+            READFLAGS(X_ZF);
+            i8 = F8S;
+            ADDI_D(xRCX, xRCX, -1);
+            ANDI(x1, xFlags, 1 << F_ZF);
+            CBZ_NEXT(x1);
+            GO(0);
+            break;
+        case 0xE2:
+            INST_NAME("LOOP");
+            i8 = F8S;
+            ADDI_D(xRCX, xRCX, -1);
+            GO(0);
+            break;
+        case 0xE3:
+            INST_NAME("JECXZ");
+            i8 = F8S;
+            GO(1);
+            break;
+        #undef GO
         case 0xE8:
             INST_NAME("CALL Id");
             i32 = F32S;
@@ -743,6 +841,22 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             *need_epilog = 0;
             *ok = 0;
             break;
+        case 0xF6:
+            nextop = F8;
+            switch ((nextop >> 3) & 7) {
+                case 0:
+                case 1:
+                    INST_NAME("TEST Eb, Ib");
+                    SETFLAGS(X_ALL, SF_SET_PENDING);
+                    GETEB(x1, 1);
+                    u8 = F8;
+                    MOV32w(x2, u8);
+                    emit_test8(dyn, ninst, x1, x2, x3, x4, x5);
+                    break;
+                default:
+                    DEFAULT;
+            }
+            break;
         case 0xF7:
             nextop = F8;
             switch ((nextop >> 3) & 7) {
@@ -816,7 +930,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                     GETEDz(0);
                     PUSH1z(ed);
                     break;
-                
+
                 default:
                     DEFAULT;
             }
diff --git a/src/dynarec/la64/dynarec_la64_0f.c b/src/dynarec/la64/dynarec_la64_0f.c
index 9a320619..1560f72a 100644
--- a/src/dynarec/la64/dynarec_la64_0f.c
+++ b/src/dynarec/la64/dynarec_la64_0f.c
@@ -59,6 +59,34 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
     MAYUSE(cacheupd);
 
     switch (opcode) {
+        case 0x01:
+            // TODO:, /0 is SGDT. While 0F 01 D0 is XGETBV, etc...
+            nextop = F8;
+            if(MODREG) {
+                switch(nextop) {
+                    case 0xD0:
+                        INST_NAME("FAKE xgetbv");
+                        nextop = F8;
+                        addr = fakeed(dyn, addr, ninst, nextop);
+                        SETFLAGS(X_ALL, SF_SET); // Hack to set flags in "don't care" state
+                        GETIP(ip);
+                        STORE_XEMU_CALL();
+                        CALL(native_ud, -1);
+                        LOAD_XEMU_CALL();
+                        jump_to_epilog(dyn, 0, xRIP, ninst);
+                        *need_epilog = 0;
+                        *ok = 0;
+                        break;
+                    default:
+                        DEFAULT;
+                }
+            } else {
+                switch((nextop>>3)&7) {
+                    default:
+                        DEFAULT;
+                }
+            }
+            break;
         case 0x05:
             INST_NAME("SYSCALL");
             NOTEST(x1);
@@ -86,7 +114,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             i32_ = F32S;                                                                            \
             BARRIER(BARRIER_MAYBE);                                                                 \
             JUMP(addr + i32_, 1);                                                                   \
-            if (la64_lbt && (opcode - 0x70) >= 0xC) {                                               \
+            if (la64_lbt && (opcode - 0x80) >= 0xC) {                                               \
                 X64_SET_EFLAGS(xFlags, F);                                                          \
                 X64_SETJ(x1, I);                                                                    \
             } else {                                                                                \
@@ -95,7 +123,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             if (dyn->insts[ninst].x64.jmp_insts == -1 || CHECK_CACHE()) {                           \
                 /* out of the block */                                                              \
                 i32 = dyn->insts[ninst].epilog - (dyn->native_size);                                \
-                if (la64_lbt && (opcode - 0x70) >= 0xC)                                             \
+                if (la64_lbt && (opcode - 0x80) >= 0xC)                                             \
                     BEQZ_safe(x1, i32);                                                             \
                 else                                                                                \
                     B##NO##_safe(x1, i32);                                                          \
@@ -111,7 +139,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
             } else {                                                                                \
                 /* inside the block */                                                              \
                 i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address - (dyn->native_size);     \
-                if (la64_lbt && (opcode - 0x70) >= 0xC)                                             \
+                if (la64_lbt && (opcode - 0x80) >= 0xC)                                             \
                     BNEZ_safe(x1, i32);                                                             \
                 else                                                                                \
                     B##YES##_safe(x1, i32);                                                         \
@@ -121,6 +149,39 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
 
         #undef GO
 
+
+        #define GO(GETFLAGS, NO, YES, F, I)                                                          \
+            READFLAGS(F);                                                                            \
+            if (la64_lbt && (opcode - 0x90) >= 0xC) {                                                \
+                X64_SET_EFLAGS(xFlags, F);                                                           \
+                X64_SETJ(x1, I);                                                                     \
+            } else {                                                                                 \
+                GETFLAGS;                                                                            \
+            }                                                                                        \
+            nextop = F8;                                                                             \
+            if (la64_lbt && (opcode - 0x90) >= 0xC)                                                  \
+                SNEZ(x3, x1);                                                                        \
+            else                                                                                     \
+                S##YES(x3, x1);                                                                      \
+            if (MODREG) {                                                                            \
+                if (rex.rex) {                                                                       \
+                    eb1 = TO_LA64((nextop & 7) + (rex.b << 3));                                      \
+                    eb2 = 0;                                                                         \
+                } else {                                                                             \
+                    ed = (nextop & 7);                                                               \
+                    eb2 = (ed >> 2) * 8;                                                             \
+                    eb1 = TO_LA64(ed & 3);                                                           \
+                }                                                                                    \
+                BSTRINS_D(eb1, x3, eb2 + 7, eb2);                                                    \
+            } else {                                                                                 \
+                addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); \
+                ST_B(x3, ed, fixedaddress);                                                          \
+                SMWRITE();                                                                           \
+            }
+
+            GOCOND(0x90, "SET", "Eb");
+        #undef GO
+
         case 0xA2:
             INST_NAME("CPUID");
             NOTEST(x1);
diff --git a/src/dynarec/la64/dynarec_la64_emit_logic.c b/src/dynarec/la64/dynarec_la64_emit_logic.c
index e1580e97..e7c31c72 100644
--- a/src/dynarec/la64/dynarec_la64_emit_logic.c
+++ b/src/dynarec/la64/dynarec_la64_emit_logic.c
@@ -71,6 +71,46 @@ void emit_xor32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
     }
 }
 
+// emit AND8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch
+void emit_and8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4)
+{
+    CLEAR_FLAGS(s3);
+    IFX(X_PEND) {
+        SET_DF(s3, d_and8);
+    } else IFX(X_ALL) {
+        SET_DFNONE();
+    }
+
+
+    IFXA(X_ALL, la64_lbt) {
+        MOV32w(s3, c);
+        X64_AND_B(s1, s3);
+        X64_GET_EFLAGS(s4, X_ALL);
+        OR(xFlags, xFlags, s4);
+    }
+
+    ANDI(s1, s1, c&0xff);
+
+    IFX(X_PEND) {
+        ST_D(s1, xEmu, offsetof(x64emu_t, res));
+    }
+
+    if (la64_lbt) return;
+
+    IFX(X_SF) {
+        SRLI_D(s3, s1, 7);
+        BEQZ(s3, 8);
+        ORI(xFlags, xFlags, 1 << F_SF);
+    }
+    IFX(X_ZF) {
+        BNEZ(s1, 8);
+        ORI(xFlags, xFlags, 1 << F_ZF);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
+
 // emit AND32 instruction, from s1, c, store result in s1 using s3 and s4 as scratch
 void emit_and32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
 {
@@ -113,4 +153,53 @@ void emit_and32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i
     IFX(X_PF) {
         emit_pf(dyn, ninst, s1, s3, s4);
     }
-}
\ No newline at end of file
+}
+
+// emit OR32 instruction, from s1, c, store result in s1 using s3 and s4 as scratch
+void emit_or32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4)
+{
+    CLEAR_FLAGS(s3);
+    IFX(X_PEND) {
+        SET_DF(s4, rex.w ? d_or64 : d_or32);
+    } else IFX(X_ALL) {
+        SET_DFNONE();
+    }
+
+    IFXA(X_ALL, la64_lbt) {
+        MOV64xw(s3, c);
+        if (rex.w) X64_OR_D(s1, s3); else X64_OR_W(s1, s3);
+        X64_GET_EFLAGS(s4, X_ALL);
+        OR(xFlags, xFlags, s4);
+    }
+
+    if (c >= 0 && c <= 4095) {
+        ORI(s1, s1, c);
+    } else {
+        IFXA(X_ALL, la64_lbt) { } else MOV64xw(s3, c);
+        OR(s1, s1, s3);
+    }
+
+    IFX(X_PEND) {
+        SDxw(s1, xEmu, offsetof(x64emu_t, res));
+    }
+
+    if (la64_lbt) return;
+
+    // test sign bit before zeroup.
+    IFX(X_SF) {
+        if (!rex.w) SEXT_W(s1, s1);
+        BGE(s1, xZR, 8);
+        ORI(xFlags, xFlags, 1 << F_SF);
+    }
+    if (!rex.w) {
+        ZEROUP(s1);
+    }
+
+    IFX(X_ZF) {
+        BNEZ(s1, 8);
+        ORI(xFlags, xFlags, 1 << F_ZF);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s1, s3, s4);
+    }
+}
diff --git a/src/dynarec/la64/dynarec_la64_emit_tests.c b/src/dynarec/la64/dynarec_la64_emit_tests.c
index fcb33eb2..20387ed6 100644
--- a/src/dynarec/la64/dynarec_la64_emit_tests.c
+++ b/src/dynarec/la64/dynarec_la64_emit_tests.c
@@ -203,6 +203,50 @@ void emit_cmp32_0(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s3, int
     }
 }
 
+
+// emit TEST8 instruction, from test s1, s2, using s3, s4 and s5 as scratch
+void emit_test8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5)
+{
+    CLEAR_FLAGS(s3);
+    IFX_PENDOR0 {
+        SET_DF(s3, d_tst8);
+    } else {
+        SET_DFNONE();
+    }
+
+    if (la64_lbt) {
+        IFX(X_ALL) {
+            X64_AND_B(s1, s2);
+            X64_GET_EFLAGS(s3, X_ALL);
+            OR(xFlags, xFlags, s3);
+        }
+
+        IFX_PENDOR0 {
+            AND(s3, s1, s2);
+            ST_D(s3, xEmu, offsetof(x64emu_t, res));
+        }
+        return;
+    }
+
+    AND(s3, s1, s2); // res = s1 & s2
+
+    IFX_PENDOR0 {
+        ST_D(s3, xEmu, offsetof(x64emu_t, res));
+    }
+    IFX(X_SF) {
+        SRLI_D(s4, s3, 7);
+        BEQZ(s4, 8);
+        ORI(xFlags, xFlags, 1 << F_SF);
+    }
+    IFX(X_ZF) {
+        BNEZ(s3, 8);
+        ORI(xFlags, xFlags, 1 << F_ZF);
+    }
+    IFX(X_PF) {
+        emit_pf(dyn, ninst, s3, s4, s5);
+    }
+}
+
 // emit TEST32 instruction, from test s1, s2, using s3 and s4 as scratch
 void emit_test32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5)
 {
diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h
index ea2b155f..b8b607eb 100644
--- a/src/dynarec/la64/dynarec_la64_helper.h
+++ b/src/dynarec/la64/dynarec_la64_helper.h
@@ -216,6 +216,10 @@
 #define CBZ_NEXT(reg1)                                                        \
     j64 = (dyn->insts) ? (dyn->insts[ninst].epilog - (dyn->native_size)) : 0; \
     BEQZ(reg1, j64)
+// Branch to NEXT if reg1!=0 (use j64)
+#define CBNZ_NEXT(reg1)                                                       \
+    j64 = (dyn->insts) ? (dyn->insts[ninst].epilog - (dyn->native_size)) : 0; \
+    BNEZ(reg1, j64)
 
 #define IFX(A)      if ((dyn->insts[ninst].x64.gen_flags & (A)))
 #define IFXA(A, B)  if ((dyn->insts[ninst].x64.gen_flags & (A)) && (B))
@@ -436,6 +440,7 @@ void* la64_next(x64emu_t* emu, uintptr_t addr);
 #define emit_cmp32_0        STEPNAME(emit_cmp32_0)
 #define emit_cmp8           STEPNAME(emit_cmp8)
 #define emit_cmp8_0         STEPNAME(emit_cmp8_0)
+#define emit_test8          STEPNAME(emit_test8)
 #define emit_test32         STEPNAME(emit_test32)
 #define emit_test32c        STEPNAME(emit_test32c)
 #define emit_add32          STEPNAME(emit_add32)
@@ -446,7 +451,9 @@ void* la64_next(x64emu_t* emu, uintptr_t addr);
 #define emit_sub32c         STEPNAME(emit_sub32c)
 #define emit_sub8           STEPNAME(emit_sub8)
 #define emit_sub8c          STEPNAME(emit_sub8c)
+#define emit_or32c          STEPNAME(emit_or32c)
 #define emit_xor32          STEPNAME(emit_xor32)
+#define emit_and8c          STEPNAME(emit_and8c)
 #define emit_and32c          STEPNAME(emit_and32c)
 #define emit_shr32c         STEPNAME(emit_shr32c)
 #define emit_sar32c         STEPNAME(emit_sar32c)
@@ -483,6 +490,7 @@ void emit_cmp8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, i
 void emit_cmp32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5, int s6);
 void emit_cmp8_0(dynarec_la64_t* dyn, int ninst, int s1, int s3, int s4);
 void emit_cmp32_0(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4);
+void emit_test8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
 void emit_test32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5);
 void emit_test32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4, int s5);
 void emit_add32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5);
@@ -493,7 +501,9 @@ void emit_sub32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s
 void emit_sub32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s2, int s3, int s4, int s5);
 void emit_sub8(dynarec_la64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5);
 void emit_sub8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s2, int s3, int s4, int s5);
+void emit_or32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4);
 void emit_xor32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4);
+void emit_and8c(dynarec_la64_t* dyn, int ninst, int s1, int32_t c, int s3, int s4);
 void emit_and32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, int s3, int s4);
 void emit_shr32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
 void emit_sar32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4);
diff --git a/src/dynarec/la64/la64_emitter.h b/src/dynarec/la64/la64_emitter.h
index c72178ce..58488586 100644
--- a/src/dynarec/la64/la64_emitter.h
+++ b/src/dynarec/la64/la64_emitter.h
@@ -173,6 +173,22 @@ f24-f31  fs0-fs7   Static registers                Callee
 // GR[rd] = {imm12, GR[rj][51:0]}
 #define LU52I_D(rd, rj, imm12) EMIT(type_2RI12(0b0000001100, imm12, rj, rd))
 
+// GR[rd] = (signed(GR[rj]) < signed(GR[rk])) ? 1 : 0
+#define SLT(rd, rj, rk) EMIT(type_3R(0b100100, rk, rj, rd))
+// GR[rd] = (unsigned(GR[rj]) < unsigned(GR[rk])) ? 1 : 0
+#define SLTU(rd, rj, rk) EMIT(type_3R(0b100101, rk, rj, rd))
+// tmp = SignExtend(si12, GRLEN)
+// GR[rd] = (signed(GR[rj]) < signed(tmp)) ? 1 : 0
+#define SLTI(rd, rj, imm12) EMIT(type_2RI12(0b1000, imm12, rj, rd))
+// tmp = SignExtend(si12, GRLEN)
+// GR[rd] = (unsigned(GR[rj]) < unsigned(tmp)) ? 1 : 0
+#define SLTUI(rd, rj, imm12) EMIT(type_2RI12(0b1001, imm12, rj, rd))
+
+// rd = rs1 == 0
+#define SEQZ(rd, rs1) SLTUI(rd, rs1, 1)
+// rd = rs1 != 0
+#define SNEZ(rd, rs1) SLTU(rd, xZR, rs1)
+
 // GR[rd] = PC + SignExtend({imm20, 2'b0}, GRLEN)
 #define PCADDI(rd, imm20) EMIT(type_1RI20(0b0001100, imm20, rd))
 // GR[rd] = PC + SignExtend({imm20, 12'b0}, GRLEN)
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c
index 6455349d..cdb53bf2 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_3.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_3.c
@@ -1015,8 +1015,6 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
                     GETEB(x1, 0);
                     CALL(idiv8, -1);
                     break;
-                default:
-                    DEFAULT;
             }
             break;
         case 0xF7: