From patchwork Sat Dec 28 21:49:03 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 22766 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ie0-f200.google.com (mail-ie0-f200.google.com [209.85.223.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 64986202E4 for ; Sat, 28 Dec 2013 21:49:20 +0000 (UTC) Received: by mail-ie0-f200.google.com with SMTP id at1sf48918888iec.11 for ; Sat, 28 Dec 2013 13:49:19 -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=P/nywiMxnlQSXYXcUCaoCEeqMgdxapy7/AlUDEENzfE=; b=j8tK/UWhBmc4aTr2mbBlq7mEKVymTqNMDkglHBO2SIubXRixD+F+eTrUUjYi3UwEVS fcuXX01Y3NHMRBBRI3N6nmhpOIYbq5SxfICPX1yoyursCYISRMwGVRjCDGYXIReyx06P VS3mdD+ILQzCTOsQiIpXxcUIqPYb0CIGiReOHbakk/IvS5QnW4Wvpco2SK9Sgtq5eATo eoavmdBV+0y3S51+8upOw9uzqwmqr8XiI4cgZrs2Lstlt7rc27mgzTPr9GaXC5EQ+mlH SZLP1RJsE8ndm9be1ir/WYHJh8bGiz+DlJu6xBjvwQKkV0MPe/5iwyYML/u79UWiyor9 LCUA== X-Gm-Message-State: ALoCoQmJwHNLjvy/TIkFrZRuH1iKX7aupcrTPB4OTu11oNeUmjYNxuZ2b1dvL//KvM5lrSfqdCo9 X-Received: by 10.50.12.68 with SMTP id w4mr23441095igb.0.1388267359371; Sat, 28 Dec 2013 13:49:19 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.86.232 with SMTP id s8ls3186658qez.67.gmail; Sat, 28 Dec 2013 13:49:19 -0800 (PST) X-Received: by 10.221.19.71 with SMTP id qj7mr110177vcb.49.1388267359235; Sat, 28 Dec 2013 13:49:19 -0800 (PST) Received: from mail-vb0-f42.google.com (mail-vb0-f42.google.com [209.85.212.42]) by mx.google.com with ESMTPS id z17si13833357vcy.83.2013.12.28.13.49.19 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 28 Dec 2013 13:49:19 -0800 (PST) Received-SPF: neutral (google.com: 209.85.212.42 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.42; Received: by mail-vb0-f42.google.com with SMTP id w5so5427544vbf.1 for ; Sat, 28 Dec 2013 13:49:19 -0800 (PST) X-Received: by 10.221.37.200 with SMTP id tf8mr104919vcb.54.1388267358985; Sat, 28 Dec 2013 13:49:18 -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 ey3csp529329ved; Sat, 28 Dec 2013 13:49:18 -0800 (PST) X-Received: by 10.194.201.65 with SMTP id jy1mr14713393wjc.43.1388267357831; Sat, 28 Dec 2013 13:49:17 -0800 (PST) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [2001:8b0:1d0::1]) by mx.google.com with ESMTPS id cu2si14802667wjb.27.2013.12.28.13.49.14 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sat, 28 Dec 2013 13:49:17 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::1 as permitted sender) client-ip=2001:8b0:1d0::1; Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1Vx1kt-0008Hn-7a; Sat, 28 Dec 2013 21:49:11 +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 Subject: [PATCH 02/10] target-arm: A64: Fix vector register access on bigendian hosts Date: Sat, 28 Dec 2013 21:49:03 +0000 Message-Id: <1388267351-31818-3-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1388267351-31818-1-git-send-email-peter.maydell@linaro.org> References: <1388267351-31818-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.42 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. 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 | 62 +++++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 6f2b26e..c3fc503 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,30 @@ 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(); if (size < 4) { switch (size) { case 0: - tcg_gen_ld8u_i64(tmp, cpu_env, freg_offs); + tcg_gen_ld8u_i64(tmp, cpu_env, fp_reg_offset(srcidx, MO_8)); break; case 1: - tcg_gen_ld16u_i64(tmp, cpu_env, freg_offs); + tcg_gen_ld16u_i64(tmp, cpu_env, fp_reg_offset(srcidx, MO_16)); break; case 2: - tcg_gen_ld32u_i64(tmp, cpu_env, freg_offs); + tcg_gen_ld32u_i64(tmp, cpu_env, fp_reg_offset(srcidx, MO_32)); break; case 3: - tcg_gen_ld_i64(tmp, cpu_env, freg_offs); + tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(srcidx, MO_64)); 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_ld_i64(tmp, cpu_env, fp_reg_offset(srcidx, MO_64)); 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 +596,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 +614,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 +3242,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 +3250,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 +3260,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; } }