diff options
| author | xctan <xctan@cirno.icu> | 2024-08-08 14:25:05 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-08 08:25:05 +0200 |
| commit | 18954abf54c75ab19a93cb51f79d67cd33a93d5a (patch) | |
| tree | 4e0e1092b0ed81a62c24d3a2a9bb6a1f252a84df /src | |
| parent | ed7ee12e7ec6d965ceef6a47dca7b92e726218d5 (diff) | |
| download | box64-18954abf54c75ab19a93cb51f79d67cd33a93d5a.tar.gz box64-18954abf54c75ab19a93cb51f79d67cd33a93d5a.zip | |
[RV64_DYNAREC] Fixed flag generation in IMUL/MUL opcode (#1715)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_3.c | 42 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_66.c | 2 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_660f.c | 2 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 5 |
4 files changed, 39 insertions, 12 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 60654a78..ada7e6d0 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -1028,7 +1028,6 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 4: INST_NAME("MUL AL, Ed"); SETFLAGS(X_ALL, SF_PENDING); - UFLAG_DF(x1, d_mul8); GETEB(x1, 0); ANDI(x2, xRAX, 0xff); MULW(x1, x2, x1); @@ -1037,11 +1036,11 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int AND(xRAX, xRAX, x2); ZEXTH(x1, x1); OR(xRAX, xRAX, x1); + UFLAG_DF(x1, d_mul8); break; case 5: INST_NAME("IMUL AL, Eb"); SETFLAGS(X_ALL, SF_PENDING); - UFLAG_DF(x1, d_imul8); GETSEB(x1, 0); SLLI(x2, xRAX, 56); SRAI(x2, x2, 56); @@ -1051,6 +1050,7 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int AND(xRAX, xRAX, x2); ZEXTH(x1, x1); OR(xRAX, xRAX, x1); + UFLAG_DF(x1, d_imul8); break; case 6: INST_NAME("DIV Eb"); @@ -1097,8 +1097,9 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int break; case 4: INST_NAME("MUL EAX, Ed"); - SETFLAGS(X_ALL, SF_PENDING); - UFLAG_DF(x2, rex.w?d_mul64:d_mul32); + SETFLAGS(X_ALL, SF_SET); + CLEAR_FLAGS(); + SET_DFNONE(); GETED(0); if(rex.w) { if(ed==xRDX) gd=x3; else gd=xRDX; @@ -1115,13 +1116,23 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int AND(xRAX, xRDX, xMASK); SRLI(xRDX, xRDX, 32); } - UFLAG_RES(xRAX); - UFLAG_OP1(xRDX); + IFX (X_CF | X_OF) { + // CF = OF = RDX != 0 + SNEZ(x6, xRDX); + IFX (X_CF) { + OR(xFlags, xFlags, x6); // F_CF == 0 + } + IFX (X_OF) { + SLLI(x6, x6, F_OF2); + OR(xFlags, xFlags, x6); + } + } break; case 5: INST_NAME("IMUL EAX, Ed"); - SETFLAGS(X_ALL, SF_PENDING); - UFLAG_DF(x2, rex.w?d_imul64:d_imul32); + SETFLAGS(X_ALL, SF_SET); + CLEAR_FLAGS(); + SET_DFNONE(); GETSED(0); if(rex.w) { if(ed==xRDX) gd=x3; else gd=xRDX; @@ -1134,8 +1145,19 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int AND(xRAX, xRDX, xMASK); SRLI(xRDX, xRDX, 32); } - UFLAG_RES(xRAX); - UFLAG_OP1(xRDX); + IFX (X_CF | X_OF) { + // CF = OF = SignExtend(RAX) != RDX:RAX + SRAIxw(x6, xRAX, rex.w ? 63 : 31); + SUBxw(x6, xRDX, x6); + SNEZ(x6, x6); + IFX (X_CF) { + OR(xFlags, xFlags, x6); // F_CF == 0 + } + IFX (X_OF) { + SLLI(x6, x6, F_OF2); + OR(xFlags, xFlags, x6); + } + } break; case 6: INST_NAME("DIV Ed"); diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index 0f101d16..a90bdb77 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -426,7 +426,6 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } SETFLAGS(X_ALL, SF_PENDING); nextop = F8; - UFLAG_DF(x1, d_imul16); GETSEW(x1, (opcode==0x69)?2:1); if(opcode==0x69) i32 = F16S; else i32 = F8S; MOV32w(x2, i32); @@ -435,6 +434,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni UFLAG_RES(x2); gd=x2; GWBACK; + UFLAG_DF(x1, d_imul16); break; case 0x70: case 0x71: diff --git a/src/dynarec/rv64/dynarec_rv64_660f.c b/src/dynarec/rv64/dynarec_rv64_660f.c index d2610cf4..d4f44b3c 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f.c +++ b/src/dynarec/rv64/dynarec_rv64_660f.c @@ -2309,13 +2309,13 @@ uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int INST_NAME("IMUL Gw,Ew"); SETFLAGS(X_ALL, SF_PENDING); nextop = F8; - UFLAG_DF(x1, d_imul16); GETSEW(x1, 0); GETSGW(x2); MULW(x2, x2, x1); UFLAG_RES(x2); ZEXTH(x2, x2); GWBACK; + UFLAG_DF(x1, d_imul16); break; case 0xB3: INST_NAME("BTR Ew, Gw"); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 9db55bf3..b45e95a4 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -854,6 +854,11 @@ if ((N) != d_none) { \ MOV_U12(S, (N)); \ SW(S, xEmu, offsetof(x64emu_t, df)); \ + if(dyn->f.pending==SF_PENDING && dyn->insts[ninst].x64.need_after && !(dyn->insts[ninst].x64.need_after&X_PEND)) { \ + CALL_(UpdateFlags, -1, 0); \ + dyn->f.pending = SF_SET; \ + SET_NODF(); \ + } \ dyn->f.dfnone = 0; \ } else \ SET_DFNONE() |