From patchwork Mon Dec 30 16:34:27 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 22817 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-yh0-f71.google.com (mail-yh0-f71.google.com [209.85.213.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id E7028218CC for ; Mon, 30 Dec 2013 16:34:45 +0000 (UTC) Received: by mail-yh0-f71.google.com with SMTP id f64sf14523558yha.10 for ; Mon, 30 Dec 2013 08:34:44 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=jActXg1AraYK6O+cSfRaUqs5zg9z5/sWzadXTDqAW48=; b=jJFoME0KX9v0POzf1fOOXll4NYs4HRQ6z5PX30+BeiEwxGV8xDWp5lNwxLAHX+Q65j rIHd3cjjUMMV8Cv2pOVCczZh6X4d3B55CRDxq5BbpvtDUJcF4gMb5vxicMkVgsTx9Rgr dL4LOrC82qXR9zyht5EUYLb56uLwbkLl3JAWiEA72HreWIpWlS9A/Hds++2EITMjTJ45 LjZYIVTQbNfpUuJD4g6eshuLb8DJt3T0ee+TkdSB8Efm7H5rvfR1msK9SLUpdJEcbuvU RInWjG669auKjUTfCbA94wlJD8AaJBRSasb0IUlQkoJm5Osa3jgUFJvALEPIjTAxRvIG Jeiw== X-Gm-Message-State: ALoCoQlfBlPYV9BPOXIMExLsLCS3hgFTDZ2n3xXUhrTgTTa9rPyXaGMw7X9Lynu6eZct8vjCS4/j X-Received: by 10.58.96.97 with SMTP id dr1mr27157833veb.1.1388421284947; Mon, 30 Dec 2013 08:34:44 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.81.133 with SMTP id a5ls3664026qey.21.gmail; Mon, 30 Dec 2013 08:34:44 -0800 (PST) X-Received: by 10.52.228.4 with SMTP id se4mr2506301vdc.80.1388421284853; Mon, 30 Dec 2013 08:34:44 -0800 (PST) Received: from mail-vb0-f45.google.com (mail-vb0-f45.google.com [209.85.212.45]) by mx.google.com with ESMTPS id mk9si17395723vcb.39.2013.12.30.08.34.44 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 30 Dec 2013 08:34:44 -0800 (PST) Received-SPF: neutral (google.com: 209.85.212.45 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.212.45; Received: by mail-vb0-f45.google.com with SMTP id i12so5878866vbh.18 for ; Mon, 30 Dec 2013 08:34:44 -0800 (PST) X-Received: by 10.220.53.135 with SMTP id m7mr37192388vcg.12.1388421284751; Mon, 30 Dec 2013 08:34:44 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.59.13.131 with SMTP id ey3csp616683ved; Mon, 30 Dec 2013 08:34:44 -0800 (PST) X-Received: by 10.14.108.6 with SMTP id p6mr2510335eeg.31.1388421282045; Mon, 30 Dec 2013 08:34:42 -0800 (PST) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [81.2.115.146]) by mx.google.com with ESMTPS id a9si53200584eew.201.2013.12.30.08.34.40 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Mon, 30 Dec 2013 08:34:42 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 81.2.115.146 as permitted sender) client-ip=81.2.115.146; Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1VxfnX-0000XQ-T5; Mon, 30 Dec 2013 16:34:35 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Alexander Graf , Michael Matz , Claudio Fontana , Dirk Mueller , Laurent Desnogues , kvmarm@lists.cs.columbia.edu, Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Christoffer Dall , Will Newton , Peter Crosthwaite Subject: [PATCH v2 02/10] target-arm: A64: Fix vector register access on bigendian hosts Date: Mon, 30 Dec 2013 16:34:27 +0000 Message-Id: <1388421275-2035-3-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1388421275-2035-1-git-send-email-peter.maydell@linaro.org> References: <1388421275-2035-1-git-send-email-peter.maydell@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: peter.maydell@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.45 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , The A64 128 bit vector registers are stored as a pair of uint64_t values in the register array. This means that if we're directly loading or storing a value of size less than 64 bits we must adjust the offset appropriately to account for whether the host is bigendian or not. Provide utility functions to abstract away the offsetof() calculations for the FP registers. For do_fp_st() we can sidestep most of the issues for 64 bit and smaller reg-to-mem transfers by always doing a 64 bit load from the register and writing just the piece we need to memory. Signed-off-by: Peter Maydell --- Didn't spot this bug until I started reviewing the FP related patches (the code also I think is cleaner without offsetof() scattered everywhere). --- target-arm/translate-a64.c | 69 +++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 326f36d..ba9573a 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -308,6 +308,26 @@ static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf) return v; } +/* Return the offset into CPUARMState of a slice (from + * the least significant end) of FP register Qn (ie + * Dn, Sn, Hn or Bn). + * (Note that this is not the same mapping as for A32; see cpu.h) + */ +static inline int fp_reg_offset(int regno, TCGMemOp size) +{ + int offs = offsetof(CPUARMState, vfp.regs[regno * 2]); +#ifdef HOST_WORDS_BIGENDIAN + offs += (8 - (1 << size)); +#endif + return offs; +} + +/* Offset of the high half of the 128 bit vector Qn */ +static inline int fp_reg_hi_offset(int regno) +{ + return offsetof(CPUARMState, vfp.regs[regno * 2 + 1]); +} + /* Set ZF and NF based on a 64 bit result. This is alas fiddlier * than the 32 bit equivalent. */ @@ -538,31 +558,15 @@ static void do_gpr_ld(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr, static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size) { /* This writes the bottom N bits of a 128 bit wide vector to memory */ - int freg_offs = offsetof(CPUARMState, vfp.regs[srcidx * 2]); TCGv_i64 tmp = tcg_temp_new_i64(); - + tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(srcidx, MO_64)); if (size < 4) { - switch (size) { - case 0: - tcg_gen_ld8u_i64(tmp, cpu_env, freg_offs); - break; - case 1: - tcg_gen_ld16u_i64(tmp, cpu_env, freg_offs); - break; - case 2: - tcg_gen_ld32u_i64(tmp, cpu_env, freg_offs); - break; - case 3: - tcg_gen_ld_i64(tmp, cpu_env, freg_offs); - break; - } tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TE + size); } else { TCGv_i64 tcg_hiaddr = tcg_temp_new_i64(); - tcg_gen_ld_i64(tmp, cpu_env, freg_offs); tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TEQ); tcg_gen_qemu_st64(tmp, tcg_addr, get_mem_index(s)); - tcg_gen_ld_i64(tmp, cpu_env, freg_offs + sizeof(float64)); + tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(srcidx)); tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8); tcg_gen_qemu_st_i64(tmp, tcg_hiaddr, get_mem_index(s), MO_TEQ); tcg_temp_free_i64(tcg_hiaddr); @@ -577,7 +581,6 @@ static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size) static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size) { /* This always zero-extends and writes to a full 128 bit wide vector */ - int freg_offs = offsetof(CPUARMState, vfp.regs[destidx * 2]); TCGv_i64 tmplo = tcg_temp_new_i64(); TCGv_i64 tmphi; @@ -596,8 +599,8 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size) tcg_temp_free_i64(tcg_hiaddr); } - tcg_gen_st_i64(tmplo, cpu_env, freg_offs); - tcg_gen_st_i64(tmphi, cpu_env, freg_offs + sizeof(float64)); + tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(destidx, MO_64)); + tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(destidx)); tcg_temp_free_i64(tmplo); tcg_temp_free_i64(tmphi); @@ -3224,7 +3227,6 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof) */ if (itof) { - int freg_offs = offsetof(CPUARMState, vfp.regs[rd * 2]); TCGv_i64 tcg_rn = cpu_reg(s, rn); switch (type) { @@ -3233,9 +3235,9 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof) /* 32 bit */ TCGv_i64 tmp = tcg_temp_new_i64(); tcg_gen_ext32u_i64(tmp, tcg_rn); - tcg_gen_st_i64(tmp, cpu_env, freg_offs); + tcg_gen_st_i64(tmp, cpu_env, fp_reg_offset(rd, MO_64)); tcg_gen_movi_i64(tmp, 0); - tcg_gen_st_i64(tmp, cpu_env, freg_offs + sizeof(float64)); + tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd)); tcg_temp_free_i64(tmp); break; } @@ -3243,32 +3245,31 @@ static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof) { /* 64 bit */ TCGv_i64 tmp = tcg_const_i64(0); - tcg_gen_st_i64(tcg_rn, cpu_env, freg_offs); - tcg_gen_st_i64(tmp, cpu_env, freg_offs + sizeof(float64)); + tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_offset(rd, MO_64)); + tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(rd)); tcg_temp_free_i64(tmp); break; } case 2: /* 64 bit to top half. */ - tcg_gen_st_i64(tcg_rn, cpu_env, freg_offs + sizeof(float64)); + tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(rd)); break; } } else { - int freg_offs = offsetof(CPUARMState, vfp.regs[rn * 2]); TCGv_i64 tcg_rd = cpu_reg(s, rd); switch (type) { case 0: /* 32 bit */ - tcg_gen_ld32u_i64(tcg_rd, cpu_env, freg_offs); + tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_32)); break; - case 2: - /* 64 bits from top half */ - freg_offs += sizeof(float64); - /* fall through */ case 1: /* 64 bit */ - tcg_gen_ld_i64(tcg_rd, cpu_env, freg_offs); + tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(rn, MO_64)); + break; + case 2: + /* 64 bits from top half */ + tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(rn)); break; } }