about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/rv64/dynarec_rv64_00_3.c52
-rw-r--r--src/dynarec/rv64/dynarec_rv64_0f.c8
-rw-r--r--src/dynarec/rv64/dynarec_rv64_67.c57
-rw-r--r--src/dynarec/rv64/rv64_emitter.h1
4 files changed, 113 insertions, 5 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c
index 2be53fc8..dece35af 100644
--- a/src/dynarec/rv64/dynarec_rv64_00_3.c
+++ b/src/dynarec/rv64/dynarec_rv64_00_3.c
@@ -621,6 +621,58 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int
         case 0xDF:
             addr = dynarec64_DF(dyn, addr, ip, ninst, rex, rep, ok, need_epilog);
             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);               \
+                } 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;
+            SUBI(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;
+            SUBI(xRCX, xRCX, 1);
+            ANDI(x1, xFlags, 1 << F_ZF);
+            CBZ_NEXT(x1);
+            GO(0);
+            break;
+        case 0xE2:
+            INST_NAME("LOOP");
+            i8 = F8S;
+            SUBI(xRCX, xRCX, 1);
+            GO(0);
+            break;
+        case 0xE3:
+            INST_NAME("JECXZ");
+            i8 = F8S;
+            GO(1);
+            break;
+        #undef GO
 
         case 0xE8:
             INST_NAME("CALL Id");
diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c
index 10c3e63d..199068cf 100644
--- a/src/dynarec/rv64/dynarec_rv64_0f.c
+++ b/src/dynarec/rv64/dynarec_rv64_0f.c
@@ -334,7 +334,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                         }
                     } else {
                         if (rex.w) {
-                            LI(x2, 0xff);
+                            MOV_U12(x2, 0xff);
                             SLLI(x1, gd, 56);
                             SRLI(x3, gd, 56);
                             SRLI(x4, gd, 40);
@@ -365,7 +365,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                             AND(x3, x3, x4);
                             OR(gd, x1, x3);
                         } else {
-                            LI(x2, 0xff);
+                            MOV_U12(x2, 0xff);
                             SLLIW(x2, x2, 8);
                             SLLIW(x1, gd, 24);
                             SRLIW(x3, gd, 24);
@@ -393,7 +393,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                         }
                     } else {
                         if (rex.w) {
-                            LI(x2, 0xff);
+                            MOV_U12(x2, 0xff);
                             SLLI(x1, gd, 56);
                             SRLI(x3, gd, 56);
                             SRLI(x4, gd, 40);
@@ -424,7 +424,7 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                             AND(x3, x3, x4);
                             OR(x1, x1, x3);
                         } else {
-                            LI(x2, 0xff);
+                            MOV_U12(x2, 0xff);
                             SLLIW(x2, x2, 8);
                             SLLIW(x1, gd, 24);
                             SRLIW(x3, gd, 24);
diff --git a/src/dynarec/rv64/dynarec_rv64_67.c b/src/dynarec/rv64/dynarec_rv64_67.c
index cb7702a8..5f102742 100644
--- a/src/dynarec/rv64/dynarec_rv64_67.c
+++ b/src/dynarec/rv64/dynarec_rv64_67.c
@@ -567,6 +567,63 @@ uintptr_t dynarec64_67(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
                 }
             }
             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(x1, xZR, i32);} else {BEQ(x1, 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);               \
+                } 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(x1, xZR, i32);} else {BNE(x1, xZR, i32);};   \
+            }
+        case 0xE0:
+            INST_NAME("LOOPNZ (32bits)");
+            READFLAGS(X_ZF);
+            i8 = F8S;
+            SUBI(xRCX, xRCX, 1);
+            ANDI(x1, xFlags, 1 << F_ZF);
+            CBNZ_NEXT(x1);
+            AND(x1, xRCX, xMASK);
+            GO(0);
+            break;
+        case 0xE1:
+            INST_NAME("LOOPZ (32bits)");
+            READFLAGS(X_ZF);
+            i8 = F8S;
+            SUBI(xRCX, xRCX, 1);
+            ANDI(x1, xFlags, 1 << F_ZF);
+            CBZ_NEXT(x1);
+            AND(x1, xRCX, xMASK);
+            GO(0);
+            break;
+        case 0xE2:
+            INST_NAME("LOOP (32bits)");
+            i8 = F8S;
+            SUBI(xRCX, xRCX, 1);
+            AND(x1, xRCX, xMASK);
+            GO(0);
+            break;
+        case 0xE3:
+            INST_NAME("JECXZ (32bits)");
+            i8 = F8S;
+            AND(x1, xRCX, xMASK);
+            GO(1);
+            break;
+        #undef GO
+
         default:
             DEFAULT;
     }
diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h
index 6a5dd4bd..f23c6716 100644
--- a/src/dynarec/rv64/rv64_emitter.h
+++ b/src/dynarec/rv64/rv64_emitter.h
@@ -129,7 +129,6 @@ f28–31  ft8–11  FP temporaries                  Caller
 // put imm20 in the [31:12] bits of rd, zero [11:0] and sign extend bits31
 #define LUI(rd, imm20)                 EMIT(U_type((imm20)<<12, rd, 0b0110111))
 
-#define LI(rd, imm12)                  if (imm12 < 0x800) { ADDI(rd, xZR, imm12);} else {LUI(rd, 1); ADDIW(rd, rd, -(0x1000 - imm12));}
 // put PC+imm20 in rd
 #define AUIPC(rd, imm20)               EMIT(U_type((imm20)<<12, rd, 0b0010111))