diff options
| author | Yang Liu <liuyang22@iscas.ac.cn> | 2024-03-08 17:34:28 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-08 10:34:28 +0100 |
| commit | 602c015321c5feca6570a47b4be5c63fe920232b (patch) | |
| tree | 88451980d82ed5d38715cf3459b831b3ce101f2b /src | |
| parent | 55c2c9ee59261540714c3861875d38d66e22ac37 (diff) | |
| download | box64-602c015321c5feca6570a47b4be5c63fe920232b.tar.gz box64-602c015321c5feca6570a47b4be5c63fe920232b.zip | |
[DYNAREC] Made shift operations handle count==0 more uniformly (#1345)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_00.c | 244 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_66.c | 88 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_67.c | 80 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_emit_shift.c | 42 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_00.c | 79 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_emit_shift.c | 10 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00_3.c | 82 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_66.c | 4 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_67.c | 15 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_shift.c | 16 |
10 files changed, 378 insertions, 282 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index c1ee3648..d19bef46 100644 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -756,7 +756,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0x62: if(rex.is32bits) { // BOUND here - DEFAULT; + DEFAULT; } else { INST_NAME("BOUND Gd, Ed"); nextop = F8; @@ -766,7 +766,7 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0x63: if(rex.is32bits) { // ARPL here - DEFAULT; + DEFAULT; } else { INST_NAME("MOVSXD Gd, Ed"); nextop = F8; @@ -1928,104 +1928,97 @@ 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 Eb, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&0x1f; - if(u8) { - SETFLAGS(X_CF|X_OF, SF_SUBSET_PENDING); + u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f; + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_CF | X_OF, SF_SUBSET_PENDING); // some flags are left undefined GETEB(x1, 1); - u8 = F8&0x1f; - emit_rol8c(dyn, ninst, x1, u8, x4, x5); - EBBACK; - } else { + } else FAKEED; - F8; - } + F8; + emit_rol8c(dyn, ninst, x1, u8, x4, x5); + if (u8) EBBACK; break; case 1: INST_NAME("ROR Eb, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&0x1f; - if(u8) { - SETFLAGS(X_CF|X_OF, SF_SUBSET_PENDING); + u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f; + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_CF | X_OF, SF_SUBSET_PENDING); GETEB(x1, 1); - u8 = F8&0x1f; - emit_ror8c(dyn, ninst, x1, u8, x4, x5); - EBBACK; - } else { + } else FAKEED; - F8; - } + F8; + emit_ror8c(dyn, ninst, x1, u8, x4, x5); + if (u8) EBBACK; break; case 2: INST_NAME("RCL Eb, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&0x1f; - if(u8) { + u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f; + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { READFLAGS(X_CF); - SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); + SETFLAGS(X_OF | X_CF, SF_SUBSET_PENDING); GETEB(x1, 1); - u8 = F8&0x1f; - emit_rcl8c(dyn, ninst, x1, u8, x4, x5); - EBBACK; - } else { + } else FAKEED; - F8; - } + F8; + emit_rcl8c(dyn, ninst, x1, u8, x4, x5); + if (u8) EBBACK; break; case 3: INST_NAME("RCR Eb, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&0x1f; - if(u8) { + u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f; + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { READFLAGS(X_CF); - SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); + SETFLAGS(X_OF | X_CF, SF_SUBSET_PENDING); GETEB(x1, 1); - u8 = F8&0x1f; - emit_rcr8c(dyn, ninst, x1, u8, x4, x5); - EBBACK; - } else { + } else FAKEED; - F8; - } + F8; + emit_rcr8c(dyn, ninst, x1, u8, x4, x5); + if (u8) EBBACK; break; case 4: case 6: INST_NAME("SHL Eb, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&0x1f; - if(u8) { - SETFLAGS(X_ALL, SF_SET_PENDING); + u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f; + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined GETEB(x1, 1); - u8 = (F8)&0x1f; - emit_shl8c(dyn, ninst, ed, u8, x4, x5); - EBBACK; - } else { + } else FAKEED; - F8; - } + F8; + emit_shl8c(dyn, ninst, ed, u8, x4, x5); + if (u8) EBBACK; break; case 5: INST_NAME("SHR Eb, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&0x1f; - if(u8) { - SETFLAGS(X_ALL, SF_SET_PENDING); + u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f; + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined GETEB(x1, 1); - u8 = (F8)&0x1f; - emit_shr8c(dyn, ninst, ed, u8, x4, x5); - EBBACK; - } else { + } else FAKEED; - F8; - } + F8; + emit_shr8c(dyn, ninst, ed, u8, x4, x5); + if (u8) EBBACK; break; case 7: INST_NAME("SAR Eb, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&0x1f; - if(u8) { - SETFLAGS(X_ALL, SF_SET_PENDING); - GETSEB(x1, 1); - u8 = (F8)&0x1f; - emit_sar8c(dyn, ninst, ed, u8, x4, x5); - EBBACK; - } else { + u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f; + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETEB(x1, 1); + } else FAKEED; - F8; - } + F8; + emit_sar8c(dyn, ninst, ed, u8, x4, x5); + if (u8) EBBACK; break; } break; @@ -2034,41 +2027,35 @@ 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, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20)); - if(u8) { - SETFLAGS(X_CF|X_OF, SF_SUBSET_PENDING); + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_CF | X_OF, SF_SUBSET_PENDING); GETED(1); - u8 = (F8)&(rex.w?0x3f:0x1f); - emit_rol32c(dyn, ninst, rex, ed, u8, x3, x4); + } else + FAKEED; + F8; + emit_rol32c(dyn, ninst, rex, ed, u8, x3, x4); + if (u8) { WBACK; - } else { - if(MODREG && ! rex.w && !rex.is32bits) { - GETED(1); - MOVw_REG(ed, ed); - } else { - FAKEED; - } - F8; - } + } else if (MODREG && !rex.w) + MOVw_REG(ed, ed); break; case 1: INST_NAME("ROR Ed, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20)); - if(u8) { - SETFLAGS(X_CF|X_OF, SF_SUBSET_PENDING); + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_CF | X_OF, SF_SUBSET_PENDING); GETED(1); - u8 = (F8)&(rex.w?0x3f:0x1f); - emit_ror32c(dyn, ninst, rex, ed, u8, x3, x4); + } else + FAKEED; + F8; + emit_ror32c(dyn, ninst, rex, ed, u8, x3, x4); + if (u8) { WBACK; - } else { - if(MODREG && ! rex.w && !rex.is32bits) { - GETED(1); - MOVw_REG(ed, ed); - } else { - FAKEED; - } - F8; - } + } else if (MODREG && !rex.w) + MOVw_REG(ed, ed); break; case 2: INST_NAME("RCL Ed, Ib"); @@ -2097,60 +2084,51 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 4: case 6: INST_NAME("SHL Ed, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20)); - if(u8) { + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { SETFLAGS(X_ALL, SF_SET_PENDING); GETED(1); - u8 = (F8)&(rex.w?0x3f:0x1f); - emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4); + } else + FAKEED; + F8; + emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4); + if (u8) { WBACK; - } else { - if(MODREG && ! rex.w && !rex.is32bits) { - GETED(1); - MOVw_REG(ed, ed); - } else { - FAKEED; - } - F8; - } + } else if (MODREG && !rex.w) + MOVw_REG(ed, ed); break; case 5: INST_NAME("SHR Ed, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20)); - if(u8) { + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { SETFLAGS(X_ALL, SF_SET_PENDING); GETED(1); - u8 = (F8)&(rex.w?0x3f:0x1f); - emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4); + } else + FAKEED; + F8; + emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4); + if (u8) { WBACK; - } else { - if(MODREG && ! rex.w && !rex.is32bits) { - GETED(1); - MOVw_REG(ed, ed); - } else { - FAKEED; - } - F8; - } + } else if (MODREG && !rex.w) + MOVw_REG(ed, ed); break; case 7: INST_NAME("SAR Ed, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20)); - if(u8) { + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { SETFLAGS(X_ALL, SF_SET_PENDING); GETED(1); - u8 = (F8)&(rex.w?0x3f:0x1f); - emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4); + } else + FAKEED; + F8; + emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4); + if (u8) { WBACK; - } else { - if(MODREG && ! rex.w && !rex.is32bits) { - GETED(1); - MOVw_REG(ed, ed); - } else { - FAKEED; - } - F8; - } + } else if (MODREG && !rex.w) + MOVw_REG(ed, ed); break; } break; diff --git a/src/dynarec/arm64/dynarec_arm64_66.c b/src/dynarec/arm64/dynarec_arm64_66.c index ce0e14d3..c0960286 100644 --- a/src/dynarec/arm64/dynarec_arm64_66.c +++ b/src/dynarec/arm64/dynarec_arm64_66.c @@ -941,31 +941,29 @@ 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, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&15; - if(u8) { - SETFLAGS(X_CF|((u8==1)?X_OF:0), SF_SUBSET_PENDING); + u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f; + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_CF | ((u8 == 1) ? X_OF : 0), SF_SUBSET_PENDING); GETEW(x1, 1); - u8 = F8; - emit_rol16c(dyn, ninst, x1, u8, x4, x5); - EWBACK; - } else { + } else FAKEED; - F8; - } + F8; + emit_rol16c(dyn, ninst, x1, u8, x4, x5); + if (u8) EWBACK; break; case 1: INST_NAME("ROR Ew, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&15; - if(geted_ib(dyn, addr, ninst, nextop)&15) { - SETFLAGS(X_CF|((u8==1)?X_OF:0), SF_SUBSET_PENDING); + u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f; + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_CF | ((u8 == 1) ? X_OF : 0), SF_SUBSET_PENDING); GETEW(x1, 1); - u8 = F8; - emit_ror16c(dyn, ninst, x1, u8, x4, x5); - EWBACK; - } else { + } else FAKEED; - F8; - } + F8; + emit_ror16c(dyn, ninst, x1, u8, x4, x5); + if (u8) EWBACK; break; case 2: INST_NAME("RCL Ew, Ib"); @@ -1002,42 +1000,42 @@ uintptr_t dynarec64_66(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 4: case 6: INST_NAME("SHL Ew, Ib"); - if(geted_ib(dyn, addr, ninst, nextop)&0x1f) { - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f; + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined GETEW(x1, 0); - u8 = (F8)&0x1f; - emit_shl16c(dyn, ninst, x1, u8, x5, x4); - EWBACK; - } else { + } else FAKEED; - F8; - } + F8; + emit_shl16c(dyn, ninst, x1, u8, x5, x4); + if (u8) EWBACK; break; case 5: - INST_NAME("SHR Ed, Ib"); - if(geted_ib(dyn, addr, ninst, nextop)&0x1f) { - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + INST_NAME("SHR Ew, Ib"); + u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f; + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined GETEW(x1, 0); - u8 = (F8)&0x1f; - emit_shr16c(dyn, ninst, x1, u8, x5, x4); - EWBACK; - } else { + } else FAKEED; - F8; - } + F8; + emit_shr16c(dyn, ninst, x1, u8, x5, x4); + if (u8) EWBACK; break; case 7: - INST_NAME("SAR Ed, Ib"); - if(geted_ib(dyn, addr, ninst, nextop)&0x1f) { - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - GETSEW(x1, 0); - u8 = (F8)&0x1f; - emit_sar16c(dyn, ninst, x1, u8, x5, x4); - EWBACK; - } else { + INST_NAME("SAR Ew, Ib"); + u8 = geted_ib(dyn, addr, ninst, nextop) & 0x1f; + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETEW(x1, 0); + } else FAKEED; - F8; - } + F8; + emit_sar16c(dyn, ninst, x1, u8, x5, x4); + if (u8) EWBACK; break; } break; diff --git a/src/dynarec/arm64/dynarec_arm64_67.c b/src/dynarec/arm64/dynarec_arm64_67.c index 82dd7a27..bf44681a 100644 --- a/src/dynarec/arm64/dynarec_arm64_67.c +++ b/src/dynarec/arm64/dynarec_arm64_67.c @@ -918,19 +918,35 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin switch((nextop>>3)&7) { case 0: INST_NAME("ROL Ed, Ib"); - SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); - GETED32(1); - u8 = (F8)&(rex.w?0x3f:0x1f); + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_OF | X_CF, SF_SUBSET_PENDING); + GETED32(1); + } else + FAKEED; + F8; emit_rol32c(dyn, ninst, rex, ed, u8, x3, x4); - if(u8) { WBACK; } + if (u8) { + WBACK; + } else if (MODREG && !rex.w) + MOVw_REG(ed, ed); break; case 1: INST_NAME("ROR Ed, Ib"); - SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); - GETED32(1); - u8 = (F8)&(rex.w?0x3f:0x1f); + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_OF | X_CF, SF_SUBSET_PENDING); + GETED32(1); + } else + FAKEED; + F8; emit_ror32c(dyn, ninst, rex, ed, u8, x3, x4); - if(u8) { WBACK; } + if (u8) { + WBACK; + } else if (MODREG && !rex.w) + MOVw_REG(ed, ed); break; case 2: INST_NAME("RCL Ed, Ib"); @@ -957,31 +973,51 @@ uintptr_t dynarec64_67(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 4: case 6: INST_NAME("SHL Ed, Ib"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - GETED32(1); - u8 = (F8)&(rex.w?0x3f:0x1f); + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED32(1); + } else + FAKEED; + F8; emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4); - WBACK; + if (u8) { + WBACK; + } else if (MODREG && !rex.w) + MOVw_REG(ed, ed); break; case 5: INST_NAME("SHR Ed, Ib"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - GETED32(1); - u8 = (F8)&(rex.w?0x3f:0x1f); + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED32(1); + } else + FAKEED; + F8; emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4); - if(u8) { + if (u8) { WBACK; - } + } else if (MODREG && !rex.w) + MOVw_REG(ed, ed); break; case 7: INST_NAME("SAR Ed, Ib"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - GETED32(1); - u8 = (F8)&(rex.w?0x3f:0x1f); + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED32(1); + } else + FAKEED; + F8; emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4); - if(u8) { + if (u8) { WBACK; - } + } else if (MODREG && !rex.w) + MOVw_REG(ed, ed); break; } break; diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c index b8686477..3ce94c9d 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c @@ -82,6 +82,8 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 // emit SHL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { + if (!c) return; + IFX(X_PEND) { MOV32w(s3, c); STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1)); @@ -185,6 +187,8 @@ void emit_shr32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 // emit SHR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { + if (!c) return; + IFX(X_PEND) { MOV32w(s3, c); STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1)); @@ -238,6 +242,8 @@ void emit_shr32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i // emit SAR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_sar32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { + if (!c) return; + IFX(X_PEND) { MOV32w(s3, c); STRxw_U12(s1, xEmu, offsetof(x64emu_t, op1)); @@ -430,8 +436,7 @@ void emit_shr8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) // emit SHR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_shr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) { - if(!c) - return; + if (!c) return; IFX(X_PEND) { MOV32w(s3, c); STRB_U12(s1, xEmu, offsetof(x64emu_t, op1)); @@ -505,8 +510,7 @@ void emit_sar8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) // emit SAR8 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) { - if(!c) - return; + if (!c) return; IFX(X_PEND) { MOV32w(s3, c); STRB_U12(s1, xEmu, offsetof(x64emu_t, op1)); @@ -587,8 +591,7 @@ void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) // emit SHL16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) { - if(!c) - return; + if (!c) return; IFX(X_PEND) { MOV32w(s3, c); STRH_U12(s1, xEmu, offsetof(x64emu_t, op1)); @@ -760,8 +763,7 @@ void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) // emit SAR16 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) { - if(!c) - return; + if (!c) return; IFX(X_PEND) { MOV32w(s3, c); STRH_U12(s1, xEmu, offsetof(x64emu_t, op1)); @@ -795,6 +797,9 @@ void emit_sar16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { MAYUSE(rex); MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); + + if (!c) return; + IFX(X_PEND) { MOV32w(s3, c); STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2)); @@ -827,6 +832,9 @@ void emit_rol32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); + + if (!c) return; + IFX(X_PEND) { MOV32w(s3, c); STRxw_U12(s3, xEmu, offsetof(x64emu_t, op2)); @@ -860,6 +868,9 @@ void emit_ror32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); + + if (!c) return; + IFX(X_PEND) { MOV32w(s3, c); STRB_U12(s3, xEmu, offsetof(x64emu_t, op2)); @@ -890,6 +901,9 @@ void emit_rol8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); + + if (!c) return; + IFX(X_PEND) { MOV32w(s3, c); STRB_U12(s3, xEmu, offsetof(x64emu_t, op2)); @@ -920,6 +934,9 @@ void emit_ror8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); + + if (!c) return; + IFX(X_PEND) { MOV32w(s3, c); STRH_U12(s3, xEmu, offsetof(x64emu_t, op2)); @@ -950,6 +967,9 @@ void emit_rol16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); + + if (!c) return; + IFX(X_PEND) { MOV32w(s3, c); STRH_U12(s3, xEmu, offsetof(x64emu_t, op2)); @@ -980,6 +1000,9 @@ void emit_ror16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int void emit_rcl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); + + if (!c) return; + IFX(X_PEND) { MOV32w(s3, c); STRB_U12(s1, xEmu, offsetof(x64emu_t, op1)); @@ -1014,6 +1037,9 @@ void emit_rcl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s void emit_rcr8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s4) { MAYUSE(s1); MAYUSE(s3); MAYUSE(s4); + + if (!c) return; + IFX(X_PEND) { MOV32w(s3, c); STRB_U12(s1, xEmu, offsetof(x64emu_t, op1)); diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c index c0583e16..466a12a8 100644 --- a/src/dynarec/la64/dynarec_la64_00.c +++ b/src/dynarec/la64/dynarec_la64_00.c @@ -652,60 +652,51 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 4: case 6: INST_NAME("SHL Ed, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20)); - if(u8) { - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); GETED(1); - u8 = (F8) & (rex.w ? 0x3f : 0x1f); - emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4, x5); + } else + FAKEED; + F8; + emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4, x5); + if (u8) { WBACK; - } else { - if(MODREG && ! rex.w && !rex.is32bits) { - GETED(1); - AND(ed, ed, xMASK); - } else { - FAKEED; - } - F8; - } + } else if (MODREG && !rex.w) + ZEROUP(ed); break; case 5: INST_NAME("SHR Ed, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20)); - if(u8) { - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); GETED(1); - u8 = (F8) & (rex.w ? 0x3f : 0x1f); - emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4); + } else + FAKEED; + F8; + emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4); + if (u8) { WBACK; - } else { - if(MODREG && ! rex.w && !rex.is32bits) { - GETED(1); - AND(ed, ed, xMASK); - } else { - FAKEED; - } - F8; - } + } else if (MODREG && !rex.w) + ZEROUP(ed); break; case 7: INST_NAME("SAR Ed, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop)&(0x1f+(rex.w*0x20)); - if(u8) { - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); GETED(1); - u8 = (F8) & (rex.w ? 0x3f : 0x1f); - emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4); - WBACK; - } else { - if(MODREG && ! rex.w && !rex.is32bits) { - GETED(1); - AND(ed, ed, xMASK); - } else { - FAKEED; - } - F8; - } + } else + FAKEED; + F8; + emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4); + if (u8) { + WBACK; + } else if (MODREG && !rex.w) + ZEROUP(ed); break; default: DEFAULT; @@ -1180,4 +1171,4 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } return addr; -} \ No newline at end of file +} diff --git a/src/dynarec/la64/dynarec_la64_emit_shift.c b/src/dynarec/la64/dynarec_la64_emit_shift.c index b4d7ccdd..f4a35991 100644 --- a/src/dynarec/la64/dynarec_la64_emit_shift.c +++ b/src/dynarec/la64/dynarec_la64_emit_shift.c @@ -91,11 +91,13 @@ void emit_shl32(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s // emit SHL32 instruction, from s1 , constant c, store result in s1 using s3, s4 and s5 as scratch void emit_shl32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4, int s5) { + if (!c) return; + IFX(X_PEND) { if (c) { MOV64x(s3, c); SDxw(s3, xEmu, offsetof(x64emu_t, op2)); - } else + } else SDxw(xZR, xEmu, offsetof(x64emu_t, op2)); SDxw(s1, xEmu, offsetof(x64emu_t, op1)); SET_DF(s4, rex.w?d_shl64:d_shl32); @@ -170,6 +172,8 @@ void emit_shl32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, // emit SHR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_shr32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { + if (!c) return; + IFX(X_PEND) { if (c) { MOV64x(s3, c); @@ -251,6 +255,8 @@ void emit_shr32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, // emit SAR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_sar32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { + if (!c) return; + IFX(X_PEND) { if (c) { MOV64x(s3, c); @@ -319,4 +325,4 @@ void emit_sar32c(dynarec_la64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, IFX(X_PF) { emit_pf(dyn, ninst, s1, s3, s4); } -} \ No newline at end of file +} diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 1158eadf..8fb520a0 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -164,21 +164,35 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int switch((nextop>>3)&7) { case 0: INST_NAME("ROL Ed, Ib"); - SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); - GETED(1); - u8 = (F8)&(rex.w?0x3f:0x1f); + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_OF | X_CF, SF_SUBSET_PENDING); + GETED(1); + } else + FAKEED; + F8; emit_rol32c(dyn, ninst, rex, ed, u8, x3, x4); - if(u8) { WBACK; } - if(!wback && !rex.w) ZEROUP(ed); + if (u8) { + WBACK; + } else if (MODREG && !rex.w) + ZEROUP(ed); break; case 1: INST_NAME("ROR Ed, Ib"); - SETFLAGS(X_OF|X_CF, SF_SUBSET_PENDING); - GETED(1); - u8 = (F8)&(rex.w?0x3f:0x1f); + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_OF | X_CF, SF_SUBSET_PENDING); + GETED(1); + } else + FAKEED; + F8; emit_ror32c(dyn, ninst, rex, ed, u8, x3, x4); - if(u8) { WBACK; } - if(!wback && !rex.w) ZEROUP(ed); + if (u8) { + WBACK; + } else if (MODREG && !rex.w) + ZEROUP(ed); break; case 2: INST_NAME("RCL Ed, Ib"); @@ -205,27 +219,51 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int case 4: case 6: INST_NAME("SHL Ed, Ib"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - GETED(1); - u8 = (F8)&(rex.w?0x3f:0x1f); + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED(1); + } else + FAKEED; + F8; emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4, x5); - if(u8) WBACK; + if (u8) { + WBACK; + } else if (MODREG && !rex.w) + ZEROUP(ed); break; case 5: INST_NAME("SHR Ed, Ib"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - GETED(1); - u8 = (F8)&(rex.w?0x3f:0x1f); + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED(1); + } else + FAKEED; + F8; emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4); - if(u8) { WBACK; } + if (u8) { + WBACK; + } else if (MODREG && !rex.w) + ZEROUP(ed); break; case 7: INST_NAME("SAR Ed, Ib"); - SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined - GETED(1); - u8 = (F8)&(rex.w?0x3f:0x1f); + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED(1); + } else + FAKEED; + F8; emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4); - if(u8) { WBACK; } + if (u8) { + WBACK; + } else if (MODREG && !rex.w) + ZEROUP(ed); break; default: DEFAULT; diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index 419df8ff..24b3bfb0 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -1002,7 +1002,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni UFLAG_DF(x3, d_shl16); break; case 5: - INST_NAME("SHR Ed, Ib"); + INST_NAME("SHR Ew, Ib"); UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");} SETFLAGS(X_ALL, SF_PENDING); GETEW(x1, 1); @@ -1015,7 +1015,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni UFLAG_DF(x3, d_shr16); break; case 7: - INST_NAME("SAR Ed, Ib"); + INST_NAME("SAR Ew, Ib"); SETFLAGS(X_ALL, SF_PENDING); UFLAG_IF {MESSAGE(LOG_DUMP, "Need Optimization for flags\n");} GETSEW(x1, 1); diff --git a/src/dynarec/rv64/dynarec_rv64_67.c b/src/dynarec/rv64/dynarec_rv64_67.c index effbb677..90f53b11 100644 --- a/src/dynarec/rv64/dynarec_rv64_67.c +++ b/src/dynarec/rv64/dynarec_rv64_67.c @@ -659,12 +659,19 @@ uintptr_t dynarec64_67(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni switch ((nextop >> 3) & 7) { case 5: INST_NAME("SHR Ed, Ib"); - SETFLAGS(X_ALL, SF_SET_PENDING); - GETED32(1); - u8 = (F8) & (rex.w ? 0x3f : 0x1f); + u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); + // flags are not affected if count is 0, we make it a nop if possible. + if (u8) { + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED32(1); + } else + FAKEED; + F8; emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4); - if (u8) + if (u8) { WBACK; + } else if (MODREG && !rex.w) + ZEROUP(ed); break; default: DEFAULT; diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c index 9008ca19..1db7344f 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c @@ -76,6 +76,8 @@ void emit_shl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s // emit SHL32 instruction, from s1 , constant c, store result in s1 using s3, s4 and s5 as scratch void emit_shl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4, int s5) { + if (!c) return; + CLEAR_FLAGS(); IFX(X_PEND) { if (c) { @@ -189,6 +191,8 @@ void emit_shr32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s // emit SHR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { + if (!c) return; + CLEAR_FLAGS(); IFX(X_PEND) { @@ -251,6 +255,8 @@ void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, // emit SAR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { + if (!c) return; + CLEAR_FLAGS(); IFX(X_PEND) { @@ -401,6 +407,8 @@ void emit_ror32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s // emit ROL32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { + if (!c) return; + IFX(X_CF | X_OF) { ANDI(xFlags, xFlags, ~(1UL<<F_CF | 1UL<<F_OF2)); } @@ -427,6 +435,9 @@ void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, SRLIxw(s1, s1, (rex.w?64:32)-c); OR(s1, s3, s1); } + + if (!rex.w) ZEROUP(s1); + IFX(X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); } @@ -448,6 +459,8 @@ void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, // emit ROR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { + if (!c) return; + IFX(X_CF | X_OF) { ANDI(xFlags, xFlags, ~(1UL<<F_CF | 1UL<<F_OF2)); } @@ -474,6 +487,9 @@ void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, SLLIxw(s1, s1, (rex.w?64:32)-c); OR(s1, s3, s1); } + + if (!rex.w) ZEROUP(s1); + IFX(X_PEND) { SDxw(s1, xEmu, offsetof(x64emu_t, res)); } |