From patchwork Tue Feb 9 10:39:55 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 8259591 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 474B6BEEE5 for ; Tue, 9 Feb 2016 10:41:03 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BF64620263 for ; Tue, 9 Feb 2016 10:41:01 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3E0822022D for ; Tue, 9 Feb 2016 10:41:00 +0000 (UTC) Received: from localhost ([::1]:54062 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aT5j9-0006jH-K7 for patchwork-qemu-devel@patchwork.kernel.org; Tue, 09 Feb 2016 05:40:59 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46242) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aT5io-0006YQ-3j for qemu-devel@nongnu.org; Tue, 09 Feb 2016 05:40:40 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aT5ih-0005QB-QH for qemu-devel@nongnu.org; Tue, 09 Feb 2016 05:40:37 -0500 Received: from mail-pf0-x242.google.com ([2607:f8b0:400e:c00::242]:35772) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aT5ih-0005Q2-18 for qemu-devel@nongnu.org; Tue, 09 Feb 2016 05:40:31 -0500 Received: by mail-pf0-x242.google.com with SMTP id 66so9830854pfe.2 for ; Tue, 09 Feb 2016 02:40:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=hEFtCwWzN1DjpeRDGRX23vnVRr6oiIjFF1DESpxoh+c=; b=duM7AW7nIoPGJKy3fUwLDYiUm67721q52DLsJaUBafUcivh+aBzR2KU9zhUUSb4NbN ThIHLHnvRnXzFCKSAYZLjLQUZXf156jrSIVsoi+abdbsPgYIL9iw3570/EfVoijoohHm CdHp8BUUOY4TwlT3voJDTM+KSMFJFjGqnzKei+AwWRf9YrRsUB0N9ZfYYKribGsVdtO+ LlzOBjlfNwdniL6uwPWYzXit/ty1CCNU0lsNeU3EcmYpY82TXoIhjTUf/kiPWbTfkdJ5 omE1Wc08P7Z0nSte6wQeRnnQM4tg9cD9KG29Qdj5AUzPRWt6vzkfX4zidMB9fieJADuA XFvQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=hEFtCwWzN1DjpeRDGRX23vnVRr6oiIjFF1DESpxoh+c=; b=QiiALBzmu/SpcPErEaSZhkSXVY2/ZGmiGQMptZY3F64Bk3TuNRbjiwCf5jJPzVknQo 7iojcmrjcdCrIUi7kZqGbJWY8PiWAnGh+BujeKJ7jN7GBwZwiy79qSbGc4cpXyKVScCv TmQERj28Ua8RA9+kRBVIPKybbndEBHg+EipInLr0qUyIJyI2xnaX12359znshEtZ6xDu X8fGY5Zrx89lJJ8EhGAepDtYZz9yxrp8x7GC51RJxEtiGuLWVA5ig9BXM94c7f+GfMxh YY3YV2o/gMrzfFlBkDLJcU3djg6EoiDZoMEp92UZFMi/bfnpNdELYbOhu75MVU6PfTZc SlGw== X-Gm-Message-State: AG10YOSpkPJg99MKwmqKwS/7a3kLot+U+89f4ogHw/OifjO8zQYlTaPG+UrSXHoKBVuF/A== X-Received: by 10.98.71.92 with SMTP id u89mr49426513pfa.122.1455014430400; Tue, 09 Feb 2016 02:40:30 -0800 (PST) Received: from bigtime.gateway (alanje.lnk.telstra.net. [120.151.179.201]) by smtp.gmail.com with ESMTPSA id 1sm49669183pfm.10.2016.02.09.02.40.27 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 09 Feb 2016 02:40:29 -0800 (PST) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 9 Feb 2016 21:39:55 +1100 Message-Id: <1455014403-10742-8-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1455014403-10742-1-git-send-email-rth@twiddle.net> References: <1455014403-10742-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400e:c00::242 Cc: james.hogan@imgtec.com, aurelien@aurel32.net Subject: [Qemu-devel] [PATCH 07/15] tcg-mips: Adjust qemu_ld/st for mips64 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+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP At the same time, use extract in the tlb_load for mips32r2. Signed-off-by: Richard Henderson --- tcg/mips/tcg-target.c | 239 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 163 insertions(+), 76 deletions(-) diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c index e986437..242db14 100644 --- a/tcg/mips/tcg-target.c +++ b/tcg/mips/tcg-target.c @@ -33,8 +33,14 @@ # define MIPS_BE 0 #endif -#define LO_OFF (MIPS_BE * 4) -#define HI_OFF (4 - LO_OFF) +#if TCG_TARGET_REG_BITS == 32 +# define LO_OFF (MIPS_BE * 4) +# define HI_OFF (4 - LO_OFF) +#else +extern int link_error(void); +# define LO_OFF link_error() +# define HI_OFF link_error() +#endif #ifndef NDEBUG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { @@ -188,7 +194,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_set(ct->u.regs, 0xffffffff); tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0); #if defined(CONFIG_SOFTMMU) - if (TARGET_LONG_BITS == 64) { + if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2); } #endif @@ -198,11 +204,11 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) tcg_regset_set(ct->u.regs, 0xffffffff); tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0); #if defined(CONFIG_SOFTMMU) - if (TARGET_LONG_BITS == 32) { - tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1); - } else { + if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2); tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3); + } else { + tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1); } #endif break; @@ -726,6 +732,16 @@ static inline void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg) } } +static inline void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg) +{ + if (use_mips32r2_instructions) { + tcg_out_opc_bf(s, OPC_DEXT, ret, arg, 31, 0); + } else { + tcg_out_dsll(s, ret, arg, 32); + tcg_out_dsrl(s, ret, ret, 32); + } +} + static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data, TCGReg addr, intptr_t ofs) { @@ -1124,6 +1140,10 @@ static void * const qemu_ld_helpers[16] = { [MO_BESW] = helper_be_ldsw_mmu, [MO_BEUL] = helper_be_ldul_mmu, [MO_BEQ] = helper_be_ldq_mmu, +#if TCG_TARGET_REG_BITS == 64 + [MO_LESL] = helper_le_ldsl_mmu, + [MO_BESL] = helper_be_ldsl_mmu, +#endif }; static void * const qemu_st_helpers[16] = { @@ -1151,6 +1171,9 @@ static int tcg_out_call_iarg_reg(TCGContext *s, int i, TCGReg arg) if (i < ARRAY_SIZE(tcg_target_call_iarg_regs)) { tcg_out_mov(s, TCG_TYPE_REG, tcg_target_call_iarg_regs[i], arg); } else { + /* For N32 and N64, the initial offset is different. But there + we also have 8 argument register so we don't run out here. */ + assert(TCG_TARGET_REG_BITS == 32); tcg_out_st(s, TCG_TYPE_REG, arg, TCG_REG_SP, 4 * i); } return i + 1; @@ -1192,6 +1215,7 @@ static int tcg_out_call_iarg_imm(TCGContext *s, int i, TCGArg arg) static int tcg_out_call_iarg_reg2(TCGContext *s, int i, TCGReg al, TCGReg ah) { + assert(TCG_TARGET_REG_BITS == 32); i = (i + 1) & ~1; i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? ah : al)); i = tcg_out_call_iarg_reg(s, i, (MIPS_BE ? al : ah)); @@ -1205,6 +1229,7 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl, tcg_insn_unit *label_ptr[2], bool is_load) { TCGMemOp s_bits = get_memop(oi) & MO_SIZE; + target_ulong mask = TARGET_PAGE_MASK | ((1 << s_bits) - 1); int mem_index = get_mmuidx(oi); int cmp_off = (is_load @@ -1212,11 +1237,24 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl, : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write)); int add_off = offsetof(CPUArchState, tlb_table[mem_index][0].addend); - tcg_out_opc_sa(s, OPC_SRL, TCG_REG_A0, addrl, - TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); - tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, - (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); - tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0); + if (use_mips32r2_instructions) { + if (TCG_TARGET_REG_BITS == 32 || TARGET_LONG_BITS == 32) { + tcg_out_opc_bf(s, OPC_EXT, TCG_REG_A0, addrl, + TARGET_PAGE_BITS + CPU_TLB_ENTRY_BITS - 1, + CPU_TLB_ENTRY_BITS); + } else { + tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU, + TCG_REG_A0, addrl, + TARGET_PAGE_BITS + CPU_TLB_ENTRY_BITS - 1, + CPU_TLB_ENTRY_BITS); + } + } else { + tcg_out_opc_sa(s, ALIAS_TSRL, TCG_REG_A0, addrl, + TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); + tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0, + (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); + } + tcg_out_opc_reg(s, ALIAS_PADD, TCG_REG_A0, TCG_REG_A0, TCG_AREG0); /* Compensate for very large offsets. */ if (add_off >= 0x8000) { @@ -1226,43 +1264,48 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, TCGReg addrl, QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1]) > 0x7ff0 + 0x7fff); - tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, TCG_REG_A0, 0x7ff0); + tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_A0, TCG_REG_A0, 0x7ff0); cmp_off -= 0x7ff0; add_off -= 0x7ff0; } - /* Load the (low half) tlb comparator. */ - tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0, - cmp_off + (TARGET_LONG_BITS == 64 ? LO_OFF : 0)); - - /* Mask the page bits, keeping the alignment bits to compare against. - In between on 32-bit targets, load the tlb addend for the fast path. */ - tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1, - TARGET_PAGE_MASK | ((1 << s_bits) - 1)); - if (TARGET_LONG_BITS == 32) { - tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0, add_off); + /* Load the (low half) tlb comparator. Mask the page bits, keeping the + alignment bits to compare against. */ + if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { + tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_REG_A0, cmp_off + LO_OFF); + tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1, mask); + } else { + tcg_out_ld(s, TCG_TYPE_TL, TCG_TMP0, TCG_REG_A0, cmp_off); + tcg_out_movi(s, TCG_TYPE_TL, TCG_TMP1, mask); + /* No second compare is required here; + load the tlb addend for the fast path. */ + tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_REG_A0, add_off); } tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrl); + /* Zero extend a 32-bit guest address for a 64-bit host. */ + if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) { + tcg_out_ext32u(s, base, addrl); + addrl = base; + } + label_ptr[0] = s->code_ptr; tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0); /* Load and test the high half tlb comparator. */ - if (TARGET_LONG_BITS == 64) { + if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { /* delay slot */ - tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0, cmp_off + HI_OFF); + tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_REG_A0, cmp_off + HI_OFF); - /* Load the tlb addend for the fast path. We can't do it earlier with - 64-bit targets or we'll clobber a0 before reading the high half tlb - comparator. */ - tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0, add_off); + /* Load the tlb addend for the fast path. */ + tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_A0, TCG_REG_A0, add_off); label_ptr[1] = s->code_ptr; tcg_out_opc_br(s, OPC_BNE, addrh, TCG_TMP0); } /* delay slot */ - tcg_out_opc_reg(s, OPC_ADDU, base, TCG_REG_A0, addrl); + tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_REG_A0, addrl); } static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOpIdx oi, @@ -1280,7 +1323,7 @@ static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOpIdx oi, label->addrhi_reg = addrhi; label->raddr = raddr; label->label_ptr[0] = label_ptr[0]; - if (TARGET_LONG_BITS == 64) { + if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { label->label_ptr[1] = label_ptr[1]; } } @@ -1294,12 +1337,12 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) /* resolve label address */ reloc_pc16(l->label_ptr[0], s->code_ptr); - if (TARGET_LONG_BITS == 64) { + if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { reloc_pc16(l->label_ptr[1], s->code_ptr); } i = 1; - if (TARGET_LONG_BITS == 64) { + if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg); } else { i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg); @@ -1311,7 +1354,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l) tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0); v0 = l->datalo_reg; - if ((opc & MO_SIZE) == MO_64) { + if (TCG_TARGET_REG_BITS == 32 && (opc & MO_SIZE) == MO_64) { /* We eliminated V0 from the possible output registers, so it cannot be clobbered here. So we must move V1 first. */ if (MIPS_BE) { @@ -1337,12 +1380,12 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) /* resolve label address */ reloc_pc16(l->label_ptr[0], s->code_ptr); - if (TARGET_LONG_BITS == 64) { + if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { reloc_pc16(l->label_ptr[1], s->code_ptr); } i = 1; - if (TARGET_LONG_BITS == 64) { + if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { i = tcg_out_call_iarg_reg2(s, i, l->addrlo_reg, l->addrhi_reg); } else { i = tcg_out_call_iarg_reg(s, i, l->addrlo_reg); @@ -1354,14 +1397,15 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) case MO_16: i = tcg_out_call_iarg_reg16(s, i, l->datalo_reg); break; - case MO_32: - i = tcg_out_call_iarg_reg(s, i, l->datalo_reg); - break; case MO_64: - i = tcg_out_call_iarg_reg2(s, i, l->datalo_reg, l->datahi_reg); - break; + if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) { + i = tcg_out_call_iarg_reg2(s, i, l->datalo_reg, l->datahi_reg); + break; + } + /* FALLTHRU */ default: - tcg_abort(); + i = tcg_out_call_iarg_reg(s, i, l->datalo_reg); + break; } i = tcg_out_call_iarg_imm(s, i, oi); @@ -1376,7 +1420,7 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l) #endif static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, - TCGReg base, TCGMemOp opc) + TCGReg base, TCGMemOp opc, bool is_64) { switch (opc & (MO_SSIZE | MO_BSWAP)) { case MO_UB: @@ -1385,6 +1429,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, case MO_SB: tcg_out_opc_imm(s, OPC_LB, datalo, base, 0); break; + case MO_UW | MO_BSWAP: tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0); tcg_out_bswap16(s, datalo, TCG_TMP1); @@ -1392,6 +1437,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, case MO_UW: tcg_out_opc_imm(s, OPC_LHU, datalo, base, 0); break; + case MO_SW | MO_BSWAP: tcg_out_opc_imm(s, OPC_LHU, TCG_TMP1, base, 0); tcg_out_bswap16s(s, datalo, TCG_TMP1); @@ -1399,22 +1445,47 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, case MO_SW: tcg_out_opc_imm(s, OPC_LH, datalo, base, 0); break; + case MO_UL | MO_BSWAP: + if (TCG_TARGET_REG_BITS == 64 && is_64) { + tcg_out_opc_imm(s, OPC_LWU, TCG_TMP1, base, 0); + tcg_out_bswap32u(s, datalo, TCG_TMP1); + break; + } + /* FALLTHRU */ + case MO_SL | MO_BSWAP: tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, 0); tcg_out_bswap32(s, datalo, TCG_TMP1); break; + case MO_UL: + if (TCG_TARGET_REG_BITS == 64 && is_64) { + tcg_out_opc_imm(s, OPC_LWU, datalo, base, 0); + break; + } + /* FALLTHRU */ + case MO_SL: tcg_out_opc_imm(s, OPC_LW, datalo, base, 0); break; + case MO_Q | MO_BSWAP: - tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, HI_OFF); - tcg_out_bswap32(s, datalo, TCG_TMP1); - tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, LO_OFF); - tcg_out_bswap32(s, datahi, TCG_TMP1); + if (TCG_TARGET_REG_BITS == 32) { + tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, HI_OFF); + tcg_out_bswap32(s, datalo, TCG_TMP1); + tcg_out_opc_imm(s, OPC_LW, TCG_TMP1, base, LO_OFF); + tcg_out_bswap32(s, datahi, TCG_TMP1); + } else { + tcg_out_opc_imm(s, OPC_LD, TCG_REG_V0, base, 0); + tcg_out_bswap64(s, datalo, TCG_REG_V0); + } break; case MO_Q: - tcg_out_opc_imm(s, OPC_LW, datalo, base, LO_OFF); - tcg_out_opc_imm(s, OPC_LW, datahi, base, HI_OFF); + if (TCG_TARGET_REG_BITS == 32) { + tcg_out_opc_imm(s, OPC_LW, datalo, base, LO_OFF); + tcg_out_opc_imm(s, OPC_LW, datahi, base, HI_OFF); + } else { + tcg_out_opc_imm(s, OPC_LD, datalo, base, 0); + } break; default: tcg_abort(); @@ -1435,33 +1506,41 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64) TCGReg base = TCG_REG_V0; data_regl = *args++; - data_regh = (is_64 ? *args++ : 0); + data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0); addr_regl = *args++; - addr_regh = (TARGET_LONG_BITS == 64 ? *args++ : 0); + addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0); oi = *args++; opc = get_memop(oi); #if defined(CONFIG_SOFTMMU) tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 1); - tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc); + tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64); add_qemu_ldst_label(s, 1, oi, data_regl, data_regh, addr_regl, addr_regh, s->code_ptr, label_ptr); #else + if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) { + tcg_out_ext32u(s, base, addr_regl); + addr_regl = base; + } if (guest_base == 0 && data_regl != addr_regl) { base = addr_regl; } else if (guest_base == (int16_t)guest_base) { - tcg_out_opc_imm(s, OPC_ADDIU, base, addr_regl, guest_base); + tcg_out_opc_imm(s, ALIAS_PADDI, base, addr_regl, guest_base); } else { tcg_out_movi(s, TCG_TYPE_PTR, base, guest_base); - tcg_out_opc_reg(s, OPC_ADDU, base, base, addr_regl); + tcg_out_opc_reg(s, ALIAS_PADD, base, base, addr_regl); } - tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc); + tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64); #endif } static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, TCGReg base, TCGMemOp opc) { + if ((datalo | datahi) == 0) { + opc &= ~MO_BSWAP; + } + switch (opc & (MO_SIZE | MO_BSWAP)) { case MO_8: tcg_out_opc_imm(s, OPC_SB, datalo, base, 0); @@ -1485,14 +1564,25 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg datalo, TCGReg datahi, break; case MO_64 | MO_BSWAP: - tcg_out_bswap32(s, TCG_TMP1, datalo); - tcg_out_opc_imm(s, OPC_SW, TCG_TMP1, base, HI_OFF); - tcg_out_bswap32(s, TCG_TMP1, datahi); - tcg_out_opc_imm(s, OPC_SW, TCG_TMP1, base, LO_OFF); - break; + if (TCG_TARGET_REG_BITS == 32) { + tcg_out_bswap32(s, TCG_TMP1, datalo); + datalo = TCG_TMP1; + tcg_out_opc_imm(s, OPC_SW, datalo, base, HI_OFF); + tcg_out_bswap32(s, TCG_TMP1, datahi); + datahi = TCG_TMP1; + tcg_out_opc_imm(s, OPC_SW, datahi, base, LO_OFF); + break; + } + tcg_out_bswap64(s, TCG_REG_A1, datalo); + datalo = TCG_REG_A1; + /* FALLTHRU */ case MO_64: - tcg_out_opc_imm(s, OPC_SW, datalo, base, LO_OFF); - tcg_out_opc_imm(s, OPC_SW, datahi, base, HI_OFF); + if (TCG_TARGET_REG_BITS == 32) { + tcg_out_opc_imm(s, OPC_SW, datalo, base, LO_OFF); + tcg_out_opc_imm(s, OPC_SW, datahi, base, HI_OFF); + } else { + tcg_out_opc_imm(s, OPC_SD, datalo, base, 0); + } break; default: @@ -1511,9 +1601,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64) #endif data_regl = *args++; - data_regh = (is_64 ? *args++ : 0); + data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0); addr_regl = *args++; - addr_regh = (TARGET_LONG_BITS == 64 ? *args++ : 0); + addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0); oi = *args++; opc = get_memop(oi); @@ -1526,16 +1616,18 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64) add_qemu_ldst_label(s, 0, oi, data_regl, data_regh, addr_regl, addr_regh, s->code_ptr, label_ptr); #else + base = TCG_REG_A0; + if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) { + tcg_out_ext32u(s, base, addr_regl); + addr_regl = base; + } if (guest_base == 0) { base = addr_regl; + } else if (guest_base == (int16_t)guest_base) { + tcg_out_opc_imm(s, ALIAS_PADDI, base, addr_regl, guest_base); } else { - base = TCG_REG_A0; - if (guest_base == (int16_t)guest_base) { - tcg_out_opc_imm(s, OPC_ADDIU, base, addr_regl, guest_base); - } else { - tcg_out_movi(s, TCG_TYPE_PTR, base, guest_base); - tcg_out_opc_reg(s, OPC_ADDU, base, base, addr_regl); - } + tcg_out_movi(s, TCG_TYPE_PTR, base, guest_base); + tcg_out_opc_reg(s, ALIAS_PADD, base, base, addr_regl); } tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc); #endif @@ -1849,12 +1941,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_ext32u_i64: case INDEX_op_extu_i32_i64: - if (use_mips32r2_instructions) { - tcg_out_opc_bf(s, OPC_DEXT, a0, a1, 31, 0); - } else { - tcg_out_dsll(s, a0, a1, 32); - tcg_out_dsrl(s, a0, a0, 32); - } + tcg_out_ext32u(s, a0, a1); break; case INDEX_op_sar_i32: