diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2025-02-16 14:41:08 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2025-02-16 14:41:08 +0100 |
| commit | 85e79a822484abb642b59dc103c08393412336b5 (patch) | |
| tree | eaba11d29e33ad176fe4013589b735efec345b00 /src | |
| parent | 9ef3e080fade70147de0569de6eb23b89f827142 (diff) | |
| download | box64-85e79a822484abb642b59dc103c08393412336b5.tar.gz box64-85e79a822484abb642b59dc103c08393412336b5.zip | |
[ARM64_DYNAREC] Improved safeflags=2
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_00.c | 134 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_0f.c | 16 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_64.c | 42 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_66.c | 66 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_660f.c | 16 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.c | 36 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.h | 14 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_pass0.h | 1 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_pass1.h | 1 |
9 files changed, 219 insertions, 107 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index 8ccf25ba..b43ea421 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -1764,10 +1764,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 1: case 2: if(rep==1) {INST_NAME("REPNZ CMPSB");} else {INST_NAME("REPZ CMPSB");} - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); SMREAD(); - SETFLAGS(X_ALL, SF_SET_PENDING); CBZx_NEXT(xRCX); TBNZ_MARK2(xFlags, F_DF); MARK; // Part with DF==0 @@ -1806,9 +1808,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 1: case 2: if(rep==1) {INST_NAME("REPNZ CMPSD");} else {INST_NAME("REPZ CMPSD");} - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); - SETFLAGS(X_ALL, SF_SET_PENDING); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); SMREAD(); CBZx_NEXT(xRCX); TBNZ_MARK2(xFlags, F_DF); @@ -1948,10 +1952,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 1: case 2: if(rep==1) {INST_NAME("REPNZ SCASB");} else {INST_NAME("REPZ SCASB");} - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); SMREAD(); - SETFLAGS(X_ALL, SF_SET_PENDING); CBZx_NEXT(xRCX); UBFXw(x1, xRAX, 0, 8); TBNZ_MARK2(xFlags, F_DF); @@ -1987,10 +1993,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 1: case 2: if(rep==1) {INST_NAME("REPNZ SCASD");} else {INST_NAME("REPZ SCASD");} - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); SMREAD(); - SETFLAGS(X_ALL, SF_SET_PENDING); CBZx_NEXT(xRCX); TBNZ_MARK2(xFlags, F_DF); MARK; // Part with DF==0 @@ -2776,14 +2784,15 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; } break; - case 0xD2: // TODO: Jump if CL is 0 + case 0xD2: nextop = F8; switch((nextop>>3)&7) { case 0: INST_NAME("ROL Eb, CL"); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } SETFLAGS(X_OF|X_CF, SF_SUBSET); - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); UFLAG_IF { ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f CBZw_NEXT(x2); @@ -2810,9 +2819,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 1: INST_NAME("ROR Eb, CL"); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } SETFLAGS(X_OF|X_CF, SF_SUBSET); - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); UFLAG_IF { ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f CBZw_NEXT(x2); @@ -2837,10 +2847,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 2: INST_NAME("RCL Eb, CL"); - READFLAGS(X_CF); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } else { + READFLAGS(X_CF); + } SETFLAGS(X_OF|X_CF, SF_SUBSET); - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f // get CL % 9 MOV32w(x3, 0x1c72); // 0x10000 / 9 + 1 (this is precise enough in the 0..31 range) @@ -2874,10 +2886,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 3: INST_NAME("RCR Eb, CL"); - READFLAGS(X_CF); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } else { + READFLAGS(X_CF); + } SETFLAGS(X_OF|X_CF, SF_SUBSET); - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f // get CL % 9 MOV32w(x3, 0x1c72); // 0x10000 / 9 + 1 @@ -2904,9 +2918,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 4: case 6: INST_NAME("SHL Eb, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f UFLAG_IF { CBZw_NEXT(x2); @@ -2917,9 +2933,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 5: INST_NAME("SHR Eb, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f UFLAG_IF { CBZw_NEXT(x2); @@ -2930,9 +2948,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 7: INST_NAME("SAR Eb, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f UFLAG_IF { CBZw_NEXT(x2); @@ -2948,9 +2968,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin switch((nextop>>3)&7) { case 0: INST_NAME("ROL Ed, CL"); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } SETFLAGS(X_OF|X_CF, SF_SUBSET); - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); if(rex.w) { ANDx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f } else { @@ -2978,9 +2999,10 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 1: INST_NAME("ROR Ed, CL"); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } SETFLAGS(X_OF|X_CF, SF_SUBSET); - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); if(rex.w) { ANDx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f } else { @@ -3010,10 +3032,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 2: INST_NAME("RCL Ed, CL"); MESSAGE(LOG_DUMP, "Need Optimization (RCL Ed, CL)\n"); - READFLAGS(X_CF); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } else { + READFLAGS(X_CF); + } SETFLAGS(X_OF|X_CF, SF_SET_DF); - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); if(rex.w) { ANDx_mask(x2, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f } else { @@ -3026,10 +3050,12 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 3: INST_NAME("RCR Ed, CL"); MESSAGE(LOG_DUMP, "Need Optimization (RCR Ed, CL)\n"); - READFLAGS(X_CF); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } else { + READFLAGS(X_CF); + } SETFLAGS(X_OF|X_CF, SF_SET_DF); - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); if(rex.w) { ANDx_mask(x2, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f } else { @@ -3042,9 +3068,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 4: case 6: INST_NAME("SHL Ed, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); if(rex.w) { ANDx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f } else { @@ -3060,9 +3088,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 5: INST_NAME("SHR Ed, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); if(rex.w) { ANDx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f } else { @@ -3078,9 +3108,11 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 7: INST_NAME("SAR Ed, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); if(rex.w) { ANDx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f } else { diff --git a/src/dynarec/arm64/dynarec_arm64_0f.c b/src/dynarec/arm64/dynarec_arm64_0f.c index a157a9a4..ec13f6aa 100644 --- a/src/dynarec/arm64/dynarec_arm64_0f.c +++ b/src/dynarec/arm64/dynarec_arm64_0f.c @@ -1771,9 +1771,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0xA5: nextop = F8; INST_NAME("SHLD Ed, Gd, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); GETGD; GETED(0); if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);} @@ -1859,9 +1861,11 @@ uintptr_t dynarec64_0F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0xAD: nextop = F8; INST_NAME("SHRD Ed, Gd, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); GETGD; GETED(0); if(!rex.w && !rex.is32bits && MODREG) {MOVw_REG(ed, ed);} diff --git a/src/dynarec/arm64/dynarec_arm64_64.c b/src/dynarec/arm64/dynarec_arm64_64.c index 1bfc1fe3..d770d4c7 100644 --- a/src/dynarec/arm64/dynarec_arm64_64.c +++ b/src/dynarec/arm64/dynarec_arm64_64.c @@ -1131,6 +1131,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin switch((nextop>>3)&7) { case 0: INST_NAME("ROL Ed, CL"); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } SETFLAGS(X_OF|X_CF, SF_SUBSET); if(rex.w) { ANDx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f @@ -1156,6 +1159,9 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 1: INST_NAME("ROR Ed, CL"); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } SETFLAGS(X_OF|X_CF, SF_SUBSET); if(rex.w) { ANDx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f @@ -1182,7 +1188,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 2: INST_NAME("RCL Ed, CL"); MESSAGE(LOG_DUMP, "Need Optimization (RCL Seg:Ed, CL)\n"); - READFLAGS(X_CF); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } else { + READFLAGS(X_CF); + } SETFLAGS(X_OF|X_CF, SF_SET_DF); if(rex.w) { ANDx_mask(x2, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f @@ -1199,7 +1209,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 3: INST_NAME("RCR Ed, CL"); MESSAGE(LOG_DUMP, "Need Optimization (RCR Seg:Ed, CL)\n"); - READFLAGS(X_CF); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } else { + READFLAGS(X_CF); + } SETFLAGS(X_OF|X_CF, SF_SET_DF); if(rex.w) { ANDx_mask(x2, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f @@ -1216,9 +1230,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 4: case 6: INST_NAME("SHL Ed, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); if(rex.w) { ANDx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f } else { @@ -1232,9 +1248,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 5: INST_NAME("SHR Ed, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); if(rex.w) { ANDx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f } else { @@ -1248,9 +1266,11 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 7: INST_NAME("SAR Ed, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); if(rex.w) { ANDx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f } else { diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c index 46cf8c90..89bc503e 100644 --- a/src/dynarec/arm64/dynarec_arm64_66.c +++ b/src/dynarec/arm64/dynarec_arm64_66.c @@ -871,9 +871,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 1: case 2: if(rep==1) {INST_NAME("REPNZ CMPSW");} else {INST_NAME("REPZ CMPSW");} - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); - SETFLAGS(X_ALL, SF_SET_PENDING); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); CBZx_NEXT(xRCX); TBNZ_MARK2(xFlags, F_DF); MARK; // Part with DF==0 @@ -971,9 +973,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 1: case 2: if(rep==1) {INST_NAME("REPNZ SCASW");} else {INST_NAME("REPZ SCASW");} - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); - SETFLAGS(X_ALL, SF_SET_PENDING); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); CBZx_NEXT(xRCX); UXTHw(x1, xRAX); TBNZ_MARK2(xFlags, F_DF); @@ -1211,9 +1215,10 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin switch((nextop>>3)&7) { case 0: INST_NAME("ROL Ew, CL"); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } SETFLAGS(X_OF|X_CF, SF_SUBSET); - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); UFLAG_IF { ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f CBZw_NEXT(x2); @@ -1240,9 +1245,10 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 1: INST_NAME("ROR Ew, CL"); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } SETFLAGS(X_OF|X_CF, SF_SUBSET); - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); UFLAG_IF { ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f CBZw_NEXT(x2); @@ -1268,9 +1274,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 2: INST_NAME("RCL Ew, CL"); MESSAGE(LOG_DUMP, "Need Optimization (RCL Ex, CL)\n"); - READFLAGS(X_CF); - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } else { + READFLAGS(X_CF); + } SETFLAGS(X_OF|X_CF, SF_SET_DF); ANDw_mask(x2, xRCX, 0, 0b00100); GETEW(x1, 0); @@ -1280,9 +1288,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 3: INST_NAME("RCR Ew, CL"); MESSAGE(LOG_DUMP, "Need Optimization (RCR Ew, CL)\n"); - READFLAGS(X_CF); - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_OF|X_CF); + } else { + READFLAGS(X_CF); + } SETFLAGS(X_OF|X_CF, SF_SET_DF); ANDw_mask(x2, xRCX, 0, 0b00100); GETEW(x1, 0); @@ -1292,9 +1302,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 4: case 6: INST_NAME("SHL Ew, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f UFLAG_IF { CBZw_NEXT(x2); @@ -1305,9 +1317,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 5: INST_NAME("SHR Ew, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f UFLAG_IF { CBZw_NEXT(x2); @@ -1318,9 +1332,11 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin break; case 7: INST_NAME("SAR Ew, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); ANDw_mask(x2, xRCX, 0, 0b00100); //mask=0x00000001f UFLAG_IF { CBZw_NEXT(x2); diff --git a/src/dynarec/arm64/dynarec_arm64_660f.c b/src/dynarec/arm64/dynarec_arm64_660f.c index ec5223ac..2306d1f3 100644 --- a/src/dynarec/arm64/dynarec_arm64_660f.c +++ b/src/dynarec/arm64/dynarec_arm64_660f.c @@ -2395,9 +2395,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n case 0xA5: nextop = F8; INST_NAME("SHLD Ew, Gw, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); GETGW(x2); GETEW(x1, 0); ANDw_mask(x4, xRCX, 0, 0b00100); //mask=0x00000001f @@ -2463,9 +2465,11 @@ uintptr_t dynarec64_660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n case 0xAD: nextop = F8; INST_NAME("SHRD Ew, Gw, CL"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - if(BOX64DRENV(dynarec_safeflags)>1) - MAYSETFLAGS(); + if(BOX64DRENV(dynarec_safeflags)>1) { + READFLAGS(X_ALL); + SETFLAGS(X_ALL, SF_SET); + } else + SETFLAGS(X_ALL, SF_SET_PENDING); GETGW(x2); GETEW(x1, 0); ANDw_mask(x4, xRCX, 0, 0b00100); //mask=0x00000001f diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index 4c8680a8..ce80938f 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -809,6 +809,42 @@ void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int save //SET_NODF(); } +void call_i(dynarec_arm_t* dyn, int ninst, void* fnc) +{ + MAYUSE(fnc); + #if STEP == 0 + dyn->insts[ninst].nat_flags_op = NAT_FLAG_OP_UNUSABLE; + #endif + STPx_S7_preindex(x6, x7, xSP, -16); + STPx_S7_preindex(x4, x5, xSP, -16); + STPx_S7_preindex(x2, x3, xSP, -16); + STPx_S7_preindex(xEmu, x1, xSP, -16); // ARM64 stack needs to be 16byte aligned + STPx_S7_offset(xRAX, xRCX, xEmu, offsetof(x64emu_t, regs[_AX])); // x9..x15, x16,x17,x18 those needs to be saved by caller + STPx_S7_offset(xRDX, xRBX, xEmu, offsetof(x64emu_t, regs[_DX])); + STPx_S7_offset(xRSP, xRBP, xEmu, offsetof(x64emu_t, regs[_SP])); + STPx_S7_offset(xRSI, xRDI, xEmu, offsetof(x64emu_t, regs[_SI])); + STPx_S7_offset(xR8, xR9, xEmu, offsetof(x64emu_t, regs[_R8])); + STRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); + fpu_pushcache(dyn, ninst, x7, 0); + + TABLE64(x7, (uintptr_t)fnc); + BLR(x7); + LDPx_S7_postindex(xEmu, x1, xSP, 16); + LDPx_S7_postindex(x2, x3, xSP, 16); + LDPx_S7_postindex(x4, x5, xSP, 16); + #define GO(A, B) LDPx_S7_offset(x##A, x##B, xEmu, offsetof(x64emu_t, regs[_##A])) + GO(RAX, RCX); + GO(RDX, RBX); + GO(RSP, RBP); + GO(RSI, RDI); + GO(R8, R9); + #undef GO + LDRx_U12(xFlags, xEmu, offsetof(x64emu_t, eflags)); + fpu_popcache(dyn, ninst, x7, 0); // savereg will not be used + LDPx_S7_postindex(x6, x7, xSP, 16); + //SET_NODF(); +} + void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w) { MAYUSE(fnc); diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index 0954022f..60aac5aa 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -728,6 +728,9 @@ // CALL_S will use x7 for the call address. Return value can be put in ret (unless ret is -1) // R0 will not be pushed/popd if ret is -2. Flags are not save/restored #define CALL_S(F, ret) call_c(dyn, ninst, F, x7, ret, 0, 0) +// CALL_ will use x7 for the call address. +// All regs are saved, including scratch. This is use to call internal function that should not change state +#define CALL_I(F) call_i(dyn, ninst, F) #define MARK dyn->insts[ninst].mark = dyn->native_size #define GETMARK dyn->insts[ninst].mark @@ -1101,7 +1104,7 @@ MOVZw(S, (N)); \ STRw_U12(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); \ + CALL_I(UpdateFlags); \ dyn->f.pending = SF_SET; \ SET_NODF(); \ } \ @@ -1114,10 +1117,6 @@ #endif #define SET_DFOK() dyn->f.dfnone = 1; dyn->f.dfnone_here=1 -#ifndef MAYSETFLAGS -#define MAYSETFLAGS() do {} while (0) -#endif - #ifndef READFLAGS #define READFLAGS(A) \ if(((A)!=X_PEND && dyn->f.pending!=SF_SET) \ @@ -1127,7 +1126,7 @@ j64 = (GETMARKF)-(dyn->native_size); \ CBZw(x3, j64); \ } \ - CALL_(UpdateFlags, -1, 0); \ + CALL_I(UpdateFlags); \ MARKF; \ dyn->f.pending = SF_SET; \ SET_DFOK(); \ @@ -1167,6 +1166,7 @@ #define UFLAG_RES(A) if(dyn->insts[ninst].x64.gen_flags) {STRxw_U12(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) +#define UFLAG_IF_DF if(dyn->insts[ninst].x64.gen_flags || (dyn->insts[ninst].f_entry.dfnone && dyn->insts[ninst].f_entry.dfnone_here)) #define UFLAG_IF2(A) if(dyn->insts[ninst].x64.gen_flags A) #ifndef DEFAULT #define DEFAULT *ok = -1; BARRIER(2) @@ -1282,6 +1282,7 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr); #define retn_to_epilog STEPNAME(retn_to_epilog) #define iret_to_epilog STEPNAME(iret_to_epilog) #define call_c STEPNAME(call_c) +#define call_i STEPNAME(call_i) #define call_n STEPNAME(call_n) #define grab_segdata STEPNAME(grab_segdata) #define emit_cmp8 STEPNAME(emit_cmp8) @@ -1452,6 +1453,7 @@ void ret_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex); void retn_to_epilog(dynarec_arm_t* dyn, int ninst, rex_t rex, int n); void iret_to_epilog(dynarec_arm_t* dyn, int ninst, int is32bits, int is64bits); void call_c(dynarec_arm_t* dyn, int ninst, void* fnc, int reg, int ret, int saveflags, int save_reg); +void call_i(dynarec_arm_t* dyn, int ninst, void* fnc); void call_n(dynarec_arm_t* dyn, int ninst, void* fnc, int w); void grab_segdata(dynarec_arm_t* dyn, uintptr_t addr, int ninst, int reg, int segment, int modreg); void emit_cmp8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); diff --git a/src/dynarec/arm64/dynarec_arm64_pass0.h b/src/dynarec/arm64/dynarec_arm64_pass0.h index 391405ef..37cc7a3f 100644 --- a/src/dynarec/arm64/dynarec_arm64_pass0.h +++ b/src/dynarec/arm64/dynarec_arm64_pass0.h @@ -6,7 +6,6 @@ if(ninst) dyn->insts[ninst-1].x64.size = dyn->insts[ninst].x64.addr - dyn->insts[ninst-1].x64.addr #define MESSAGE(A, ...) do {} while (0) -#define MAYSETFLAGS() dyn->insts[ninst].x64.may_set = 1 #define READFLAGS(A) \ dyn->insts[ninst].x64.use_flags = A; dyn->f.dfnone = 1;\ if(!BOX64ENV(dynarec_df) && (A)&X_PEND) dyn->insts[ninst].x64.use_flags = X_ALL; \ diff --git a/src/dynarec/arm64/dynarec_arm64_pass1.h b/src/dynarec/arm64/dynarec_arm64_pass1.h index 7e81b167..f5ad6a7b 100644 --- a/src/dynarec/arm64/dynarec_arm64_pass1.h +++ b/src/dynarec/arm64/dynarec_arm64_pass1.h @@ -2,7 +2,6 @@ #define FINI #define MESSAGE(A, ...) do {} while (0) #define EMIT(A) do {} while (0) -#define MAYSETFLAGS() dyn->insts[ninst].x64.may_set = 1 #define SET_NODF() \ if(!dyn->insts[ninst].x64.gen_flags && !dyn->insts[ninst].x64.use_flags) \ propagate_nodf(dyn, ninst); \ |