about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-10-18 17:18:50 +0200
committerptitSeb <sebastien.chev@gmail.com>2023-10-18 17:18:50 +0200
commit0481589615582cfd7ef737ac90ccb9a9a19f3d41 (patch)
tree3f9f25db6e8cd7d1ed1c228117fd0e3eb3fc6a9b /src
parent6ef2b22a3ce4aaf5df5069dab226c1eeab806b19 (diff)
downloadbox64-0481589615582cfd7ef737ac90ccb9a9a19f3d41.tar.gz
box64-0481589615582cfd7ef737ac90ccb9a9a19f3d41.zip
[ARM64_DYNAREC] More changes to Strong memory model emulation
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_00.c16
-rw-r--r--src/dynarec/arm64/dynarec_arm64_66.c7
-rw-r--r--src/dynarec/arm64/dynarec_arm64_66f0.c8
-rw-r--r--src/dynarec/arm64/dynarec_arm64_f0.c21
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.c2
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h21
-rw-r--r--src/dynarec/arm64/dynarec_arm64_pass0.h2
-rw-r--r--src/dynarec/arm64/dynarec_arm64_private.h1
-rw-r--r--src/dynarec/dynarec_native_pass.c1
-rw-r--r--src/include/debug.h1
-rw-r--r--src/librarian/library.c4
-rw-r--r--src/main.c14
-rw-r--r--src/tools/rcfile.c10
13 files changed, 59 insertions, 49 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c
index 49f0a757..6b2936e2 100644
--- a/src/dynarec/arm64/dynarec_arm64_00.c
+++ b/src/dynarec/arm64/dynarec_arm64_00.c
@@ -1341,7 +1341,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             else
                 u64 = F64;
             MOV64z(x1, u64);
-            SMREAD();
+            if(isLockAddress(u64)) lock=1; else lock = 0;
+            SMREADLOCK(lock);
             LDRB_U12(x2, x1, 0);
             BFIx(xRAX, x2, 0, 8);
             break;
@@ -1352,7 +1353,8 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             else
                 u64 = F64;
             MOV64z(x1, u64);
-            SMREAD();
+            if(isLockAddress(u64)) lock=1; else lock = 0;
+            SMREADLOCK(lock);
             LDRxw_U12(xRAX, x1, 0);
             break;
         case 0xA2:
@@ -1362,8 +1364,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             else
                 u64 = F64;
             MOV64z(x1, u64);
+            if(isLockAddress(u64)) lock=1; else lock = 0;
             STRB_U12(xRAX, x1, 0);
-            SMWRITE();
+            SMWRITELOCK(lock);
             break;
         case 0xA3:
             INST_NAME("MOV Od,EAX");
@@ -1372,8 +1375,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             else
                 u64 = F64;
             MOV64z(x1, u64);
+            if(isLockAddress(u64)) lock=1; else lock = 0;
             STRxw_U12(xRAX, x1, 0);
-            SMWRITE();
+            SMWRITELOCK(lock);
             break;
         case 0xA4:
             if(rep) {
@@ -1993,6 +1997,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     MESSAGE(LOG_DUMP, "Native Call to %s\n", GetNativeName(GetNativeFnc(ip)));
                     x87_forget(dyn, ninst, x3, x4, 0);
                     sse_purge07cache(dyn, ninst, x3);
+                    SMEND();
                     tmp = isSimpleWrapper(*(wrapper_t*)(addr));
                     if(isRetX87Wrapper(*(wrapper_t*)(addr)))
                         // return value will be on the stack, so the stack depth needs to be updated
@@ -2486,6 +2491,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     MESSAGE(LOG_DUMP, "Native Call to %s (retn=%d)\n", GetNativeName(GetNativeFnc(dyn->insts[ninst].natcall-1)), dyn->insts[ninst].retn);
                     SKIPTEST(x1);    // disable test as this hack dos 2 instructions for 1
                     // calling a native function
+                    SMEND();
                     sse_purge07cache(dyn, ninst, x3);
                     if((box64_log<2 && !cycle_log) && dyn->insts[ninst].natcall) {
                         tmp=isSimpleWrapper(*(wrapper_t*)(dyn->insts[ninst].natcall+2));
@@ -2962,7 +2968,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         INST_NAME("JMP FAR Ed");
                         READFLAGS(X_PEND);
                         BARRIER(BARRIER_FLOAT);
-                        SMREAD()
+                        SMREAD();
                         addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0, 0, rex, NULL, 0, 0);
                         LDxw(x1, wback, 0);
                         ed = x1;
diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c
index a87fc84e..b3504b48 100644
--- a/src/dynarec/arm64/dynarec_arm64_66.c
+++ b/src/dynarec/arm64/dynarec_arm64_66.c
@@ -15,6 +15,7 @@
 #include "emu/x64run_private.h"

 #include "x64trace.h"

 #include "dynarec_native.h"

+#include "custommem.h"

 

 #include "arm64_printer.h"

 #include "dynarec_arm64_private.h"

@@ -669,7 +670,8 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             else

                 u64 = F64;

             MOV64z(x1, u64);

-            SMREAD();

+            if(isLockAddress(u64)) lock=1; else lock = 0;

+            SMREADLOCK(lock);

             LDRH_U12(x2, x1, 0);

             BFIx(xRAX, x2, 0, 16);

             break;

@@ -681,8 +683,9 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             else

                 u64 = F64;

             MOV64z(x1, u64);

+            if(isLockAddress(u64)) lock=1; else lock = 0;

             STRH_U12(xRAX, x1, 0);

-            SMWRITE();

+            SMWRITELOCK(lock);

             break;

 

         case 0xA5:

diff --git a/src/dynarec/arm64/dynarec_arm64_66f0.c b/src/dynarec/arm64/dynarec_arm64_66f0.c
index 3e8fb480..5a4cd4b9 100644
--- a/src/dynarec/arm64/dynarec_arm64_66f0.c
+++ b/src/dynarec/arm64/dynarec_arm64_66f0.c
@@ -53,7 +53,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
             SETFLAGS(X_ALL, SF_SET_PENDING);
             nextop = F8;
             GETGW(x5);
-            SMDMB();
             if(MODREG) {
                 ed = xRAX+(nextop&7)+(rex.b<<3);
                 UXTHw(x6, ed);
@@ -142,7 +141,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
                     nextop = F8;
                     gd = xRAX+((nextop&0x38)>>3)+(rex.r<<3);
                     UXTHx(x5, gd);
-                    SMDMB();
                     if(MODREG) {
                         ed = xRAX+(nextop&7)+(rex.b<<3);
                         BFIx(gd, ed, 0, 16);
@@ -165,7 +163,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
                         }
                         BFIx(gd, x1, 0, 16);
                     }
-                    SMDMB();
                     break;
 
                 default:
@@ -178,7 +175,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
             SETFLAGS(X_ALL, SF_SET_PENDING);
             nextop = F8;
             GETGW(x5);
-            SMDMB();
             if(MODREG) {
                 ed = xRAX+(nextop&7)+(rex.b<<3);
                 UXTHw(x6, ed);
@@ -192,12 +188,10 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
                 STLXRH(x3, x1, wback);
                 CBNZx_MARKLOCK(x3);
             }
-            SMDMB();
             break;
         case 0x81:
         case 0x83:
             nextop = F8;
-            SMDMB();
             switch((nextop>>3)&7) {
                 case 0: //ADD
                     if(opcode==0x81) {
@@ -454,7 +448,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
                     case 0: // INC Ew
                         INST_NAME("LOCK INC Ew");
                         SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
-                        SMDMB();
                         if(MODREG) {
                             ed = xRAX+(nextop&7)+(rex.b<<3);
                             UXTHw(x6, ed);
@@ -482,7 +475,6 @@ uintptr_t dynarec64_66F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n
                     case 1: //DEC Ew
                         INST_NAME("LOCK DEC Ew");
                         SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
-                        SMDMB();
                         if(MODREG) {
                             ed = xRAX+(nextop&7)+(rex.b<<3);
                             UXTHw(x6, ed);
diff --git a/src/dynarec/arm64/dynarec_arm64_f0.c b/src/dynarec/arm64/dynarec_arm64_f0.c
index e5a8d097..7e65cc9d 100644
--- a/src/dynarec/arm64/dynarec_arm64_f0.c
+++ b/src/dynarec/arm64/dynarec_arm64_f0.c
@@ -116,7 +116,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             INST_NAME("LOCK OR Eb, Gb");
             SETFLAGS(X_ALL, SF_SET_PENDING);
             nextop = F8;
-            SMDMB();
             GETGB(x2);
             if((nextop&0xC0)==0xC0) {
                 if(rex.rex) {
@@ -151,7 +150,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             SETFLAGS(X_ALL, SF_SET_PENDING);
             nextop = F8;
             GETGD;
-            SMDMB();
             if(MODREG) {
                 ed = xRAX+(nextop&7)+(rex.b<<3);
                 emit_or32(dyn, ninst, rex, ed, gd, x3, x4);
@@ -207,7 +205,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         } else {
                             ANDw_mask(x2, gd, 0, 0b00010);  //mask=0x000000007
                         }
-                        SMDMB();
                         addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
                         ASRxw(x1, gd, 3); // r1 = (gd>>3)
                         ADDx_REG_LSL(x3, wback, x1, 0); //(&ed)+=r1;
@@ -223,7 +220,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         ORRw_REG(ed, ed, x4);
                         STLXRB(x4, ed, wback);
                         CBNZw_MARKLOCK(x4);
-                        SMDMB();
                     }
                     break;
                 case 0xB0:
@@ -391,7 +387,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         } else {
                             ANDw_mask(x2, gd, 0, 0b00010);  //mask=0x000000007
                         }
-                        SMDMB();
                         addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
                         ASRx(x1, gd, 3); // r1 = (gd>>3)
                         ADDx_REG_LSL(x3, wback, x1, 0); //(&ed)+=r1;
@@ -407,7 +402,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         ORRw_REG(ed, ed, x4);
                         STLXRB(x4, ed, wback);
                         CBNZw_MARKLOCK(x4);
-                        SMDMB();
                     }
                     break;
 
@@ -418,7 +412,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                             SETFLAGS(X_ALL, SF_SET_PENDING);
                             nextop = F8;
                             GETGD;
-                            SMDMB();
                             if(MODREG) {
                                 ed = xRAX+(nextop&7)+(rex.b<<3);
                                 MOVxw_REG(x1, ed);
@@ -539,7 +532,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             READFLAGS(X_CF);
             SETFLAGS(X_ALL, SF_SET_PENDING);
             nextop = F8;
-            SMDMB();
             GETGB(x2);
             if((nextop&0xC0)==0xC0) {
                 if(rex.rex) {
@@ -561,7 +553,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 STLXRB(x4, x1, wback);
                 CBNZx_MARKLOCK(x4);
             }
-            SMDMB();
             break;
         case 0x11:
             INST_NAME("LOCK ADC Ed, Gd");
@@ -569,7 +560,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             SETFLAGS(X_ALL, SF_SET_PENDING);
             nextop = F8;
             GETGD;
-            SMDMB();
             if(MODREG) {
                 ed = xRAX+(nextop&7)+(rex.b<<3);
                 emit_adc32(dyn, ninst, rex, ed, gd, x3, x4);
@@ -581,7 +571,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 STLXRxw(x4, x1, wback);
                 CBNZx_MARKLOCK(x4);
             }
-            SMDMB();
             break;
         case 0x21:
             INST_NAME("LOCK AND Ed, Gd");
@@ -616,7 +605,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             SETFLAGS(X_ALL, SF_SET_PENDING);
             nextop = F8;
             GETGD;
-            SMDMB();
             if(MODREG) {
                 ed = xRAX+(nextop&7)+(rex.b<<3);
                 emit_sub32(dyn, ninst, rex, ed, gd, x3, x4);
@@ -645,7 +633,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
 
         case 0x80:
             nextop = F8;
-            SMDMB();
             switch((nextop>>3)&7) {
                 case 0: //ADD
                     INST_NAME("ADD Eb, Ib");
@@ -855,7 +842,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 default:
                     DEFAULT;
             }
-            SMDMB();
             break;
         case 0x81:
         case 0x83:
@@ -1142,7 +1128,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 MOVxw_REG(ed, x1);
             } else {
                 GETGD;
-                SMDMB();
                 addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
                 if(!ALIGNED_ATOMICxw) {
                     TSTx_mask(ed, 1, 0, 1+rex.w);    // mask=3 or 7
@@ -1198,14 +1183,12 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         MVNw_REG(x1, x1);
                         EBBACK;
                     } else {
-                        SMDMB();
                         addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
                         MARKLOCK;
                         LDAXRB(x1, wback);
                         MVNw_REG(x1, x1);
                         STLXRB(x3, x1, wback);
                         CBNZx_MARKLOCK(x3);
-                        SMDMB();
                     }
                     break;
                 default:
@@ -1220,7 +1203,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 0: // INC Eb
                     INST_NAME("LOCK INC Eb");
                     SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
-                    SMDMB();
                     if(MODREG) {
                         GETEB(x1, 0);
                         emit_inc8(dyn, ninst, x1, x2, x4);
@@ -1247,7 +1229,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 1: //DEC Eb
                     INST_NAME("LOCK DEC Eb");
                     SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
-                    SMDMB();
                     if(MODREG) {
                         GETEB(x1, 0);
                         emit_dec8(dyn, ninst, x1, x2, x4);
@@ -1282,7 +1263,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 0: // INC Ed
                     INST_NAME("LOCK INC Ed");
                     SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
-                    SMDMB();
                     if(MODREG) {
                         ed = xRAX+(nextop&7)+(rex.b<<3);
                         emit_inc32(dyn, ninst, rex, ed, x3, x4);
@@ -1324,7 +1304,6 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 case 1: //DEC Ed
                     INST_NAME("LOCK DEC Ed");
                     SETFLAGS(X_ALL&~X_CF, SF_SUBSET_PENDING);
-                    SMDMB();
                     if(MODREG) {
                         ed = xRAX+(nextop&7)+(rex.b<<3);
                         emit_dec32(dyn, ninst, rex, ed, x3, x4);
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c
index 59f6c4f4..c73d566d 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.c
+++ b/src/dynarec/arm64/dynarec_arm64_helper.c
@@ -32,6 +32,8 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
 {
     MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta);
 
+    if(l==LOCK_LOCK) { SMDMB(); }
+
     if(rex.is32bits)
         return geted_32(dyn, addr, ninst, nextop, ed, hint, fixaddress, unscaled, absmax, mask, l, s);
 
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index a5c9170b..be4c5814 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -33,20 +33,23 @@
 #define PKip(a)   *(uint8_t*)(ip+a)
 
 // Strong mem emulation helpers
-// Sequence of Read will trigger a DMB on "first" read if strongmem is 2
-// Sequence of Write will trigger a DMB on "last" write if strongmem is 1
+#define SMREAD_MIN  2
+#define SMWRITE_MIN 1
+// Sequence of Read will trigger a DMB on "first" read if strongmem is >= SMREAD_MIN
+// Sequence of Write will trigger a DMB on "last" write if strongmem is >= 1
+// All Write operation that might use a lock all have a memory barrier if strongmem is >= SMWRITE_MIN
 // Opcode will read
-#define SMREAD()    if((dyn->smread==0) && (box64_dynarec_strongmem>1)) {SMDMB();}
+#define SMREAD()    if((dyn->smread==0) && (box64_dynarec_strongmem>SMREAD_MIN)) {SMDMB();} else dyn->smread=1
 // Opcode will read with option forced lock
-#define SMREADLOCK(lock)    if((lock) || ((dyn->smread==0) && (box64_dynarec_strongmem>1))) {SMDMB();}
+#define SMREADLOCK(lock)    if((lock) || ((dyn->smread==0) && (box64_dynarec_strongmem>SMREAD_MIN))) {SMDMB();}
 // Opcode might read (depend on nextop)
 #define SMMIGHTREAD()   if(!MODREG) {SMREAD();}
 // Opcode has wrote
 #define SMWRITE()   dyn->smwrite=1
 // Opcode has wrote (strongmem>1 only)
-#define SMWRITE2()   if(box64_dynarec_strongmem>1) dyn->smwrite=1
+#define SMWRITE2()   if(box64_dynarec_strongmem>SMREAD_MIN) dyn->smwrite=1
 // Opcode has wrote with option forced lock
-#define SMWRITELOCK(lock)   if(lock) {SMDMB();} else dyn->smwrite=1
+#define SMWRITELOCK(lock)   if(lock || (box64_dynarec_strongmem>SMWRITE_MIN /*&& (!ninst || dyn->smlastdmb!=ninst-1)*/)) {SMDMB();} else dyn->smwrite=1
 // Opcode might have wrote (depend on nextop)
 #define SMMIGHTWRITE()   if(!MODREG) {SMWRITE();}
 // Start of sequence
@@ -54,7 +57,7 @@
 // End of sequence
 #define SMEND()     if(dyn->smwrite && box64_dynarec_strongmem) {DMB_ISH();} dyn->smwrite=0; dyn->smread=0;
 // Force a Data memory barrier (for LOCK: prefix)
-#define SMDMB()     DMB_ISH(); dyn->smwrite=0; dyn->smread=1
+#define SMDMB()     DMB_ISH(); dyn->smwrite=0; dyn->smread=1; dyn->smlastdmb = ninst
 
 //LOCK_* define
 #define LOCK_LOCK   (int*)1
@@ -66,7 +69,7 @@
                     ed = xRAX+(nextop&7)+(rex.b<<3);    \
                     wback = 0;                          \
                 } else {                                \
-                    SMREAD()                            \
+                    SMREAD();                           \
                     addr = geted(dyn, addr, ninst, nextop, &wback, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, NULL, 0, D); \
                     LDxw(x1, wback, fixedaddress);      \
                     ed = x1;                            \
@@ -825,7 +828,7 @@
     } else dyn->f.pending = SF_SET
 #endif
 #ifndef JUMP
-#define JUMP(A, C)
+#define JUMP(A, C) SMEND()
 #endif
 #ifndef BARRIER
 #define BARRIER(A)
diff --git a/src/dynarec/arm64/dynarec_arm64_pass0.h b/src/dynarec/arm64/dynarec_arm64_pass0.h
index 774d13d9..4bfc0acf 100644
--- a/src/dynarec/arm64/dynarec_arm64_pass0.h
+++ b/src/dynarec/arm64/dynarec_arm64_pass0.h
@@ -16,7 +16,7 @@
         dyn->f.pending=(B)&SF_SET_PENDING;      \
         dyn->f.dfnone=((B)&SF_SET)?1:0;
 #define EMIT(A)     
-#define JUMP(A, C)         add_next(dyn, (uintptr_t)A); dyn->insts[ninst].x64.jmp = A; dyn->insts[ninst].x64.jmp_cond = C
+#define JUMP(A, C)         add_next(dyn, (uintptr_t)A); SMEND(); dyn->insts[ninst].x64.jmp = A; dyn->insts[ninst].x64.jmp_cond = C
 #define BARRIER(A)      if(A!=BARRIER_MAYBE) {fpu_purgecache(dyn, ninst, 0, x1, x2, x3); dyn->insts[ninst].x64.barrier = A;} else dyn->insts[ninst].barrier_maybe = 1
 #define BARRIER_NEXT(A) dyn->insts[ninst+1].x64.barrier = A
 #define NEW_INST \
diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h
index acbbe2e8..e73a01f4 100644
--- a/src/dynarec/arm64/dynarec_arm64_private.h
+++ b/src/dynarec/arm64/dynarec_arm64_private.h
@@ -108,6 +108,7 @@ typedef struct dynarec_arm_s {
     size_t              insts_size; // size of the instruction size array (calculated)
     uint8_t             smread;     // for strongmem model emulation
     uint8_t             smwrite;    // for strongmem model emulation
+    uint32_t            smlastdmb;  // for strongmem model 3+
     uintptr_t           forward;    // address of the last end of code while testing forward
     uintptr_t           forward_to; // address of the next jump to (to check if everything is ok)
     int32_t             forward_size;   // size at the forward point
diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c
index 0562fb6b..02166a63 100644
--- a/src/dynarec/dynarec_native_pass.c
+++ b/src/dynarec/dynarec_native_pass.c
@@ -43,6 +43,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
     dyn->forward_to = 0;
     dyn->forward_size = 0;
     dyn->forward_ninst = 0;
+    dyn->smlastdmb = ~0;
     fpu_reset(dyn);
     ARCH_INIT();
     int reset_n = -1;
diff --git a/src/include/debug.h b/src/include/debug.h
index c21ff7ec..a426a19a 100644
--- a/src/include/debug.h
+++ b/src/include/debug.h
@@ -24,6 +24,7 @@ extern int box64_dynarec_safeflags;
 extern int box64_dynarec_callret;
 extern int box64_dynarec_bleeding_edge;
 extern int box64_dynarec_jvm;
+extern int box64_dynarec_tbb;
 extern int box64_dynarec_hotpage;
 extern int box64_dynarec_fastpage;
 extern int box64_dynarec_wait;
diff --git a/src/librarian/library.c b/src/librarian/library.c
index c8438f1b..a64ea596 100644
--- a/src/librarian/library.c
+++ b/src/librarian/library.c
@@ -316,6 +316,10 @@ static int loadEmulatedLib(const char* libname, library_t *lib, box64context_t*
             box64_dynarec_bigblock = 0;
             box64_dynarec_strongmem = 1;
         }
+        if(libname && box64_dynarec_tbb && strstr(libname, "libtbb.so")) {
+            printf_dump(LOG_INFO, "libtbb detected, enable Dynarec StrongMem\n");
+            box64_dynarec_strongmem = 3;
+        }
         #endif
         if(libname && box64_libcef && strstr(libname, "libcef.so")) {
             printf_dump(LOG_INFO, "libcef detected, using malloc_hack_2\n");
diff --git a/src/main.c b/src/main.c
index cdbff19c..8fde0052 100644
--- a/src/main.c
+++ b/src/main.c
@@ -63,6 +63,7 @@ int box64_dynarec_hotpage = 0;
 int box64_dynarec_fastpage = 0;
 int box64_dynarec_bleeding_edge = 1;
 int box64_dynarec_jvm = 1;
+int box64_dynarec_tbb = 1;
 int box64_dynarec_wait = 1;
 int box64_dynarec_test = 0;
 int box64_dynarec_missing = 0;
@@ -537,11 +538,11 @@ void LoadLogEnv()
     p = getenv("BOX64_DYNAREC_STRONGMEM");
     if(p) {
         if(strlen(p)==1) {
-            if(p[0]>='0' && p[0]<='2')
+            if(p[0]>='0' && p[0]<='3')
                 box64_dynarec_strongmem = p[0]-'0';
         }
         if(box64_dynarec_strongmem)
-            printf_log(LOG_INFO, "Dynarec will try to emulate a strong memory model%s\n", (box64_dynarec_strongmem==1)?" with limited performance loss":"");
+            printf_log(LOG_INFO, "Dynarec will try to emulate a strong memory model%s\n", (box64_dynarec_strongmem==1)?" with limited performance loss":((box64_dynarec_strongmem==3)?" with more performance loss":""));
     }
     p = getenv("BOX64_DYNAREC_X87DOUBLE");
     if(p) {
@@ -608,6 +609,15 @@ void LoadLogEnv()
         if(!box64_dynarec_jvm)
             printf_log(LOG_INFO, "Dynarec will not detect libjvm\n");
     }
+    p = getenv("BOX64_DYNAREC_TBB");
+    if(p) {
+        if(strlen(p)==1) {
+            if(p[0]>='0' && p[0]<='1')
+                box64_dynarec_tbb = p[0]-'0';
+        }
+        if(!box64_dynarec_tbb)
+            printf_log(LOG_INFO, "Dynarec will not detect libtbb\n");
+    }
     p = getenv("BOX64_DYNAREC_WAIT");
     if(p) {
         if(strlen(p)==1) {
diff --git a/src/tools/rcfile.c b/src/tools/rcfile.c
index 098d2616..cd6c70a7 100644
--- a/src/tools/rcfile.c
+++ b/src/tools/rcfile.c
@@ -104,6 +104,7 @@ ENTRYBOOL(BOX64_EXIT, want_exit)                        \
 ENTRYBOOL(BOX64_LIBCEF, box64_libcef)                   \
 ENTRYBOOL(BOX64_SDL2_JGUID, box64_sdl2_jguid)           \
 ENTRYINT(BOX64_MALLOC_HACK, box64_malloc_hack, 0, 2, 2) \
+ENTRYSTRING_(BOX64_ENV, new_env)                        \
 
 #ifdef HAVE_TRACE
 #define SUPER2()                                        \
@@ -132,7 +133,7 @@ ENTRYINT(BOX64_DYNAREC_DUMP, box64_dynarec_dump, 0, 2, 2)           \
 ENTRYINT(BOX64_DYNAREC_LOG, box64_dynarec_log, 0, 3, 2)             \
 ENTRYINT(BOX64_DYNAREC_BIGBLOCK, box64_dynarec_bigblock, 0, 3, 2)   \
 ENTRYSTRING_(BOX64_DYNAREC_FORWARD, box64_dynarec_forward)          \
-ENTRYINT(BOX64_DYNAREC_STRONGMEM, box64_dynarec_strongmem, 0, 2, 2) \
+ENTRYINT(BOX64_DYNAREC_STRONGMEM, box64_dynarec_strongmem, 0, 3, 2) \
 ENTRYBOOL(BOX64_DYNAREC_X87DOUBLE, box64_dynarec_x87double)         \
 ENTRYBOOL(BOX64_DYNAREC_FASTNAN, box64_dynarec_fastnan)             \
 ENTRYBOOL(BOX64_DYNAREC_FASTROUND, box64_dynarec_fastround)         \
@@ -140,6 +141,7 @@ ENTRYINT(BOX64_DYNAREC_SAFEFLAGS, box64_dynarec_safeflags, 0, 2, 2) \
 ENTRYBOOL(BOX64_DYNAREC_CALLRET, box64_dynarec_callret)             \
 ENTRYBOOL(BOX64_DYNAREC_BLEEDING_EDGE, box64_dynarec_bleeding_edge) \
 ENTRYBOOL(BOX64_DYNAREC_JVM, box64_dynarec_jvm)                     \
+ENTRYBOOL(BOX64_DYNAREC_TBB, box64_dynarec_tbb)                     \
 ENTRYINT(BOX64_DYNAREC_HOTPAGE, box64_dynarec_hotpage, 0, 255, 8)   \
 ENTRYBOOL(BOX64_DYNAREC_FASTPAGE, box64_dynarec_fastpage)           \
 ENTRYBOOL(BOX64_DYNAREC_ALIGNED_ATOMICS, box64_dynarec_aligned_atomics) \
@@ -163,6 +165,7 @@ IGNORE(BOX64_DYNAREC_SAFEFLAGS)                                     \
 IGNORE(BOX64_DYNAREC_CALLRET)                                       \
 IGNORE(BOX64_DYNAREC_BLEEDING_EDGE)                                 \
 IGNORE(BOX64_DYNAREC_JVM)                                           \
+IGNORE(BOX64_DYNAREC_TBB)                                           \
 IGNORE(BOX64_DYNAREC_HOTPAGE)                                       \
 IGNORE(BOX64_DYNAREC_FASTPAGE)                                      \
 IGNORE(BOX64_DYNAREC_ALIGNED_ATOMICS)                               \
@@ -446,6 +449,7 @@ extern int ftrace_has_pid;
 extern FILE* ftrace;
 extern char* ftrace_name;
 void openFTrace(const char* newtrace);
+void addNewEnvVar(const char* s);
 #ifdef DYNAREC
 void GatherDynarecExtensions();
 #endif
@@ -519,6 +523,10 @@ void ApplyParams(const char* name)
         AppendList(&my_context->box64_emulated_libs, param->emulated_libs, 0);
         printf_log(LOG_INFO, "Applying %s=%s\n", "BOX64_EMULATED_LIBS", param->emulated_libs);
     }
+    if(param->is_new_env_present) {
+        addNewEnvVar(param->new_env);
+        printf_log(LOG_INFO, "Applying %s=%s\n", "BOX64_ENV", param->new_env);
+    }
     if(param->is_bash_present && FileIsX64ELF(param->bash)) {
         if(my_context->bashpath)
             free(my_context->bashpath);