mirror of
https://github.com/ptitSeb/box64.git
synced 2025-10-14 02:38:54 +08:00
[ARM64_DYNAREC] More work on LOCK prefixed opcodes (Atomic still disabled)
This commit is contained in:
@@ -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})
|
||||||
|
@@ -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))
|
||||||
|
@@ -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)) {
|
||||||
|
@@ -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;
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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);
|
||||||
|
@@ -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
2
tests/ref29.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Lock XADD: Res = 0x456, Ed = 0x579
|
||||||
|
Lock XCHG: Res = 0x579, Ed = 0x123
|
BIN
tests/test29
Executable file
BIN
tests/test29
Executable file
Binary file not shown.
40
tests/test29.c
Normal file
40
tests/test29.c
Normal 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;
|
||||||
|
}
|
Reference in New Issue
Block a user