[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 026/108] arm: translate.c: Fix smlald Instruction
From: |
Michael Roth |
Subject: |
[Qemu-devel] [PATCH 026/108] arm: translate.c: Fix smlald Instruction |
Date: |
Wed, 6 Aug 2014 15:38:36 -0500 |
From: Peter Crosthwaite <address@hidden>
The smlald (and probably smlsld) instruction was doing incorrect sign
extensions of the operands amongst 64bit result calculation. The
instruction psuedo-code is:
operand2 = if m_swap then ROR(R[m],16) else R[m];
product1 = SInt(R[n]<15:0>) * SInt(operand2<15:0>);
product2 = SInt(R[n]<31:16>) * SInt(operand2<31:16>);
result = product1 + product2 + SInt(R[dHi]:R[dLo]);
R[dHi] = result<63:32>;
R[dLo] = result<31:0>;
The result calculation should be done in 64 bit arithmetic, and hence
product1 and product2 should be sign extended to 64b before calculation.
The current implementation was adding product1 and product2 together
then sign-extending the intermediate result leading to false negatives.
E.G. if product1 = product2 = 0x4000000, their sum = 0x80000000, which
will be incorrectly interpreted as -ve on sign extension.
We fix by doing the 64b extensions on both product1 and product2 before
any addition/subtraction happens.
We also fix where we were possibly incorrectly setting the Q saturation
flag for SMLSLD, which the ARM ARM specifically says is not set.
Reported-by: Christina Smith <address@hidden>
Signed-off-by: Peter Crosthwaite <address@hidden>
Reviewed-by: Peter Maydell <address@hidden>
Message-id: address@hidden
Cc: address@hidden
Signed-off-by: Peter Maydell <address@hidden>
(cherry picked from commit 33bbd75a7c3321432fe40a8cbacd64619c56138c)
Signed-off-by: Michael Roth <address@hidden>
---
target-arm/translate.c | 34 +++++++++++++++++++++++-----------
1 file changed, 23 insertions(+), 11 deletions(-)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 56e3b4b..0335f10 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -8328,27 +8328,39 @@ static void disas_arm_insn(CPUARMState * env,
DisasContext *s)
if (insn & (1 << 5))
gen_swap_half(tmp2);
gen_smul_dual(tmp, tmp2);
- if (insn & (1 << 6)) {
- /* This subtraction cannot overflow. */
- tcg_gen_sub_i32(tmp, tmp, tmp2);
- } else {
- /* This addition cannot overflow 32 bits;
- * however it may overflow considered as a signed
- * operation, in which case we must set the Q flag.
- */
- gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
- }
- tcg_temp_free_i32(tmp2);
if (insn & (1 << 22)) {
/* smlald, smlsld */
+ TCGv_i64 tmp64_2;
+
tmp64 = tcg_temp_new_i64();
+ tmp64_2 = tcg_temp_new_i64();
tcg_gen_ext_i32_i64(tmp64, tmp);
+ tcg_gen_ext_i32_i64(tmp64_2, tmp2);
tcg_temp_free_i32(tmp);
+ tcg_temp_free_i32(tmp2);
+ if (insn & (1 << 6)) {
+ tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
+ } else {
+ tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
+ }
+ tcg_temp_free_i64(tmp64_2);
gen_addq(s, tmp64, rd, rn);
gen_storeq_reg(s, rd, rn, tmp64);
tcg_temp_free_i64(tmp64);
} else {
/* smuad, smusd, smlad, smlsd */
+ if (insn & (1 << 6)) {
+ /* This subtraction cannot overflow. */
+ tcg_gen_sub_i32(tmp, tmp, tmp2);
+ } else {
+ /* This addition cannot overflow 32 bits;
+ * however it may overflow considered as a
+ * signed operation, in which case we must set
+ * the Q flag.
+ */
+ gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
+ }
+ tcg_temp_free_i32(tmp2);
if (rd != 15)
{
tmp2 = load_reg(s, rd);
--
1.9.1
- [Qemu-devel] [PATCH 016/108] openpic: avoid buffer overrun on incoming migration, (continued)
- [Qemu-devel] [PATCH 016/108] openpic: avoid buffer overrun on incoming migration, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 033/108] target-i386: fix set of registers zeroed on reset, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 031/108] stellaris_enet: block migration, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 032/108] s390x/kvm: rework KVM synchronize to tracing for some ONEREGS, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 036/108] target-arm: Make vbar_write 64bit friendly on 32bit hosts, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 037/108] linux-user/elfload.c: Fix incorrect ARM HWCAP bits, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 040/108] spapr_pci: Fix number of returned vectors in ibm, change-msi, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 038/108] linux-user/elfload.c: Update ARM HWCAP bits, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 035/108] target-arm: A64: Handle blr lr, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 039/108] linux-user/elfload.c: Fix A64 code which was incorrectly acting like A32, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 026/108] arm: translate.c: Fix smlald Instruction,
Michael Roth <=
- [Qemu-devel] [PATCH 041/108] configure: remove bashism, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 043/108] pci-assign: limit # of msix vectors, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 042/108] Revert "qapi: Clean up superfluous null check in qapi_dealloc_type_str()", Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 045/108] qcow1: Make padding in the header explicit, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 047/108] qcow1: Validate L2 table size (CVE-2014-0222), Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 044/108] virtio: allow mapping up to max queue size, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 046/108] qcow1: Check maximum cluster size, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 049/108] qcow1: Stricter backing file length check, Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 048/108] qcow1: Validate image size (CVE-2014-0223), Michael Roth, 2014/08/06
- [Qemu-devel] [PATCH 052/108] cputlb: Fix regression with TCG interpreter (bug 1310324), Michael Roth, 2014/08/06