about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-10-30 16:39:06 +0100
committerptitSeb <sebastien.chev@gmail.com>2023-10-30 16:39:06 +0100
commit00744bc0e5708bab3bf69b4b8bfa08054629c39a (patch)
tree7f1af92c0e27e3bb46102273a07caad2ba292fa9
parentcb2a623faa78b02b93b402f665030f6b75cdf0a9 (diff)
downloadbox64-00744bc0e5708bab3bf69b4b8bfa08054629c39a.tar.gz
box64-00744bc0e5708bab3bf69b4b8bfa08054629c39a.zip
[ARM64_DYNAREC] Added support for F2 0F 38 F0/F1 CRC32 opcodes
-rw-r--r--src/dynarec/arm64/arm64_emitter.h7
-rw-r--r--src/dynarec/arm64/dynarec_arm64_f20f.c53
2 files changed, 39 insertions, 21 deletions
diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h
index 58eac553..886ecfa0 100644
--- a/src/dynarec/arm64/arm64_emitter.h
+++ b/src/dynarec/arm64/arm64_emitter.h
@@ -2151,5 +2151,12 @@
 #define FRINT64XS(Sd, Sn)           EMIT(FRINTxx_scalar(0b00, 0b11, Sn, Sd))
 #define FRINT64XD(Dd, Dn)           EMIT(FRINTxx_scalar(0b01, 0b11, Dn, Dd))
 
+// CRC32 extension
+#define CRC32C_gen(sf, Rm, sz, Rn, Rd)  ((sf)<<31 | 0b11010110<<21 | (Rm)<<16 | 0b010<<13 | 1<<12 | (sz)<<10 | (Rn)<<5 | (Rd))
+#define CRC32CB(Wd, Wn, Wm)         EMIT(CRC32C_gen(0, Wm, 0b00, Wn, Wd))
+#define CRC32CH(Wd, Wn, Wm)         EMIT(CRC32C_gen(0, Wm, 0b01, Wn, Wd))
+#define CRC32CW(Wd, Wn, Wm)         EMIT(CRC32C_gen(0, Wm, 0b10, Wn, Wd))
+#define CRC32CX(Wd, Wn, Xm)         EMIT(CRC32C_gen(1, Xm, 0b11, Wn, Wd))
+#define CRC32Cxw(Wd, Wn, Rm)        EMIT(CRC32C_gen(rex.w, Rm, 0b10|rex.w, Wn, Wd))
 
 #endif  //__ARM64_EMITTER_H__
diff --git a/src/dynarec/arm64/dynarec_arm64_f20f.c b/src/dynarec/arm64/dynarec_arm64_f20f.c
index 99edd187..7e84e970 100644
--- a/src/dynarec/arm64/dynarec_arm64_f20f.c
+++ b/src/dynarec/arm64/dynarec_arm64_f20f.c
@@ -28,7 +28,7 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
     uint8_t opcode = F8;

     uint8_t nextop;

     uint8_t gd, ed;

-    uint8_t wback;

+    uint8_t wback, wb1, wb2;

     uint8_t u8;

     uint64_t u64, j64;

     int v0, v1;

@@ -159,30 +159,41 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
             switch(opcode) {

 

                 case 0xF0:

-                    INST_NAME("(unsupported) CRC32 Gd, Eb)");

+                    INST_NAME("CRC32 Gd, Eb");

                     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(xRIP);

-                    CALL(native_ud, -1);

-                    LOAD_XEMU_CALL(xRIP);

-                    jump_to_epilog(dyn, 0, xRIP, ninst);

-                    *need_epilog = 0;

-                    *ok = 0;

+                    GETEB(x1, 0);

+                    GETGD;

+                    if(arm64_crc32) {

+                        CRC32CB(gd, gd, ed);

+                    } else {

+                        EORw_REG(gd, gd, ed);

+                        MOV32w(x2, 0x82f63b78);

+                        for(int i=0; i<8; ++i) {

+                            LSRw_IMM((i&1)?gd:x4, (i&1)?x4:gd, 1);

+                            TBZ((i&1)?x4:gd, 0, 4+4);

+                            EORw_REG((i&1)?gd:x4, (i&1)?gd:x4, x2);

+                        }

+                    }

                     break;

                 case 0xF1:

-                    INST_NAME("(unsupported) CRC32 Gd, Ed)");

+                    INST_NAME("CRC32 Gd, Ed");

                     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(xRIP);

-                    CALL(native_ud, -1);

-                    LOAD_XEMU_CALL(xRIP);

-                    jump_to_epilog(dyn, 0, xRIP, ninst);

-                    *need_epilog = 0;

-                    *ok = 0;

+                    GETED(0);

+                    GETGD;

+                    if(arm64_crc32) {

+                        CRC32Cxw(gd, gd, ed);

+                    } else {

+                        MOV32w(x2, 0x82f63b78);

+                        for(int j=0; j<4*(1+rex.w); ++j) {

+                            UBFXxw(x3, ed, 8*j, 8);

+                            EORw_REG(gd, gd, x3);

+                            for(int i=0; i<8; ++i) {

+                                LSRw_IMM((i&1)?gd:x4, (i&1)?x4:gd, 1);

+                                TBZ((i&1)?x4:gd, 0, 4+4);

+                                EORw_REG((i&1)?gd:x4, (i&1)?gd:x4, x2);

+                            }

+                        }

+                    }

                     break;

 

                 default: