From patchwork Tue Sep 20 14:15:41 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 76610 Delivered-To: patches@linaro.org Received: by 10.140.106.72 with SMTP id d66csp1510799qgf; Tue, 20 Sep 2016 07:15:43 -0700 (PDT) X-Received: by 10.28.155.212 with SMTP id d203mr3709177wme.103.1474380943628; Tue, 20 Sep 2016 07:15:43 -0700 (PDT) Return-Path: Received: from orth.archaic.org.uk (orth.archaic.org.uk. [2001:8b0:1d0::2]) by mx.google.com with ESMTPS id gv3si24711942wjb.110.2016.09.20.07.15.43 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 20 Sep 2016 07:15:43 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) client-ip=2001:8b0:1d0::2; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::2 as permitted sender) smtp.mailfrom=pm215@archaic.org.uk; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org Received: from pm215 by orth.archaic.org.uk with local (Exim 4.84_2) (envelope-from ) id 1bmLpm-0005tW-KD; Tue, 20 Sep 2016 15:15:42 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: patches@linaro.org, stu.axon@gmail.com Subject: [PATCH] target-arm: Correctly handle 'sub pc, pc, 1' for ARMv6 Date: Tue, 20 Sep 2016 15:15:41 +0100 Message-Id: <1474380941-4730-1-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 2.7.4 In the ARM v6 architecture, 'sub pc, pc, 1' is not an interworking branch, so the computed new value is written to r15 as a normal value. The architecture says that in this case, bits [1:0] of the value written must be ignored if we are in ARM mode (or bit [0] ignored if in Thumb mode); this is a change from the ARMv4/v5 specification that behaviour is UNPREDICTABLE. Use the correct mask on the PC value when doing a non-interworking store to PC. A popular library used on RaspberryPi uses this instruction as part of a trick to determine whether it is running on ARMv6 or ARMv7, and we were mishandling the sequence. Fixes bug: https://bugs.launchpad.net/bugs/1625295 Reported-by: Signed-off-by: Peter Maydell --- target-arm/translate.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) -- 2.7.4 diff --git a/target-arm/translate.c b/target-arm/translate.c index 693d4bc..8df24bf 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -180,7 +180,12 @@ static inline TCGv_i32 load_reg(DisasContext *s, int reg) static void store_reg(DisasContext *s, int reg, TCGv_i32 var) { if (reg == 15) { - tcg_gen_andi_i32(var, var, ~1); + /* In Thumb mode, we must ignore bit 0. + * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0] + * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0]. + * We choose to ignore [1:0] in ARM mode for all architecture versions. + */ + tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3); s->is_jmp = DISAS_JUMP; } tcg_gen_mov_i32(cpu_R[reg], var);