about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2024-02-03 18:03:26 +0100
committerptitSeb <sebastien.chev@gmail.com>2024-02-03 18:03:26 +0100
commit3fa527b45ba5945b1c8596621c96986e534e4888 (patch)
treec88e7917500b0fb1ea6aca5bdba41c16935349ed /src
parent121d986b1114990ae69a6834cea6979200e0c39b (diff)
downloadbox64-3fa527b45ba5945b1c8596621c96986e534e4888.tar.gz
box64-3fa527b45ba5945b1c8596621c96986e534e4888.zip
[ARM64_DYNAREC] Reworked STRONGMEM 2 & 3
Diffstat (limited to 'src')
-rw-r--r--src/dynarec/arm64/dynarec_arm64_00.c40
-rw-r--r--src/dynarec/arm64/dynarec_arm64_66.c12
-rw-r--r--src/dynarec/arm64/dynarec_arm64_67.c4
-rw-r--r--src/dynarec/arm64/dynarec_arm64_functions.c4
-rw-r--r--src/dynarec/arm64/dynarec_arm64_helper.h41
-rw-r--r--src/dynarec/arm64/dynarec_arm64_private.h7
6 files changed, 89 insertions, 19 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c
index 78ed6bd3..a269e5cf 100644
--- a/src/dynarec/arm64/dynarec_arm64_00.c
+++ b/src/dynarec/arm64/dynarec_arm64_00.c
@@ -244,6 +244,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 INST_NAME("PUSH SS");
                 LDRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_SS]));
                 PUSH1_32(x1);
+                SMWRITE();
             } else {
                 DEFAULT;
             }
@@ -251,6 +252,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0x17:
             if(rex.is32bits) {
                 INST_NAME("POP SS");
+                SMREAD();
                 POP1_32(x1);
                 STRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_SS]));
                 STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_SS]));
@@ -319,6 +321,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 INST_NAME("PUSH DS");
                 LDRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_DS]));
                 PUSH1_32(x1);
+                SMWRITE();
             } else {
                 DEFAULT;
             }
@@ -326,6 +329,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0x1F:
             if(rex.is32bits) {
                 INST_NAME("POP DS");
+                SMREAD();
                 POP1_32(x1);
                 STRH_U12(x1, xEmu, offsetof(x64emu_t, segs[_DS]));
                 STRw_U12(xZR, xEmu, offsetof(x64emu_t, segs_serial[_DS]));
@@ -632,6 +636,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 SKIPTEST(x1);
                 dyn->doublepush = 0;
             } else {
+                WILLWRITE();
                 gd = xRAX+(opcode&0x07)+(rex.b<<3);
                 u32 = PK(0);
                 i32 = 1;
@@ -660,6 +665,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         PUSH1z(gd);
                     }
                 }
+                SMWRITE();
             }
             break;
         case 0x58:
@@ -675,6 +681,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 SKIPTEST(x1);
                 dyn->doublepop = 0;
             } else {
+                SMREAD();
                 gd = xRAX+(opcode&0x07)+(rex.b<<3);
                 u32 = PK(0);
                 i32 = 1;
@@ -713,11 +720,13 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0x60:
             if(rex.is32bits) {
                 INST_NAME("PUSHAD");
+                WILLWRITE();
                 MOVw_REG(x1, xRSP);
                 PUSH2_32(xRAX, xRCX);
                 PUSH2_32(xRDX, xRBX);
                 PUSH2_32(x1, xRBP);
                 PUSH2_32(xRSI, xRDI);
+                SMWRITE();
             } else {
                 DEFAULT;
             }
@@ -725,6 +734,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0x61:
             if(rex.is32bits) {
                 INST_NAME("POPAD");
+                SMREAD();
                 POP2_32(xRDI, xRSI);
                 POP2_32(xRBP, x1);
                 POP2_32(xRBX, xRDX);
@@ -794,8 +804,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 LDRSW_U12(x1, x3, 0);
                 PUSH1z(x1);
             } else {
+                WILLWRITE();
                 MOV64z(x3, i64);
                 PUSH1z(x3);
+                SMWRITE();
             }
             break;
         case 0x69:
@@ -835,7 +847,9 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             INST_NAME("PUSH Ib");
             i64 = F8S;
             MOV64z(x3, i64);
+            WILLWRITE();
             PUSH1z(x3);
+            SMWRITE();
             break;
         case 0x6B:
             INST_NAME("IMUL Gd, Ed, Ib");
@@ -870,7 +884,6 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 }
             }
             break;
-
         case 0x6C:
         case 0x6D:
             INST_NAME(opcode == 0x6C ? "INSB" : "INSD");
@@ -1212,6 +1225,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 BFIx(eb1, gd, eb2*8, 8);
             } else {
                 addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff, 0, rex, &lock, 0, 0);
+                WILLWRITELOCK(lock);
                 STB(gd, ed, fixedaddress);
                 SMWRITELOCK(lock);
             }
@@ -1224,6 +1238,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);
             } else {                    // mem <= reg
                 addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);
+                WILLWRITELOCK(lock);
                 STxw(gd, ed, fixedaddress);
                 SMWRITELOCK(lock);
             }
@@ -1321,6 +1336,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0x8F:
             INST_NAME("POP Ed");
             nextop = F8;
+            SMREAD();
             if(MODREG) {
                 POP1z(xRAX+(nextop&7)+(rex.b<<3));
             } else {
@@ -1375,10 +1391,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             INST_NAME("PUSHF");
             READFLAGS(X_ALL);
             PUSH1z(xFlags);
+            SMWRITE();
             break;
         case 0x9D:
             INST_NAME("POPF");
             SETFLAGS(X_ALL, SF_SET);
+            SMREAD();
             POP1z(xFlags);
             MOV32w(x1, 0x3F7FD7);
             ANDw_REG(xFlags, xFlags, x1);
@@ -1436,6 +1454,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 u64 = F64;
             MOV64z(x1, u64);
             if(isLockAddress(u64)) lock=1; else lock = 0;
+            WILLWRITELOCK(lock);
             STRB_U12(xRAX, x1, 0);
             SMWRITELOCK(lock);
             break;
@@ -1447,6 +1466,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 u64 = F64;
             MOV64z(x1, u64);
             if(isLockAddress(u64)) lock=1; else lock = 0;
+            WILLWRITELOCK(lock);
             STRxw_U12(xRAX, x1, 0);
             SMWRITELOCK(lock);
             break;
@@ -1512,6 +1532,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             case 2:
                 if(rep==1) {INST_NAME("REPNZ CMPSB");} else {INST_NAME("REPZ CMPSB");}
                 MAYSETFLAGS();
+                SMREAD();
                 SETFLAGS(X_ALL, SF_SET_PENDING);
                 CBZx_NEXT(xRCX);
                 TBNZ_MARK2(xFlags, F_DF);
@@ -1537,6 +1558,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 INST_NAME("CMPSB");
                 SETFLAGS(X_ALL, SF_SET_PENDING);
                 GETDIR(x3, 1);
+                SMREAD();
                 LDRB_U12(x1, xRSI, 0);
                 LDRB_U12(x2, xRDI, 0);
                 ADDx_REG(xRSI, xRSI, x3);
@@ -1552,6 +1574,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 if(rep==1) {INST_NAME("REPNZ CMPSD");} else {INST_NAME("REPZ CMPSD");}
                 MAYSETFLAGS();
                 SETFLAGS(X_ALL, SF_SET_PENDING);
+                SMREAD();
                 CBZx_NEXT(xRCX);
                 TBNZ_MARK2(xFlags, F_DF);
                 MARK;   // Part with DF==0
@@ -1576,6 +1599,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 INST_NAME("CMPSD");
                 SETFLAGS(X_ALL, SF_SET_PENDING);
                 GETDIR(x3, rex.w?8:4);
+                SMREAD();
                 LDRxw_U12(x1, xRSI, 0);
                 LDRxw_U12(x2, xRDI, 0);
                 ADDx_REG(xRSI, xRSI, x3);
@@ -1600,6 +1624,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             emit_test32(dyn, ninst, rex, xRAX, x2, x3, x4, x5);
             break;
         case 0xAA:
+            WILLWRITE();
             if(rep) {
                 INST_NAME("REP STOSB");
                 CBZx_NEXT(xRCX);
@@ -1608,11 +1633,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 STRB_S9_postindex(xRAX, xRDI, 1);
                 SUBx_U12(xRCX, xRCX, 1);
                 CBNZx_MARK(xRCX);
-                B_NEXT_nocond;
+                B_MARK3_nocond;
                 MARK2;  // Part with DF==1
                 STRB_S9_postindex(xRAX, xRDI, -1);
                 SUBx_U12(xRCX, xRCX, 1);
                 CBNZx_MARK2(xRCX);
+                MARK3;
                 // done
             } else {
                 INST_NAME("STOSB");
@@ -1623,6 +1649,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             SMWRITE();
             break;
         case 0xAB:
+            WILLWRITE();
             if(rep) {
                 INST_NAME("REP STOSD");
                 CBZx_NEXT(xRCX);
@@ -1631,11 +1658,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 STRxw_S9_postindex(xRAX, xRDI, rex.w?8:4);
                 SUBx_U12(xRCX, xRCX, 1);
                 CBNZx_MARK(xRCX);
-                B_NEXT_nocond;
+                B_MARK3_nocond;
                 MARK2;  // Part with DF==1
                 STRxw_S9_postindex(xRAX, xRDI, rex.w?-8:-4);
                 SUBx_U12(xRCX, xRCX, 1);
                 CBNZx_MARK2(xRCX);
+                MARK3;
                 // done
             } else {
                 INST_NAME("STOSD");
@@ -1652,6 +1680,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 INST_NAME("LODSB");
             }
             GETDIR(x1, 1);
+            SMREAD();
             if(rep) {
                 CBZx_NEXT(xRCX);
                 MARK;
@@ -1688,6 +1717,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             case 2:
                 if(rep==1) {INST_NAME("REPNZ SCASB");} else {INST_NAME("REPZ SCASB");}
                 MAYSETFLAGS();
+                SMREAD();
                 SETFLAGS(X_ALL, SF_SET_PENDING);
                 CBZx_NEXT(xRCX);
                 UBFXw(x1, xRAX, 0, 8);
@@ -1725,6 +1755,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             case 2:
                 if(rep==1) {INST_NAME("REPNZ SCASD");} else {INST_NAME("REPZ SCASD");}
                 MAYSETFLAGS();
+                SMREAD();
                 SETFLAGS(X_ALL, SF_SET_PENDING);
                 CBZx_NEXT(xRCX);
                 TBNZ_MARK2(xFlags, F_DF);
@@ -2065,6 +2096,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     ed = x3;
                 } else
                     ed = xZR;
+                WILLWRITELOCK(lock);
                 STB(ed, wback, fixedaddress);
                 SMWRITELOCK(lock);
             }
@@ -2084,6 +2116,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     ed = x3;
                 } else
                     ed = xZR;
+                WILLWRITELOCK(lock);
                 STxw(ed, wback, fixedaddress);
                 SMWRITELOCK(lock);
             }
@@ -3328,6 +3361,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                     INST_NAME("PUSH Ed");
                     GETEDz(0);
                     PUSH1z(ed);
+                    SMWRITE();
                     break;
 
                 default:
diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c
index ee261791..aa5384cd 100644
--- a/src/dynarec/arm64/dynarec_arm64_66.c
+++ b/src/dynarec/arm64/dynarec_arm64_66.c
@@ -705,11 +705,14 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
         case 0x9C:

             INST_NAME("PUSHF");

             READFLAGS(X_ALL);

+            WILLWRITE();

             PUSH1_16(xFlags);

+            SMWRITE();

             break;

         case 0x9D:

             INST_NAME("POPF");

             SETFLAGS(X_ALL, SF_SET);

+            SMREAD();

             POP1_16(x1);    // probably not usefull...

             BFIw(xFlags, x1, 0, 16);

             MOV32w(x1, 0x3F7FD7);

@@ -746,11 +749,13 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 u64 = F64;

             MOV64z(x1, u64);

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

+            WILLWRITELOCK(lock);

             STRH_U12(xRAX, x1, 0);

             SMWRITELOCK(lock);

             break;

 

         case 0xA5:

+            SMREAD();

             if(rep) {

                 INST_NAME("REP MOVSW");

                 CBZx_NEXT(xRCX);

@@ -775,9 +780,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 ADDx_REG(xRSI, xRSI, x3);

                 ADDx_REG(xRDI, xRDI, x3);

             }

+            SMWRITE();

             break;

 

         case 0xA7:

+            SMREAD();

             switch(rep) {

             case 1:

             case 2:

@@ -827,6 +834,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
             break;

 

         case 0xAB:

+            WILLWRITE();

             if(rep) {

                 INST_NAME("REP STOSW");

                 CBZx_NEXT(xRCX);

@@ -835,11 +843,12 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 STRH_S9_postindex(xRAX, xRDI, 2);

                 SUBx_U12(xRCX, xRCX, 1);

                 CBNZx_MARK(xRCX);

-                B_NEXT_nocond;

+                B_MARK3_nocond;

                 MARK2;  // Part with DF==1

                 STRH_S9_postindex(xRAX, xRDI, -2);

                 SUBx_U12(xRCX, xRCX, 1);

                 CBNZx_MARK2(xRCX);

+                MARK3;

                 // done

             } else {

                 INST_NAME("STOSW");

@@ -847,6 +856,7 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 STRH_U12(xRAX, xRDI, 0);

                 ADDx_REG(xRDI, xRDI, x3);

             }

+            SMWRITE();

             break;

 

         case 0xAD:

diff --git a/src/dynarec/arm64/dynarec_arm64_67.c b/src/dynarec/arm64/dynarec_arm64_67.c
index 3c379e0c..cde17af2 100644
--- a/src/dynarec/arm64/dynarec_arm64_67.c
+++ b/src/dynarec/arm64/dynarec_arm64_67.c
@@ -666,6 +666,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                         }

                     } else {

                         addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<1, 1, rex, &lock, 0, 0);

+                        WILLWRITELOCK(lock);

                         STH(gd, ed, fixedaddress);

                         SMWRITELOCK(lock);

                     }

@@ -832,6 +833,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 BFIx(eb1, gd, eb2*8, 8);

             } else {

                 addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff, 0, rex, &lock, 0, 0);

+                WILLWRITELOCK(lock);

                 STB(gd, ed, fixedaddress);

                 SMWRITELOCK(lock);

             }

@@ -844,6 +846,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 MOVxw_REG(xRAX+(nextop&7)+(rex.b<<3), gd);

             } else {                    // mem <= reg

                 addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 0);

+                WILLWRITELOCK(lock);

                 STxw(gd, ed, fixedaddress);

                 SMWRITELOCK(lock);

             }

@@ -993,6 +996,7 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
                 addr = geted32(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, &unscaled, 0xfff<<(2+rex.w), (1<<(2+rex.w))-1, rex, &lock, 0, 4);

                 i64 = F32S;

                 MOV64xw(x3, i64);

+                WILLWRITELOCK(lock);

                 STxw(x3, ed, fixedaddress);

                 SMWRITELOCK(lock);

             }

diff --git a/src/dynarec/arm64/dynarec_arm64_functions.c b/src/dynarec/arm64/dynarec_arm64_functions.c
index 27280dc5..c747fc7e 100644
--- a/src/dynarec/arm64/dynarec_arm64_functions.c
+++ b/src/dynarec/arm64/dynarec_arm64_functions.c
@@ -537,7 +537,7 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
 {
     if(box64_dynarec_dump) {
         printf_x64_instruction(rex.is32bits?my_context->dec32:my_context->dec, &dyn->insts[ninst].x64, name);
-        dynarec_log(LOG_NONE, "%s%p: %d emitted opcodes, inst=%d, barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X, sm=%d/%d",
+        dynarec_log(LOG_NONE, "%s%p: %d emitted opcodes, inst=%d, barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X, sm=%d(%d/%d)",
             (box64_dynarec_dump>1)?"\e[32m":"",
             (void*)(dyn->native_start+dyn->insts[ninst].address),
             dyn->insts[ninst].size/4,
@@ -552,7 +552,7 @@ void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t r
             dyn->insts[ninst].x64.use_flags,
             dyn->insts[ninst].x64.need_before,
             dyn->insts[ninst].x64.need_after,
-            dyn->smread, dyn->smwrite);
+            dyn->smwrite, dyn->insts[ninst].will_write, dyn->insts[ninst].last_write);
         if(dyn->insts[ninst].pred_sz) {
             dynarec_log(LOG_NONE, ", pred=");
             for(int ii=0; ii<dyn->insts[ninst].pred_sz; ++ii)
diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h
index 1bcc968e..f66f4e08 100644
--- a/src/dynarec/arm64/dynarec_arm64_helper.h
+++ b/src/dynarec/arm64/dynarec_arm64_helper.h
@@ -34,30 +34,51 @@
 
 // Strong mem emulation helpers
 #define SMREAD_MIN  2
-#define SMWRITE_MIN 1
-// Sequence of Read will trigger a DMB on "first" read if strongmem is >= SMREAD_MIN
+#define SMFIRST_MIN 1
+#if STEP == 0
+// pass 0 will store is opcode write memory
+#define SMWRITE()   dyn->insts[ninst].will_write = 1; dyn->smwrite = 1
+#define SMREAD()
+#define SMREADLOCK(lock)
+#define SMMIGHTREAD()
+#define SMWRITE2()   if(box64_dynarec_strongmem>SMREAD_MIN) {SMWRITE();}
+#define SMWRITELOCK(lock)   SMWRITE()
+#define WILLWRITELOCK(lock)
+#define WILLWRITE()
+#define SMMIGHTWRITE()   if(!MODREG) {SMWRITE();}
+#define SMSTART() dyn->smwrite = 0;
+#define SMEND() if(dyn->smwrite && (box64_dynarec_strongmem>SMFIRST_MIN)) {int i = ninst; while(i>=0 && !dyn->insts[i].will_write) --i; if(i>=0) {dyn->insts[i].last_write = 1;}} dyn->smwrite = 0
+#define SMDMB()
+#else
 // 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
+// Block will trigget at 1st and last if strongmem is >= SMFIRST_MIN
+// Read will contribute to trigger a DMB on "first" read if strongmem is >= SMREAD_MIN
 // Opcode will read
-#define SMREAD()    if((dyn->smread==0) && (box64_dynarec_strongmem>SMREAD_MIN)) {SMDMB();} else dyn->smread=1
+#define SMREAD()    if(dyn->insts[ninst].will_write) {WILLWRITE();} else if(box64_dynarec_strongmem>SMREAD_MIN) {SMWRITE();}
 // Opcode will read with option forced lock
-#define SMREADLOCK(lock)    if((lock) || ((dyn->smread==0) && (box64_dynarec_strongmem>SMREAD_MIN))) {SMDMB();}
+#define SMREADLOCK(lock)    if((lock) || (box64_dynarec_strongmem>SMREAD_MIN)) {SMWRITELOCK(lock);}
 // Opcode might read (depend on nextop)
 #define SMMIGHTREAD()   if(!MODREG) {SMREAD();}
 // Opcode has wrote
-#define SMWRITE()   dyn->smwrite=1
+#define SMWRITE()   if((box64_dynarec_strongmem>=SMFIRST_MIN) && dyn->smwrite==0) {SMDMB();} dyn->smwrite=1
 // Opcode has wrote (strongmem>1 only)
-#define SMWRITE2()   if(box64_dynarec_strongmem>SMREAD_MIN) dyn->smwrite=1
+#define SMWRITE2()   if(box64_dynarec_strongmem>SMREAD_MIN) {SMWRITE();}
 // Opcode has wrote with option forced lock
-#define SMWRITELOCK(lock)   if(lock || (box64_dynarec_strongmem>SMWRITE_MIN)) {SMDMB();} else dyn->smwrite=1
+#define SMWRITELOCK(lock)   if(lock) {SMDMB();} else {SMWRITE();}
+// Opcode has wrote with option forced lock
+#define WILLWRITELOCK(lock)   if(lock) {DMB_ISH();} else {WILLWRITE();}
 // Opcode might have wrote (depend on nextop)
 #define SMMIGHTWRITE()   if(!MODREG) {SMWRITE();}
+// Opcode will write (without reading)
+#define WILLWRITE() if((box64_dynarec_strongmem>=SMFIRST_MIN) && dyn->smwrite==0) {SMDMB();} else if(box64_dynarec_strongmem>=SMFIRST_MIN && dyn->insts[ninst].last_write) {SMDMB();} dyn->smwrite=1
 // Start of sequence
 #define SMSTART()   SMEND()
 // End of sequence
-#define SMEND()     if(dyn->smwrite && box64_dynarec_strongmem) {if(box64_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();}} dyn->smwrite=0; dyn->smread=0;
+#define SMEND()     if(dyn->smwrite && box64_dynarec_strongmem) {DMB_ISH();} dyn->smwrite=0;
 // Force a Data memory barrier (for LOCK: prefix)
-#define SMDMB()     if(box64_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();} dyn->smwrite=0; dyn->smread=1
+#define SMDMB()     if(box64_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();} dyn->smwrite=0;
+
+#endif
 
 //LOCK_* define
 #define LOCK_LOCK   (int*)1
diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h
index 0e5c0e9b..1a7b387e 100644
--- a/src/dynarec/arm64/dynarec_arm64_private.h
+++ b/src/dynarec/arm64/dynarec_arm64_private.h
@@ -76,7 +76,9 @@ typedef struct instruction_arm64_s {
     int                 pass2choice;// value for choices that are fixed on pass2 for pass3
     uintptr_t           natcall;
     int                 retn;
-    int                 barrier_maybe;
+    uint8_t             barrier_maybe;
+    uint8_t             will_write;
+    uint8_t             last_write;
     flagcache_t         f_exit;     // flags status at end of instruction
     neoncache_t         n;          // neoncache at end of instruction (but before poping)
     flagcache_t         f_entry;    // flags status before the instruction begin
@@ -109,12 +111,11 @@ typedef struct dynarec_arm_s {
     dynablock_t*        dynablock;
     instsize_t*         instsize;
     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
     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
     int                 forward_ninst;  // ninst at the forward point
+    uint8_t             smwrite;    // for strongmem model emulation
     uint8_t             doublepush;
     uint8_t             doublepop;
     uint8_t             always_test;