diff mbox

target-arm: fix UMAAL instruction

Message ID 1293822669-3983-1-git-send-email-aurelien@aurel32.net
State New
Headers show

Commit Message

Aurelien Jarno Dec. 31, 2010, 7:11 p.m. UTC
UMAAL should use unsigned multiply instead of signed.

This patch fixes this issue by handling UMAAL separately from
UMULL/UMLAL/SMULL/SUMLAL are these instructions are different
enough. It also explicitely list instructions in case and catch
inexistant instruction as illegal. Also fixes a few style issues.

This fixes the issues reported in
https://bugs.launchpad.net/qemu/+bug/696015

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
---
 target-arm/translate.c |   30 +++++++++++++++++++++---------
 1 files changed, 21 insertions(+), 9 deletions(-)

Comments

Peter Maydell Dec. 31, 2010, 8:18 p.m. UTC | #1
On 31 December 2010 19:11, Aurelien Jarno <aurelien@aurel32.net> wrote:
> UMAAL should use unsigned multiply instead of signed.

Looks like we've both been working on the same thing this
evening :-)

> This patch fixes this issue by handling UMAAL separately from
> UMULL/UMLAL/SMULL/SUMLAL are these instructions are different

"SMLAL as".

> It also explicitely list instructions in case and catch
> inexistant instruction as illegal.

"explicitly" and "nonexistent", if you're tweaking the commit msg
anyway.

(If you want to use the ARM ARM terminology these instruction
patterns are "UNDEFINED" rather than "illegal".)

> +                    case 4:
> +                        /* 64 bit mul double accumulate */

Can we list the instruction mnemonic in the comment too?
(Saves future readers having to wade through the decode logic...)
This case is UMAAL.

> +                    case 8: case 9: case 10: case 11:
> +                    case 12: case 13: case 14: case 15:

/* UMULL, UMLAL, SMULL, SMLAL. */

I've run the patch through my random-sequence test and it passes.

-- PMM
diff mbox

Patch

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 8d494ec..eb207a8 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6637,26 +6637,38 @@  static void disas_arm_insn(CPUState * env, DisasContext *s)
                             gen_logic_CC(tmp);
                         store_reg(s, rd, tmp);
                         break;
-                    default:
+                    case 4:
+                        /* 64 bit mul double accumulate */
+                        ARCH(6);
+                        tmp = load_reg(s, rs);
+                        tmp2 = load_reg(s, rm);
+                        tmp64 = gen_mulu_i64_i32(tmp, tmp2);
+                        gen_addq_lo(s, tmp64, rn);
+                        gen_addq_lo(s, tmp64, rd);
+                        gen_storeq_reg(s, rn, rd, tmp64);
+                        tcg_temp_free_i64(tmp64);
+                        break;
+                    case 8: case 9: case 10: case 11:
+                    case 12: case 13: case 14: case 15:
                         /* 64 bit mul */
                         tmp = load_reg(s, rs);
                         tmp2 = load_reg(s, rm);
-                        if (insn & (1 << 22))
+                        if (insn & (1 << 22)) {
                             tmp64 = gen_muls_i64_i32(tmp, tmp2);
-                        else
+                        } else {
                             tmp64 = gen_mulu_i64_i32(tmp, tmp2);
-                        if (insn & (1 << 21)) /* mult accumulate */
+                        }
+                        if (insn & (1 << 21)) { /* mult accumulate */
                             gen_addq(s, tmp64, rn, rd);
-                        if (!(insn & (1 << 23))) { /* double accumulate */
-                            ARCH(6);
-                            gen_addq_lo(s, tmp64, rn);
-                            gen_addq_lo(s, tmp64, rd);
                         }
-                        if (insn & (1 << 20))
+                        if (insn & (1 << 20)) {
                             gen_logicq_cc(tmp64);
+                        }
                         gen_storeq_reg(s, rn, rd, tmp64);
                         tcg_temp_free_i64(tmp64);
                         break;
+                    default:
+                        goto illegal_op;
                     }
                 } else {
                     rn = (insn >> 16) & 0xf;