diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-04-07 10:29:52 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-04-07 10:29:52 +0200 |
| commit | 14695faa43b34bc4d81a8fc0d3756a2f7f60b398 (patch) | |
| tree | 122f6472baa1b6d44415cc26a6c2609e982fa27d /src | |
| parent | 1159c0530bba39bd293c146b313bfd5968c9efa0 (diff) | |
| download | box64-14695faa43b34bc4d81a8fc0d3756a2f7f60b398.tar.gz box64-14695faa43b34bc4d81a8fc0d3756a2f7f60b398.zip | |
[ARM64_DYNAREC] Handling of FASTROUND=0 for F2 0F E6 opcode
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/arm64/arm64_printer.c | 14 | ||||
| -rwxr-xr-x | src/dynarec/arm64/dynarec_arm64_f20f.c | 38 |
2 files changed, 46 insertions, 6 deletions
diff --git a/src/dynarec/arm64/arm64_printer.c b/src/dynarec/arm64/arm64_printer.c index 9fe7535d..55c06494 100755 --- a/src/dynarec/arm64/arm64_printer.c +++ b/src/dynarec/arm64/arm64_printer.c @@ -1108,6 +1108,20 @@ const char* arm64_print(uint32_t opcode, uintptr_t addr) return buff; } + // FRINTI + if(isMask(opcode, "0Q1011101f100001100110nnnnnddddd", &a)) { + char s = a.Q?'V':'D'; + char d = sf?'D':'S'; + int n = (a.Q && !sf)?4:2; + snprintf(buff, sizeof(buff), "VFRINTI %c%d.%d%c, %c%d.%d%c", s, Rd, n, d, s, Rn, n, d); + return buff; + } + if(isMask(opcode, "00011110ff100111110000nnnnnddddd", &a)) { + char s = (sf==0)?'S':((sf==1)?'D':'?'); + snprintf(buff, sizeof(buff), "FRINTI %c%d, %c%d", s, Rd, s, Rn); + return buff; + } + //CMP if(isMask(opcode, "00011110ff1mmmmm001000nnnnn0c000", &a)) { char s = (sf==0)?'S':((sf==1)?'D':'?'); diff --git a/src/dynarec/arm64/dynarec_arm64_f20f.c b/src/dynarec/arm64/dynarec_arm64_f20f.c index 144ae8d3..31745377 100755 --- a/src/dynarec/arm64/dynarec_arm64_f20f.c +++ b/src/dynarec/arm64/dynarec_arm64_f20f.c @@ -422,13 +422,39 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n case 0xE6: INST_NAME("CVTPD2DQ Gx, Ex"); nextop = F8; - GETEXSD(v1, 0, 0); + GETEX(v1, 0, 0); GETGX_empty(v0); - u8 = sse_setround(dyn, ninst, x1, x2, x3); - VFRINTIDQ(v0, v1); - x87_restoreround(dyn, ninst, u8); - VFCVTNSQD(v0, v0); // convert double -> int64 - SQXTN_32(v0, v0); // convert int64 -> int32 with saturation in lower part, RaZ high part + if(box64_dynarec_fastround) { + u8 = sse_setround(dyn, ninst, x1, x2, x3); + VFRINTIDQ(v0, v1); + x87_restoreround(dyn, ninst, u8); + VFCVTNSQD(v0, v0); // convert double -> int64 + SQXTN_32(v0, v0); // convert int64 -> int32 with saturation in lower part, RaZ high part + } else { + u8 = sse_setround(dyn, ninst, x1, x2, x3); + MRS_fpsr(x5); + BFCw(x5, FPSR_IOC, 1); // reset IOC bit + MSR_fpsr(x5); + ORRw_mask(x4, xZR, 1, 0); //0x80000000 + d0 = fpu_get_scratch(dyn); + for(int i=1; i>=0; --i) { + BFCw(x5, FPSR_IOC, 1); // reset IOC bit + MSR_fpsr(x5); + if(i) { + VMOVeD(d0, 0, v1, i); + FRINTID(d0, d0); + } else { + FRINTID(d0, v1); + } + FCVTZSwD(x1, d0); + MRS_fpsr(x5); // get back FPSR to check the IOC bit + TBZ(x5, FPSR_IOC, 4+4); + MOVw_REG(x1, x4); + VMOVQSfrom(v0, i, x1); + } + x87_restoreround(dyn, ninst, u8); + VMOVQDfrom(v0, 1, xZR); + } break; case 0xF0: |