[ARM64_DYNAREC] More work on LOCK prefixed opcodes (Atomic still disabled)

This commit is contained in:
ptitSeb
2023-12-03 18:26:11 +01:00
parent fa175e7d24
commit b67975a820
10 changed files with 106 additions and 22 deletions

View File

@@ -1097,6 +1097,11 @@ add_test(shaext ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref28.txt -D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref28.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake ) -P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(lock ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX64}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test29 -D TEST_OUTPUT=tmpfile29.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref29.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c") file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests}) foreach(file ${extension_tests})

View File

@@ -200,6 +200,12 @@
#define SBCSw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(0, 1, 1, Rm, Rn, Rd)) #define SBCSw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(0, 1, 1, Rm, Rn, Rd))
#define SBCSxw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(rex.w, 1, 1, Rm, Rn, Rd)) #define SBCSxw_REG(Rd, Rn, Rm) EMIT(ADDSUBC_gen(rex.w, 1, 1, Rm, Rn, Rd))
// CCMP compare if cond is true, set nzcv if false
#define CCMP_reg(sf, Rm, cond, Rn, nzcv) ((sf)<<31 | 1<<30 | 1<<29 | 0b11010010<<21 | (Rm)<<16 | (cond)<<12 | (Rn)<<5 | (nzcv))
#define CCMPw(Wn, Wm, nzcv, cond) EMIT(CCMP_reg(0, Wm, cond, Wn, nzcv))
#define CCMPx(Xn, Xm, nzcv, cond) EMIT(CCMP_reg(1, Xm, cond, Xn, nzcv))
#define CCMPxw(Xn, Xm, nzcv, cond) EMIT(CCMP_reg(rex.w, Xm, cond, Xn, nzcv))
// ADR // ADR
#define ADR_gen(immlo, immhi, Rd) ((immlo)<<29 | 0b10000<<24 | (immhi)<<5 | (Rd)) #define ADR_gen(immlo, immhi, Rd) ((immlo)<<29 | 0b10000<<24 | (immhi)<<5 | (Rd))
#define ADR_S20(Rd, imm) EMIT(ADR_gen((imm)&3, ((imm)>>2)&0x7ffff, (Rd))) #define ADR_S20(Rd, imm) EMIT(ADR_gen((imm)&3, ((imm)>>2)&0x7ffff, (Rd)))
@@ -430,6 +436,12 @@
#define DMB_ISH() EMIT(DMB_gen(0b1011)) #define DMB_ISH() EMIT(DMB_gen(0b1011))
#define DMB_SY() EMIT(DMB_gen(0b1111)) #define DMB_SY() EMIT(DMB_gen(0b1111))
// Data Synchronization Barrier
#define DSB_gen(CRm) (0b1101010100<<22 | 0b011<<16 | 0b0011<<12 | (CRm)<<8 | 1<<7 | 0b00<<5 | 0b11111)
#define DSB_ISH() EMIT(DSB_gen(0b1011))
#define DSB_ISHST() EMIT(DSB_gen(0b1010))
#define DSB_SY() EMIT(DSB_gen(0b1111))
// Break // Break
#define BRK_gen(imm16) (0b11010100<<24 | 0b001<<21 | (((imm16)&0xffff)<<5)) #define BRK_gen(imm16) (0b11010100<<24 | 0b001<<21 | (((imm16)&0xffff)<<5))
#define BRK(imm16) EMIT(BRK_gen(imm16)) #define BRK(imm16) EMIT(BRK_gen(imm16))

View File

@@ -797,6 +797,11 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "CSEL %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], conds[cond]); snprintf(buff, sizeof(buff), "CSEL %s, %s, %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], conds[cond]);
return buff; return buff;
} }
if(isMask(opcode, "f1111010010mmmmmcccc00nnnnn0iiii", &a)) {
snprintf(buff, sizeof(buff), "CCMP %s, %s, %s 0x%x", sf?Xt[Rn]:Wt[Rn], sf?Xt[Rm]:Wt[Rm], conds[cond], imm);
return buff;
}
// MISC Bits // MISC Bits
if(isMask(opcode, "f10110101100000000010onnnnnddddd", &a)) { if(isMask(opcode, "f10110101100000000010onnnnnddddd", &a)) {
snprintf(buff, sizeof(buff), "CL%c %s, %s", option?'S':'Z', sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn]); snprintf(buff, sizeof(buff), "CL%c %s, %s", option?'S':'Z', sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn]);
@@ -1621,6 +1626,11 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
snprintf(buff, sizeof(buff), "DMB %s", (Rn==0b1011)?"ISH":"???"); snprintf(buff, sizeof(buff), "DMB %s", (Rn==0b1011)?"ISH":"???");
return buff; return buff;
} }
// DSB ISH/ISHST
if(isMask(opcode, "11010101000000110011nnnn10011111", &a)) {
snprintf(buff, sizeof(buff), "DSB %s", (Rn==0b1011)?"ISH":((Rn==0b1010)?"ISHST":"???"));
return buff;
}
// CASxw // CASxw
if(isMask(opcode, "1f0010001L1ssssso11111nnnnnttttt", &a)) { if(isMask(opcode, "1f0010001L1ssssso11111nnnnnttttt", &a)) {

View File

@@ -591,18 +591,36 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
} else { } else {
GETGD; GETGD;
addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0); addr = geted(dyn, addr, ninst, nextop, &ed, x2, &fixedaddress, NULL, 0, 0, rex, LOCK_LOCK, 0, 0);
TSTx_mask(ed, 1, 0, 0); // mask=1 if(!ALIGNED_ATOMICH) {
B_MARK(cNE); TSTx_mask(ed, 1, 0, 0); // mask=1
MARKLOCK; B_MARK(cNE);
LDAXRH(x1, ed); }
STLXRH(x3, gd, ed); if(arm64_atomics) {
CBNZx_MARKLOCK(x3); SWPALH(gd, x1, ed);
B_MARK2_nocond; SMDMB();
MARK; if(!ALIGNED_ATOMICH) {
LDRH_U12(x1, ed, 0); B_MARK2_nocond;
STRH_U12(gd, ed, 0); }
MARK2; } else {
SMDMB(); MARKLOCK;
LDAXRH(x1, ed);
STLXRH(x3, gd, ed);
CBNZx_MARKLOCK(x3);
SMDMB();
if(!ALIGNED_ATOMICH) {
B_MARK2_nocond;
}
}
if(!ALIGNED_ATOMICH) {
MARK;
LDRH_U12(x1, ed, 0);
LDAXRB(x3, ed);
STLXRB(x3, gd, ed);
CBNZx_MARK(x3);
STRH_U12(gd, ed, 0);
SMDMB();
MARK2;
}
BFIx(gd, x1, 0, 16); BFIx(gd, x1, 0, 16);
} }
break; break;

View File

@@ -612,10 +612,8 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
CASPALxw(x2, x4, wback); CASPALxw(x2, x4, wback);
UFLAG_IF { UFLAG_IF {
CMPSxw_REG(x2, xRAX); CMPSxw_REG(x2, xRAX);
CSETw(x4, cEQ); CCMPxw(x3, xRDX, 0, cEQ);
CMPSxw_REG(x3, xRDX); CSETw(x1, cEQ);
CSETw(x5, cEQ);
ANDw_REG(x1, x4, x5);
} }
MOVx_REG(xRAX, x2); MOVx_REG(xRAX, x2);
MOVx_REG(xRDX, x3); MOVx_REG(xRDX, x3);
@@ -623,9 +621,8 @@ uintptr_t dynarec64_F0(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin
MARKLOCK; MARKLOCK;
LDAXPxw(x2, x3, wback); LDAXPxw(x2, x3, wback);
CMPSxw_REG(xRAX, x2); CMPSxw_REG(xRAX, x2);
B_MARK(cNE); // EAX != Ed[0] CCMPxw(xRDX, x3, 0, cEQ);
CMPSxw_REG(xRDX, x3); B_MARK(cNE); // EAX!=ED[0] || EDX!=Ed[1]
B_MARK(cNE); // EDX != Ed[1]
STLXPxw(x4, xRBX, xRCX, wback); STLXPxw(x4, xRBX, xRCX, wback);
CBNZx_MARKLOCK(x4); CBNZx_MARKLOCK(x4);
UFLAG_IF { UFLAG_IF {

View File

@@ -32,7 +32,7 @@ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, u
{ {
MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta); MAYUSE(dyn); MAYUSE(ninst); MAYUSE(delta);
if(l==LOCK_LOCK) { SMDMB(); } if(l==LOCK_LOCK) { /*SMDMB();*/DMB_ISH(); }
if(rex.is32bits) if(rex.is32bits)
return geted_32(dyn, addr, ninst, nextop, ed, hint, fixaddress, unscaled, absmax, mask, l, s); return geted_32(dyn, addr, ninst, nextop, ed, hint, fixaddress, unscaled, absmax, mask, l, s);

View File

@@ -55,9 +55,9 @@
// Start of sequence // Start of sequence
#define SMSTART() SMEND() #define SMSTART() SMEND()
// End of sequence // End of sequence
#define SMEND() if(dyn->smwrite && box64_dynarec_strongmem) {DMB_ISH();} dyn->smwrite=0; dyn->smread=0; #define SMEND() if(dyn->smwrite && box64_dynarec_strongmem) {if(box64_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();}} dyn->smwrite=0; dyn->smread=0;
// Force a Data memory barrier (for LOCK: prefix) // Force a Data memory barrier (for LOCK: prefix)
#define SMDMB() DMB_ISH(); dyn->smwrite=0; dyn->smread=1; dyn->smlastdmb = ninst #define SMDMB() if(box64_dynarec_strongmem){DSB_ISH();}else{DMB_ISH();} dyn->smwrite=0; dyn->smread=1; dyn->smlastdmb = ninst
//LOCK_* define //LOCK_* define
#define LOCK_LOCK (int*)1 #define LOCK_LOCK (int*)1

2
tests/ref29.txt Normal file
View File

@@ -0,0 +1,2 @@
Lock XADD: Res = 0x456, Ed = 0x579
Lock XCHG: Res = 0x579, Ed = 0x123

BIN
tests/test29 Executable file

Binary file not shown.

40
tests/test29.c Normal file
View File

@@ -0,0 +1,40 @@
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
// Build with `gcc -march=core2 -O0 test29.c -o test29`
uint64_t lock_xadd(uint64_t Gd, uint64_t volatile* Ed) {
uint64_t Res;
asm(
"lock xadd %[_Gd], (%[_Ed])\n"
"movq %[_Gd], %[_Res]\n"
: [_Res] "+r"(Res)
: [_Gd] "r"(Gd)
, [_Ed] "r"(Ed)
);
return Res;
}
uint64_t lock_xchg(uint64_t Gd, uint64_t volatile* Ed) {
uint64_t Res;
asm(
"lock xchg %[_Gd], (%[_Ed])\n"
"movq %[_Gd], %[_Res]\n"
: [_Res] "+r"(Res)
: [_Gd] "r"(Gd)
, [_Ed] "r"(Ed)
);
return Res;
}
int main() {
uint64_t Gd = 0x123;
uint64_t volatile Ed = 0x456;
uint64_t Res = lock_xadd(Gd, &Ed);
printf("Lock XADD: Res = 0x%lx, Ed = 0x%lx\n", Res, Ed);
Gd = 0x123;
Res = lock_xchg(Gd, &Ed);
printf("Lock XCHG: Res = 0x%lx, Ed = 0x%lx\n", Res, Ed);
return 0;
}