diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2024-03-08 12:05:09 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2024-03-08 12:05:09 +0100 |
| commit | c0f78342e1571306f5d30087ccd8f0b289ea949e (patch) | |
| tree | 4ad01c7b2c25a5d3f2b7bd4668ea3a19b4c22a88 /src | |
| parent | 75494978ad84b8a0523b2560328466525f770288 (diff) | |
| download | box64-c0f78342e1571306f5d30087ccd8f0b289ea949e.tar.gz box64-c0f78342e1571306f5d30087ccd8f0b289ea949e.zip | |
[ARM64_DYNAREC] Improved MOV32w and MOV64x with a funciton with more speciall cases
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/arm64/arm64_emitter.h | 25 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.c | 76 | ||||
| -rw-r--r-- | src/dynarec/arm64/dynarec_arm64_helper.h | 6 |
3 files changed, 84 insertions, 23 deletions
diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h index 46de26cf..05728675 100644 --- a/src/dynarec/arm64/arm64_emitter.h +++ b/src/dynarec/arm64/arm64_emitter.h @@ -116,29 +116,8 @@ int convert_bitmask(uint64_t bitmask); #define MOVKw(Rd, imm16) EMIT(MOVK_gen(0, 0, ((uint16_t)(imm16))&0xffff, Rd)) #define MOVKw_LSL(Rd, imm16, shift) EMIT(MOVK_gen(0, (shift)/16, ((uint16_t)(imm16))&0xffff, Rd)) -// This macro will give a -Wsign-compare warning, probably bug #38341 -#define MOV32w(Rd, imm32) \ - if(~((uint32_t)(imm32))<0xffffu) { \ - MOVNw(Rd, (~(uint32_t)(imm32))&0xffff); \ - } else if((uint32_t)(imm32)>0xffff && convert_bitmask_w(imm32)) { \ - int mask = convert_bitmask_w(imm32); \ - ORRw_mask(Rd, xZR, mask&0x3F, (mask>>6)&0x3F); \ - } else { \ - MOVZw(Rd, (imm32)&0xffff); \ - if((imm32)&0xffff0000) {MOVKw_LSL(Rd, ((imm32)>>16)&0xffff, 16);} \ - } -#define MOV64x(Rd, imm64) \ - if(~((uint64_t)(imm64))<0xffff) { \ - MOVNx(Rd, (~(uint64_t)(imm64))&0xffff); \ - } else if((uint64_t)(imm64)>0xffff && convert_bitmask_x(imm64)) { \ - int mask = convert_bitmask_x(imm64); \ - ORRx_mask(Rd, xZR, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F); \ - } else { \ - MOVZx(Rd, ((uint64_t)(imm64))&0xffff); \ - if(((uint64_t)(imm64))&0xffff0000) {MOVKx_LSL(Rd, (((uint64_t)(imm64))>>16)&0xffff, 16);} \ - if(((uint64_t)(imm64))&0xffff00000000LL) {MOVKx_LSL(Rd, (((uint64_t)(imm64))>>32)&0xffff, 32);} \ - if(((uint64_t)(imm64))&0xffff000000000000LL) {MOVKx_LSL(Rd, (((uint64_t)(imm64))>>48)&0xffff, 48);} \ - } +#define MOV32w(Rd, imm32) arm64_move32(dyn, ninst, Rd, imm32) +#define MOV64x(Rd, imm64) arm64_move64(dyn, ninst, Rd, imm64) #define MOV64xw(Rd, imm64) if(rex.w) {MOV64x(Rd, imm64);} else {MOV32w(Rd, imm64);} #define MOV64z(Rd, imm64) if(rex.is32bits) {MOV32w(Rd, imm64);} else {MOV64x(Rd, imm64);} diff --git a/src/dynarec/arm64/dynarec_arm64_helper.c b/src/dynarec/arm64/dynarec_arm64_helper.c index b6dff229..27a73238 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.c +++ b/src/dynarec/arm64/dynarec_arm64_helper.c @@ -2145,6 +2145,82 @@ void emit_pf(dynarec_arm_t* dyn, int ninst, int s1, int s3, int s4) BFIw(xFlags, s4, F_PF, 1); } +void arm64_move32(dynarec_arm_t* dyn, int ninst, int reg, uint32_t val) +{ + // simple cases with only 1 operations + for(int i=0; i<2; ++i) + if((val&(0xFFFF<<(i*16)))==val) { + MOVZw_LSL(reg, (val>>(i*16))&0xFFFF, i*16); + return; + } + // same but with negation + for(int i=0; i<2; ++i) + if(((~val)&(0xFFFF<<(i*16)))==(~val)) { + MOVNw_LSL(reg, ((~val)>>(i*16))&0xFFFF, i*16); + return; + } + // generic cases + int mask = convert_bitmask_w(val); + if(mask) { + ORRw_mask(reg, xZR, mask&0x3F, (mask>>6)&0x3F); + } else { + MOVZw(reg, val&0xFFFF); + MOVKw_LSL(reg, (val>>16)&0xFFFF, 16); + } +} +void arm64_move64(dynarec_arm_t* dyn, int ninst, int reg, uint64_t val) +{ + // simple cases with only 1 operations + for(int i=0; i<4; ++i) + if((val&(0xFFFFLL<<(i*16)))==val) { + MOVZx_LSL(reg, (val>>(i*16))&0xFFFF, i*16); + return; + } + // same but with negation + for(int i=0; i<4; ++i) + if(((~val)&(0xFFFFLL<<(i*16)))==(~val)) { + MOVNx_LSL(reg, ((~val)>>(i*16))&0xFFFF, i*16); + return; + } + // mask + int mask = convert_bitmask_x(val); + if(mask) { + ORRx_mask(reg, xZR, (mask>>12)&1, mask&0x3F, (mask>>6)&0x3F); + return; + } + // 32bit value? + if((val&0xFFFFFFFF)==val) { + arm64_move32(dyn, ninst, reg, val); + return; + } + int n = 0; + // negatives values + if((val&0xFFFF000000000000LL)==0xFFFF000000000000LL) { + for(int i=0; i<3; ++i) { + if(((~val)>>(i*16))&0xFFFF) { + if(n) { + MOVKx_LSL(reg, (val>>(i*16))&0xFFFF, i*16); + } else { + MOVNx_LSL(reg, ((~val)>>(i*16))&0xFFFF, i*16); + n = 1; + } + } + } + return; + } + // positive values + for(int i=0; i<4; ++i) { + if((val>>(i*16))&0xFFFF) { + if(n) { + MOVKx_LSL(reg, (val>>(i*16))&0xFFFF, i*16); + } else { + MOVZx_LSL(reg, (val>>(i*16))&0xFFFF, i*16); + n = 1; + } + } + } +} + void fpu_reset_cache(dynarec_arm_t* dyn, int ninst, int reset_n) { diff --git a/src/dynarec/arm64/dynarec_arm64_helper.h b/src/dynarec/arm64/dynarec_arm64_helper.h index 563327e8..46a6a750 100644 --- a/src/dynarec/arm64/dynarec_arm64_helper.h +++ b/src/dynarec/arm64/dynarec_arm64_helper.h @@ -1130,6 +1130,9 @@ void* arm64_next(x64emu_t* emu, uintptr_t addr); #define CacheTransform STEPNAME(CacheTransform) +#define arm64_move32 STEPNAME(arm64_move32) +#define arm64_move64 STEPNAME(arm64_move64) + /* setup r2 to address pointed by */ uintptr_t geted(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int* unscaled, int absmax, uint32_t mask, rex_t rex, int* l, int s, int delta); @@ -1283,6 +1286,9 @@ int sse_setround(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3); void CacheTransform(dynarec_arm_t* dyn, int ninst, int cacheupd, int s1, int s2, int s3); +void arm64_move32(dynarec_arm_t* dyn, int ninst, int reg, uint32_t val); +void arm64_move64(dynarec_arm_t* dyn, int ninst, int reg, uint64_t val); + #if STEP < 2 #define CHECK_CACHE() 0 #else |