diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2025-01-07 09:58:13 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2025-01-07 09:58:13 +0100 |
| commit | a61888e06cd4dadc06717b8ca58c161f85ce7fb8 (patch) | |
| tree | 96ebb328f44af5554275d1ccf1bcd4621dc73954 /src | |
| parent | 691259ec0d612d45b77c0544d947a5a15e4becaa (diff) | |
| download | box64-a61888e06cd4dadc06717b8ca58c161f85ce7fb8.tar.gz box64-a61888e06cd4dadc06717b8ca58c161f85ce7fb8.zip | |
[ARM64_DYNAREC] Optimized 8bits OR when no flags is needed
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_00.c | 71 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.h | 21 |
2 files changed, 77 insertions, 15 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index b711230f..dc04a661 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -126,10 +126,23 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin INST_NAME("OR Eb, Gb"); SETFLAGS(X_ALL, SF_SET_PENDING); nextop = F8; - GETEB(x1, 0); - GETGB(x2); - emit_or8(dyn, ninst, x1, x2, x4, x5); - EBBACK; + UFLAG_IF { + GETEB(x1, 0); + GETGB(x2); + emit_or8(dyn, ninst, x1, x2, x4, x5); + EBBACK; + } else { + if(MODREG) { + GETGB(x2); + CALCEB(); + ORRx_REG_LSL(wback, wback, x2, wb2); + } else { + GETEB(x1, 0); + CALCGB(); + ORRw_REG_LSR(x1, x1, gb1, 8*gb2); + EBBACK; + } + } break; case 0x09: INST_NAME("OR Ed, Gd"); @@ -144,10 +157,16 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin INST_NAME("OR Gb, Eb"); SETFLAGS(X_ALL, SF_SET_PENDING); nextop = F8; - GETEB(x2, 0); - GETGB(x1); - emit_or8(dyn, ninst, x1, x2, x3, x4); - GBBACK; + UFLAG_IF { + GETEB(x2, 0); + GETGB(x1); + emit_or8(dyn, ninst, x1, x2, x3, x4); + GBBACK; + } else { + GETEB(x2, 0); + CALCGB(); + ORRx_REG_LSL(gb1, gb1, x2, gb2*8); + } break; case 0x0B: INST_NAME("OR Gd, Ed"); @@ -161,9 +180,19 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin INST_NAME("OR AL, Ib"); SETFLAGS(X_ALL, SF_SET_PENDING); u8 = F8; - UXTBw(x1, xRAX); - emit_or8c(dyn, ninst, x1, u8, x3, x4); - BFIx(xRAX, x1, 0, 8); + UFLAG_IF { + UXTBw(x1, xRAX); + emit_or8c(dyn, ninst, x1, u8, x3, x4); + BFIx(xRAX, x1, 0, 8); + } else { + int mask = convert_bitmask_x(u8); + if(mask) + ORRx_mask(xRAX, xRAX, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F); + else { + MOV32w(x1, u8); + ORRx_REG(xRAX, xRAX, x1); + } + } break; case 0x0D: INST_NAME("OR EAX, Id"); @@ -1024,10 +1053,22 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 1: //OR INST_NAME("OR Eb, Ib"); SETFLAGS(X_ALL, SF_SET_PENDING); - GETEB(x1, 1); - u8 = F8; - emit_or8c(dyn, ninst, x1, u8, x2, x4); - EBBACK; + UFLAG_IF2(|| !MODREG) { + GETEB(x1, 1); + u8 = F8; + emit_or8c(dyn, ninst, x1, u8, x2, x4); + EBBACK; + } else { + CALCEB(); + u8 = F8; + int mask = convert_bitmask_x(((uint32_t)u8)<<wb2); + if(mask) + ORRx_mask(wback, wback, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F); + else { + MOV32w(x1, ((uint32_t)u8)<<wb2); + ORRx_REG(wback, wback, x1); + } + } break; case 2: //ADC INST_NAME("ADC Eb, Ib"); diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index 0f6f132a..403f1535 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -322,6 +322,16 @@ #define EWBACKW(w) if(wb1) {STH(w, wback, fixedaddress); SMWRITE();} else {BFIx(wback, w, 0, 16);} // Write back gd in correct register #define GWBACK BFIx(TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)), gd, 0, 16); +// no fetch version of GETEB for MODREG path only +#define CALCEB() \ + if (rex.rex) { \ + wback = TO_NAT((nextop & 7) + (rex.b << 3)); \ + wb2 = 0; \ + } else { \ + wback = (nextop & 7); \ + wb2 = (wback >> 2) * 8; \ + wback = TO_NAT(wback & 3); \ + } \ //GETEB will use i for ed, and can use r3 for wback. #define GETEB(i, D) \ if (MODREG) { \ @@ -410,6 +420,16 @@ } // Write eb (ed) back to original register / memory #define EBBACK if(wb1) {STB(ed, wback, fixedaddress); SMWRITE();} else {BFIx(wback, ed, wb2, 8);} +// no fetch version of GETGB +#define CALCGB() \ + if (rex.rex) { \ + gb1 = TO_NAT(((nextop & 0x38) >> 3) + (rex.r << 3)); \ + gb2 = 0; \ + } else { \ + gd = (nextop & 0x38) >> 3; \ + gb2 = ((gd & 4) << 1); \ + gb1 = TO_NAT(gd & 3); \ + } \ //GETGB will use i for gd #define GETGB(i) \ if (rex.rex) { \ @@ -1169,6 +1189,7 @@ #define UFLAG_RES(A) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(A, xEmu, offsetof(x64emu_t, res));} #define UFLAG_DF(r, A) if(dyn->insts[ninst].x64.gen_flags) {SET_DF(r, A)} #define UFLAG_IF if(dyn->insts[ninst].x64.gen_flags) +#define UFLAG_IF2(A) if(dyn->insts[ninst].x64.gen_flags A) #ifndef DEFAULT #define DEFAULT *ok = -1; BARRIER(2) #endif |