diff options
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/arm64_emitter.h | 14 | ||||
| -rwxr-xr-x | src/dynarec/arm64_printer.c | 11 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_0f.c | 31 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_660f.c | 35 |
4 files changed, 90 insertions, 1 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h index 50455be3..08117512 100755 --- a/src/dynarec/arm64_emitter.h +++ b/src/dynarec/arm64_emitter.h @@ -488,6 +488,20 @@ #define MULw(Rd, Rn, Rm) MADDw(Rd, Rn, Rm, xZR) #define MULxw(Rd, Rn, Rm) MADDxw(Rd, Rn, Rm, xZR) +// CLZ +#define CL_gen(sf, op, Rn, Rd) ((sf)<<31 | 1<<30 | 0b11010110<<21 | 0b00010<<11 | (op)<<10 | (Rn)<<5 | (Rd)) +#define CLZx(Rd, Rn) EMIT(CL_gen(1, 0, Rn, Rd)) +#define CLZw(Rd, Rn) EMIT(CL_gen(0, 0, Rn, Rd)) +#define CLZxw(Rd, Rn) EMIT(CL_gen(rex.w, 0, Rn, Rd)) +#define CLSx(Rd, Rn) EMIT(CL_gen(1, 1, Rn, Rd)) +#define CLSw(Rd, Rn) EMIT(CL_gen(0, 1, Rn, Rd)) +#define CLSxw(Rd, Rn) EMIT(CL_gen(rex.w, 1, Rn, Rd)) + +// RBIT +#define RBIT_gen(sf, Rn, Rd) ((sf)<<31 | 1<<30 | 0b11010110<<21 | (Rn)<<5 | (Rd)) +#define RBITx(Rd, Rn) EMIT(RBIT_gen(1, Rn, Rd)) +#define RBITw(Rd, Rn) EMIT(RBIT_gen(0, Rn, Rd)) +#define RBITxw(Rd, Rn) EMIT(RBIT_gen(rex.w, Rn, Rd)) // MRS #define MRS_gen(L, o0, op1, CRn, CRm, op2, Rt) (0b1101010100<<22 | (L)<<21 | 1<<20 | (o0)<<19 | (op1)<<16 | (CRn)<<12 | (CRm)<<8 | (op2)<<5 | (Rt)) diff --git a/src/dynarec/arm64_printer.c b/src/dynarec/arm64_printer.c index 53d72975..00fd4476 100755 --- a/src/dynarec/arm64_printer.c +++ b/src/dynarec/arm64_printer.c @@ -641,6 +641,17 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) 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]); + return buff; + } + if(isMask(opcode, "f101101011000000000000nnnnnddddd", &a)) { + snprintf(buff, sizeof(buff), "RBIT %s, %s", sf?Xt[Rd]:Wt[Rd], sf?Xt[Rn]:Wt[Rn]); + return buff; + } + + // MULL ADD if(isMask(opcode, "10011011U01mmmmm0aaaaannnnnddddd", &a)) { if(Ra==31) diff --git a/src/dynarec/dynarec_arm64_0f.c b/src/dynarec/dynarec_arm64_0f.c index 8e00682e..4694db51 100755 --- a/src/dynarec/dynarec_arm64_0f.c +++ b/src/dynarec/dynarec_arm64_0f.c @@ -310,6 +310,37 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin STRxw_U12(ed, wback, fixedaddress); } break; + case 0xBC: + INST_NAME("BSF Gd, Ed"); + SETFLAGS(X_ZF, SF_SET); + nextop = F8; + GETED(0); + GETGD; + TSTxw_REG(ed, ed); + B_MARK(cEQ); + RBITxw(x1, ed); // reverse + CLZxw(gd, x1); // x2 gets leading 0 == BSF + MARK; + CSETw(x1, cEQ); //ZF not set + BFIw(xFlags, x1, F_ZF, 1); + SET_DFNONE(x1); + break; + case 0xBD: + INST_NAME("BSR Gd, Ed"); + SETFLAGS(X_ZF, SF_SET); + nextop = F8; + GETED(0); + GETGD; + TSTxw_REG(ed, ed); + B_MARK(cEQ); + CLZxw(gd, ed); // x2 gets leading 0 + SUBxw_U12(gd, gd, rex.w?63:31); + NEGxw_REG(gd, gd); // complement + MARK; + CSETw(x1, cEQ); //ZF not set + BFIw(xFlags, x1, F_ZF, 1); + SET_DFNONE(x1); + break; default: DEFAULT; diff --git a/src/dynarec/dynarec_arm64_660f.c b/src/dynarec/dynarec_arm64_660f.c index 475bcab1..b768af74 100755 --- a/src/dynarec/dynarec_arm64_660f.c +++ b/src/dynarec/dynarec_arm64_660f.c @@ -166,7 +166,40 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n EORxw_REG(ed, ed, x1); EWBACK; break; - + case 0xBC: + INST_NAME("BSF Ew,Gw"); + SETFLAGS(X_ZF, SF_SET); + nextop = F8; + GETGD; + GETEW(x1, 0); // Get EW + TSTw_REG(x1, x1); + B_MARK(cEQ); + RBITw(x1, x1); // reverse + CLZw(x2, x1); // x2 gets leading 0 == BSF + BFIw(gd, x2, 0, 16); + MARK; + CSETw(x1, cEQ); //ZF not set + BFIw(xFlags, x1, F_ZF, 1); + SET_DFNONE(x1); + break; + case 0xBD: + INST_NAME("BSR Ew,Gw"); + SETFLAGS(X_ZF, SF_SET); + nextop = F8; + GETGD; + GETEW(x1, 0); // Get EW + TSTw_REG(x1, x1); + B_MARK(cEQ); + LSLw(x1, x1, 16); // put bits on top + CLZw(x2, x1); // x2 gets leading 0 + SUBw_U12(x2, x2, 15); + NEGw_REG(x2, x2); // complement + BFIx(gd, x2, 0, 16); + MARK; + CSETw(x1, cEQ); //ZF not set + BFIw(xFlags, x1, F_ZF, 1); + SET_DFNONE(x1); + break; default: DEFAULT; } |