All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v3 0/8] target-arm: A64 decoder set 3: loads, stores, misc integer
@ 2013-12-13 19:17 Peter Maydell
  2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 1/8] target-arm: A64: add support for ld/st pair Peter Maydell
                   ` (7 more replies)
  0 siblings, 8 replies; 14+ messages in thread
From: Peter Maydell @ 2013-12-13 19:17 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Matz, Claudio Fontana, Dirk Mueller,
	Will Newton, Laurent Desnogues, Alex Bennée, kvmarm,
	Christoffer Dall, Richard Henderson

Version 3 of the third set of A64 decoder patches
(loads, stores, misc integer).

(Fourth set is very nearly ready to roll, I just need to
review the load/store exclusive patch.)

Changes v2->v3:
 * added the non-temporal forms of LDP/STP (fixing a miscoded
   unallocated_encoding() codepath)
 * updated function names to follow convention that disas_foo are
   passed a uint32_t insn to decode and handle_foo are passed
   decoded field values

Changes v1->v2:
 * merged ldp and stp into one function/patch
 * minor cleanup as per RTH review
 * use the new tcg ops for guest load/store
 * catch the missing UNALLOCATED cases for load/store
 * add missing returns after unallocated_encoding() calls
   in vector load/store decode
 * use tcg ops for mul[su]h

thanks
-- PMM

Alex Bennée (6):
  target-arm: A64: add support for ld/st pair
  target-arm: A64: add support for ld/st unsigned imm
  target-arm: A64: add support for ld/st with reg offset
  target-arm: A64: add support for ld/st with index
  target-arm: A64: add support for add, addi, sub, subi
  target-arm: A64: add support for move wide instructions

Alexander Graf (2):
  target-arm: A64: add support for 3 src data proc insns
  target-arm: A64: implement SVC, BRK

 target-arm/translate-a64.c | 1115 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 1100 insertions(+), 15 deletions(-)

-- 
1.8.5

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 1/8] target-arm: A64: add support for ld/st pair
  2013-12-13 19:17 [Qemu-devel] [PATCH v3 0/8] target-arm: A64 decoder set 3: loads, stores, misc integer Peter Maydell
@ 2013-12-13 19:17 ` Peter Maydell
  2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 2/8] target-arm: A64: add support for ld/st unsigned imm Peter Maydell
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2013-12-13 19:17 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Matz, Claudio Fontana, Dirk Mueller,
	Will Newton, Laurent Desnogues, Alex Bennée, kvmarm,
	Christoffer Dall, Richard Henderson

From: Alex Bennée <alex.bennee@linaro.org>

This patch support the basic load and store pair instructions and
includes the generic helper functions:

  * do_gpr_st()
  * do_fp_st()
  * do_gpr_ld()
  * do_fp_ld()
  * read_cpu_reg_sp()
  * gen_check_sp_alignment()

The last function gen_check_sp_alignment() is a NULL op currently but
put in place to make it easy to add SP alignment checking later.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/translate-a64.c | 277 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 275 insertions(+), 2 deletions(-)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 0a76130..e4ce038 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -99,6 +99,15 @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
     cpu_fprintf(f, "\n");
 }
 
+static int get_mem_index(DisasContext *s)
+{
+#ifdef CONFIG_USER_ONLY
+    return 1;
+#else
+    return s->user;
+#endif
+}
+
 void gen_a64_set_pc_im(uint64_t val)
 {
     tcg_gen_movi_i64(cpu_pc, val);
@@ -250,6 +259,17 @@ static TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)
     return v;
 }
 
+static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
+{
+    TCGv_i64 v = new_tmp_a64(s);
+    if (sf) {
+        tcg_gen_mov_i64(v, cpu_X[reg]);
+    } else {
+        tcg_gen_ext32u_i64(v, cpu_X[reg]);
+    }
+    return v;
+}
+
 /* Set ZF and NF based on a 64 bit result. This is alas fiddlier
  * than the 32 bit equivalent.
  */
@@ -278,6 +298,124 @@ static inline void gen_logic_CC(int sf, TCGv_i64 result)
 }
 
 /*
+ * Load/Store generators
+ */
+
+/*
+ *  Store from GPR register to memory
+ */
+static void do_gpr_st(DisasContext *s, TCGv_i64 source,
+                      TCGv_i64 tcg_addr, int size)
+{
+    g_assert(size <= 3);
+    tcg_gen_qemu_st_i64(source, tcg_addr, get_mem_index(s), MO_TE + size);
+}
+
+/*
+ * Load from memory to GPR register
+ */
+static void do_gpr_ld(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
+                      int size, bool is_signed, bool extend)
+{
+    TCGMemOp memop =  MO_TE + size;
+
+    g_assert(size <= 3);
+
+    if (is_signed) {
+        memop += MO_SIGN;
+    }
+
+    tcg_gen_qemu_ld_i64(dest, tcg_addr, get_mem_index(s), memop);
+
+    if (extend && is_signed) {
+        g_assert(size < 3);
+        tcg_gen_ext32u_i64(dest, dest);
+    }
+}
+
+/*
+ * Store from FP register to memory
+ */
+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);
+            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_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);
+    }
+
+    tcg_temp_free_i64(tmp);
+}
+
+/* Load from memory to FP register */
+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;
+
+    if (size < 4) {
+        TCGMemOp memop =  MO_TE + size;
+        tmphi = tcg_const_i64(0);
+        tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
+    } else {
+        TCGv_i64 tcg_hiaddr;
+        tmphi = tcg_temp_new_i64();
+        tcg_hiaddr = tcg_temp_new_i64();
+
+        tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), MO_TEQ);
+        tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
+        tcg_gen_qemu_ld_i64(tmphi, tcg_hiaddr, get_mem_index(s), MO_TEQ);
+        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_temp_free_i64(tmplo);
+    tcg_temp_free_i64(tmphi);
+}
+
+static inline void gen_check_sp_alignment(DisasContext *s)
+{
+    /* The AArch64 architecture mandates that (if enabled via PSTATE
+     * or SCTLR bits) there is a check that SP is 16-aligned on every
+     * SP-relative load or store (with an exception generated if it is not).
+     * In line with general QEMU practice regarding misaligned accesses,
+     * we omit these checks for the sake of guest program performance.
+     * This function is provided as a hook so we can more easily add these
+     * checks in future (possibly as a "favour catching guest program bugs
+     * over speed" user selectable option).
+     */
+}
+
+/*
  * the instruction disassembly implemented here matches
  * the instruction encoding classifications in chapter 3 (C3)
  * of the ARM Architecture Reference Manual (DDI0487A_a)
@@ -620,10 +758,145 @@ static void disas_ld_lit(DisasContext *s, uint32_t insn)
     unsupported_encoding(s, insn);
 }
 
-/* Load/store pair (all forms) */
+/*
+ * C5.6.80 LDNP (Load Pair - non-temporal hint)
+ * C5.6.81 LDP (Load Pair - non vector)
+ * C5.6.82 LDPSW (Load Pair Signed Word - non vector)
+ * C5.6.176 STNP (Store Pair - non-temporal hint)
+ * C5.6.177 STP (Store Pair - non vector)
+ * C6.3.165 LDNP (Load Pair of SIMD&FP - non-temporal hint)
+ * C6.3.165 LDP (Load Pair of SIMD&FP)
+ * C6.3.284 STNP (Store Pair of SIMD&FP - non-temporal hint)
+ * C6.3.284 STP (Store Pair of SIMD&FP)
+ *
+ *  31 30 29   27  26  25 24   23  22 21   15 14   10 9    5 4    0
+ * +-----+-------+---+---+-------+---+-----------------------------+
+ * | opc | 1 0 1 | V | 0 | index | L |  imm7 |  Rt2  |  Rn  | Rt   |
+ * +-----+-------+---+---+-------+---+-------+-------+------+------+
+ *
+ * opc: LDP/STP/LDNP/STNP        00 -> 32 bit, 10 -> 64 bit
+ *      LDPSW                    01
+ *      LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit
+ *   V: 0 -> GPR, 1 -> Vector
+ * idx: 00 -> signed offset with non-temporal hint, 01 -> post-index,
+ *      10 -> signed offset, 11 -> pre-index
+ *   L: 0 -> Store 1 -> Load
+ *
+ * Rt, Rt2 = GPR or SIMD registers to be stored
+ * Rn = general purpose register containing address
+ * imm7 = signed offset (multiple of 4 or 8 depending on size)
+ */
 static void disas_ldst_pair(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rt = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int rt2 = extract32(insn, 10, 5);
+    int64_t offset = sextract32(insn, 15, 7);
+    int index = extract32(insn, 23, 2);
+    bool is_vector = extract32(insn, 26, 1);
+    bool is_load = extract32(insn, 22, 1);
+    int opc = extract32(insn, 30, 2);
+
+    bool is_signed = false;
+    bool postindex = false;
+    bool wback = false;
+
+    TCGv_i64 tcg_addr; /* calculated address */
+    int size;
+
+    if (is_vector) {
+        if (opc == 3) {
+            unallocated_encoding(s);
+            return;
+        }
+        size = 2 + opc;
+    } else {
+        size = 2 + extract32(opc, 1, 1);
+        if (is_load) {
+            is_signed = opc & 1;
+        } else if (opc & 1) {
+            unallocated_encoding(s);
+            return;
+        }
+    }
+
+    switch (index) {
+    case 1: /* post-index */
+        postindex = true;
+        wback = true;
+        break;
+    case 0:
+        /* signed offset with "non-temporal" hint. Since we don't emulate
+         * caches we don't care about hints to the cache system about
+         * data access patterns, and handle this identically to plain
+         * signed offset.
+         */
+        if (is_signed) {
+            /* There is no non-temporal-hint version of LDPSW */
+            unallocated_encoding(s);
+            return;
+        }
+        postindex = false;
+        break;
+    case 2: /* signed offset, rn not updated */
+        postindex = false;
+        break;
+    case 3: /* pre-index */
+        postindex = false;
+        wback = true;
+        break;
+    }
+
+    offset <<= size;
+
+    if (rn == 31) {
+        gen_check_sp_alignment(s);
+    }
+
+    tcg_addr = read_cpu_reg_sp(s, rn, 1);
+
+    if (!postindex) {
+        tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
+    }
+
+    if (is_vector) {
+        if (is_load) {
+            do_fp_ld(s, rt, tcg_addr, size);
+        } else {
+            do_fp_st(s, rt, tcg_addr, size);
+        }
+    } else {
+        TCGv_i64 tcg_rt = cpu_reg(s, rt);
+        if (is_load) {
+            do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false);
+        } else {
+            do_gpr_st(s, tcg_rt, tcg_addr, size);
+        }
+    }
+    tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
+    if (is_vector) {
+        if (is_load) {
+            do_fp_ld(s, rt2, tcg_addr, size);
+        } else {
+            do_fp_st(s, rt2, tcg_addr, size);
+        }
+    } else {
+        TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
+        if (is_load) {
+            do_gpr_ld(s, tcg_rt2, tcg_addr, size, is_signed, false);
+        } else {
+            do_gpr_st(s, tcg_rt2, tcg_addr, size);
+        }
+    }
+
+    if (wback) {
+        if (postindex) {
+            tcg_gen_addi_i64(tcg_addr, tcg_addr, offset - (1 << size));
+        } else {
+            tcg_gen_subi_i64(tcg_addr, tcg_addr, 1 << size);
+        }
+        tcg_gen_mov_i64(cpu_reg_sp(s, rn), tcg_addr);
+    }
 }
 
 /* Load/store register (all forms) */
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 2/8] target-arm: A64: add support for ld/st unsigned imm
  2013-12-13 19:17 [Qemu-devel] [PATCH v3 0/8] target-arm: A64 decoder set 3: loads, stores, misc integer Peter Maydell
  2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 1/8] target-arm: A64: add support for ld/st pair Peter Maydell
@ 2013-12-13 19:17 ` Peter Maydell
  2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 3/8] target-arm: A64: add support for ld/st with reg offset Peter Maydell
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2013-12-13 19:17 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Matz, Claudio Fontana, Dirk Mueller,
	Will Newton, Laurent Desnogues, Alex Bennée, kvmarm,
	Christoffer Dall, Richard Henderson

From: Alex Bennée <alex@bennee.com>

This adds support for the forms of ld/st with a 12 bit
unsigned immediate offset.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/translate-a64.c | 89 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 88 insertions(+), 1 deletion(-)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index e4ce038..3712a6d 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -899,10 +899,97 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
     }
 }
 
+/*
+ * C3.3.13 Load/store (unsigned immediate)
+ *
+ * 31 30 29   27  26 25 24 23 22 21        10 9     5
+ * +----+-------+---+-----+-----+------------+-------+------+
+ * |size| 1 1 1 | V | 0 1 | opc |   imm12    |  Rn   |  Rt  |
+ * +----+-------+---+-----+-----+------------+-------+------+
+ *
+ * For non-vector:
+ *   size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
+ *   opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
+ * For vector:
+ *   size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
+ *   opc<0>: 0 -> store, 1 -> load
+ * Rn: base address register (inc SP)
+ * Rt: target register
+ */
+static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn)
+{
+    int rt = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    unsigned int imm12 = extract32(insn, 10, 12);
+    bool is_vector = extract32(insn, 26, 1);
+    int size = extract32(insn, 30, 2);
+    int opc = extract32(insn, 22, 2);
+    unsigned int offset;
+
+    TCGv_i64 tcg_addr;
+
+    bool is_store;
+    bool is_signed = false;
+    bool is_extended = false;
+
+    if (is_vector) {
+        size |= (opc & 2) << 1;
+        if (size > 4) {
+            unallocated_encoding(s);
+            return;
+        }
+        is_store = ((opc & 1) == 0);
+    } else {
+        if (size == 3 && opc == 2) {
+            /* PRFM - prefetch */
+            return;
+        }
+        if (opc == 3 && size > 1) {
+            unallocated_encoding(s);
+            return;
+        }
+        is_store = (opc == 0);
+        is_signed = opc & (1<<1);
+        is_extended = (size < 3) && (opc & 1);
+    }
+
+    if (rn == 31) {
+        gen_check_sp_alignment(s);
+    }
+    tcg_addr = read_cpu_reg_sp(s, rn, 1);
+    offset = imm12 << size;
+    tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
+
+    if (is_vector) {
+        if (is_store) {
+            do_fp_st(s, rt, tcg_addr, size);
+        } else {
+            do_fp_ld(s, rt, tcg_addr, size);
+        }
+    } else {
+        TCGv_i64 tcg_rt = cpu_reg(s, rt);
+        if (is_store) {
+            do_gpr_st(s, tcg_rt, tcg_addr, size);
+        } else {
+            do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
+        }
+    }
+}
+
 /* Load/store register (all forms) */
 static void disas_ldst_reg(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    switch (extract32(insn, 24, 2)) {
+    case 0:
+        unsupported_encoding(s, insn);
+        break;
+    case 1:
+        disas_ldst_reg_unsigned_imm(s, insn);
+        break;
+    default:
+        unallocated_encoding(s);
+        break;
+    }
 }
 
 /* AdvSIMD load/store multiple structures */
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 3/8] target-arm: A64: add support for ld/st with reg offset
  2013-12-13 19:17 [Qemu-devel] [PATCH v3 0/8] target-arm: A64 decoder set 3: loads, stores, misc integer Peter Maydell
  2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 1/8] target-arm: A64: add support for ld/st pair Peter Maydell
  2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 2/8] target-arm: A64: add support for ld/st unsigned imm Peter Maydell
@ 2013-12-13 19:17 ` Peter Maydell
  2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 4/8] target-arm: A64: add support for ld/st with index Peter Maydell
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2013-12-13 19:17 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Matz, Claudio Fontana, Dirk Mueller,
	Will Newton, Laurent Desnogues, Alex Bennée, kvmarm,
	Christoffer Dall, Richard Henderson

From: Alex Bennée <alex@bennee.com>

This adds support for the load/store forms using a register offset.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/translate-a64.c | 144 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 143 insertions(+), 1 deletion(-)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 3712a6d..742c714 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -402,6 +402,54 @@ static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
     tcg_temp_free_i64(tmphi);
 }
 
+/*
+ * This utility function is for doing register extension with an
+ * optional shift. You will likely want to pass a temporary for the
+ * destination register. See DecodeRegExtend() in the ARM ARM.
+ */
+static void ext_and_shift_reg(TCGv_i64 tcg_out, TCGv_i64 tcg_in,
+                              int option, unsigned int shift)
+{
+    int extsize = extract32(option, 0, 2);
+    bool is_signed = extract32(option, 2, 1);
+
+    if (is_signed) {
+        switch (extsize) {
+        case 0:
+            tcg_gen_ext8s_i64(tcg_out, tcg_in);
+            break;
+        case 1:
+            tcg_gen_ext16s_i64(tcg_out, tcg_in);
+            break;
+        case 2:
+            tcg_gen_ext32s_i64(tcg_out, tcg_in);
+            break;
+        case 3:
+            tcg_gen_mov_i64(tcg_out, tcg_in);
+            break;
+        }
+    } else {
+        switch (extsize) {
+        case 0:
+            tcg_gen_ext8u_i64(tcg_out, tcg_in);
+            break;
+        case 1:
+            tcg_gen_ext16u_i64(tcg_out, tcg_in);
+            break;
+        case 2:
+            tcg_gen_ext32u_i64(tcg_out, tcg_in);
+            break;
+        case 3:
+            tcg_gen_mov_i64(tcg_out, tcg_in);
+            break;
+        }
+    }
+
+    if (shift) {
+        tcg_gen_shli_i64(tcg_out, tcg_out, shift);
+    }
+}
+
 static inline void gen_check_sp_alignment(DisasContext *s)
 {
     /* The AArch64 architecture mandates that (if enabled via PSTATE
@@ -900,6 +948,96 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
 }
 
 /*
+ * C3.3.10 Load/store (register offset)
+ *
+ * 31 30 29   27  26 25 24 23 22 21  20  16 15 13 12 11 10 9  5 4  0
+ * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
+ * |size| 1 1 1 | V | 0 0 | opc | 1 |  Rm  | opt | S| 1 0 | Rn | Rt |
+ * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
+ *
+ * For non-vector:
+ *   size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
+ *   opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
+ * For vector:
+ *   size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
+ *   opc<0>: 0 -> store, 1 -> load
+ * V: 1 -> vector/simd
+ * opt: extend encoding (see DecodeRegExtend)
+ * S: if S=1 then scale (essentially index by sizeof(size))
+ * Rt: register to transfer into/out of
+ * Rn: address register or SP for base
+ * Rm: offset register or ZR for offset
+ */
+static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn)
+{
+    int rt = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int shift = extract32(insn, 12, 1);
+    int rm = extract32(insn, 16, 5);
+    int opc = extract32(insn, 22, 2);
+    int opt = extract32(insn, 13, 3);
+    int size = extract32(insn, 30, 2);
+    bool is_signed = false;
+    bool is_store = false;
+    bool is_extended = false;
+    bool is_vector = extract32(insn, 26, 1);
+
+    TCGv_i64 tcg_rm;
+    TCGv_i64 tcg_addr;
+
+    if (extract32(opt, 1, 1) == 0) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    if (is_vector) {
+        size |= (opc & 2) << 1;
+        if (size > 4) {
+            unallocated_encoding(s);
+            return;
+        }
+        is_store = ((opc & 1) == 0);
+    } else {
+        if (size == 3 && opc == 2) {
+            /* PRFM - prefetch */
+            return;
+        }
+        if (opc == 3 && size > 1) {
+            unallocated_encoding(s);
+            return;
+        }
+        is_store = (opc == 0);
+        is_signed = opc & (1<<1);
+        is_extended = (size < 3) && (opc & 1);
+    }
+
+    if (rn == 31) {
+        gen_check_sp_alignment(s);
+    }
+    tcg_addr = read_cpu_reg_sp(s, rn, 1);
+
+    tcg_rm = read_cpu_reg(s, rm, 1);
+    ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
+
+    tcg_gen_add_i64(tcg_addr, tcg_addr, tcg_rm);
+
+    if (is_vector) {
+        if (is_store) {
+            do_fp_st(s, rt, tcg_addr, size);
+        } else {
+            do_fp_ld(s, rt, tcg_addr, size);
+        }
+    } else {
+        TCGv_i64 tcg_rt = cpu_reg(s, rt);
+        if (is_store) {
+            do_gpr_st(s, tcg_rt, tcg_addr, size);
+        } else {
+            do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
+        }
+    }
+}
+
+/*
  * C3.3.13 Load/store (unsigned immediate)
  *
  * 31 30 29   27  26 25 24 23 22 21        10 9     5
@@ -981,7 +1119,11 @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
 {
     switch (extract32(insn, 24, 2)) {
     case 0:
-        unsupported_encoding(s, insn);
+        if (extract32(insn, 21, 1) == 1 && extract32(insn, 10, 2) == 2) {
+            disas_ldst_reg_roffset(s, insn);
+        } else {
+            unsupported_encoding(s, insn);
+        }
         break;
     case 1:
         disas_ldst_reg_unsigned_imm(s, insn);
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 4/8] target-arm: A64: add support for ld/st with index
  2013-12-13 19:17 [Qemu-devel] [PATCH v3 0/8] target-arm: A64 decoder set 3: loads, stores, misc integer Peter Maydell
                   ` (2 preceding siblings ...)
  2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 3/8] target-arm: A64: add support for ld/st with reg offset Peter Maydell
@ 2013-12-13 19:17 ` Peter Maydell
  2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 5/8] target-arm: A64: add support for add, addi, sub, subi Peter Maydell
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2013-12-13 19:17 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Matz, Claudio Fontana, Dirk Mueller,
	Will Newton, Laurent Desnogues, Alex Bennée, kvmarm,
	Christoffer Dall, Richard Henderson

From: Alex Bennée <alex@bennee.com>

This adds support for the pre/post-index ld/st forms with immediate
offsets as well as the un-scaled immediate form (which are all
variations on the same 9-bit immediate instruction form).

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/translate-a64.c | 125 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 124 insertions(+), 1 deletion(-)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 742c714..1b34a98 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -948,6 +948,110 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn)
 }
 
 /*
+ * C3.3.8 Load/store (immediate post-indexed)
+ * C3.3.9 Load/store (immediate pre-indexed)
+ * C3.3.12 Load/store (unscaled immediate)
+ *
+ * 31 30 29   27  26 25 24 23 22 21  20    12 11 10 9    5 4    0
+ * +----+-------+---+-----+-----+---+--------+-----+------+------+
+ * |size| 1 1 1 | V | 0 0 | opc | 0 |  imm9  | idx |  Rn  |  Rt  |
+ * +----+-------+---+-----+-----+---+--------+-----+------+------+
+ *
+ * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
+ * V = 0 -> non-vector
+ * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
+ * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
+ */
+static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn)
+{
+    int rt = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int imm9 = sextract32(insn, 12, 9);
+    int opc = extract32(insn, 22, 2);
+    int size = extract32(insn, 30, 2);
+    int idx = extract32(insn, 10, 2);
+    bool is_signed = false;
+    bool is_store = false;
+    bool is_extended = false;
+    bool is_vector = extract32(insn, 26, 1);
+    bool post_index;
+    bool writeback;
+
+    TCGv_i64 tcg_addr;
+
+    if (is_vector) {
+        size |= (opc & 2) << 1;
+        if (size > 4) {
+            unallocated_encoding(s);
+            return;
+        }
+        is_store = ((opc & 1) == 0);
+    } else {
+        if (size == 3 && opc == 2) {
+            /* PRFM - prefetch */
+            return;
+        }
+        if (opc == 3 && size > 1) {
+            unallocated_encoding(s);
+            return;
+        }
+        is_store = (opc == 0);
+        is_signed = opc & (1<<1);
+        is_extended = (size < 3) && (opc & 1);
+    }
+
+    switch (idx) {
+    case 0:
+        post_index = false;
+        writeback = false;
+        break;
+    case 1:
+        post_index = true;
+        writeback = true;
+        break;
+    case 3:
+        post_index = false;
+        writeback = true;
+        break;
+    case 2:
+        g_assert(false);
+        break;
+    }
+
+    if (rn == 31) {
+        gen_check_sp_alignment(s);
+    }
+    tcg_addr = read_cpu_reg_sp(s, rn, 1);
+
+    if (!post_index) {
+        tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
+    }
+
+    if (is_vector) {
+        if (is_store) {
+            do_fp_st(s, rt, tcg_addr, size);
+        } else {
+            do_fp_ld(s, rt, tcg_addr, size);
+        }
+    } else {
+        TCGv_i64 tcg_rt = cpu_reg(s, rt);
+        if (is_store) {
+            do_gpr_st(s, tcg_rt, tcg_addr, size);
+        } else {
+            do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
+        }
+    }
+
+    if (writeback) {
+        TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
+        if (post_index) {
+            tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
+        }
+        tcg_gen_mov_i64(tcg_rn, tcg_addr);
+    }
+}
+
+/*
  * C3.3.10 Load/store (register offset)
  *
  * 31 30 29   27  26 25 24 23 22 21  20  16 15 13 12 11 10 9  5 4  0
@@ -1114,6 +1218,25 @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn)
     }
 }
 
+/* Load/store register (immediate forms) */
+static void disas_ldst_reg_imm(DisasContext *s, uint32_t insn)
+{
+    switch (extract32(insn, 10, 2)) {
+    case 0: case 1: case 3:
+        /* Load/store register (unscaled immediate) */
+        /* Load/store immediate pre/post-indexed */
+        disas_ldst_reg_imm9(s, insn);
+        break;
+    case 2:
+        /* Load/store register unprivileged */
+        unsupported_encoding(s, insn);
+        break;
+    default:
+        unallocated_encoding(s);
+        break;
+    }
+}
+
 /* Load/store register (all forms) */
 static void disas_ldst_reg(DisasContext *s, uint32_t insn)
 {
@@ -1122,7 +1245,7 @@ static void disas_ldst_reg(DisasContext *s, uint32_t insn)
         if (extract32(insn, 21, 1) == 1 && extract32(insn, 10, 2) == 2) {
             disas_ldst_reg_roffset(s, insn);
         } else {
-            unsupported_encoding(s, insn);
+            disas_ldst_reg_imm(s, insn);
         }
         break;
     case 1:
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 5/8] target-arm: A64: add support for add, addi, sub, subi
  2013-12-13 19:17 [Qemu-devel] [PATCH v3 0/8] target-arm: A64 decoder set 3: loads, stores, misc integer Peter Maydell
                   ` (3 preceding siblings ...)
  2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 4/8] target-arm: A64: add support for ld/st with index Peter Maydell
@ 2013-12-13 19:17 ` Peter Maydell
  2013-12-16 10:11   ` C Fontana
  2013-12-13 19:18 ` [Qemu-devel] [PATCH v3 6/8] target-arm: A64: add support for move wide instructions Peter Maydell
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 14+ messages in thread
From: Peter Maydell @ 2013-12-13 19:17 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Matz, Claudio Fontana, Dirk Mueller,
	Will Newton, Laurent Desnogues, Alex Bennée, kvmarm,
	Christoffer Dall, Richard Henderson

From: Alex Bennée <alex.bennee@linaro.org>

Implement the non-carry forms of addition and subtraction
(immediate, extended register and shifted register).
This includes the code to calculate NZCV if the instruction
calls for setting the flags.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 target-arm/translate-a64.c | 291 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 285 insertions(+), 6 deletions(-)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 1b34a98..00dd369 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -297,6 +297,102 @@ static inline void gen_logic_CC(int sf, TCGv_i64 result)
     tcg_gen_movi_i32(cpu_VF, 0);
 }
 
+/* dest = T0 + T1; compute C, N, V and Z flags */
+static void gen_add_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
+{
+    if (sf) {
+        TCGv_i64 result, flag, tmp;
+        result = tcg_temp_new_i64();
+        flag = tcg_temp_new_i64();
+        tmp = tcg_temp_new_i64();
+
+        tcg_gen_movi_i64(tmp, 0);
+        tcg_gen_add2_i64(result, flag, t0, tmp, t1, tmp);
+
+        tcg_gen_trunc_i64_i32(cpu_CF, flag);
+
+        gen_set_NZ64(result);
+
+        tcg_gen_xor_i64(flag, result, t0);
+        tcg_gen_xor_i64(tmp, t0, t1);
+        tcg_gen_andc_i64(flag, flag, tmp);
+        tcg_temp_free_i64(tmp);
+        tcg_gen_shri_i64(flag, flag, 32);
+        tcg_gen_trunc_i64_i32(cpu_VF, flag);
+
+        tcg_gen_mov_i64(dest, result);
+        tcg_temp_free_i64(result);
+        tcg_temp_free_i64(flag);
+    } else {
+        /* 32 bit arithmetic */
+        TCGv_i32 t0_32 = tcg_temp_new_i32();
+        TCGv_i32 t1_32 = tcg_temp_new_i32();
+        TCGv_i32 tmp = tcg_temp_new_i32();
+
+        tcg_gen_movi_i32(tmp, 0);
+        tcg_gen_trunc_i64_i32(t0_32, t0);
+        tcg_gen_trunc_i64_i32(t1_32, t1);
+        tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, t1_32, tmp);
+        tcg_gen_mov_i32(cpu_ZF, cpu_NF);
+        tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
+        tcg_gen_xor_i32(tmp, t0_32, t1_32);
+        tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
+        tcg_gen_extu_i32_i64(dest, cpu_NF);
+
+        tcg_temp_free_i32(tmp);
+        tcg_temp_free_i32(t0_32);
+        tcg_temp_free_i32(t1_32);
+    }
+}
+
+/* dest = T0 - T1; compute C, N, V and Z flags */
+static void gen_sub_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
+{
+    if (sf) {
+        /* 64 bit arithmetic */
+        TCGv_i64 result, flag, tmp;
+
+        result = tcg_temp_new_i64();
+        flag = tcg_temp_new_i64();
+        tcg_gen_sub_i64(result, t0, t1);
+
+        gen_set_NZ64(result);
+
+        tcg_gen_setcond_i64(TCG_COND_GEU, flag, t0, t1);
+        tcg_gen_trunc_i64_i32(cpu_CF, flag);
+
+        tcg_gen_xor_i64(flag, result, t0);
+        tmp = tcg_temp_new_i64();
+        tcg_gen_xor_i64(tmp, t0, t1);
+        tcg_gen_and_i64(flag, flag, tmp);
+        tcg_temp_free_i64(tmp);
+        tcg_gen_shri_i64(flag, flag, 32);
+        tcg_gen_trunc_i64_i32(cpu_VF, flag);
+        tcg_gen_mov_i64(dest, result);
+        tcg_temp_free_i64(flag);
+        tcg_temp_free_i64(result);
+    } else {
+        /* 32 bit arithmetic */
+        TCGv_i32 t0_32 = tcg_temp_new_i32();
+        TCGv_i32 t1_32 = tcg_temp_new_i32();
+        TCGv_i32 tmp;
+
+        tcg_gen_trunc_i64_i32(t0_32, t0);
+        tcg_gen_trunc_i64_i32(t1_32, t1);
+        tcg_gen_sub_i32(cpu_NF, t0_32, t1_32);
+        tcg_gen_mov_i32(cpu_ZF, cpu_NF);
+        tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0_32, t1_32);
+        tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
+        tmp = tcg_temp_new_i32();
+        tcg_gen_xor_i32(tmp, t0_32, t1_32);
+        tcg_temp_free_i32(t0_32);
+        tcg_temp_free_i32(t1_32);
+        tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
+        tcg_temp_free_i32(tmp);
+        tcg_gen_extu_i32_i64(dest, cpu_NF);
+    }
+}
+
 /*
  * Load/Store generators
  */
@@ -1326,10 +1422,67 @@ static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
     tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
 }
 
-/* Add/subtract (immediate) */
+/*
+ * C3.4.1 Add/subtract (immediate)
+ *
+ *  31 30 29 28       24 23 22 21         10 9   5 4   0
+ * +--+--+--+-----------+-----+-------------+-----+-----+
+ * |sf|op| S| 1 0 0 0 1 |shift|    imm12    |  Rn | Rd  |
+ * +--+--+--+-----------+-----+-------------+-----+-----+
+ *
+ *    sf: 0 -> 32bit, 1 -> 64bit
+ *    op: 0 -> add  , 1 -> sub
+ *     S: 1 -> set flags
+ * shift: 00 -> LSL imm by 0, 01 -> LSL imm by 12
+ */
 static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    uint64_t imm = extract32(insn, 10, 12);
+    int shift = extract32(insn, 22, 2);
+    bool setflags = extract32(insn, 29, 1);
+    bool sub_op = extract32(insn, 30, 1);
+    bool is_64bit = extract32(insn, 31, 1);
+
+    TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
+    TCGv_i64 tcg_rd = setflags ? cpu_reg(s, rd) : cpu_reg_sp(s, rd);
+    TCGv_i64 tcg_result;
+
+    switch (shift) {
+    case 0x0:
+        break;
+    case 0x1:
+        imm <<= 12;
+        break;
+    default:
+        unallocated_encoding(s);
+    }
+
+    tcg_result = tcg_temp_new_i64();
+    if (!setflags) {
+        if (sub_op) {
+            tcg_gen_subi_i64(tcg_result, tcg_rn, imm);
+        } else {
+            tcg_gen_addi_i64(tcg_result, tcg_rn, imm);
+        }
+    } else {
+        TCGv_i64 tcg_imm = tcg_const_i64(imm);
+        if (sub_op) {
+            gen_sub_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
+        } else {
+            gen_add_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
+        }
+        tcg_temp_free_i64(tcg_imm);
+    }
+
+    if (is_64bit) {
+        tcg_gen_mov_i64(tcg_rd, tcg_result);
+    } else {
+        tcg_gen_ext32u_i64(tcg_rd, tcg_result);
+    }
+
+    tcg_temp_free_i64(tcg_result);
 }
 
 /* The input should be a value in the bottom e bits (with higher
@@ -1787,16 +1940,142 @@ static void disas_logic_reg(DisasContext *s, uint32_t insn)
     }
 }
 
-/* Add/subtract (extended register) */
+/*
+ * C3.5.1 Add/subtract (extended register)
+ *
+ *  31|30|29|28       24|23 22|21|20   16|15  13|12  10|9  5|4  0|
+ * +--+--+--+-----------+-----+--+-------+------+------+----+----+
+ * |sf|op| S| 0 1 0 1 1 | opt | 1|  Rm   |option| imm3 | Rn | Rd |
+ * +--+--+--+-----------+-----+--+-------+------+------+----+----+
+ *
+ *  sf: 0 -> 32bit, 1 -> 64bit
+ *  op: 0 -> add  , 1 -> sub
+ *   S: 1 -> set flags
+ * opt: 00
+ * option: extension type (see DecodeRegExtend)
+ * imm3: optional shift to Rm
+ *
+ * Rd = Rn + LSL(extend(Rm), amount)
+ */
 static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int imm3 = extract32(insn, 10, 3);
+    int option = extract32(insn, 13, 3);
+    int rm = extract32(insn, 16, 5);
+    bool setflags = extract32(insn, 29, 1);
+    bool sub_op = extract32(insn, 30, 1);
+    bool sf = extract32(insn, 31, 1);
+
+    TCGv_i64 tcg_rm, tcg_rn; /* temps */
+    TCGv_i64 tcg_rd;
+    TCGv_i64 tcg_result;
+
+    if (imm3 > 4) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    /* non-flag setting ops may use SP */
+    if (!setflags) {
+        tcg_rn = read_cpu_reg_sp(s, rn, sf);
+        tcg_rd = cpu_reg_sp(s, rd);
+    } else {
+        tcg_rn = read_cpu_reg(s, rn, sf);
+        tcg_rd = cpu_reg(s, rd);
+    }
+
+    tcg_rm = read_cpu_reg(s, rm, sf);
+    ext_and_shift_reg(tcg_rm, tcg_rm, option, imm3);
+
+    tcg_result = tcg_temp_new_i64();
+
+    if (!setflags) {
+        if (sub_op) {
+            tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
+        } else {
+            tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
+        }
+    } else {
+        if (sub_op) {
+            gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
+        } else {
+            gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
+        }
+    }
+
+    if (sf) {
+        tcg_gen_mov_i64(tcg_rd, tcg_result);
+    } else {
+        tcg_gen_ext32u_i64(tcg_rd, tcg_result);
+    }
+
+    tcg_temp_free_i64(tcg_result);
 }
 
-/* Add/subtract (shifted register) */
+/*
+ * C3.5.2 Add/subtract (shifted register)
+ *
+ *  31 30 29 28       24 23 22 21 20   16 15     10 9    5 4    0
+ * +--+--+--+-----------+-----+--+-------+---------+------+------+
+ * |sf|op| S| 0 1 0 1 1 |shift| 0|  Rm   |  imm6   |  Rn  |  Rd  |
+ * +--+--+--+-----------+-----+--+-------+---------+------+------+
+ *
+ *    sf: 0 -> 32bit, 1 -> 64bit
+ *    op: 0 -> add  , 1 -> sub
+ *     S: 1 -> set flags
+ * shift: 00 -> LSL, 01 -> LSR, 10 -> ASR, 11 -> RESERVED
+ *  imm6: Shift amount to apply to Rm before the add/sub
+ */
 static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int imm6 = extract32(insn, 10, 6);
+    int rm = extract32(insn, 16, 5);
+    int shift_type = extract32(insn, 22, 2);
+    bool setflags = extract32(insn, 29, 1);
+    bool sub_op = extract32(insn, 30, 1);
+    bool sf = extract32(insn, 31, 1);
+
+    TCGv_i64 tcg_rd = cpu_reg(s, rd);
+    TCGv_i64 tcg_rn, tcg_rm;
+    TCGv_i64 tcg_result;
+
+    if ((shift_type == 3) || (!sf && (imm6 > 31))) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    tcg_rn = read_cpu_reg(s, rn, sf);
+    tcg_rm = read_cpu_reg(s, rm, sf);
+
+    shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, imm6);
+
+    tcg_result = tcg_temp_new_i64();
+
+    if (!setflags) {
+        if (sub_op) {
+            tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
+        } else {
+            tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
+        }
+    } else {
+        if (sub_op) {
+            gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
+        } else {
+            gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
+        }
+    }
+
+    if (sf) {
+        tcg_gen_mov_i64(tcg_rd, tcg_result);
+    } else {
+        tcg_gen_ext32u_i64(tcg_rd, tcg_result);
+    }
+
+    tcg_temp_free_i64(tcg_result);
 }
 
 /* Data-processing (3 source) */
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 6/8] target-arm: A64: add support for move wide instructions
  2013-12-13 19:17 [Qemu-devel] [PATCH v3 0/8] target-arm: A64 decoder set 3: loads, stores, misc integer Peter Maydell
                   ` (4 preceding siblings ...)
  2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 5/8] target-arm: A64: add support for add, addi, sub, subi Peter Maydell
@ 2013-12-13 19:18 ` Peter Maydell
  2013-12-13 19:18 ` [Qemu-devel] [PATCH v3 7/8] target-arm: A64: add support for 3 src data proc insns Peter Maydell
  2013-12-13 19:18 ` [Qemu-devel] [PATCH v3 8/8] target-arm: A64: implement SVC, BRK Peter Maydell
  7 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2013-12-13 19:18 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Matz, Claudio Fontana, Dirk Mueller,
	Will Newton, Laurent Desnogues, Alex Bennée, kvmarm,
	Christoffer Dall, Richard Henderson

From: Alex Bennée <alex.bennee@linaro.org>

This patch adds emulation for the mov wide instructions
(MOVN, MOVZ, MOVK).

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 target-arm/translate-a64.c | 51 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 49 insertions(+), 2 deletions(-)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 00dd369..a6f1945 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -1641,10 +1641,57 @@ static void disas_logic_imm(DisasContext *s, uint32_t insn)
     }
 }
 
-/* Move wide (immediate) */
+/*
+ * C3.4.5 Move wide (immediate)
+ *
+ *  31 30 29 28         23 22 21 20             5 4    0
+ * +--+-----+-------------+-----+----------------+------+
+ * |sf| opc | 1 0 0 1 0 1 |  hw |  imm16         |  Rd  |
+ * +--+-----+-------------+-----+----------------+------+
+ *
+ * sf: 0 -> 32 bit, 1 -> 64 bit
+ * opc: 00 -> N, 10 -> Z, 11 -> K
+ * hw: shift/16 (0,16, and sf only 32, 48)
+ */
 static void disas_movw_imm(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    uint64_t imm = extract32(insn, 5, 16);
+    int sf = extract32(insn, 31, 1);
+    int opc = extract32(insn, 29, 2);
+    int pos = extract32(insn, 21, 2) << 4;
+    TCGv_i64 tcg_rd = cpu_reg(s, rd);
+    TCGv_i64 tcg_imm;
+
+    if (!sf && (pos >= 32)) {
+        unallocated_encoding(s);
+        return;
+    }
+
+    switch (opc) {
+    case 0: /* MOVN */
+    case 2: /* MOVZ */
+        imm <<= pos;
+        if (opc == 0) {
+            imm = ~imm;
+        }
+        if (!sf) {
+            imm &= 0xffffffffu;
+        }
+        tcg_gen_movi_i64(tcg_rd, imm);
+        break;
+    case 3: /* MOVK */
+        tcg_imm = tcg_const_i64(imm);
+        tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_imm, pos, 16);
+        tcg_temp_free_i64(tcg_imm);
+        if (!sf) {
+            tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
+        }
+        break;
+    default:
+        unallocated_encoding(s);
+        break;
+    }
 }
 
 /* C3.4.2 Bitfield
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 7/8] target-arm: A64: add support for 3 src data proc insns
  2013-12-13 19:17 [Qemu-devel] [PATCH v3 0/8] target-arm: A64 decoder set 3: loads, stores, misc integer Peter Maydell
                   ` (5 preceding siblings ...)
  2013-12-13 19:18 ` [Qemu-devel] [PATCH v3 6/8] target-arm: A64: add support for move wide instructions Peter Maydell
@ 2013-12-13 19:18 ` Peter Maydell
  2013-12-16  8:54   ` Claudio Fontana
  2013-12-16 10:49   ` Peter Maydell
  2013-12-13 19:18 ` [Qemu-devel] [PATCH v3 8/8] target-arm: A64: implement SVC, BRK Peter Maydell
  7 siblings, 2 replies; 14+ messages in thread
From: Peter Maydell @ 2013-12-13 19:18 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Matz, Claudio Fontana, Dirk Mueller,
	Will Newton, Laurent Desnogues, Alex Bennée, kvmarm,
	Christoffer Dall, Richard Henderson

From: Alexander Graf <agraf@suse.de>

This patch adds emulation for the "Data-processing (3 source)"
family of instructions, namely MADD, MSUB, SMADDL, SMSUBL, SMULH,
UMADDL, UMSUBL, UMULH.

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target-arm/translate-a64.c | 91 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 89 insertions(+), 2 deletions(-)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index a6f1945..b3e9449 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -2125,10 +2125,97 @@ static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
     tcg_temp_free_i64(tcg_result);
 }
 
-/* Data-processing (3 source) */
+/* C3.5.9 Data-processing (3 source)
+
+   31 30  29 28       24 23 21  20  16  15  14  10 9    5 4    0
+  +--+------+-----------+------+------+----+------+------+------+
+  |sf| op54 | 1 1 0 1 1 | op31 |  Rm  | o0 |  Ra  |  Rn  |  Rd  |
+  +--+------+-----------+------+------+----+------+------+------+
+
+ */
 static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int rd = extract32(insn, 0, 5);
+    int rn = extract32(insn, 5, 5);
+    int ra = extract32(insn, 10, 5);
+    int rm = extract32(insn, 16, 5);
+    int op_id = (extract32(insn, 29, 3) << 4) |
+        (extract32(insn, 21, 3) << 1) |
+        extract32(insn, 15, 1);
+    bool is_32bit = !extract32(insn, 31, 1);
+    bool is_sub = extract32(op_id, 0, 1);
+    bool is_high = extract32(op_id, 2, 1);
+    bool is_signed = false;
+    TCGv_i64 tcg_op1;
+    TCGv_i64 tcg_op2;
+    TCGv_i64 tcg_tmp;
+
+    /* Note that op_id is sf:op54:op31:o0 so it includes the 32/64 size flag */
+    switch (op_id) {
+    case 0x42: /* SMADDL */
+    case 0x43: /* SMSUBL */
+    case 0x44: /* SMULH */
+        is_signed = true;
+        break;
+    case 0x0: /* MADD (32bit) */
+    case 0x1: /* MSUB (32bit) */
+    case 0x40: /* MADD (64bit) */
+    case 0x41: /* MSUB (64bit) */
+    case 0x4a: /* UMADDL */
+    case 0x4b: /* UMSUBL */
+    case 0x4c: /* UMULH */
+        break;
+    default:
+        unallocated_encoding(s);
+    }
+
+    if (is_high) {
+        TCGv_i64 low_bits = tcg_temp_new_i64(); /* low bits discarded */
+        TCGv_i64 tcg_rd = cpu_reg(s, rd);
+        TCGv_i64 tcg_rn = cpu_reg(s, rn);
+        TCGv_i64 tcg_rm = cpu_reg(s, rm);
+
+        if (is_signed) {
+            tcg_gen_muls2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
+        } else {
+            tcg_gen_mulu2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
+        }
+
+        tcg_temp_free(low_bits);
+        return;
+    }
+
+    tcg_op1 = tcg_temp_new_i64();
+    tcg_op2 = tcg_temp_new_i64();
+    tcg_tmp = tcg_temp_new_i64();
+
+    if (op_id < 0x42) {
+        tcg_gen_mov_i64(tcg_op1, cpu_reg(s, rn));
+        tcg_gen_mov_i64(tcg_op2, cpu_reg(s, rm));
+    } else {
+        if (is_signed) {
+            tcg_gen_ext32s_i64(tcg_op1, cpu_reg(s, rn));
+            tcg_gen_ext32s_i64(tcg_op2, cpu_reg(s, rm));
+        } else {
+            tcg_gen_ext32u_i64(tcg_op1, cpu_reg(s, rn));
+            tcg_gen_ext32u_i64(tcg_op2, cpu_reg(s, rm));
+        }
+    }
+
+    tcg_gen_mul_i64(tcg_tmp, tcg_op1, tcg_op2);
+    if (is_sub) {
+        tcg_gen_sub_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
+    } else {
+        tcg_gen_add_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
+    }
+
+    if (is_32bit) {
+        tcg_gen_ext32u_i64(cpu_reg(s, rd), cpu_reg(s, rd));
+    }
+
+    tcg_temp_free_i64(tcg_op1);
+    tcg_temp_free_i64(tcg_op2);
+    tcg_temp_free_i64(tcg_tmp);
 }
 
 /* Add/subtract (with carry) */
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [Qemu-devel] [PATCH v3 8/8] target-arm: A64: implement SVC, BRK
  2013-12-13 19:17 [Qemu-devel] [PATCH v3 0/8] target-arm: A64 decoder set 3: loads, stores, misc integer Peter Maydell
                   ` (6 preceding siblings ...)
  2013-12-13 19:18 ` [Qemu-devel] [PATCH v3 7/8] target-arm: A64: add support for 3 src data proc insns Peter Maydell
@ 2013-12-13 19:18 ` Peter Maydell
  7 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2013-12-13 19:18 UTC (permalink / raw)
  To: qemu-devel
  Cc: patches, Michael Matz, Claudio Fontana, Dirk Mueller,
	Will Newton, Laurent Desnogues, Alex Bennée, kvmarm,
	Christoffer Dall, Richard Henderson

From: Alexander Graf <agraf@suse.de>

Add decoding for the exception generating instructions, and implement
SVC (syscalls) and BRK (software breakpoint).

Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <rth@twiddle.net>
---
 target-arm/translate-a64.c | 51 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 49 insertions(+), 2 deletions(-)

diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index b3e9449..56d1616 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -806,10 +806,57 @@ static void disas_system(DisasContext *s, uint32_t insn)
     }
 }
 
-/* Exception generation */
+/* C3.2.3 Exception generation
+ *
+ *  31             24 23 21 20                     5 4   2 1  0
+ * +-----------------+-----+------------------------+-----+----+
+ * | 1 1 0 1 0 1 0 0 | opc |          imm16         | op2 | LL |
+ * +-----------------------+------------------------+----------+
+ */
 static void disas_exc(DisasContext *s, uint32_t insn)
 {
-    unsupported_encoding(s, insn);
+    int opc = extract32(insn, 21, 3);
+    int op2_ll = extract32(insn, 0, 5);
+
+    switch (opc) {
+    case 0:
+        /* SVC, HVC, SMC; since we don't support the Virtualization
+         * or TrustZone extensions these all UNDEF except SVC.
+         */
+        if (op2_ll != 1) {
+            unallocated_encoding(s);
+            break;
+        }
+        gen_exception_insn(s, 0, EXCP_SWI);
+        break;
+    case 1:
+        if (op2_ll != 0) {
+            unallocated_encoding(s);
+            break;
+        }
+        /* BRK */
+        gen_exception_insn(s, 0, EXCP_BKPT);
+        break;
+    case 2:
+        if (op2_ll != 0) {
+            unallocated_encoding(s);
+            break;
+        }
+        /* HLT */
+        unsupported_encoding(s, insn);
+        break;
+    case 5:
+        if (op2_ll < 1 || op2_ll > 3) {
+            unallocated_encoding(s);
+            break;
+        }
+        /* DCPS1, DCPS2, DCPS3 */
+        unsupported_encoding(s, insn);
+        break;
+    default:
+        unallocated_encoding(s);
+        break;
+    }
 }
 
 /* C3.2.7 Unconditional branch (register)
-- 
1.8.5

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH v3 7/8] target-arm: A64: add support for 3 src data proc insns
  2013-12-13 19:18 ` [Qemu-devel] [PATCH v3 7/8] target-arm: A64: add support for 3 src data proc insns Peter Maydell
@ 2013-12-16  8:54   ` Claudio Fontana
  2013-12-16  9:36     ` Peter Maydell
  2013-12-16 10:49   ` Peter Maydell
  1 sibling, 1 reply; 14+ messages in thread
From: Claudio Fontana @ 2013-12-16  8:54 UTC (permalink / raw)
  To: Peter Maydell, qemu-devel
  Cc: Laurent Desnogues, patches, Michael Matz, Claudio Fontana,
	Dirk Mueller, Will Newton, Alex Bennée, kvmarm,
	Christoffer Dall, Richard Henderson

Hello Peter,

On 13.12.2013 20:18, Peter Maydell wrote:
> From: Alexander Graf <agraf@suse.de>
> 
> This patch adds emulation for the "Data-processing (3 source)"
> family of instructions, namely MADD, MSUB, SMADDL, SMSUBL, SMULH,
> UMADDL, UMSUBL, UMULH.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> ---
>  target-arm/translate-a64.c | 91 +++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 89 insertions(+), 2 deletions(-)
> 
> diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
> index a6f1945..b3e9449 100644
> --- a/target-arm/translate-a64.c
> +++ b/target-arm/translate-a64.c
> @@ -2125,10 +2125,97 @@ static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
>      tcg_temp_free_i64(tcg_result);
>  }
>  
> -/* Data-processing (3 source) */
> +/* C3.5.9 Data-processing (3 source)
> +
> +   31 30  29 28       24 23 21  20  16  15  14  10 9    5 4    0
> +  +--+------+-----------+------+------+----+------+------+------+
> +  |sf| op54 | 1 1 0 1 1 | op31 |  Rm  | o0 |  Ra  |  Rn  |  Rd  |
> +  +--+------+-----------+------+------+----+------+------+------+
> +
> + */
>  static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
>  {
> -    unsupported_encoding(s, insn);
> +    int rd = extract32(insn, 0, 5);
> +    int rn = extract32(insn, 5, 5);
> +    int ra = extract32(insn, 10, 5);
> +    int rm = extract32(insn, 16, 5);
> +    int op_id = (extract32(insn, 29, 3) << 4) |
> +        (extract32(insn, 21, 3) << 1) |
> +        extract32(insn, 15, 1);
> +    bool is_32bit = !extract32(insn, 31, 1);

we have used "sf" everywhere else..

> +    bool is_sub = extract32(op_id, 0, 1);
> +    bool is_high = extract32(op_id, 2, 1);
> +    bool is_signed = false;
> +    TCGv_i64 tcg_op1;
> +    TCGv_i64 tcg_op2;
> +    TCGv_i64 tcg_tmp;
> +
> +    /* Note that op_id is sf:op54:op31:o0 so it includes the 32/64 size flag */
> +    switch (op_id) {
> +    case 0x42: /* SMADDL */
> +    case 0x43: /* SMSUBL */
> +    case 0x44: /* SMULH */
> +        is_signed = true;
> +        break;
> +    case 0x0: /* MADD (32bit) */
> +    case 0x1: /* MSUB (32bit) */
> +    case 0x40: /* MADD (64bit) */
> +    case 0x41: /* MSUB (64bit) */
> +    case 0x4a: /* UMADDL */
> +    case 0x4b: /* UMSUBL */
> +    case 0x4c: /* UMULH */
> +        break;
> +    default:
> +        unallocated_encoding(s);
> +    }
> +
> +    if (is_high) {
> +        TCGv_i64 low_bits = tcg_temp_new_i64(); /* low bits discarded */
> +        TCGv_i64 tcg_rd = cpu_reg(s, rd);
> +        TCGv_i64 tcg_rn = cpu_reg(s, rn);
> +        TCGv_i64 tcg_rm = cpu_reg(s, rm);
> +
> +        if (is_signed) {
> +            tcg_gen_muls2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
> +        } else {
> +            tcg_gen_mulu2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
> +        }
> +
> +        tcg_temp_free(low_bits);

should this be tcg_temp_free_i64()?

> +        return;
> +    }
> +
> +    tcg_op1 = tcg_temp_new_i64();
> +    tcg_op2 = tcg_temp_new_i64();
> +    tcg_tmp = tcg_temp_new_i64();
> +
> +    if (op_id < 0x42) {
> +        tcg_gen_mov_i64(tcg_op1, cpu_reg(s, rn));
> +        tcg_gen_mov_i64(tcg_op2, cpu_reg(s, rm));
> +    } else {
> +        if (is_signed) {
> +            tcg_gen_ext32s_i64(tcg_op1, cpu_reg(s, rn));
> +            tcg_gen_ext32s_i64(tcg_op2, cpu_reg(s, rm));
> +        } else {
> +            tcg_gen_ext32u_i64(tcg_op1, cpu_reg(s, rn));
> +            tcg_gen_ext32u_i64(tcg_op2, cpu_reg(s, rm));
> +        }
> +    }
> +
> +    tcg_gen_mul_i64(tcg_tmp, tcg_op1, tcg_op2);
> +    if (is_sub) {
> +        tcg_gen_sub_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
> +    } else {
> +        tcg_gen_add_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
> +    }
> +
> +    if (is_32bit) {
> +        tcg_gen_ext32u_i64(cpu_reg(s, rd), cpu_reg(s, rd));
> +    }
> +
> +    tcg_temp_free_i64(tcg_op1);
> +    tcg_temp_free_i64(tcg_op2);
> +    tcg_temp_free_i64(tcg_tmp);
>  }
>  
>  /* Add/subtract (with carry) */
> 

Ciao,

Claudio

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH v3 7/8] target-arm: A64: add support for 3 src data proc insns
  2013-12-16  8:54   ` Claudio Fontana
@ 2013-12-16  9:36     ` Peter Maydell
  0 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2013-12-16  9:36 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: Laurent Desnogues, Patch Tracking, Michael Matz, QEMU Developers,
	Claudio Fontana, Dirk Mueller, Will Newton, Alex Bennée,
	kvmarm, Christoffer Dall, Richard Henderson

On 16 December 2013 08:54, Claudio Fontana <claudio.fontana@huawei.com> wrote:
> Hello Peter,
>
> On 13.12.2013 20:18, Peter Maydell wrote:
>> From: Alexander Graf <agraf@suse.de>
>>
>> This patch adds emulation for the "Data-processing (3 source)"
>> family of instructions, namely MADD, MSUB, SMADDL, SMSUBL, SMULH,
>> UMADDL, UMSUBL, UMULH.
>>
>> Signed-off-by: Alexander Graf <agraf@suse.de>
>> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
>> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
>> ---
>>  target-arm/translate-a64.c | 91 +++++++++++++++++++++++++++++++++++++++++++++-
>>  1 file changed, 89 insertions(+), 2 deletions(-)
>>
>> diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
>> index a6f1945..b3e9449 100644
>> --- a/target-arm/translate-a64.c
>> +++ b/target-arm/translate-a64.c
>> @@ -2125,10 +2125,97 @@ static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
>>      tcg_temp_free_i64(tcg_result);
>>  }
>>
>> -/* Data-processing (3 source) */
>> +/* C3.5.9 Data-processing (3 source)
>> +
>> +   31 30  29 28       24 23 21  20  16  15  14  10 9    5 4    0
>> +  +--+------+-----------+------+------+----+------+------+------+
>> +  |sf| op54 | 1 1 0 1 1 | op31 |  Rm  | o0 |  Ra  |  Rn  |  Rd  |
>> +  +--+------+-----------+------+------+----+------+------+------+
>> +
>> + */
>>  static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
>>  {
>> -    unsupported_encoding(s, insn);
>> +    int rd = extract32(insn, 0, 5);
>> +    int rn = extract32(insn, 5, 5);
>> +    int ra = extract32(insn, 10, 5);
>> +    int rm = extract32(insn, 16, 5);
>> +    int op_id = (extract32(insn, 29, 3) << 4) |
>> +        (extract32(insn, 21, 3) << 1) |
>> +        extract32(insn, 15, 1);
>> +    bool is_32bit = !extract32(insn, 31, 1);
>
> we have used "sf" everywhere else..

Yes, might as well be consistent.

>> +        tcg_temp_free(low_bits);
>
> should this be tcg_temp_free_i64()?

Yes, since we're preferring to be explicit about i32 vs i64
temps. (We know we're always building a 64 bit binary for
translate-a64.c so in fact we can guarantee that tcg_temp_free
is always tcg_temp_free_i64; but consistency with the 32 bit
decoder is nice.)

Fixed these nits in my working tree.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH v3 5/8] target-arm: A64: add support for add, addi, sub, subi
  2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 5/8] target-arm: A64: add support for add, addi, sub, subi Peter Maydell
@ 2013-12-16 10:11   ` C Fontana
  2013-12-16 10:48     ` Peter Maydell
  0 siblings, 1 reply; 14+ messages in thread
From: C Fontana @ 2013-12-16 10:11 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Patch Tracking, Michael Matz, QEMU Developers, Will Newton,
	Dirk Mueller, Laurent Desnogues, Alex Bennée, kvmarm,
	Christoffer Dall, Richard Henderson

Sorry for noticing only now,
but there is a missing return here as well I think:

On 13 December 2013 20:17, Peter Maydell <peter.maydell@linaro.org> wrote:
> From: Alex Bennée <alex.bennee@linaro.org>
>
> Implement the non-carry forms of addition and subtraction
> (immediate, extended register and shifted register).
> This includes the code to calculate NZCV if the instruction
> calls for setting the flags.
>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
> Reviewed-by: Richard Henderson <rth@twiddle.net>
> ---
>  target-arm/translate-a64.c | 291 ++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 285 insertions(+), 6 deletions(-)
>
> diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
> index 1b34a98..00dd369 100644
> --- a/target-arm/translate-a64.c
> +++ b/target-arm/translate-a64.c
> @@ -297,6 +297,102 @@ static inline void gen_logic_CC(int sf, TCGv_i64 result)
>      tcg_gen_movi_i32(cpu_VF, 0);
>  }
>
> +/* dest = T0 + T1; compute C, N, V and Z flags */
> +static void gen_add_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
> +{
> +    if (sf) {
> +        TCGv_i64 result, flag, tmp;
> +        result = tcg_temp_new_i64();
> +        flag = tcg_temp_new_i64();
> +        tmp = tcg_temp_new_i64();
> +
> +        tcg_gen_movi_i64(tmp, 0);
> +        tcg_gen_add2_i64(result, flag, t0, tmp, t1, tmp);
> +
> +        tcg_gen_trunc_i64_i32(cpu_CF, flag);
> +
> +        gen_set_NZ64(result);
> +
> +        tcg_gen_xor_i64(flag, result, t0);
> +        tcg_gen_xor_i64(tmp, t0, t1);
> +        tcg_gen_andc_i64(flag, flag, tmp);
> +        tcg_temp_free_i64(tmp);
> +        tcg_gen_shri_i64(flag, flag, 32);
> +        tcg_gen_trunc_i64_i32(cpu_VF, flag);
> +
> +        tcg_gen_mov_i64(dest, result);
> +        tcg_temp_free_i64(result);
> +        tcg_temp_free_i64(flag);
> +    } else {
> +        /* 32 bit arithmetic */
> +        TCGv_i32 t0_32 = tcg_temp_new_i32();
> +        TCGv_i32 t1_32 = tcg_temp_new_i32();
> +        TCGv_i32 tmp = tcg_temp_new_i32();
> +
> +        tcg_gen_movi_i32(tmp, 0);
> +        tcg_gen_trunc_i64_i32(t0_32, t0);
> +        tcg_gen_trunc_i64_i32(t1_32, t1);
> +        tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, t1_32, tmp);
> +        tcg_gen_mov_i32(cpu_ZF, cpu_NF);
> +        tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
> +        tcg_gen_xor_i32(tmp, t0_32, t1_32);
> +        tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
> +        tcg_gen_extu_i32_i64(dest, cpu_NF);
> +
> +        tcg_temp_free_i32(tmp);
> +        tcg_temp_free_i32(t0_32);
> +        tcg_temp_free_i32(t1_32);
> +    }
> +}
> +
> +/* dest = T0 - T1; compute C, N, V and Z flags */
> +static void gen_sub_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
> +{
> +    if (sf) {
> +        /* 64 bit arithmetic */
> +        TCGv_i64 result, flag, tmp;
> +
> +        result = tcg_temp_new_i64();
> +        flag = tcg_temp_new_i64();
> +        tcg_gen_sub_i64(result, t0, t1);
> +
> +        gen_set_NZ64(result);
> +
> +        tcg_gen_setcond_i64(TCG_COND_GEU, flag, t0, t1);
> +        tcg_gen_trunc_i64_i32(cpu_CF, flag);
> +
> +        tcg_gen_xor_i64(flag, result, t0);
> +        tmp = tcg_temp_new_i64();
> +        tcg_gen_xor_i64(tmp, t0, t1);
> +        tcg_gen_and_i64(flag, flag, tmp);
> +        tcg_temp_free_i64(tmp);
> +        tcg_gen_shri_i64(flag, flag, 32);
> +        tcg_gen_trunc_i64_i32(cpu_VF, flag);
> +        tcg_gen_mov_i64(dest, result);
> +        tcg_temp_free_i64(flag);
> +        tcg_temp_free_i64(result);
> +    } else {
> +        /* 32 bit arithmetic */
> +        TCGv_i32 t0_32 = tcg_temp_new_i32();
> +        TCGv_i32 t1_32 = tcg_temp_new_i32();
> +        TCGv_i32 tmp;
> +
> +        tcg_gen_trunc_i64_i32(t0_32, t0);
> +        tcg_gen_trunc_i64_i32(t1_32, t1);
> +        tcg_gen_sub_i32(cpu_NF, t0_32, t1_32);
> +        tcg_gen_mov_i32(cpu_ZF, cpu_NF);
> +        tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0_32, t1_32);
> +        tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
> +        tmp = tcg_temp_new_i32();
> +        tcg_gen_xor_i32(tmp, t0_32, t1_32);
> +        tcg_temp_free_i32(t0_32);
> +        tcg_temp_free_i32(t1_32);
> +        tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
> +        tcg_temp_free_i32(tmp);
> +        tcg_gen_extu_i32_i64(dest, cpu_NF);
> +    }
> +}
> +
>  /*
>   * Load/Store generators
>   */
> @@ -1326,10 +1422,67 @@ static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
>      tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
>  }
>
> -/* Add/subtract (immediate) */
> +/*
> + * C3.4.1 Add/subtract (immediate)
> + *
> + *  31 30 29 28       24 23 22 21         10 9   5 4   0
> + * +--+--+--+-----------+-----+-------------+-----+-----+
> + * |sf|op| S| 1 0 0 0 1 |shift|    imm12    |  Rn | Rd  |
> + * +--+--+--+-----------+-----+-------------+-----+-----+
> + *
> + *    sf: 0 -> 32bit, 1 -> 64bit
> + *    op: 0 -> add  , 1 -> sub
> + *     S: 1 -> set flags
> + * shift: 00 -> LSL imm by 0, 01 -> LSL imm by 12
> + */
>  static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
>  {
> -    unsupported_encoding(s, insn);
> +    int rd = extract32(insn, 0, 5);
> +    int rn = extract32(insn, 5, 5);
> +    uint64_t imm = extract32(insn, 10, 12);
> +    int shift = extract32(insn, 22, 2);
> +    bool setflags = extract32(insn, 29, 1);
> +    bool sub_op = extract32(insn, 30, 1);
> +    bool is_64bit = extract32(insn, 31, 1);
> +
> +    TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
> +    TCGv_i64 tcg_rd = setflags ? cpu_reg(s, rd) : cpu_reg_sp(s, rd);
> +    TCGv_i64 tcg_result;
> +
> +    switch (shift) {
> +    case 0x0:
> +        break;
> +    case 0x1:
> +        imm <<= 12;
> +        break;
> +    default:
> +        unallocated_encoding(s);

should return; here I think.

> +    }
> +
> +    tcg_result = tcg_temp_new_i64();
> +    if (!setflags) {
> +        if (sub_op) {
> +            tcg_gen_subi_i64(tcg_result, tcg_rn, imm);
> +        } else {
> +            tcg_gen_addi_i64(tcg_result, tcg_rn, imm);
> +        }
> +    } else {
> +        TCGv_i64 tcg_imm = tcg_const_i64(imm);
> +        if (sub_op) {
> +            gen_sub_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
> +        } else {
> +            gen_add_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
> +        }
> +        tcg_temp_free_i64(tcg_imm);
> +    }
> +
> +    if (is_64bit) {
> +        tcg_gen_mov_i64(tcg_rd, tcg_result);
> +    } else {
> +        tcg_gen_ext32u_i64(tcg_rd, tcg_result);
> +    }
> +
> +    tcg_temp_free_i64(tcg_result);
>  }
>
>  /* The input should be a value in the bottom e bits (with higher
> @@ -1787,16 +1940,142 @@ static void disas_logic_reg(DisasContext *s, uint32_t insn)
>      }
>  }
>
> -/* Add/subtract (extended register) */
> +/*
> + * C3.5.1 Add/subtract (extended register)
> + *
> + *  31|30|29|28       24|23 22|21|20   16|15  13|12  10|9  5|4  0|
> + * +--+--+--+-----------+-----+--+-------+------+------+----+----+
> + * |sf|op| S| 0 1 0 1 1 | opt | 1|  Rm   |option| imm3 | Rn | Rd |
> + * +--+--+--+-----------+-----+--+-------+------+------+----+----+
> + *
> + *  sf: 0 -> 32bit, 1 -> 64bit
> + *  op: 0 -> add  , 1 -> sub
> + *   S: 1 -> set flags
> + * opt: 00
> + * option: extension type (see DecodeRegExtend)
> + * imm3: optional shift to Rm
> + *
> + * Rd = Rn + LSL(extend(Rm), amount)
> + */
>  static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
>  {
> -    unsupported_encoding(s, insn);
> +    int rd = extract32(insn, 0, 5);
> +    int rn = extract32(insn, 5, 5);
> +    int imm3 = extract32(insn, 10, 3);
> +    int option = extract32(insn, 13, 3);
> +    int rm = extract32(insn, 16, 5);
> +    bool setflags = extract32(insn, 29, 1);
> +    bool sub_op = extract32(insn, 30, 1);
> +    bool sf = extract32(insn, 31, 1);
> +
> +    TCGv_i64 tcg_rm, tcg_rn; /* temps */
> +    TCGv_i64 tcg_rd;
> +    TCGv_i64 tcg_result;
> +
> +    if (imm3 > 4) {
> +        unallocated_encoding(s);
> +        return;
> +    }
> +
> +    /* non-flag setting ops may use SP */
> +    if (!setflags) {
> +        tcg_rn = read_cpu_reg_sp(s, rn, sf);
> +        tcg_rd = cpu_reg_sp(s, rd);
> +    } else {
> +        tcg_rn = read_cpu_reg(s, rn, sf);
> +        tcg_rd = cpu_reg(s, rd);
> +    }
> +
> +    tcg_rm = read_cpu_reg(s, rm, sf);
> +    ext_and_shift_reg(tcg_rm, tcg_rm, option, imm3);
> +
> +    tcg_result = tcg_temp_new_i64();
> +
> +    if (!setflags) {
> +        if (sub_op) {
> +            tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
> +        } else {
> +            tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
> +        }
> +    } else {
> +        if (sub_op) {
> +            gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
> +        } else {
> +            gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
> +        }
> +    }
> +
> +    if (sf) {
> +        tcg_gen_mov_i64(tcg_rd, tcg_result);
> +    } else {
> +        tcg_gen_ext32u_i64(tcg_rd, tcg_result);
> +    }
> +
> +    tcg_temp_free_i64(tcg_result);
>  }
>
> -/* Add/subtract (shifted register) */
> +/*
> + * C3.5.2 Add/subtract (shifted register)
> + *
> + *  31 30 29 28       24 23 22 21 20   16 15     10 9    5 4    0
> + * +--+--+--+-----------+-----+--+-------+---------+------+------+
> + * |sf|op| S| 0 1 0 1 1 |shift| 0|  Rm   |  imm6   |  Rn  |  Rd  |
> + * +--+--+--+-----------+-----+--+-------+---------+------+------+
> + *
> + *    sf: 0 -> 32bit, 1 -> 64bit
> + *    op: 0 -> add  , 1 -> sub
> + *     S: 1 -> set flags
> + * shift: 00 -> LSL, 01 -> LSR, 10 -> ASR, 11 -> RESERVED
> + *  imm6: Shift amount to apply to Rm before the add/sub
> + */
>  static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
>  {
> -    unsupported_encoding(s, insn);
> +    int rd = extract32(insn, 0, 5);
> +    int rn = extract32(insn, 5, 5);
> +    int imm6 = extract32(insn, 10, 6);
> +    int rm = extract32(insn, 16, 5);
> +    int shift_type = extract32(insn, 22, 2);
> +    bool setflags = extract32(insn, 29, 1);
> +    bool sub_op = extract32(insn, 30, 1);
> +    bool sf = extract32(insn, 31, 1);
> +
> +    TCGv_i64 tcg_rd = cpu_reg(s, rd);
> +    TCGv_i64 tcg_rn, tcg_rm;
> +    TCGv_i64 tcg_result;
> +
> +    if ((shift_type == 3) || (!sf && (imm6 > 31))) {
> +        unallocated_encoding(s);
> +        return;
> +    }
> +
> +    tcg_rn = read_cpu_reg(s, rn, sf);
> +    tcg_rm = read_cpu_reg(s, rm, sf);
> +
> +    shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, imm6);
> +
> +    tcg_result = tcg_temp_new_i64();
> +
> +    if (!setflags) {
> +        if (sub_op) {
> +            tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
> +        } else {
> +            tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
> +        }
> +    } else {
> +        if (sub_op) {
> +            gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
> +        } else {
> +            gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
> +        }
> +    }
> +
> +    if (sf) {
> +        tcg_gen_mov_i64(tcg_rd, tcg_result);
> +    } else {
> +        tcg_gen_ext32u_i64(tcg_rd, tcg_result);
> +    }
> +
> +    tcg_temp_free_i64(tcg_result);
>  }
>
>  /* Data-processing (3 source) */
> --
> 1.8.5
>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH v3 5/8] target-arm: A64: add support for add, addi, sub, subi
  2013-12-16 10:11   ` C Fontana
@ 2013-12-16 10:48     ` Peter Maydell
  0 siblings, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2013-12-16 10:48 UTC (permalink / raw)
  To: C Fontana
  Cc: Patch Tracking, Michael Matz, QEMU Developers, Will Newton,
	Dirk Mueller, Laurent Desnogues, Alex Bennée, kvmarm,
	Christoffer Dall, Richard Henderson

On 16 December 2013 10:11, C Fontana <claudio.fontana@linaro.org> wrote:
> Sorry for noticing only now,
> but there is a missing return here as well I think:
>
>>  static void disas_add_sub_imm(DisasContext *s, uint32_t insn)

>> +    default:
>> +        unallocated_encoding(s);
>
> should return; here I think.

Yes, fixed.

-- PMM

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [Qemu-devel] [PATCH v3 7/8] target-arm: A64: add support for 3 src data proc insns
  2013-12-13 19:18 ` [Qemu-devel] [PATCH v3 7/8] target-arm: A64: add support for 3 src data proc insns Peter Maydell
  2013-12-16  8:54   ` Claudio Fontana
@ 2013-12-16 10:49   ` Peter Maydell
  1 sibling, 0 replies; 14+ messages in thread
From: Peter Maydell @ 2013-12-16 10:49 UTC (permalink / raw)
  To: QEMU Developers
  Cc: Laurent Desnogues, Patch Tracking, Michael Matz, Claudio Fontana,
	Dirk Mueller, Will Newton, kvmarm, Richard Henderson

On 13 December 2013 19:18, Peter Maydell <peter.maydell@linaro.org> wrote:
>  static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
>  {
> -    unsupported_encoding(s, insn);
> +    int rd = extract32(insn, 0, 5);
> +    int rn = extract32(insn, 5, 5);
> +    int ra = extract32(insn, 10, 5);
> +    int rm = extract32(insn, 16, 5);
> +    int op_id = (extract32(insn, 29, 3) << 4) |
> +        (extract32(insn, 21, 3) << 1) |
> +        extract32(insn, 15, 1);
> +    bool is_32bit = !extract32(insn, 31, 1);
> +    bool is_sub = extract32(op_id, 0, 1);
> +    bool is_high = extract32(op_id, 2, 1);
> +    bool is_signed = false;
> +    TCGv_i64 tcg_op1;
> +    TCGv_i64 tcg_op2;
> +    TCGv_i64 tcg_tmp;
> +
> +    /* Note that op_id is sf:op54:op31:o0 so it includes the 32/64 size flag */
> +    switch (op_id) {
> +    case 0x42: /* SMADDL */
> +    case 0x43: /* SMSUBL */
> +    case 0x44: /* SMULH */
> +        is_signed = true;
> +        break;
> +    case 0x0: /* MADD (32bit) */
> +    case 0x1: /* MSUB (32bit) */
> +    case 0x40: /* MADD (64bit) */
> +    case 0x41: /* MSUB (64bit) */
> +    case 0x4a: /* UMADDL */
> +    case 0x4b: /* UMSUBL */
> +    case 0x4c: /* UMULH */
> +        break;
> +    default:
> +        unallocated_encoding(s);
> +    }

Missing 'return' after unallocated_encoding(), fixed in my
working tree.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2013-12-16 10:50 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-13 19:17 [Qemu-devel] [PATCH v3 0/8] target-arm: A64 decoder set 3: loads, stores, misc integer Peter Maydell
2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 1/8] target-arm: A64: add support for ld/st pair Peter Maydell
2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 2/8] target-arm: A64: add support for ld/st unsigned imm Peter Maydell
2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 3/8] target-arm: A64: add support for ld/st with reg offset Peter Maydell
2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 4/8] target-arm: A64: add support for ld/st with index Peter Maydell
2013-12-13 19:17 ` [Qemu-devel] [PATCH v3 5/8] target-arm: A64: add support for add, addi, sub, subi Peter Maydell
2013-12-16 10:11   ` C Fontana
2013-12-16 10:48     ` Peter Maydell
2013-12-13 19:18 ` [Qemu-devel] [PATCH v3 6/8] target-arm: A64: add support for move wide instructions Peter Maydell
2013-12-13 19:18 ` [Qemu-devel] [PATCH v3 7/8] target-arm: A64: add support for 3 src data proc insns Peter Maydell
2013-12-16  8:54   ` Claudio Fontana
2013-12-16  9:36     ` Peter Maydell
2013-12-16 10:49   ` Peter Maydell
2013-12-13 19:18 ` [Qemu-devel] [PATCH v3 8/8] target-arm: A64: implement SVC, BRK Peter Maydell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.