diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/arm64_emitter.h | 2 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_avx_0f38.c | 113 |
2 files changed, 113 insertions, 2 deletions
diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h index f56a68dc..0ecfa33c 100644 --- a/src/dynarec/arm64/arm64_emitter.h +++ b/src/dynarec/arm64/arm64_emitter.h @@ -586,7 +586,7 @@ int convert_bitmask(uint64_t bitmask); #define CSINV_gen(sf, Rm, cond, Rn, Rd) ((sf)<<31 | 1<<30 | 0b11010100<<21 | (Rm)<<16 | (cond)<<12 | (Rn)<<5 | (Rd)) #define CSINVx(Rd, Rn, Rm, cond) EMIT(CSINV_gen(1, Rm, cond, Rn, Rd)) #define CSINVw(Rd, Rn, Rm, cond) EMIT(CSINV_gen(0, Rm, cond, Rn, Rd)) -#define CSINVxw(Rd, Rn, Rm, cond) EMIT(CSINV_gen(rex.w?, Rm, cond, Rn, Rd)) +#define CSINVxw(Rd, Rn, Rm, cond) EMIT(CSINV_gen(rex.w, Rm, cond, Rn, Rd)) #define CINVx(Rd, Rn, cond) CSINVx(Rd, Rn, Rn, invertCond(cond)) #define CINVw(Rd, Rn, cond) CSINVw(Rd, Rn, Rn, invertCond(cond)) #define CINVxw(Rd, Rn, cond) CSINVxw(Rd, Rn, Rn, invertCond(cond)) diff --git a/src/dynarec/arm64/dynarec_arm64_avx_0f38.c b/src/dynarec/arm64/dynarec_arm64_avx_0f38.c index bd0a1baf..c5a9baf5 100644 --- a/src/dynarec/arm64/dynarec_arm64_avx_0f38.c +++ b/src/dynarec/arm64/dynarec_arm64_avx_0f38.c @@ -137,6 +137,82 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i IFX(X_PF) BFCw(xFlags, F_PF, 1); } break; + + case 2: + INST_NAME("BLSMSK Vd, Ed"); + SETFLAGS(X_ALL, SF_SET); + GETED(0); + GETVD; + IFX(X_CF) { + TSTxw_REG(ed, ed); + CSETMw(x3, cEQ); + BFIw(xFlags, x3, F_CF, 1); + } + SUBxw_U12(x3, ed, 1); + need_tst = 0; + IFX(X_ZF) need_tst = 1; + IFXNATIVE(X_SF, NF_SF) need_tst = 1; + IFXNATIVE(X_OF, NF_VF) need_tst = 1; + EORxw_REG(vd, ed, x3); + if(need_tst) + TSTxw_REG(vd, vd); + IFX(X_ZF) { + IFNATIVE(NF_EQ) {} else { + CSETMw(x3, cEQ); + BFIw(xFlags, x3, F_ZF, 1); + } + } + IFX(X_SF) { + IFNATIVE(NF_SF) {} else { + LSRxw(x3, vd, rex.w?63:31); + BFIw(xFlags, x3, F_SF, 1); + } + } + IFX(X_OF) IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);} + if (BOX64ENV(dynarec_test)) { + IFX(X_AF) BFCw(xFlags, F_AF, 1); + IFX(X_PF) BFCw(xFlags, F_PF, 1); + } + break; + + case 3: + INST_NAME("BLSI Vd, Ed"); + SETFLAGS(X_ALL, SF_SET); + GETED(0); + GETVD; + IFX(X_CF) { + TSTxw_REG(ed, ed); + CSETMw(x3, cEQ); + BFIw(xFlags, x3, F_CF, 1); + } + NEGxw_REG(x3, ed); + need_tst = 0; + IFX(X_ZF) need_tst = 1; + IFXNATIVE(X_SF, NF_SF) need_tst = 1; + IFXNATIVE(X_OF, NF_VF) need_tst = 1; + if(need_tst) + ANDSxw_REG(vd, ed, x3); + else + ANDxw_REG(vd, ed, x3); + IFX(X_ZF) { + IFNATIVE(NF_EQ) {} else { + CSETMw(x3, cEQ); + BFIw(xFlags, x3, F_ZF, 1); + } + } + IFX(X_SF) { + IFNATIVE(NF_SF) {} else { + LSRxw(x3, vd, rex.w?63:31); + BFIw(xFlags, x3, F_SF, 1); + } + } + IFX(X_OF) IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);} + if (BOX64ENV(dynarec_test)) { + IFX(X_AF) BFCw(xFlags, F_AF, 1); + IFX(X_PF) BFCw(xFlags, F_PF, 1); + } + break; + default: DEFAULT; } @@ -151,7 +227,7 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i GETVD; UXTBw(x1, vd); CMPSw_U12(x1, rex.w?64:32); - CSETxw(x2, cPL); + CSETMxw(x2, cPL); IFX(F_CF) { BFIw(xFlags, x2, F_CF, 1); } @@ -184,6 +260,41 @@ uintptr_t dynarec64_AVX_0F38(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, i IFX(X_OF) IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);} break; + case 0xF7: + INST_NAME("BEXTR Gd, Ed, Vd"); + nextop = F8; + SETFLAGS(X_ALL, SF_SET); + GETGD; + GETED(0); + GETVD; + MOV64xw(x1, 0); + UXTBw(x2, vd); // start + BFXILw(x3, vd, 8, 8); // length + TSTw_REG(x3, x3); + B_MARK(cEQ); + LSRxw_REG(x1, ed, x2); + CMPSw_U12(x3, rex.w?64:32); + B_MARK(cGE); + MOV32w(x2, rex.w?64:32); + SUBw_REG(x2, x2, x3); + LSLxw_REG(x1, x1, x2); + LSRxw_REG(x1, x1, x2); + TSTxw_REG(x1, x1); + MARK; + MOVxw_REG(gd, x1); + IFX(X_ZF) { + IFNATIVE(NF_EQ) {} else { + CSETw(x3, cEQ); + BFIw(xFlags, x3, F_ZF, 1); + } + } + IFX(X_AF) BFCw(xFlags, F_AF, 1); + IFX(X_PF) BFCw(xFlags, F_PF, 1); + IFX(X_CF) BFCw(xFlags, F_CF, 1); + IFX(X_OF) IFNATIVE(NF_VF) {} else {BFCw(xFlags, F_OF, 1);} + IFX(X_SF) IFNATIVE(NF_SF) {} else {BFCw(xFlags, F_SF, 1);} + break; + default: DEFAULT; } |