Skip to content

Commit 7586bd4

Browse files
authored
[LA64_DYNAREC] Refacfored the handling of deferred flags (#3288)
1 parent 7f20c20 commit 7586bd4

File tree

9 files changed

+117
-100
lines changed

9 files changed

+117
-100
lines changed

src/dynarec/dynarec_native_functions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ static int flagsCacheNeedsTransform(dynarec_native_t* dyn, int ninst) {
720720
int jmp = dyn->insts[ninst].x64.jmp_insts;
721721
if(jmp<0)
722722
return 0;
723-
#ifdef ARM64
723+
#if defined(ARM64) || defined(LA64)
724724
// df_none is now a defered information
725725
if(dyn->insts[ninst].f_exit==dyn->insts[jmp].f_entry)
726726
return 0;

src/dynarec/dynarec_native_pass.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
4444
int rep = 0; // 0 none, 1=F2 prefix, 2=F3 prefix
4545
int need_epilog = 1;
4646
// Clean up (because there are multiple passes)
47-
#ifdef ARM64
47+
#if defined(ARM64) || defined(LA64)
4848
dyn->f = status_unk;
4949
#else
5050
dyn->f.pending = 0;
@@ -111,7 +111,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
111111
dyn->last_ip = 0;
112112
if(reset_n==-2) {
113113
MESSAGE(LOG_DEBUG, "Reset Caches to zero\n");
114-
#ifdef ARM64
114+
#if defined(ARM64) || defined(LA64)
115115
dyn->f = status_unk;
116116
#else
117117
dyn->f.dfnone = 0;
@@ -128,7 +128,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
128128
}
129129
if(dyn->insts[ninst].x64.barrier&BARRIER_FLAGS) {
130130
MESSAGE(LOG_DEBUG, "Apply Barrier Flags\n");
131-
#ifdef ARM64
131+
#if defined(ARM64) || defined(LA64)
132132
dyn->f = status_unk;
133133
#else
134134
dyn->f.dfnone = 0;
@@ -262,7 +262,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
262262
#endif
263263
}
264264
if(dyn->insts[next].x64.barrier&BARRIER_FLAGS) {
265-
#ifdef ARM64
265+
#if defined(ARM64) || defined(LA64)
266266
dyn->f = status_unk;
267267
#else
268268
dyn->f.pending = 0;
@@ -288,7 +288,7 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int
288288
// we use the 1st predecessor here
289289
if((ninst+1)<dyn->size && !dyn->insts[ninst+1].x64.alive) {
290290
// reset fpu value...
291-
#ifdef ARM64
291+
#if defined(ARM64) || defined(LA64)
292292
dyn->f = status_unk;
293293
#else
294294
dyn->f.dfnone = 0;

src/dynarec/la64/dynarec_la64_00.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2679,7 +2679,7 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
26792679
break;
26802680
case 0xCF:
26812681
INST_NAME("IRET");
2682-
SETFLAGS(X_ALL, SF_SET_NODF, NAT_FLAGS_NOFUSION); // Not a hack, EFLAGS are restored
2682+
SETFLAGS(X_ALL, SF_SET_DF, NAT_FLAGS_NOFUSION); // Not a hack, EFLAGS are restored
26832683
BARRIER(BARRIER_FLOAT);
26842684
iret_to_epilog(dyn, ip, ninst, rex.w);
26852685
*need_epilog = 0;

src/dynarec/la64/dynarec_la64_0f.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,7 @@ uintptr_t dynarec64_0F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni
417417
} else {
418418
INST_NAME("UCOMISS Gx, Ex");
419419
}
420-
SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION);
421-
SET_DFNONE();
420+
SETFLAGS(X_ALL, SF_SET_DF, NAT_FLAGS_NOFUSION);
422421
nextop = F8;
423422
GETGX(d0, 0);
424423
GETEXSS(v0, 0, 0);

src/dynarec/la64/dynarec_la64_functions.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -599,17 +599,20 @@ static const char* Ft[] = { "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", "fa6", "fa
599599
static const char* Vt[] = { "vra0", "vra1", "vra2", "vra3", "vra4", "vra5", "vra6", "vra7", "vrt0", "vrt1", "vrt2", "vrt3", "vrt4", "vrt5", "vrt6", "vrt7", "vrt8", "vrt9", "vrt10", "vrt11", "vrt12", "vrt13", "vrt14", "vrt15", "vrs0", "vrs1", "vrs2", "vrs3", "vrs4", "vrs5", "vrs6", "vrs7" };
600600
static const char* XVt[] = { "xvra0", "xvra1", "xvra2", "xvra3", "xvra4", "xvra5", "xvra6", "xvra7", "xvrt0", "xvrt1", "xvrt2", "xvrt3", "xvrt4", "xvrt5", "xvrt6", "xvrt7", "xvrt8", "xvrt9", "xvrt10", "xvrt11", "xvrt12", "xvrt13", "xvrt14", "xvrt15", "xvrs0", "xvrs1", "xvrs2", "xvrs3", "xvrs4", "xvrs5", "xvrs6", "xvrs7" };
601601

602+
static const char* df_status[] = { "unknown", "set", "none_pending", "none" };
603+
602604
void printf_x64_instruction(dynarec_native_t* dyn, zydis_dec_t* dec, instruction_x64_t* inst, const char* name);
603605
void inst_name_pass3(dynarec_native_t* dyn, int ninst, const char* name, rex_t rex)
604606
{
605607
if (!dyn->need_dump && !BOX64ENV(dynarec_gdbjit) && !BOX64ENV(dynarec_perf_map)) return;
606608

607609
static char buf[4096];
608-
int length = sprintf(buf, "barrier=%d state=%d/%d(%d), %s=%X/%X, use=%X, need=%X/%X, fuse=%d/%d, sm=%d(%d/%d)",
610+
int length = sprintf(buf, "barrier=%d state=%d/%s(%s->%s), %s=%X/%X, use=%X, need=%X/%X, fuse=%d/%d, sm=%d(%d/%d)",
609611
dyn->insts[ninst].x64.barrier,
610612
dyn->insts[ninst].x64.state_flags,
611-
dyn->f.pending,
612-
dyn->f.dfnone,
613+
df_status[dyn->f],
614+
df_status[dyn->insts[ninst].f_entry],
615+
df_status[dyn->insts[ninst].f_exit],
613616
dyn->insts[ninst].x64.may_set ? "may" : "set",
614617
dyn->insts[ninst].x64.set_flags,
615618
dyn->insts[ninst].x64.gen_flags,

src/dynarec/la64/dynarec_la64_helper.c

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ void jump_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst)
349349
}
350350
TABLE64C(x2, const_epilog);
351351
SMEND();
352+
CHECK_DFNONE(0);
352353
BR(x2);
353354
}
354355

@@ -368,6 +369,7 @@ void jump_to_epilog_fast(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst)
368369
}
369370
TABLE64C(x2, const_epilog_fast);
370371
SMEND();
372+
CHECK_DFNONE(0);
371373
BR(x2);
372374
}
373375

@@ -407,6 +409,7 @@ void jump_to_next(dynarec_la64_t* dyn, uintptr_t ip, int reg, int ninst, int is3
407409
if (is32bits)
408410
ip &= 0xffffffffLL;
409411

412+
CHECK_DFNONE(0);
410413
int dest;
411414
if (reg) {
412415
if (reg != xRIP) {
@@ -441,6 +444,7 @@ void ret_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex)
441444
MAYUSE(dyn);
442445
MAYUSE(ninst);
443446
MESSAGE(LOG_DUMP, "Ret to epilog\n");
447+
CHECK_DFNONE(0);
444448
POP1z(xRIP);
445449
MVz(x1, xRIP);
446450
SMEND();
@@ -465,6 +469,7 @@ void retn_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, rex_t rex, int
465469
MAYUSE(dyn);
466470
MAYUSE(ninst);
467471
MESSAGE(LOG_DUMP, "Retn to epilog\n");
472+
CHECK_DFNONE(0);
468473
POP1z(xRIP);
469474
if (n > 0x7ff) {
470475
MOV64x(x1, n);
@@ -513,7 +518,7 @@ void iret_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, int is64bits)
513518
AND(xFlags, xFlags, x1);
514519
ORI(xFlags, xFlags, 0x2);
515520
SPILL_EFLAGS();
516-
SET_DFNONE();
521+
FORCE_DFNONE();
517522
// POP RSP
518523
if (is64bits) {
519524
POP1(x3); // rsp
@@ -540,6 +545,7 @@ void iret_to_epilog(dynarec_la64_t* dyn, uintptr_t ip, int ninst, int is64bits)
540545
void call_c(dynarec_la64_t* dyn, int ninst, la64_consts_t fnc, int reg, int ret, int saveflags, int savereg, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6)
541546
{
542547
MAYUSE(fnc);
548+
CHECK_DFNONE(1);
543549
if (savereg == 0)
544550
savereg = x87pc;
545551
if (saveflags) {
@@ -608,6 +614,7 @@ void call_c(dynarec_la64_t* dyn, int ninst, la64_consts_t fnc, int reg, int ret,
608614
void call_n(dynarec_la64_t* dyn, int ninst, void* fnc, int w)
609615
{
610616
MAYUSE(fnc);
617+
CHECK_DFNONE(1);
611618
fpu_pushcache(dyn, ninst, x3, 1);
612619
ST_D(xRSP, xEmu, offsetof(x64emu_t, regs[_SP]));
613620
ST_D(xRBP, xEmu, offsetof(x64emu_t, regs[_BP]));
@@ -2269,31 +2276,44 @@ static void flagsCacheTransform(dynarec_la64_t* dyn, int ninst, int s1)
22692276
int jmp = dyn->insts[ninst].x64.jmp_insts;
22702277
if (jmp < 0)
22712278
return;
2272-
if (dyn->f.dfnone || ((dyn->insts[jmp].f_exit.dfnone && !dyn->insts[jmp].f_entry.dfnone) && !dyn->insts[jmp].x64.use_flags)) // flags are fully known, nothing we can do more
2279+
if (dyn->insts[jmp].f_exit == dyn->insts[jmp].f_entry) // flags will be fully known, nothing we can do more
22732280
return;
22742281
MESSAGE(LOG_DUMP, "\tFlags fetch ---- ninst=%d -> %d\n", ninst, jmp);
2275-
int go = (dyn->insts[jmp].f_entry.dfnone && !dyn->f.dfnone && !dyn->insts[jmp].df_notneeded) ? 1 : 0;
2276-
switch (dyn->insts[jmp].f_entry.pending) {
2277-
case SF_UNKNOWN:
2278-
go = 0;
2282+
int go_fetch = 0;
2283+
switch (dyn->insts[jmp].f_entry) {
2284+
case status_unk:
2285+
if (dyn->insts[ninst].f_exit == status_none_pending) {
2286+
FORCE_DFNONE();
2287+
}
22792288
break;
2280-
default:
2281-
if (go && !(dyn->insts[jmp].x64.need_before & X_PEND) && (dyn->f.pending != SF_UNKNOWN)) {
2282-
// just clear df flags
2283-
go = 0;
2284-
ST_W(xZR, xEmu, offsetof(x64emu_t, df));
2289+
case status_set:
2290+
if (dyn->insts[ninst].f_exit == status_none_pending) {
2291+
FORCE_DFNONE();
22852292
}
2293+
if (dyn->insts[ninst].f_exit == status_unk)
2294+
go_fetch = 1;
2295+
break;
2296+
case status_none_pending:
2297+
if (dyn->insts[ninst].f_exit != status_none)
2298+
go_fetch = 1;
2299+
break;
2300+
case status_none:
2301+
if (dyn->insts[ninst].f_exit == status_none_pending) {
2302+
FORCE_DFNONE();
2303+
} else
2304+
go_fetch = 1;
22862305
break;
22872306
}
2288-
if (go) {
2289-
if (dyn->f.pending != SF_PENDING) {
2307+
if (go_fetch) {
2308+
if (dyn->f == status_unk) {
22902309
LD_WU(s1, xEmu, offsetof(x64emu_t, df));
22912310
j64 = (GETMARKF2) - (dyn->native_size);
22922311
BEQZ(s1, j64);
22932312
}
22942313
CALL_(const_updateflags, -1, 0, 0, 0);
22952314
MARKF2;
22962315
}
2316+
MESSAGE(LOG_DUMP, "\t---- Flags fetch\n");
22972317
}
22982318

22992319
void CacheTransform(dynarec_la64_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3)

src/dynarec/la64/dynarec_la64_helper.h

Lines changed: 44 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -831,36 +831,29 @@
831831
LOAD_REG(R15);
832832

833833
#define FORCE_DFNONE() ST_W(xZR, xEmu, offsetof(x64emu_t, df))
834+
#define CHECK_DFNONE(N) \
835+
do { \
836+
if (dyn->f == status_none_pending) { \
837+
FORCE_DFNONE(); \
838+
if (N) dyn->f = status_none; \
839+
} \
840+
} while (0)
834841

835-
#define SET_DFNONE() \
836-
do { \
837-
if (!dyn->f.dfnone) { \
838-
FORCE_DFNONE(); \
839-
} \
840-
if (!dyn->insts[ninst].x64.may_set) { \
841-
dyn->f.dfnone = 1; \
842-
} \
842+
#define SET_DFNONE() \
843+
do { \
844+
if (!dyn->insts[ninst].x64.may_set && (dyn->f != status_none)) { \
845+
dyn->f = status_none_pending; \
846+
} \
843847
} while (0)
844848

845-
#define SET_DF(S, N) \
846-
if ((N) != d_none) { \
847-
MOV32w(S, (N)); \
848-
ST_W(S, xEmu, offsetof(x64emu_t, df)); \
849-
if (dyn->f.pending == SF_PENDING \
850-
&& dyn->insts[ninst].x64.need_after \
851-
&& !(dyn->insts[ninst].x64.need_after & X_PEND)) { \
852-
CALL_(const_updateflags, -1, 0, 0, 0); \
853-
dyn->f.pending = SF_SET; \
854-
SET_NODF(); \
855-
} \
856-
dyn->f.dfnone = 0; \
857-
} else \
849+
#define SET_DF(S, N) \
850+
if ((N) != d_none) { \
851+
MOV32w(S, (N)); \
852+
ST_W(S, xEmu, offsetof(x64emu_t, df)); \
853+
dyn->f = status_set; \
854+
} else \
858855
SET_DFNONE()
859856

860-
#define SET_NODF() dyn->f.dfnone = 0
861-
#define SET_DFOK() \
862-
dyn->f.dfnone = 1
863-
864857
#define CLEAR_FLAGS_(s) \
865858
MOV64x(s, (1UL << F_AF) | (1UL << F_CF) | (1UL << F_OF) | (1UL << F_ZF) | (1UL << F_SF) | (1UL << F_PF)); \
866859
ANDN(xFlags, xFlags, s);
@@ -942,18 +935,11 @@
942935
#endif
943936

944937
#ifndef READFLAGS
945-
#define READFLAGS(A) \
946-
if (((A) != X_PEND && dyn->f.pending != SF_SET) \
947-
&& (dyn->f.pending != SF_SET_PENDING)) { \
948-
if (dyn->f.pending != SF_PENDING) { \
949-
LD_WU(x3, xEmu, offsetof(x64emu_t, df)); \
950-
j64 = (GETMARKF) - (dyn->native_size); \
951-
BEQ(x3, xZR, j64); \
952-
} \
953-
CALL_(const_updateflags, -1, 0, 0, 0); \
954-
MARKF; \
955-
dyn->f.pending = SF_SET; \
956-
SET_DFOK(); \
938+
#define READFLAGS(A) \
939+
if ((A) != X_PEND \
940+
&& (dyn->f == status_unk)) { \
941+
CALL_(const_updateflags, -1, 0, 0, 0); \
942+
dyn->f = status_none; \
957943
}
958944
#endif
959945

@@ -987,32 +973,28 @@
987973
#define NAT_FLAGS_ENABLE_SIGN() dyn->insts[ninst].nat_flags_sign = 1
988974

989975
#ifndef SETFLAGS
990-
#define SETFLAGS(A, B, FUSION) \
991-
if (dyn->f.pending != SF_SET \
992-
&& ((B) & SF_SUB) \
993-
&& (dyn->insts[ninst].x64.gen_flags & (~(A)))) \
994-
READFLAGS(((dyn->insts[ninst].x64.gen_flags & X_PEND) ? X_ALL : dyn->insts[ninst].x64.gen_flags) & (~(A))); \
995-
if (dyn->insts[ninst].x64.gen_flags) switch (B) { \
996-
case SF_SUBSET: \
997-
case SF_SET: dyn->f.pending = SF_SET; break; \
998-
case SF_SET_DF: \
999-
dyn->f.pending = SF_SET; \
1000-
dyn->f.dfnone = 1; \
1001-
break; \
1002-
case SF_SET_NODF: \
1003-
dyn->f.pending = SF_SET; \
1004-
dyn->f.dfnone = 0; \
1005-
break; \
1006-
case SF_PENDING: dyn->f.pending = SF_PENDING; break; \
1007-
case SF_SUBSET_PENDING: \
1008-
case SF_SET_PENDING: \
1009-
dyn->f.pending = (dyn->insts[ninst].x64.gen_flags & X_PEND) ? SF_SET_PENDING : SF_SET; \
1010-
break; \
1011-
} \
1012-
else \
1013-
dyn->f.pending = SF_SET; \
1014-
dyn->insts[ninst].nat_flags_nofusion = (FUSION)
976+
#define SETFLAGS(A, B, FUSION) \
977+
do { \
978+
if (((B) & SF_SUB) \
979+
&& (dyn->insts[ninst].x64.gen_flags & (~(A)))) \
980+
READFLAGS(((dyn->insts[ninst].x64.gen_flags & X_PEND) ? X_ALL : dyn->insts[ninst].x64.gen_flags) & (~(A))); \
981+
if (dyn->insts[ninst].x64.gen_flags) switch (B) { \
982+
case SF_SET_DF: dyn->f = status_set; break; \
983+
case SF_SET_NODF: SET_DFNONE(); break; \
984+
case SF_SUBSET: \
985+
case SF_SUBSET_PENDING: \
986+
case SF_SET: \
987+
case SF_PENDING: \
988+
case SF_SET_PENDING: \
989+
SET_DFNONE(); \
990+
break; \
991+
} \
992+
else \
993+
SET_DFNONE(); \
994+
dyn->insts[ninst].nat_flags_nofusion = (FUSION); \
995+
} while (0)
1015996
#endif
997+
1016998
#ifndef JUMP
1017999
#define JUMP(A, C)
10181000
#endif

0 commit comments

Comments
 (0)