diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-24 16:49:27 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-24 16:49:27 +0100 |
| commit | 12ee624358632c25c6f891c5d4e7c9cf886d0798 (patch) | |
| tree | 4bc25cb24bb7578985411e91ea5454b0c55a7d73 /src | |
| parent | 571de7f07f026aa955f7ffb926124e87c737aba1 (diff) | |
| download | box64-12ee624358632c25c6f891c5d4e7c9cf886d0798.tar.gz box64-12ee624358632c25c6f891c5d4e7c9cf886d0798.zip | |
[DYNAREC] Added 0F BA opcode
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/dynarec_arm64_0f.c | 105 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_helper.h | 8 |
2 files changed, 110 insertions, 3 deletions
diff --git a/src/dynarec/dynarec_arm64_0f.c b/src/dynarec/dynarec_arm64_0f.c index 25ffec7e..3ebf3cd7 100755 --- a/src/dynarec/dynarec_arm64_0f.c +++ b/src/dynarec/dynarec_arm64_0f.c @@ -476,7 +476,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0: INST_NAME("FXSAVE Ed"); fpu_purgecache(dyn, ninst, x1, x2, x3); - if((nextop&0xC0)==0xC0) { + if(MODREG) { DEFAULT; } else { addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0); @@ -487,7 +487,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 1: INST_NAME("FXRSTOR Ed"); fpu_purgecache(dyn, ninst, x1, x2, x3); - if((nextop&0xC0)==0xC0) { + if(MODREG) { DEFAULT; } else { addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0, 0, rex, 0, 0); @@ -502,7 +502,7 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 3: INST_NAME("STMXCSR Md"); - if((nextop&0xC0)==0xC0) { + if(MODREG) { ed = xRAX+(nextop&7)+(rex.b<<3); LDRw_U12(ed, xEmu, offsetof(x64emu_t, mxcsr)); } else { @@ -617,6 +617,105 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin } break; + case 0xBA: + nextop = F8; + switch((nextop>>3)&7) { + case 4: + INST_NAME("BT Ed, Ib"); + SETFLAGS(X_CF, SF_SUBSET); + gd = x2; + if(MODREG) { + ed = xRAX+(nextop&7)+(rex.b<<3); + u8 = F8; + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0); + u8 = F8; + fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4); + LDRxw_U12(x1, wback, fixedaddress); + ed = x1; + } + u8&=rex.w?0x3f:0x1f; + if(u8) { + LSRxw(x1, ed, u8); + ed = x1; + } + BFIw(xFlags, ed, F_CF, 1); + break; + case 5: + INST_NAME("BTS Ed, Ib"); + SETFLAGS(X_CF, SF_SUBSET); + if(MODREG) { + ed = xRAX+(nextop&7)+(rex.b<<3); + u8 = F8; + wback = 0; + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0); + u8 = F8; + fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4); + LDRxw_U12(x1, wback, fixedaddress); + ed = x1; + } + LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f)); + BFIw(xFlags, x4, F_CF, 1); + TBNZ_MARK3(x4, 0); // bit already set, jump to next instruction + MOV32w(x4, 1); + EORxw_REG_LSL(ed, ed, x4, u8&(rex.w?0x3f:0x1f)); + if(wback) { + STRxw_U12(ed, wback, fixedaddress); + } + MARK3; + break; + case 6: + INST_NAME("BTR Ed, Ib"); + SETFLAGS(X_CF, SF_SUBSET); + if(MODREG) { + ed = xRAX+(nextop&7)+(rex.b<<3); + u8 = F8; + wback = 0; + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0); + u8 = F8; + fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4); + LDRxw_U12(x1, wback, fixedaddress); + ed = x1; + } + LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f)); + BFIw(xFlags, x4, F_CF, 1); + TBZ_MARK3(x4, 0); // bit already clear, jump to next instruction + //MOVW(x14, 1); // already 0x01 + EORxw_REG_LSL(ed, ed, x4, u8&(rex.w?0x3f:0x1f)); + if(wback) { + STRxw_U12(ed, wback, fixedaddress); + } + MARK3; + break; + case 7: + INST_NAME("BTC Ed, Ib"); + SETFLAGS(X_CF, SF_SUBSET); + if(MODREG) { + ed = xRAX+(nextop&7)+(rex.b<<3); + u8 = F8; + wback = 0; + } else { + addr = geted(dyn, addr, ninst, nextop, &wback, x3, &fixedaddress, 0xff0<<2, 3, rex, 0, 0); + u8 = F8; + fixedaddress+=(u8>>(rex.w?6:5))*(rex.w?8:4); + LDRxw_U12(x1, wback, fixedaddress); + ed = x1; + } + LSRxw(x4, ed, u8&(rex.w?0x3f:0x1f)); + BFIw(xFlags, x4, F_CF, 1); + MOV32w(x4, 1); + EORxw_REG_LSL(ed, ed, x4, u8&(rex.w?0x3f:0x1f)); + if(wback) { + STRxw_U12(ed, wback, fixedaddress); + } + MARK3; + break; + default: + DEFAULT; + } + break; case 0xBB: INST_NAME("BTC Ed, Gd"); SETFLAGS(X_CF, SF_SET); diff --git a/src/dynarec/dynarec_arm64_helper.h b/src/dynarec/dynarec_arm64_helper.h index 53f8da67..d51260bf 100755 --- a/src/dynarec/dynarec_arm64_helper.h +++ b/src/dynarec/dynarec_arm64_helper.h @@ -300,6 +300,14 @@ #define CBNZx_MARK3(reg) \ j32 = GETMARK3-(dyn->arm_size); \ CBNZx(reg, j32) +// Test bit N of A and branch to MARK3 if set +#define TBNZ_MARK3(A, N) \ + j32 = GETMARK3-(dyn->arm_size); \ + TBNZ(A, N, j32) +// Test bit N of A and branch to MARK3 if not set +#define TBZ_MARK3(A, N) \ + j32 = GETMARK3-(dyn->arm_size); \ + TBZ(A, N, j32) // Branch to next instruction if cond (use j32) #define B_NEXT(cond) \ j32 = (dyn->insts)?(dyn->insts[ninst].epilog-(dyn->arm_size)):0; \ |