[LA64_DYNAREC] Add macros help unaligned lock opcodes. (#3107)

This patch add Macro for 32/64 bits lock opcodes.
Added lock add ed, gd/lock add ed, ib/id.
This commit is contained in:
phorcys authored and GitHub committed 2025-11-02 17:21:23 +01:00
1 parent 75ea309ca1
commit 44822bb07b
2 files changed
+129 -26

No files matched your search

+58 -26
View File
@@ -62,11 +62,35 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
emit_add32(dyn, ninst, rex, ed, gd, x3, x4, x5);
} else {
addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, LOCK_LOCK, 0, 0);
MARKLOCK;
LLxw(x1, wback, 0);
ADDxw(x4, x1, gd);
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
if (rex.w) {
if (!ALIGNED_ATOMICxw) {
ANDI(x3, wback, 0b111);
BNEZ_MARK2(x3);
}
AMADD_DB_D(x1, gd, wback);
B_MARK3_nocond;
} else {
if (!ALIGNED_ATOMICxw) {
ANDI(x3, wback, 0b11);
BNEZ_MARK(x3);
}
// aligned 4byte
AMADD_DB_W(x1, gd, wback);
if (!ALIGNED_ATOMICxw) {
B_MARK3_nocond;
MARK;
ANDI(x3, wback, 0b111);
SLTI(x4, x3, 4);
BEQZ_MARK2(x4); // addr %8 >4 , cross 8bytes or cross cacheline
LOCK_32_IN_8BYTE(ADD_W(x4, x1, gd), x1, wback, x3, x4, x5, x6, x7);
B_MARK3_nocond;
}
}
if (!ALIGNED_ATOMICxw) {
MARK2;
LOCK_3264_CROSS_8BYTE(ADDxw(x4, x1, gd), x1, wback, x4, x5, x6);
MARK3;
}
IFXORNAT (X_ALL | X_PEND) {
emit_add32(dyn, ninst, rex, x1, gd, x3, x4, x5);
}
@@ -662,27 +686,35 @@ uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
else
i64 = F8S;
MOV64xw(x7, i64);
ANDI(x1, wback, (1 << (rex.w + 2)) - 1);
BNEZ_MARK3(x1);
// Aligned
MARKLOCK;
LLxw(x1, wback, 0);
ADDxw(x4, x1, x7);
SCxw(x4, wback, 0);
BEQZ_MARKLOCK(x4);
B_MARK_nocond;
MARK3;
// Unaligned
ADDI_D(x5, xZR, -(1 << (rex.w + 2)));
AND(x5, wback, x5);
MARKLOCK2;
LDxw(x1, wback, 0);
LLxw(x6, x5, 0);
ADDxw(x4, x1, x7);
SCxw(x6, x5, 0);
BEQZ_MARKLOCK2(x6);
SDxw(x4, wback, 0);
MARK;
if (rex.w) {
if (!ALIGNED_ATOMICxw) {
ANDI(x3, wback, 0b111);
BNEZ_MARK2(x3);
}
AMADD_DB_D(x1, x7, wback);
B_MARK3_nocond;
} else {
if (!ALIGNED_ATOMICxw) {
ANDI(x3, wback, 0b11);
BNEZ_MARK(x3);
}
// aligned 4byte
AMADD_DB_W(x1, x7, wback);
if (!ALIGNED_ATOMICxw) {
B_MARK3_nocond;
MARK;
ANDI(x3, wback, 0b111);
SLTI(x4, x3, 4);
BEQZ_MARK2(x4); // addr %8 >4 , cross 8bytes or cross cacheline
LOCK_32_IN_8BYTE(ADD_W(x4, x1, x7), x1, wback, x3, x4, x5, x6, x7);
B_MARK3_nocond;
}
}
if (!ALIGNED_ATOMICxw) {
MARK2;
LOCK_3264_CROSS_8BYTE(ADDxw(x4, x1, x7), x1, wback, x4, x5, x6);
MARK3;
}
IFXORNAT (X_ALL | X_PEND) {
emit_add32c(dyn, ninst, rex, x1, i64, x3, x4, x5, x6);
}
+71
View File
@@ -1810,4 +1810,75 @@ uintptr_t dynarec64_DF(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
#define PURGE_YMM()
#define ALIGNED_ATOMICxw ((fixedaddress && !(fixedaddress & (((1 << (2 + rex.w)) - 1)))) || BOX64ENV(dynarec_aligned_atomics))
#define ALIGNED_ATOMICH ((fixedaddress && !(fixedaddress & 1)) || BOX64ENV(dynarec_aligned_atomics))
// lock op related macros
/*
LOCK_3264_CROSS_8BYTE cross 8byte, lock lower part 8byte.
use ll.d lock lower 8byte. ld.d load ed to likely emulate atomic 4byte/8byte operation
op = atomic function
x1 = original ed
x2 = wback ed addr
x4 = result
x5 = 8 byte lower block for sc
x6 = aligned addr
*/
#define LOCK_3264_CROSS_8BYTE(op, x1, wback, x4, x5, x6) \
MV(x6, wback); \
BSTRINS_D(x6, xZR, 2, 0); \
MARKLOCK2; \
LL_D(x5, x6, 0); \
DBAR(0b00101); \
LDxw(x1, wback, 0); \
op; \
SC_D(x5, x6, 0); \
BEQZ_MARKLOCK2(x5); \
SDxw(x4, wback, 0);
/*
LOCK_3264_IN_8BYTE unaligned but in 8 bytes.
use ll.d/sc.d to atomic operation. use amcas.db.d when possible
x1 = original ed
x2 = wback ed addr / aligned ed addr
x3 = offset
x4 = result
x5 = 8 byte block
x6 = mask, amcas orignal val
x7 = imm if inst use imm op
*/
#define LOCK_32_IN_8BYTE(op, x1, wback, x3, x4, x5, x6, x7) \
BSTRINS_D(wback, xZR, 2, 0); \
if(wback != x2) { \
MV(x2, wback); \
wback = x2; \
} \
SLLI_W(x3, x3, 3); \
if (cpuext.lamcas) { \
LD_D(x5, wback, 0); \
MARKLOCK; \
} else { \
MARKLOCK; \
LL_D(x5, wback, 0); \
} \
SRL_D(x1, x5, x3); \
BSTRPICK_D(x1, x1, 31, 0); \
op; \
BSTRPICK_D(x4, x4, 31, 0); \
SLL_D(x4, x4, x3); \
ADDI_D(x6, xZR, -1); \
BSTRINS_D(x6, xZR, 63, 32); \
SLL_D(x6, x6, x3); \
ANDN(x6, x5, x6); \
OR(x4, x6, x4); \
if (cpuext.lamcas) { \
MV(x6, x5); \
AMCAS_DB_D(x5, x4, wback); \
BNE_MARKLOCK(x5, x6); \
} else { \
SC_D(x4, wback, 0); \
BEQZ_MARKLOCK(x4); \
}
#endif //__DYNAREC_LA64_HELPER_H__