diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-05-07 22:00:53 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-05-07 22:00:53 +0200 |
| commit | 404bfdc78271bf15db14e6b5539d22026f2bc964 (patch) | |
| tree | cca4b9683f041948aecdf2f79f3f70a70053eb79 /src | |
| parent | b74a1b5a3287907d123d05d7ddef1fa2dd7592e2 (diff) | |
| download | box64-404bfdc78271bf15db14e6b5539d22026f2bc964.tar.gz box64-404bfdc78271bf15db14e6b5539d22026f2bc964.zip | |
[ARM64_DYNAREC] Added F3 0F B8 opcode
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/arm64/arm64_emitter.h | 5 | ||||
| -rwxr-xr-x | src/dynarec/arm64/dynarec_arm64_f30f.c | 36 |
2 files changed, 41 insertions, 0 deletions
diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h index 2d552874..d480d2d9 100755 --- a/src/dynarec/arm64/arm64_emitter.h +++ b/src/dynarec/arm64/arm64_emitter.h @@ -1691,6 +1691,11 @@ #define UADDLV_16(Rd, Rn) EMIT(ADDLV_vector(0, 1, 0b01, Rn, Rd)) #define UADDLV_32(Rd, Rn) EMIT(ADDLV_vector(0, 1, 0b10, Rn, Rd)) +// Population Count per byte +#define CNT_vector(Q, size, Rn, Rd) ((Q)<<30 | 0b01110<<24 | (size)<<22 | 0b10000<<17 | 0b00101<<12 | 0b10<<10 | (Rn)<<5 | (Rd)) +#define CNT_8(Rd, Rn) EMIT(CNT_vector(0, 0b00, Rn, Rd)) +#define CNTQ_8(Rd, Rn) EMIT(CNT_vector(1, 0b00, Rn, Rd)) + // MOV Immediate #define MOVI_vector(Q, op, abc, cmode, defgh, Rd) ((Q)<<30 | (op)<<29 | 0b0111100000<<19 | (abc)<<16 | (cmode)<<12 | 1<<10 | (defgh)<<5 | (Rd)) #define MOVIQ_8(Rd, imm8) EMIT(MOVI_vector(1, 0, (((imm8)>>5)&0b111), 0b1110, ((imm8)&0b11111), Rd)) diff --git a/src/dynarec/arm64/dynarec_arm64_f30f.c b/src/dynarec/arm64/dynarec_arm64_f30f.c index ca5ef767..5b3aa85e 100755 --- a/src/dynarec/arm64/dynarec_arm64_f30f.c +++ b/src/dynarec/arm64/dynarec_arm64_f30f.c @@ -378,6 +378,42 @@ uintptr_t dynarec64_F30F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n } break; + case 0xB8: + INST_NAME("POPCNT Gd, Ed"); + SETFLAGS(X_ALL, SF_SET); + SET_DFNONE(x1); + nextop = F8; + v1 = fpu_get_scratch(dyn); + GETGD; + if(MODREG) { + GETED(0); + if(rex.w) + VMOVQDfrom(v1, 0, ed); + else { + MOVxw_REG(x1, ed); // need to clear uper part + VMOVQDfrom(v1, 0, x1); + } + } else { + if(rex.w) { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, &unscaled, 0xfff<<3, 7, rex, NULL, 0, 0); + VLD64(v1, ed, fixedaddress); + } else { + GETED(0); // just load and clear the upper part + VMOVQDfrom(v1, 0, ed); + } + } + CNT_8(v1, v1); + UADDLV_8(v1, v1); + VMOVQDto(gd, v1, 0); + IFX(X_ALL) { + MOV32w(x1, (1<<F_OF) | (1<<F_SF) | (1<<F_ZF) | (1<<F_AF) | (1<<F_CF) | (1<<F_PF)); + BICw(xFlags, xFlags, x1); + CBNZx(gd, 4+4); + BFIw(xFlags, xFlags, F_ZF, 1); + } + break; + case 0xBC: INST_NAME("TZCNT Gd, Ed"); SETFLAGS(X_CF|X_ZF, SF_SUBSET); |