diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-03-15 19:11:19 +0000 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-03-15 19:11:19 +0000 |
| commit | f64d21e8c294f3160ec0493f69affb2ad695e4d8 (patch) | |
| tree | 84de2ae531f857de113eeb90d05f4af2ae0cd34f /src | |
| parent | d5284a570430af9ea1666c87b2da70e7c0e97ad4 (diff) | |
| download | box64-f64d21e8c294f3160ec0493f69affb2ad695e4d8.tar.gz box64-f64d21e8c294f3160ec0493f69affb2ad695e4d8.zip | |
[RV64_DYNAREC] Implemented a solutionfor the problematic F_OF flag (use F_OF2 now)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_math.c | 2 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.c | 4 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 54 | ||||
| -rw-r--r-- | src/dynarec/rv64/rv64_emitter.h | 3 | ||||
| -rw-r--r-- | src/dynarec/rv64/rv64_epilog.S | 6 | ||||
| -rw-r--r-- | src/dynarec/rv64/rv64_prolog.S | 5 |
6 files changed, 68 insertions, 6 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_emit_math.c b/src/dynarec/rv64/dynarec_rv64_emit_math.c index 51491555..c151cfab 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_math.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_math.c @@ -98,7 +98,7 @@ void emit_add32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int64_t c, i XOR(s3, s3, s4); ANDI(s3, s3, 1); // OF: xor of two MSB's of cc BEQZ(s3, 4); - ORI(xFlags, xFlags, 1 << F_OF); + ORI(xFlags, xFlags, 1 << F_OF2); } } IFX(X_SF) { diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index f44a7ffe..36800a31 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -245,6 +245,7 @@ void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int sav if(savereg==0) savereg = x6; if(saveflags) { + FLAGS_ADJUST_TO11(xFlags, reg); SD(xFlags, xEmu, offsetof(x64emu_t, eflags)); } fpu_pushcache(dyn, ninst, reg, 0); @@ -288,6 +289,7 @@ void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int sav fpu_popcache(dyn, ninst, reg, 0); if(saveflags) { LD(xFlags, xEmu, offsetof(x64emu_t, eflags)); + FLAGS_ADJUST_FROM11(xFlags, reg); } SET_NODF(); dyn->last_ip = 0; @@ -296,6 +298,7 @@ void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int sav void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w) { MAYUSE(fnc); + FLAGS_ADJUST_TO11(xFlags, x3); SD(xFlags, xEmu, offsetof(x64emu_t, eflags)); fpu_pushcache(dyn, ninst, x3, 1); // x5..x8, x10..x17, x28..x31 those needs to be saved by caller @@ -351,6 +354,7 @@ void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w) fpu_popcache(dyn, ninst, x3, 1); LD(xFlags, xEmu, offsetof(x64emu_t, eflags)); + FLAGS_ADJUST_FROM11(xFlags, x3); SET_NODF(); } diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index a38fdf46..c50a3e20 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -176,7 +176,7 @@ #define SET_NODF() dyn->f.dfnone = 0 #define SET_DFOK() dyn->f.dfnone = 1 -#define CLEAR_FLAGS() IFX(X_ALL) {ANDI(xFlags, xFlags, ~((1UL<<F_AF) | (1UL<<F_CF) | (1UL<<F_OF) | (1UL<<F_ZF) | (1UL<<F_SF) | (1UL<<F_PF)));} +#define CLEAR_FLAGS() IFX(X_ALL) {ANDI(xFlags, xFlags, ~((1UL<<F_AF) | (1UL<<F_CF) | (1UL<<F_OF2) | (1UL<<F_ZF) | (1UL<<F_SF) | (1UL<<F_PF)));} #define CALC_SUB_FLAGS(op1_, op2, res, scratch1, scratch2, width) \ IFX(X_AF | X_CF | X_OF) { \ @@ -210,22 +210,61 @@ XOR(scratch1, scratch1, scratch2); \ ANDI(scratch1, scratch1, 1); \ BEQZ(scratch1, 4); \ - ORI(xFlags, xFlags, 1 << F_OF); \ + ORI(xFlags, xFlags, 1 << F_OF2); \ } \ } +// Adjust the xFlags bit 11 -> bit 5, result in reg (can be xFlags, but not s1) +#define FLAGS_ADJUST_FROM11(reg, s1)\ + ANDI(reg, xFlags, ~(1<<5)); \ + SRLI(s1, reg, 11-5); \ + ANDI(s1, s1, 1<<5); \ + OR(reg, reg, s1) + +// Adjust the xFlags bit 5 -> bit 11, source in reg (can be xFlags, but not s1) +#define FLAGS_ADJUST_TO11(reg, s1) \ + MOV64x(s1, ~(1<<11)); \ + AND(xFlags, reg, s1); \ + ANDI(s1, xFlags, 1<<5); \ + SLLI(s1, s1, 11-5); \ + OR(xFlags, xFlags, s1) + #ifndef MAYSETFLAGS #define MAYSETFLAGS() #endif #ifndef READFLAGS #define READFLAGS(A) \ - + if(((A)!=X_PEND && dyn->f.pending!=SF_SET) \ + && (dyn->f.pending!=SF_SET_PENDING)) { \ + if(dyn->f.pending!=SF_PENDING) { \ + LD(x3, xEmu, offsetof(x64emu_t, df)); \ + j64 = (GETMARKF)-(dyn->native_size); \ + BEQ(x3, xZR, j64); \ + } \ + CALL_(UpdateFlags, -1, 0); \ + FLAGS_ADJUST_FROM11(xFlags, x3); \ + MARKF; \ + dyn->f.pending = SF_SET; \ + SET_DFOK(); \ + } #endif #ifndef SETFLAGS #define SETFLAGS(A, B) \ - + if(dyn->f.pending!=SF_SET \ + && ((B)&SF_SUB) \ + && (dyn->insts[ninst].x64.gen_flags&(~(A)))) \ + READFLAGS(((dyn->insts[ninst].x64.gen_flags&X_PEND)?X_ALL:dyn->insts[ninst].x64.gen_flags)&(~(A)));\ + if(dyn->insts[ninst].x64.gen_flags) switch(B) { \ + case SF_SUBSET: \ + case SF_SET: dyn->f.pending = SF_SET; break; \ + case SF_PENDING: dyn->f.pending = SF_PENDING; break; \ + case SF_SUBSET_PENDING: \ + case SF_SET_PENDING: \ + dyn->f.pending = (dyn->insts[ninst].x64.gen_flags&X_PEND)?SF_SET_PENDING:SF_SET; \ + break; \ + } else dyn->f.pending = SF_SET #endif #ifndef JUMP #define JUMP(A, C) @@ -236,7 +275,12 @@ #ifndef BARRIER_NEXT #define BARRIER_NEXT(A) #endif - +#define UFLAG_OP1(A) if(dyn->insts[ninst].x64.gen_flags) {SDxw(A, xEmu, offsetof(x64emu_t, op1));} +#define UFLAG_OP2(A) if(dyn->insts[ninst].x64.gen_flags) {SDxw(A, xEmu, offsetof(x64emu_t, op2));} +#define UFLAG_OP12(A1, A2) if(dyn->insts[ninst].x64.gen_flags) {SDxw(A1, xEmu, offsetof(x64emu_t, op1));SDxw(A2, 0, offsetof(x64emu_t, op2));} +#define UFLAG_RES(A) if(dyn->insts[ninst].x64.gen_flags) {SDxw(A, xEmu, offsetof(x64emu_t, res));} +#define UFLAG_DF(r, A) if(dyn->insts[ninst].x64.gen_flags) {SET_DF(r, A)} +#define UFLAG_IF if(dyn->insts[ninst].x64.gen_flags) #ifndef DEFAULT #define DEFAULT *ok = -1; BARRIER(2) #endif diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index cd8e594b..566613fe 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -101,6 +101,9 @@ f28–31 ft8–11 FP temporaries Caller #define xZR 0 #define wZR xZR +// replacement for F_OF internaly, using a reserved bit. Need to use F_OF2 internaly, never F_OF directly! +#define F_OF2 F_res3 + // split a 32bits value in 20bits + 12bits, adjust the upper part is 12bits is negative #define SPLIT20(A) (((A)+0x800)>>12) #define SPLIT12(A) ((A)&0xfff) diff --git a/src/dynarec/rv64/rv64_epilog.S b/src/dynarec/rv64/rv64_epilog.S index af04279b..cf40153c 100644 --- a/src/dynarec/rv64/rv64_epilog.S +++ b/src/dynarec/rv64/rv64_epilog.S @@ -25,6 +25,12 @@ rv64_epilog: sd x29, 104(a0) sd x30, 112(a0) sd x31, 120(a0) + // adjust flags bit 5 -> bit 11 + li x7, ~(1<<11) + and x5, x5, x7 + andi x7, x5, 1<<5 + slli x7, x7, 11-5 + or x5, x5, x7 sd x5, 128(a0) //xFlags sd x6, 136(a0) // put back reg value in emu, including EIP (so x27 must be EIP now) //restore all used register diff --git a/src/dynarec/rv64/rv64_prolog.S b/src/dynarec/rv64/rv64_prolog.S index 229910b9..dd99cfec 100644 --- a/src/dynarec/rv64/rv64_prolog.S +++ b/src/dynarec/rv64/rv64_prolog.S @@ -46,6 +46,11 @@ rv64_prolog: ld x31, 120(a0) ld x5, 128(a0) //xFlags ld x6, 136(a0) // xRIP + // // adjust flags bit 11 -> bit 5 + andi x5, x5, ~(1<<5) // probably not usefull? + srli x7, x5, 11-5 + andi x7, x7, 1<<5 + or x5, x5, x7 // setup xMASK xori x7, x0, -1 srli x7, x7, 32 |