From patchwork Thu May 27 20:46:03 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 53793 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id F1A9DB7D1B for ; Fri, 28 May 2010 07:02:31 +1000 (EST) Received: from localhost ([127.0.0.1]:53883 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OHkDj-00064z-QN for incoming@patchwork.ozlabs.org; Thu, 27 May 2010 17:02:27 -0400 Received: from [140.186.70.92] (port=55935 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OHjz4-000200-GG for qemu-devel@nongnu.org; Thu, 27 May 2010 16:47:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OHjz3-0005Il-0m for qemu-devel@nongnu.org; Thu, 27 May 2010 16:47:18 -0400 Received: from are.twiddle.net ([75.149.56.221]:51207) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OHjz2-0005Ie-Ig for qemu-devel@nongnu.org; Thu, 27 May 2010 16:47:16 -0400 Received: from anchor.twiddle.home (anchor.twiddle.home [172.31.0.4]) by are.twiddle.net (Postfix) with ESMTPS id E97B1EFA; Thu, 27 May 2010 13:47:15 -0700 (PDT) Received: from anchor.twiddle.home (anchor.twiddle.home [127.0.0.1]) by anchor.twiddle.home (8.14.4/8.14.4) with ESMTP id o4RKlFR3030921; Thu, 27 May 2010 13:47:15 -0700 Received: (from rth@localhost) by anchor.twiddle.home (8.14.4/8.14.4/Submit) id o4RKlE9f030920; Thu, 27 May 2010 13:47:14 -0700 From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 27 May 2010 13:46:03 -0700 Message-Id: <1274993204-30766-22-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 1.7.0.1 In-Reply-To: <1274993204-30766-1-git-send-email-rth@twiddle.net> References: <1274993204-30766-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) Cc: agraf@suse.de, aurelien@aurel32.net Subject: [Qemu-devel] [PATCH 21/62] tcg-s390: Generalize the direct load/store emission. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Define tcg_out_ldst which can properly choose between RX and RXY format instructions based on the offset used, and also handles large offsets. Use it to implement all the INDEX_op_ld/st operations. Signed-off-by: Richard Henderson --- tcg/s390/tcg-target.c | 152 +++++++++++++++++++++++-------------------------- 1 files changed, 71 insertions(+), 81 deletions(-) diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index b150d1a..21ad1a3 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -90,17 +90,22 @@ typedef enum S390Opcode { RS_SRL = 0x88, RXY_CG = 0xe320, + RXY_LB = 0xe376, RXY_LG = 0xe304, RXY_LGB = 0xe377, RXY_LGF = 0xe314, RXY_LGH = 0xe315, + RXY_LHY = 0xe378, + RXY_LLC = 0xe394, RXY_LLGC = 0xe390, RXY_LLGF = 0xe316, RXY_LLGH = 0xe391, + RXY_LLH = 0xe395, RXY_LMG = 0xeb04, RXY_LRV = 0xe31e, RXY_LRVG = 0xe30f, RXY_LRVH = 0xe31f, + RXY_LY = 0xe358, RXY_STCY = 0xe372, RXY_STG = 0xe324, RXY_STHY = 0xe370, @@ -108,7 +113,10 @@ typedef enum S390Opcode { RXY_STRV = 0xe33e, RXY_STRVG = 0xe32f, RXY_STRVH = 0xe33f, + RXY_STY = 0xe350, + RX_L = 0x58, + RX_LH = 0x48, RX_ST = 0x50, RX_STC = 0x42, RX_STH = 0x40, @@ -362,22 +370,52 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type, } } -/* load data without address translation or endianness conversion */ -static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg data, - TCGReg base, tcg_target_long ofs) + +/* Emit a load/store type instruction. Inputs are: + DATA: The register to be loaded or stored. + BASE+OFS: The effective address. + OPC_RX: If the operation has an RX format opcode (e.g. STC), otherwise 0. + OPC_RXY: The RXY format opcode for the operation (e.g. STCY). */ + +static void tcg_out_ldst(TCGContext *s, S390Opcode opc_rx, S390Opcode opc_rxy, + TCGReg data, TCGReg base, tcg_target_long ofs) { - S390Opcode op; + TCGReg index = 0; + + if (ofs < -0x80000 || ofs >= 0x80000) { + /* Combine the low 16 bits of the offset with the actual load insn; + the high 48 bits must come from an immediate load. */ + index = TCG_REG_R13; + tcg_out_movi(s, TCG_TYPE_PTR, index, ofs & ~0xffff); + ofs &= 0xffff; + } - op = (type == TCG_TYPE_I32) ? RXY_LLGF : RXY_LG; + if (opc_rx && ofs >= 0 && ofs < 0x1000) { + tcg_out_insn_RX(s, opc_rx, data, base, index, ofs); + } else { + tcg_out_insn_RXY(s, opc_rxy, data, base, index, ofs); + } +} - if (ofs < -0x80000 || ofs > 0x7ffff) { - /* load the displacement */ - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, ofs); - /* load the data */ - tcg_out_insn_RXY(s, op, data, base, TCG_REG_R13, 0); + +/* load data without address translation or endianness conversion */ +static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg data, + TCGReg base, tcg_target_long ofs) +{ + if (type == TCG_TYPE_I32) { + tcg_out_ldst(s, RX_L, RXY_LY, data, base, ofs); } else { - /* load the data */ - tcg_out_insn_RXY(s, op, data, base, 0, ofs); + tcg_out_ldst(s, 0, RXY_LG, data, base, ofs); + } +} + +static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg data, + TCGReg base, tcg_target_long ofs) +{ + if (type == TCG_TYPE_I32) { + tcg_out_ldst(s, RX_ST, RXY_STY, data, base, ofs); + } else { + tcg_out_ldst(s, 0, RXY_STG, data, base, ofs); } } @@ -693,28 +731,6 @@ static void tcg_out_qemu_st(TCGContext* s, const TCGArg* args, int opc) tcg_finish_qemu_ldst(s, label2_ptr); } -static inline void tcg_out_st(TCGContext *s, TCGType type, int arg, - int arg1, tcg_target_long arg2) -{ - dprintf("tcg_out_st arg 0x%x arg1 0x%x arg2 0x%lx\n", arg, arg1, arg2); - - if (type == TCG_TYPE_I32) { - if (((long)arg2) < -0x800 || ((long)arg2) > 0x7ff) { - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, arg2); - tcg_out_insn(s, RRE, AGR, 13, arg1); - tcg_out_insn(s, RX, ST, arg, TCG_REG_R13, 0, 0); - } else { - tcg_out_insn(s, RX, ST, arg, arg1, 0, arg2); - } - } - else { - if (((long)arg2) < -0x80000 || ((long)arg2) > 0x7ffff) { - tcg_abort(); - } - tcg_out_insn(s, RXY, STG, arg, arg1, 0, arg2); - } -} - static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, const int *const_args) { @@ -780,51 +796,41 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_ld8u_i32: + tcg_out_ldst(s, 0, RXY_LLC, args[0], args[1], args[2]); + break; case INDEX_op_ld8u_i64: - if ((long)args[2] > -0x80000 && (long)args[2] < 0x7ffff) { - tcg_out_insn(s, RXY, LLGC, args[0], args[1], 0, args[2]); - } else { - /* XXX displacement too large, have to calculate address manually */ - tcg_abort(); - } + tcg_out_ldst(s, 0, RXY_LLGC, args[0], args[1], args[2]); break; case INDEX_op_ld8s_i32: - /* XXX */ - tcg_abort(); + tcg_out_ldst(s, 0, RXY_LB, args[0], args[1], args[2]); + break; + case INDEX_op_ld8s_i64: + tcg_out_ldst(s, 0, RXY_LGB, args[0], args[1], args[2]); break; case INDEX_op_ld16u_i32: - if ((long)args[2] > -0x80000 && (long)args[2] < 0x7ffff) { - tcg_out_insn(s, RXY, LLGH, args[0], args[1], 0, args[2]); - } else { - /* XXX displacement too large, have to calculate address manually */ - tcg_abort(); - } + tcg_out_ldst(s, 0, RXY_LLH, args[0], args[1], args[2]); + break; + case INDEX_op_ld16u_i64: + tcg_out_ldst(s, 0, RXY_LLGH, args[0], args[1], args[2]); break; case INDEX_op_ld16s_i32: - /* XXX */ - tcg_abort(); + tcg_out_ldst(s, RX_LH, RXY_LHY, args[0], args[1], args[2]); + break; + case INDEX_op_ld16s_i64: + tcg_out_ldst(s, 0, RXY_LGH, args[0], args[1], args[2]); break; case INDEX_op_ld_i32: - case INDEX_op_ld32u_i64: tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]); break; - + case INDEX_op_ld32u_i64: + tcg_out_ldst(s, 0, RXY_LLGF, args[0], args[1], args[2]); + break; case INDEX_op_ld32s_i64: - if (args[2] < -0x80000 || args[2] > 0x7ffff) { - /* load the displacement */ - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, args[2]); - /* add the address */ - tcg_out_insn(s, RRE, AGR, TCG_REG_R13, args[1]); - /* load the data (sign-extended) */ - tcg_out_insn(s, RXY, LGF, args[0], TCG_REG_R13, 0, 0); - } else { - /* load the data (sign-extended) */ - tcg_out_insn(s, RXY, LGF, args[0], args[1], 0, args[2]); - } + tcg_out_ldst(s, 0, RXY_LGF, args[0], args[1], args[2]); break; case INDEX_op_ld_i64: @@ -833,28 +839,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_st8_i32: case INDEX_op_st8_i64: - if (((long)args[2]) >= -0x800 && ((long)args[2]) < 0x800) { - tcg_out_insn(s, RX, STC, args[0], args[1], 0, args[2]); - } else if (((long)args[2]) >= -0x80000 && ((long)args[2]) < 0x80000) { - /* FIXME: requires long displacement facility */ - tcg_out_insn(s, RXY, STCY, args[0], args[1], 0, args[2]); - tcg_abort(); - } else { - tcg_abort(); - } + tcg_out_ldst(s, RX_STC, RXY_STCY, args[0], args[1], args[2]); break; case INDEX_op_st16_i32: case INDEX_op_st16_i64: - if (((long)args[2]) >= -0x800 && ((long)args[2]) < 0x800) { - tcg_out_insn(s, RX, STH, args[0], args[1], 0, args[2]); - } else if (((long)args[2]) >= -0x80000 && ((long)args[2]) < 0x80000) { - /* FIXME: requires long displacement facility */ - tcg_out_insn(s, RXY, STHY, args[0], args[1], 0, args[2]); - tcg_abort(); - } else { - tcg_abort(); - } + tcg_out_ldst(s, RX_STH, RXY_STHY, args[0], args[1], args[2]); break; case INDEX_op_st_i32: