diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-06-14 12:19:21 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-06-14 12:19:21 +0200 |
| commit | 883fc1681d214efe8c2d43089e2e38900d6d7db2 (patch) | |
| tree | 9d5a19abcebdc6bde925e453dc28bd18beab354d /src | |
| parent | 6b2b672c5ec8adba9a5a184c114d678339cf6200 (diff) | |
| download | box64-883fc1681d214efe8c2d43089e2e38900d6d7db2.tar.gz box64-883fc1681d214efe8c2d43089e2e38900d6d7db2.zip | |
Added 66 0F 3A 0B opcode ([DYNAREC] too)
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/arm64_emitter.h | 8 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_660f.c | 19 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_helper.c | 7 | ||||
| -rw-r--r-- | src/emu/x64run660f.c | 25 |
4 files changed, 54 insertions, 5 deletions
diff --git a/src/dynarec/arm64_emitter.h b/src/dynarec/arm64_emitter.h index 3d3fe8f6..7de69a59 100755 --- a/src/dynarec/arm64_emitter.h +++ b/src/dynarec/arm64_emitter.h @@ -1208,10 +1208,18 @@ #define FRINT64XD(Dd, Dn) EMIT(FRINTxx_scalar(0b01, 0b11, Dn, Dd)) #define FRINT_scalar(type, rmode, Rn, Rd) (0b11110<<24 | (type)<<22 | 1<<21 | 0b001<<18 | (rmode)<<15 | 0b10000<<10 | (Rn)<<5 | (Rd)) +// round toward 0 (truncate) #define FRINTZS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b011, Sn, Sd)) +// round toward 0 (truncate) #define FRINTZD(Sd, Sn) EMIT(FRINT_scalar(0b01, 0b011, Sn, Sd)) +// round with current FPCR mode #define FRINTXS(Sd, Sn) EMIT(FRINT_scalar(0b00, 0b110, Sn, Sd)) +// round with current FPCR mode #define FRINTXD(Sd, Sn) EMIT(FRINT_scalar(0b01, 0b110, Sn, Sd)) +// round with mode, mode is 0 = TieEven, 1=+inf, 2=-inf, 3=zero +#define FRINTRRS(Sd, Sn, mode) EMIT(FRINT_scalar(0b00, ((mode)&3), Sn, Sd)) +// round with mode, mode is 0 = TieEven, 1=+inf, 2=-inf, 3=zero +#define FRINTRRD(Dd, Dn, mode) EMIT(FRINT_scalar(0b01, ((mode)&3), Dn, Dd)) // FMAX / FMIN #define FMINMAX_vector(Q, U, o1, sz, Rm, Rn, Rd) ((Q)<<30 | (U)<<29 | 0b01110<<24 | (o1)<<23 | (sz)<<22 | 0b1<<21 | (Rm)<<16 | 0b11110<<11 | 1<<10 | (Rn)<<5 | (Rd)) diff --git a/src/dynarec/dynarec_arm64_660f.c b/src/dynarec/dynarec_arm64_660f.c index 45610ab0..66abfafa 100755 --- a/src/dynarec/dynarec_arm64_660f.c +++ b/src/dynarec/dynarec_arm64_660f.c @@ -319,6 +319,25 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n case 0x3A: // these are some more SSSE3 opcodes opcode = F8; switch(opcode) { + case 0x0B: + INST_NAME("ROUNDSD Gx, Ex, Ib"); + nextop = F8; + GETGX(q0); + GETEX(q1, 1); + u8 = F8; + v1 = fpu_get_scratch(dyn); + if(u8&4) { + u8 = sse_setround(dyn, ninst, x1, x2, x3); + FRINTXD(v1, q1); + x87_restoreround(dyn, ninst, u8); + } else { + const uint8_t rounds[] = {0, 2, 1, 3}; + MAYUSE(rounds); + FRINTRRD(v1, q1, rounds[u8&3]); + } + VMOVeD(q0, 0, v1, 0); + break; + case 0x0F: INST_NAME("PALIGNR Gx, Ex, Ib"); nextop = F8; diff --git a/src/dynarec/dynarec_arm64_helper.c b/src/dynarec/dynarec_arm64_helper.c index b0aedef6..3365cc6b 100755 --- a/src/dynarec/dynarec_arm64_helper.c +++ b/src/dynarec/dynarec_arm64_helper.c @@ -901,8 +901,6 @@ void x87_reget_st(dynarec_arm_t* dyn, int ninst, int s1, int s2, int st) #endif } -static int round_map[] = {0, 2, 1, 3}; // map x64 -> arm round flag - // Set rounding according to cw flags, return reg to restore flags int x87_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3) { @@ -924,9 +922,8 @@ int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3) MAYUSE(dyn); MAYUSE(ninst); MAYUSE(s1); MAYUSE(s2); LDRH_U12(s1, xEmu, offsetof(x64emu_t, mxcsr)); - UBFXx(s2, s1, 13, 2); // extract round... - MOV64x(s1, (uintptr_t)round_map); - LDRw_REG_LSL2(s2, s1, s2); + RBITw(s2, s1); // round is on bits 13-14 on x86, + LSRw(s2, s2, 17); // but we want the reverse of that MRS_fpcr(s1); // get fpscr MOVx_REG(s3, s1); BFIx(s1, s2, 22, 2); // inject new round diff --git a/src/emu/x64run660f.c b/src/emu/x64run660f.c index 3b2ad0cf..0c287acd 100644 --- a/src/emu/x64run660f.c +++ b/src/emu/x64run660f.c @@ -309,6 +309,31 @@ int Run660F(x64emu_t *emu, rex_t rex) case 0x3A: // these are some SSE3 opcodes opcode = F8; switch(opcode) { + case 0x0B: // ROUNDSD Gx, Ex, u8 + nextop = F8; + GETEX(1); + GETGX; + tmp8u = F8; // ignoring bit 3 interupt thingy + if(tmp8u&4) + tmp8u = (emu->mxcsr>>13)&3; + else + tmp8u &= 3; + switch(tmp8u) { + case ROUND_Nearest: + GX->d[0] = floor(EX->d[0]+0.5); + break; + case ROUND_Down: + GX->d[0] = floor(EX->d[0]); + break; + case ROUND_Up: + GX->d[0] = ceil(EX->d[0]); + break; + case ROUND_Chop: + GX->d[0] = EX->d[0]; + break; + } + break; + case 0x0F: // PALIGNR GX, EX, u8 nextop = F8; GETEX(1); |