From 9794c572199db933485d1c000ed735f234908b17 Mon Sep 17 00:00:00 2001 From: Ali Gholami Rudi Date: Tue, 30 Aug 2016 21:15:02 +0430 Subject: [PATCH] x86: use push instruction for saving registers --- x86.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/x86.c b/x86.c index 5283184..3459b8e 100644 --- a/x86.c +++ b/x86.c @@ -129,6 +129,16 @@ static void mov_r2r(int rd, int r1, unsigned bt) op_rr(movrx_op(bt, I_MOVR), rd, r1, movrx_bt(bt)); } +static void i_push(int reg) +{ + op_x(I_PUSH | (reg & 0x7), 0, reg, LONGSZ); +} + +static void i_pop(int reg) +{ + op_x(I_POP | (reg & 0x7), 0, reg, LONGSZ); +} + static void i_mov(int rd, int rn) { op_rr(movrx_op(LONGSZ, I_MOVR), rd, rn, movrx_bt(LONGSZ)); @@ -390,14 +400,47 @@ static void i_sym(int rd, int sym, int off) oi(off, LONGSZ); } -static void i_saveregs(long sregs, long sregs_pos, int st) +static void i_subsp(long val) +{ + if (!val) + return; + if (val <= 127 && val >= -128) { + os("\x83\xec", 2); + oi(val, 1); + } else { + os("\x81\xec", 2); + oi(val, 4); + } +} + +static int regs_count(long regs) +{ + int cnt = 0; + int i; + for (i = 0; i < N_REGS; i++) + if (((1 << i) & R_TMPS) & regs) + cnt++; + return cnt; +} + +static void regs_save(long sregs, long dis) { - int nsregs = 0; int i; - for (i = 0; i < N_TMPS; i++) - if ((1 << tmpregs[i]) & sregs) - op_rm(st ? I_MOV : I_MOVR, tmpregs[i], REG_FP, - sregs_pos + nsregs++ * ULNG, ULNG); + for (i = 0; i < N_REGS; i++) + if (((1 << i) & R_TMPS) & sregs) + i_push(i); + if (dis) + i_subsp(dis); +} + +static void regs_load(long sregs, long dis) +{ + int i; + if (dis) + i_subsp(-dis); + for (i = N_REGS - 1; i >= 0; --i) + if (((1 << i) & R_TMPS) & sregs) + i_pop(i); } void i_wrap(int argc, long sargs, long spsub, int initfp, long sregs, long sregs_pos) @@ -420,16 +463,17 @@ void i_wrap(int argc, long sargs, long spsub, int initfp, long sregs, long sregs os("\x89\xe5", 2); /* mov rbp, rsp */ } if (spsub) { - os("\x81\xec", 2); spsub = ALIGN(spsub, 8); - oi(spsub, 4); + i_subsp(sregs ? -sregs_pos - regs_count(sregs) * ULNG : spsub); } - i_saveregs(sregs, sregs_pos, 1); /* saving registers */ + if (sregs) /* saving registers */ + regs_save(sregs, spsub + sregs_pos); diff = mem_len(&cs); mem_put(&cs, body, body_n); free(body); /* generating function epilogue */ - i_saveregs(sregs, sregs_pos, 0); /* restoring saved registers */ + if (sregs) /* restoring saved registers */ + regs_load(sregs, spsub + sregs_pos); if (initfp) os("\xc9", 1); /* leave */ os("\xc3", 1); /* ret */ -- 2.11.4.GIT