diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-03-13 17:55:51 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-03-13 17:55:51 +0100 |
| commit | 8730f2b0735bb384d756c9aab622a68795db8fc2 (patch) | |
| tree | 2f7f454f5c5d9f348b1fc9a47adfa0a4c6b21926 /src | |
| parent | 20a6e66e115b6cd1c21103cd7439f0dfcda0f07b (diff) | |
| download | box64-8730f2b0735bb384d756c9aab622a68795db8fc2.tar.gz box64-8730f2b0735bb384d756c9aab622a68795db8fc2.zip | |
[ARM64_DYNAREC] Optimised double push/pop with stp/ldp opcode
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/arm64/arm64_emitter.h | 2 | ||||
| -rwxr-xr-x | src/dynarec/arm64/dynarec_arm64_00.c | 77 | ||||
| -rwxr-xr-x | src/dynarec/arm64/dynarec_arm64_private.h | 2 |
3 files changed, 70 insertions, 11 deletions
diff --git a/src/dynarec/arm64/arm64_emitter.h b/src/dynarec/arm64/arm64_emitter.h index 5a440520..ab397a2b 100755 --- a/src/dynarec/arm64/arm64_emitter.h +++ b/src/dynarec/arm64/arm64_emitter.h @@ -309,6 +309,8 @@ // PUSH / POP helper #define POP1(reg) LDRx_S9_postindex(reg, xRSP, 8) #define PUSH1(reg) STRx_S9_preindex(reg, xRSP, -8) +#define POP2(reg1, reg2) LDPx_S7_postindex(reg1, reg2, xRSP, 16) +#define PUSH2(reg1, reg2) STPx_S7_preindex(reg2, reg1, xRSP, -16) // LOAD/STORE Acquire Exclusive #define MEMAX_gen(size, L, Rs, Rn, Rt) ((size)<<30 | 0b001000<<24 | (L)<<22 | (Rs)<<16 | 1<<15 | 0b11111<<10 | (Rn)<<5 | (Rt)) diff --git a/src/dynarec/arm64/dynarec_arm64_00.c b/src/dynarec/arm64/dynarec_arm64_00.c index b71f0bb8..3035514f 100755 --- a/src/dynarec/arm64/dynarec_arm64_00.c +++ b/src/dynarec/arm64/dynarec_arm64_00.c @@ -498,12 +498,36 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0x56: case 0x57: INST_NAME("PUSH reg"); - gd = xRAX+(opcode&0x07)+(rex.b<<3); - if(gd==xRSP) { - MOVx_REG(x1, gd); - gd = x1; + if(dyn->doublepush) + dyn->doublepush = 0; + else { + gd = xRAX+(opcode&0x07)+(rex.b<<3); + if(gd==xRSP) { + MOVx_REG(x1, gd); + gd = x1; + } + u32 = PK(0); + i32 = 1; + rex.rex = 0; + while(u32>=0x40 && u32<=0x4f) { + rex.rex = u32; + u32 = PK(i32); + i32++; + } + if(u32>=0x50 && u32<=0x57 && (dyn->size && dyn->insts[ninst+1].pred_sz==1)) { + // double push! + u32= xRAX+(u32&0x07)+(rex.b<<3); + MESSAGE(LOG_DUMP, "DOUBLE PUSH\n"); + if(u32==xRSP) { + MOVx_REG(x1, u32); + u32 = x1; + } + PUSH2(gd, u32); + dyn->doublepush = 1; + } else { + PUSH1(gd); + } } - PUSH1(gd); break; case 0x58: case 0x59: @@ -514,12 +538,43 @@ uintptr_t dynarec64_00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nin case 0x5E: case 0x5F: INST_NAME("POP reg"); - gd = xRAX+(opcode&0x07)+(rex.b<<3); - if(gd == xRSP) { - POP1(x1); - MOVx_REG(gd, x1); - } else { - POP1(gd); + if(dyn->doublepop) + dyn->doublepop = 0; + else { + gd = xRAX+(opcode&0x07)+(rex.b<<3); + u32 = PK(0); + i32 = 1; + rex.rex = 0; + while(u32>=0x40 && u32<=0x4f) { + rex.rex = u32; + u32 = PK(i32); + i32++; + } + if(u32>=0x58 && u32<=0x5f && (dyn->size && dyn->insts[ninst+1].pred_sz==1)) { + // double pop! + u32= xRAX+(u32&0x07)+(rex.b<<3); + MESSAGE(LOG_DUMP, "DOUBLE POP\n"); + if(gd==u32) { + ADDx_U12(xRSP, xRSP, 0x8); + POP1((gd==xRSP)?x1:gd); + } else { + POP2((gd==xRSP)?x1:gd, (u32==xRSP)?x1:u32); + if(u32==xRSP) { + MOVx_REG(u32, x1); + } + } + if(gd == xRSP) { + MOVx_REG(gd, x1); + } + dyn->doublepop = 1; + } else { + if(gd == xRSP) { + POP1(x1); + MOVx_REG(gd, x1); + } else { + POP1(gd); + } + } } break; diff --git a/src/dynarec/arm64/dynarec_arm64_private.h b/src/dynarec/arm64/dynarec_arm64_private.h index d0ca7c9c..dcf78084 100755 --- a/src/dynarec/arm64/dynarec_arm64_private.h +++ b/src/dynarec/arm64/dynarec_arm64_private.h @@ -110,6 +110,8 @@ typedef struct dynarec_arm_s { uintptr_t forward_to; // address of the next jump to (to check if everything is ok) int32_t forward_size; // size at the forward point int forward_ninst; // ninst at the forward point + uint8_t doublepush; + uint8_t doublepop; } dynarec_arm_t; void add_next(dynarec_arm_t *dyn, uintptr_t addr); |