diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-12-03 18:26:11 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-12-03 18:26:11 +0100 |
| commit | b67975a820d481577f8ea7515858b2f35450b0d0 (patch) | |
| tree | 4b9e322c9e2fa04267dbe2046539b12b2af7af6d /src | |
| parent | fa175e7d2405d0b521cfd98d549a94252b697bf6 (diff) | |
| download | box64-b67975a820d481577f8ea7515858b2f35450b0d0.tar.gz box64-b67975a820d481577f8ea7515858b2f35450b0d0.zip | |
[ARM64_DYNAREC] More work on LOCK prefixed opcodes (Atomic still disabled)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/arm64_emitter.h | 12 | ||||
| -rw-r--r-- | src/dynarec/arm64/arm64_printer.c | 10 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_66.c | 42 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_f0.c | 11 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.c | 2 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.h | 4 |
6 files changed, 59 insertions, 22 deletions
diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h index 178c5b20..cbfa8371 100644 --- a/src/dynarec/arm64/arm64_emitter.h +++ b/src/dynarec/arm64/arm64_emitter.h @@ -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)) diff --git a/src/dynarec/arm64/arm64_printer.c b/src/dynarec/arm64/arm64_printer.c index eca8c632..572d645f 100644 --- a/src/dynarec/arm64/arm64_printer.c +++ b/src/dynarec/arm64/arm64_printer.c @@ -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)) { diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c index bb4a757e..e8540776 100644 --- a/src/dynarec/arm64/dynarec_arm64_66.c +++ b/src/dynarec/arm64/dynarec_arm64_66.c @@ -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; diff --git a/src/dynarec/arm64/dynarec_arm64_f0.c b/src/dynarec/arm64/dynarec_arm64_f0.c index 033b1f81..09d053cb 100644 --- a/src/dynarec/arm64/dynarec_arm64_f0.c +++ b/src/dynarec/arm64/dynarec_arm64_f0.c @@ -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 { diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index d404c6f3..ab49bc1e 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -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); diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index b511457d..664ccaaf 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -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 |