diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-11-14 15:00:58 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-11-14 15:00:58 +0100 |
| commit | cd2638d11a1ce7d1db868e47953740ac540c40ee (patch) | |
| tree | 5a740662a6f737700c8a6f965a34c31ab84d2576 /src | |
| parent | c87796e51cacf7758523fe1fb20ef2b2b5193b49 (diff) | |
| download | box64-cd2638d11a1ce7d1db868e47953740ac540c40ee.tar.gz box64-cd2638d11a1ce7d1db868e47953740ac540c40ee.zip | |
[ARM64_DYNAREC] Some refactor on 8/16/32/64bits SHL/SHR/SAR opcodes
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_64.c | 6 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_67.c | 8 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_emit_shift.c | 132 |
3 files changed, 67 insertions, 79 deletions
diff --git a/src/dynarec/arm64/dynarec_arm64_64.c b/src/dynarec/arm64/dynarec_arm64_64.c index 7e76fb20..9ad0be88 100644 --- a/src/dynarec/arm64/dynarec_arm64_64.c +++ b/src/dynarec/arm64/dynarec_arm64_64.c @@ -1244,6 +1244,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 6: INST_NAME("SHL Ed, CL"); SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + if(box64_dynarec_safeflags>1) + MAYSETFLAGS(); if(rex.w) { ANDx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f } else { @@ -1258,6 +1260,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 5: INST_NAME("SHR Ed, CL"); SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + if(box64_dynarec_safeflags>1) + MAYSETFLAGS(); if(rex.w) { ANDx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f } else { @@ -1272,6 +1276,8 @@ uintptr_t dynarec64_64(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 7: INST_NAME("SAR Ed, CL"); SETFLAGS(X_ALL, SF_SET_PENDING); + if(box64_dynarec_safeflags>1) + MAYSETFLAGS(); if(rex.w) { ANDx_mask(x3, xRCX, 1, 0, 0b00101); //mask=0x000000000000003f } else { diff --git a/src/dynarec/arm64/dynarec_arm64_67.c b/src/dynarec/arm64/dynarec_arm64_67.c index a109f95d..a77d88a5 100644 --- a/src/dynarec/arm64/dynarec_arm64_67.c +++ b/src/dynarec/arm64/dynarec_arm64_67.c @@ -1248,11 +1248,13 @@ 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); - emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4); - WBACK; + if(u8) { //should create the geted32_ib utility function for that + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + emit_shl32c(dyn, ninst, rex, ed, u8, x3, x4); + WBACK; + } break; case 5: INST_NAME("SHR Ed, Ib"); diff --git a/src/dynarec/arm64/dynarec_arm64_emit_shift.c b/src/dynarec/arm64/dynarec_arm64_emit_shift.c index c2d74576..464fb7d7 100644 --- a/src/dynarec/arm64/dynarec_arm64_emit_shift.c +++ b/src/dynarec/arm64/dynarec_arm64_emit_shift.c @@ -21,7 +21,7 @@ #include "dynarec_arm64_functions.h" #include "dynarec_arm64_helper.h" -// emit SHL32 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2 +// emit SHL32 instruction, from s1 , shift s2, store result in s1 using s3 and s4 as scratch. s3 can be same as s2. s2 must be non-0 void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4) { MAYUSE(s2); @@ -35,15 +35,6 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 } else IFX(X_ALL) { SET_DFNONE(s4); } - IFX(X_OF) { - CMPSxw_U12(s2, 0); - Bcond(cNE, +8+((dyn->insts[ninst].x64.gen_flags&X_PEND)?4:0)); - BFCw(xFlags, F_OF, 1); - IFX(X_PEND) { - STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); - } - B_NEXT(cEQ); - } IFX(X_CF | X_OF) { MOV32w(s4, rex.w?64:32); SUBxw_REG(s4, s4, s2); @@ -54,28 +45,28 @@ void emit_shl32(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3 IFX(X_PEND) { STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); } + IFX(X_OF) { + CMPSxw_U12(s2, 1); // if s2==1 + LSRxw(s4, s1, (rex.w)?63:31); + EORxw_REG(s3, s4, xFlags); // CF is set if OF is asked + CSELw(s3, s3, wZR, cEQ); + BFIw(xFlags, s3, F_OF, 1); + } int need_tst = 0; IFX(X_ZF) need_tst = 1; IFXNATIVE(X_SF, NF_SF) need_tst = 1; if(need_tst) TSTxw_REG(s1, s1); - IFX(X_ZF) { - IFNATIVE(NF_EQ) {} else { - CSETw(s4, cEQ); - BFIw(xFlags, s4, F_ZF, 1); - } - } IFX(X_SF) { IFNATIVE(NF_SF) {} else { - LSRxw(s4, s1, (rex.w)?63:31); + IFX(X_OF) {} else {LSRxw(s4, s1, (rex.w)?63:31);} BFIw(xFlags, s4, F_SF, 1); } } - IFX(X_OF) { - CMPSxw_U12(s2, 1); // if s2==1 - IFX(X_SF) {} else {LSRxw(s4, s1, (rex.w)?63:31);} - EORxw_REG(s4, s4, xFlags); // CF is set if OF is asked - CSELw(s4, s4, wZR, cEQ); - BFIw(xFlags, s4, F_OF, 1); + IFX(X_ZF) { + IFNATIVE(NF_EQ) {} else { + CSETw(s4, cEQ); + BFIw(xFlags, s4, F_ZF, 1); + } } if(box64_dynarec_test) IFX(X_AF) { @@ -99,15 +90,6 @@ void emit_shl32c(dynarec_arm_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, i } else IFX(X_ALL) { SET_DFNONE(s4); } - if(c==0) { - IFX(X_OF) { - BFCw(xFlags, F_OF, 1); - } - IFX(X_PEND) { - STRxw_U12(s1, xEmu, offsetof(x64emu_t, res)); - } - return; - } IFX(X_CF|X_OF) { LSRxw(s3, s1, (rex.w?64:32)-c); BFIxw(xFlags, s3, F_CF, 1); @@ -391,14 +373,14 @@ void emit_shl8(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) IFX(X_PEND) { STRB_U12(s1, xEmu, offsetof(x64emu_t, res)); } - COMP_ZFSF(s1, 8) IFX(X_OF) { CMPSw_U12(s2, 1); // if s2==1 - IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 7);} + LSRw(s3, s1, 7); EORw_REG(s4, s3, xFlags); // CF is set if OF is asked CSELw(s4, s4, wZR, cEQ); BFIw(xFlags, s4, F_OF, 1); } + COMP_ZFSF(s1, 8) if(box64_dynarec_test) IFX(X_AF) { BFCw(xFlags, F_AF, 1); @@ -433,7 +415,7 @@ void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s COMP_ZFSF(s1, 8) IFX(X_OF) { if(c==1) { - IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 7);} + IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 7);} //use COMP_ZFSF operation EORw_REG(s4, s3, xFlags); // CF is set if OF is asked BFIw(xFlags, s4, F_OF, 1); } else { @@ -447,11 +429,7 @@ void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s emit_pf(dyn, ninst, s1, s4); } } else { - IFX(X_CF) { - LSLw(s3, s1, c-1); - BFXILw(xFlags, s3, 7, 1); // insert F_CF from s3[7:1] - } - IFXNATIVE(X_ZF|X_SF, NF_EQ|NF_SF) { + IFXNATIVE(X_ZF|X_SF|X_CF, NF_EQ|NF_SF|NF_CF) { SUBSw_REG(s1, s1, s1); } else { MOVw_REG(s1, xZR); @@ -459,6 +437,10 @@ void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s IFX(X_PEND) { STRB_U12(s1, xEmu, offsetof(x64emu_t, res)); } + IFX(X_CF) { + // sub X, X will generate a carry flags + IFNATIVE(NF_CF) {GEN_INVERTED_CARRY();} else {BFCw(xFlags, F_CF, 1);} + } IFX(X_OF) { BFCw(xFlags, F_OF, 1); } @@ -468,17 +450,14 @@ void emit_shl8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s if(box64_dynarec_test) IFX(X_AF) { BFCw(xFlags, F_AF, 1); } - IFX(X_PF | X_ZF) { - IFNATIVE(NF_EQ) {IFX(X_PF) {MOV32w(s3, 1);}} else { - MOV32w(s3, 1); - IFX(X_ZF) { - BFIw(xFlags, s3, F_ZF, 1); - } - } - IFX(X_PF) { - BFIw(xFlags, s3, F_PF, 1); + IFX(X_ZF) { + IFNATIVE(NF_EQ) {} else { + ORRw_mask(xFlags, xFlags, 26, 0); //1<<F_ZF } } + IFX(X_PF) { + ORRw_mask(xFlags, xFlags, 30, 0); //1<<F_PF + } } } @@ -625,13 +604,18 @@ void emit_sar8c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int s emit_pf(dyn, ninst, s1, s4); } } else { - LSRw(s3, s1, 7); - BFIw(xFlags, s3, F_CF, 1); - BFIw(wFlags, s3, F_SF, 1); - EORw_mask(s3, s3, 0, 0); //1 - BFIw(xFlags, s3, F_ZF, 1); - MOV32w(s3, 1); - BFIw(xFlags, s3, F_PF, 1); + IFX(X_CF|X_ZF|X_SF|X_PF) { + LSRw(s3, s1, 7); + IFX(X_CF){ BFIw(xFlags, s3, F_CF, 1); } + IFX(X_SF){ BFIw(wFlags, s3, F_SF, 1); } + IFX(X_ZF) { + EORw_mask(s3, s3, 0, 0); //1 + BFIw(xFlags, s3, F_ZF, 1); + } + IFX(X_PF) { + ORRw_mask(xFlags, xFlags, 30, 0); //1<<F_PF + } + } } if(box64_dynarec_test) IFX(X_AF) { @@ -659,14 +643,14 @@ void emit_shl16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) IFX(X_PEND) { STRH_U12(s1, xEmu, offsetof(x64emu_t, res)); } - COMP_ZFSF(s1, 16) IFX(X_OF) { CMPSw_U12(s2, 1); // if s2==1 - IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 15);} + LSRw(s3, s1, 15); EORw_REG(s4, s3, xFlags); // CF is set if OF is asked CSELw(s4, s4, wZR, cEQ); BFIw(xFlags, s4, F_OF, 1); } + COMP_ZFSF(s1, 16) if(box64_dynarec_test) IFX(X_AF) { BFCw(xFlags, F_AF, 1); @@ -701,7 +685,7 @@ void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int COMP_ZFSF(s1, 16) IFX(X_OF) { if(c==1) { - IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 15);} + IFX2(X_SF, && !arm64_flagm) {} else {LSRw(s3, s1, 15);} // use COMP_ZFSF operation EORw_REG(s4, s3, xFlags); // CF is set if OF is asked BFIw(xFlags, s4, F_OF, 1); } else { @@ -714,17 +698,12 @@ void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int IFX(X_PF) { if(c>7) { // the 0xff area will be 0, so PF is known - MOV32w(s3, 1); - BFIw(xFlags, s3, F_PF, 1); + ORRw_mask(xFlags, xFlags, 30, 0); //1<<F_PF } else emit_pf(dyn, ninst, s1, s4); } } else { - IFX(X_CF) { - LSLw(s3, s1, c-1); - BFXILw(xFlags, s3, 15, 1); // insert F_CF from s3[15:1] - } - IFXNATIVE(X_ZF|X_SF, NF_EQ|NF_SF) { + IFXNATIVE(X_ZF|X_SF|X_CF, NF_EQ|NF_SF|NF_CF) { SUBSw_REG(s1, s1, s1); } else { MOVw_REG(s1, xZR); @@ -735,23 +714,24 @@ void emit_shl16c(dynarec_arm_t* dyn, int ninst, int s1, uint32_t c, int s3, int IFX(X_OF) { BFCw(xFlags, F_OF, 1); } + IFX(X_CF) { + // sub X, X will generate a carry flags + IFNATIVE(NF_CF) {GEN_INVERTED_CARRY();} else {BFCw(xFlags, F_CF, 1);} + } IFX(X_SF) { IFNATIVE(NF_SF) {} else BFCw(xFlags, F_SF, 1); } if(box64_dynarec_test) IFX(X_AF) { BFCw(xFlags, F_AF, 1); } - IFX(X_PF | X_ZF) { - IFNATIVE(NF_EQ) {IFX(X_PF) {MOV32w(s3, 1);}} else { - MOV32w(s3, 1); - IFX(X_ZF) { - BFIw(xFlags, s3, F_ZF, 1); - } - } - IFX(X_PF) { - BFIw(xFlags, s3, F_PF, 1); + IFX(X_ZF) { + IFNATIVE(NF_EQ) {} else { + ORRw_mask(xFlags, xFlags, 26, 0); //1<<F_ZF } } + IFX(X_PF) { + ORRw_mask(xFlags, xFlags, 30, 0); //1<<F_PF + } } } @@ -850,12 +830,12 @@ void emit_sar16(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int s4) IFX(X_PEND) { STRH_U12(s1, xEmu, offsetof(x64emu_t, res)); } - COMP_ZFSF(s1, 16) IFX(X_OF) { SUBw_U12(s4, s2, 1); CBNZw(s4, 4+4); BFCw(xFlags, F_OF, 1); } + COMP_ZFSF(s1, 16) if(box64_dynarec_test) IFX(X_AF) { BFCw(xFlags, F_AF, 1); |