From patchwork Thu Mar 28 15:32:57 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 232083 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 08AC12C00BC for ; Fri, 29 Mar 2013 02:56:20 +1100 (EST) Received: from localhost ([::1]:41851 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ULEw5-0000V7-HW for incoming@patchwork.ozlabs.org; Thu, 28 Mar 2013 11:40:17 -0400 Received: from eggs.gnu.org ([208.118.235.92]:57471) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ULEpw-0001oo-5x for qemu-devel@nongnu.org; Thu, 28 Mar 2013 11:34:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ULEps-0003ef-Rw for qemu-devel@nongnu.org; Thu, 28 Mar 2013 11:33:56 -0400 Received: from mail-pa0-f45.google.com ([209.85.220.45]:40518) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ULEps-0003eW-Jf for qemu-devel@nongnu.org; Thu, 28 Mar 2013 11:33:52 -0400 Received: by mail-pa0-f45.google.com with SMTP id kl13so2735793pab.32 for ; Thu, 28 Mar 2013 08:33:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:sender:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references; bh=/IlMuoTKOVroLLYtlBWpXAekyavNx49P+n6xnqOV34I=; b=ZioaCjlb5h4eo7V4xFyfoCXKJyYugIE4e/9z90N8idd4lDkXz5Ekb42y5RzPZMMpcb A9b6GtVufQs1UE0Ju8Jp7dMUzqLwb48ME4y08yqC/sN+AhkkHAmDfDx3oUrOUQ+YXKDi WzV5AbEukrd6dxA3wJU5KMwfHC3bXQph8uef0xqLu6mLmac1WbP+bJvLT3Pjq41fRYF0 TWkup7DbqV9lwpIdE9iyPVcxFOfkEm8/rlwWjZExTBFNrn/ziD6ELBqZAVZ77FOOzmh6 SEpMIEfM5YRh9mCK6yVmXBA9L8fOFVOp/rX4laXktoRKC2iVUvhXS7iO+H5pjHoNjElc xkgA== X-Received: by 10.68.252.193 with SMTP id zu1mr35827946pbc.175.1364484831903; Thu, 28 Mar 2013 08:33:51 -0700 (PDT) Received: from fremont.twiddle.net (50-194-63-110-static.hfc.comcastbusiness.net. [50.194.63.110]) by mx.google.com with ESMTPS id kb3sm25939542pbc.21.2013.03.28.08.33.49 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Thu, 28 Mar 2013 08:33:50 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 28 Mar 2013 08:32:57 -0700 Message-Id: <1364484781-15561-17-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 1.8.1.4 In-Reply-To: <1364484781-15561-1-git-send-email-rth@twiddle.net> References: <1364484781-15561-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 209.85.220.45 Cc: Peter Maydell , Aurelien Jarno Subject: [Qemu-devel] [PATCH v3 16/20] tcg-arm: Fix local stack frame X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org We were not allocating TCG_STATIC_CALL_ARGS_SIZE, so this meant that any helper with more than 4 arguments would clobber the saved regs. Realizing that we're supposed to have this memory pre-allocated means we can clean up the tcg_out_arg functions, which were trying to do more stack allocation. Allocate stack memory for the TCG temporaries while we're at it. Signed-off-by: Richard Henderson Reviewed-by: Aurelien Jarno --- tcg/arm/tcg-target.c | 120 ++++++++++++++++++--------------------------------- 1 file changed, 43 insertions(+), 77 deletions(-) diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index fb8c96d..70f63cb 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -1074,65 +1074,35 @@ static const void * const qemu_st_helpers[4] = { * argreg is where we want to put this argument, arg is the argument itself. * Return value is the updated argreg ready for the next call. * Note that argreg 0..3 is real registers, 4+ on stack. - * When we reach the first stacked argument, we allocate space for it - * and the following stacked arguments using "str r8, [sp, #-0x10]!". - * Following arguments are filled in with "str r8, [sp, #0xNN]". - * For more than 4 stacked arguments we'd need to know how much - * space to allocate when we pushed the first stacked argument. - * We don't need this, so don't implement it (and will assert if you try it.) * * We provide routines for arguments which are: immediate, 32 bit * value in register, 16 and 8 bit values in register (which must be zero * extended before use) and 64 bit value in a lo:hi register pair. */ -#define DEFINE_TCG_OUT_ARG(NAME, ARGPARAM) \ - static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGPARAM) \ - { \ - if (argreg < 4) { \ - TCG_OUT_ARG_GET_ARG(argreg); \ - } else if (argreg == 4) { \ - TCG_OUT_ARG_GET_ARG(TCG_REG_TMP); \ - tcg_out32(s, (COND_AL << 28) | 0x052d0010 | (TCG_REG_TMP << 12)); \ - } else { \ - assert(argreg < 8); \ - TCG_OUT_ARG_GET_ARG(TCG_REG_TMP); \ - tcg_out_st32_12(s, COND_AL, TCG_REG_TMP, TCG_REG_CALL_STACK, \ - (argreg - 4) * 4); \ - } \ - return argreg + 1; \ - } - -#define TCG_OUT_ARG_GET_ARG(A) tcg_out_dat_imm(s, COND_AL, ARITH_MOV, A, 0, arg) -DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32, uint32_t arg) -#undef TCG_OUT_ARG_GET_ARG -#define TCG_OUT_ARG_GET_ARG(A) tcg_out_ext8u(s, COND_AL, A, arg) -DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8, TCGReg arg) -#undef TCG_OUT_ARG_GET_ARG -#define TCG_OUT_ARG_GET_ARG(A) tcg_out_ext16u(s, COND_AL, A, arg) -DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16, TCGReg arg) -#undef TCG_OUT_ARG_GET_ARG - -/* We don't use the macro for this one to avoid an unnecessary reg-reg - * move when storing to the stack. - */ -static TCGReg tcg_out_arg_reg32(TCGContext *s, TCGReg argreg, TCGReg arg) -{ - if (argreg < 4) { - tcg_out_mov_reg(s, COND_AL, argreg, arg); - } else if (argreg == 4) { - /* str arg, [sp, #-0x10]! */ - tcg_out32(s, (COND_AL << 28) | 0x052d0010 | (arg << 12)); - } else { - assert(argreg < 8); - /* str arg, [sp, #0xNN] */ - tcg_out32(s, (COND_AL << 28) | 0x058d0000 | - (arg << 12) | (argreg - 4) * 4); - } - return argreg + 1; -} - -static inline TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg, - TCGReg arglo, TCGReg arghi) +#define DEFINE_TCG_OUT_ARG(NAME, ARGTYPE, MOV_ARG, EXT_ARG) \ +static TCGReg NAME(TCGContext *s, TCGReg argreg, ARGTYPE arg) \ +{ \ + if (argreg < 4) { \ + MOV_ARG(s, COND_AL, argreg, arg); \ + } else { \ + int ofs = (argreg - 4) * 4; \ + EXT_ARG; \ + assert(ofs + 4 <= TCG_STATIC_CALL_ARGS_SIZE); \ + tcg_out_st32_12(s, COND_AL, arg, TCG_REG_CALL_STACK, ofs); \ + } \ + return argreg + 1; \ +} + +DEFINE_TCG_OUT_ARG(tcg_out_arg_imm32, uint32_t, tcg_out_movi32, + (tcg_out_movi32(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP)) +DEFINE_TCG_OUT_ARG(tcg_out_arg_reg8, TCGReg, tcg_out_ext8u, + (tcg_out_ext8u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP)) +DEFINE_TCG_OUT_ARG(tcg_out_arg_reg16, TCGReg, tcg_out_ext16u, + (tcg_out_ext16u(s, COND_AL, TCG_REG_TMP, arg), arg = TCG_REG_TMP)) +DEFINE_TCG_OUT_ARG(tcg_out_arg_reg32, TCGReg, tcg_out_mov_reg, ) + +static TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg, + TCGReg arglo, TCGReg arghi) { /* 64 bit arguments must go in even/odd register pairs * and in 8-aligned stack slots. @@ -1144,16 +1114,7 @@ static inline TCGReg tcg_out_arg_reg64(TCGContext *s, TCGReg argreg, argreg = tcg_out_arg_reg32(s, argreg, arghi); return argreg; } - -static inline void tcg_out_arg_stacktidy(TCGContext *s, TCGReg argreg) -{ - /* Output any necessary post-call cleanup of the stack */ - if (argreg > 4) { - tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10); - } -} - -#endif +#endif /* SOFTMMU */ #define TLB_SHIFT (CPU_TLB_ENTRY_BITS + CPU_TLB_BITS) @@ -1284,7 +1245,6 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc) #endif argreg = tcg_out_arg_imm32(s, argreg, mem_index); tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[s_bits]); - tcg_out_arg_stacktidy(s, argreg); switch (opc) { case 0 | 4: @@ -1502,7 +1462,6 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) argreg = tcg_out_arg_imm32(s, argreg, mem_index); tcg_out_call(s, (tcg_target_long) qemu_st_helpers[s_bits]); - tcg_out_arg_stacktidy(s, argreg); reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr); #else /* !CONFIG_SOFTMMU */ @@ -1560,6 +1519,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc) } static uint32_t tb_pop_ret; +static uint32_t tb_frame_size; static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, const int *const_args) @@ -1570,14 +1530,16 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, switch (opc) { case INDEX_op_exit_tb: a0 = args[0]; + tcg_out_dat_rI(s, COND_AL, ARITH_ADD, TCG_REG_CALL_STACK, + TCG_REG_CALL_STACK, tb_frame_size, 1); if (use_armv7_instructions || check_fit_imm(a0)) { - tcg_out_movi32(s, COND_AL, TCG_REG_R0, args[0]); + tcg_out_movi32(s, COND_AL, TCG_REG_R0, a0); tcg_out32(s, tb_pop_ret); } else { /* pc is always current address + 8, so 0 reads the word. */ tcg_out_ld32_12(s, COND_AL, TCG_REG_R0, TCG_REG_PC, 0); tcg_out32(s, tb_pop_ret); - tcg_out32(s, args[0]); + tcg_out32(s, a0); } break; case INDEX_op_goto_tb: @@ -2002,8 +1964,6 @@ static void tcg_target_init(TCGContext *s) tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC); tcg_add_target_add_op_defs(arm_op_defs); - tcg_set_frame(s, TCG_AREG0, offsetof(CPUArchState, temp_buf), - CPU_TEMP_BUF_NLONGS * sizeof(long)); } static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg, @@ -2032,17 +1992,23 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type, static void tcg_target_qemu_prologue(TCGContext *s) { - /* Calling convention requires us to save r4-r11 and lr; - * save also r12 to maintain stack 8-alignment. - */ - + /* Calling convention requires us to save r4-r11 and lr; save also r12 + to maintain stack 8-alignment. */ /* stmdb sp!, { r4 - r12, lr } */ tcg_out32(s, (COND_AL << 28) | 0x092d5ff0); + /* ldmia sp!, { r4 - r12, pc } */ + tb_pop_ret = (COND_AL << 28) | 0x08bd9ff0; + + /* Allocate the local stack frame. */ + tb_frame_size = TCG_STATIC_CALL_ARGS_SIZE; + tb_frame_size += CPU_TEMP_BUF_NLONGS * sizeof(long); + tcg_out_dat_rI(s, COND_AL, ARITH_SUB, TCG_REG_CALL_STACK, + TCG_REG_CALL_STACK, tb_frame_size, 1); + tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE, + CPU_TEMP_BUF_NLONGS * sizeof(long)); + tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]); tcg_out_bx(s, COND_AL, tcg_target_call_iarg_regs[1]); - - /* ldmia sp!, { r4 - r12, pc } */ - tb_pop_ret = (COND_AL << 28) | 0x08bd9ff0; }