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
|
||||
-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")
|
||||
foreach(file ${extension_tests})
|
||||
|
@@ -200,6 +200,12 @@
|
||||
#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))
|
||||
|
||||
// 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
|
||||
#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)))
|
||||
@@ -430,6 +436,12 @@
|
||||
#define DMB_ISH() EMIT(DMB_gen(0b1011))
|
||||
#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
|
||||
#define BRK_gen(imm16) (0b11010100<<24 | 0b001<<21 | (((imm16)&0xffff)<<5))
|
||||
#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]);
|
||||
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
|
||||
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]);
|
||||
@@ -1621,6 +1626,11 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr)
|
||||
snprintf(buff, sizeof(buff), "DMB %s", (Rn==0b1011)?"ISH":"???");
|
||||
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
|
||||
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 {
|
||||
GETGD;
|
||||
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
|
||||
B_MARK(cNE);
|
||||
MARKLOCK;
|
||||
LDAXRH(x1, ed);
|
||||
STLXRH(x3, gd, ed);
|
||||
CBNZx_MARKLOCK(x3);
|
||||
B_MARK2_nocond;
|
||||
MARK;
|
||||
LDRH_U12(x1, ed, 0);
|
||||
STRH_U12(gd, ed, 0);
|
||||
MARK2;
|
||||
SMDMB();
|
||||
if(!ALIGNED_ATOMICH) {
|
||||
TSTx_mask(ed, 1, 0, 0); // mask=1
|
||||
B_MARK(cNE);
|
||||
}
|
||||
if(arm64_atomics) {
|
||||
SWPALH(gd, x1, ed);
|
||||
SMDMB();
|
||||
if(!ALIGNED_ATOMICH) {
|
||||
B_MARK2_nocond;
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
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);
|
||||
UFLAG_IF {
|
||||
CMPSxw_REG(x2, xRAX);
|
||||
CSETw(x4, cEQ);
|
||||
CMPSxw_REG(x3, xRDX);
|
||||
CSETw(x5, cEQ);
|
||||
ANDw_REG(x1, x4, x5);
|
||||
CCMPxw(x3, xRDX, 0, cEQ);
|
||||
CSETw(x1, cEQ);
|
||||
}
|
||||
MOVx_REG(xRAX, x2);
|
||||
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;
|
||||
LDAXPxw(x2, x3, wback);
|
||||
CMPSxw_REG(xRAX, x2);
|
||||
B_MARK(cNE); // EAX != Ed[0]
|
||||
CMPSxw_REG(xRDX, x3);
|
||||
B_MARK(cNE); // EDX != Ed[1]
|
||||
CCMPxw(xRDX, x3, 0, cEQ);
|
||||
B_MARK(cNE); // EAX!=ED[0] || EDX!=Ed[1]
|
||||
STLXPxw(x4, xRBX, xRCX, wback);
|
||||
CBNZx_MARKLOCK(x4);
|
||||
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);
|
||||
|
||||
if(l==LOCK_LOCK) { SMDMB(); }
|
||||
if(l==LOCK_LOCK) { /*SMDMB();*/DMB_ISH(); }
|
||||
|
||||
if(rex.is32bits)
|
||||
return geted_32(dyn, addr, ninst, nextop, ed, hint, fixaddress, unscaled, absmax, mask, l, s);
|
||||
|
@@ -55,9 +55,9 @@
|
||||
// Start of sequence
|
||||
#define SMSTART() SMEND()
|
||||
// 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)
|
||||
#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
|
||||
#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