[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 30/38] target-arm: A64: Add integer ops from SIMD 3-s
From: |
Peter Maydell |
Subject: |
[Qemu-devel] [PULL 30/38] target-arm: A64: Add integer ops from SIMD 3-same group |
Date: |
Wed, 29 Jan 2014 13:39:57 +0000 |
Add some of the integer operations in the SIMD 3-same group:
specifically, the comparisons, addition and subtraction.
Signed-off-by: Peter Maydell <address@hidden>
Reviewed-by: Richard Henderson <address@hidden>
---
target-arm/translate-a64.c | 165 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 164 insertions(+), 1 deletion(-)
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index aa53ddc..9e7401c 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -72,6 +72,9 @@ typedef struct AArch64DecodeTable {
AArch64DecodeFn *disas_fn;
} AArch64DecodeTable;
+/* Function prototype for gen_ functions for calling Neon helpers */
+typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
+
/* initialize TCG globals. */
void a64_translate_init(void)
{
@@ -787,6 +790,25 @@ static void write_vec_element(DisasContext *s, TCGv_i64
tcg_src, int destidx,
}
}
+static void write_vec_element_i32(DisasContext *s, TCGv_i32 tcg_src,
+ int destidx, int element, TCGMemOp memop)
+{
+ int vect_off = vec_reg_offset(destidx, element, memop & MO_SIZE);
+ switch (memop) {
+ case MO_8:
+ tcg_gen_st8_i32(tcg_src, cpu_env, vect_off);
+ break;
+ case MO_16:
+ tcg_gen_st16_i32(tcg_src, cpu_env, vect_off);
+ break;
+ case MO_32:
+ tcg_gen_st_i32(tcg_src, cpu_env, vect_off);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+}
+
/* Clear the high 64 bits of a 128 bit vector (in general non-quad
* vector ops all need to do this).
*/
@@ -6012,7 +6034,148 @@ static void disas_simd_3same_float(DisasContext *s,
uint32_t insn)
/* Integer op subgroup of C3.6.16. */
static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
{
- unsupported_encoding(s, insn);
+ int is_q = extract32(insn, 30, 1);
+ int u = extract32(insn, 29, 1);
+ int size = extract32(insn, 22, 2);
+ int opcode = extract32(insn, 11, 5);
+ int rm = extract32(insn, 16, 5);
+ int rn = extract32(insn, 5, 5);
+ int rd = extract32(insn, 0, 5);
+ int pass;
+
+ switch (opcode) {
+ case 0x13: /* MUL, PMUL */
+ if (u && size != 0) {
+ unallocated_encoding(s);
+ return;
+ }
+ /* fall through */
+ case 0x0: /* SHADD, UHADD */
+ case 0x2: /* SRHADD, URHADD */
+ case 0x4: /* SHSUB, UHSUB */
+ case 0xc: /* SMAX, UMAX */
+ case 0xd: /* SMIN, UMIN */
+ case 0xe: /* SABD, UABD */
+ case 0xf: /* SABA, UABA */
+ case 0x12: /* MLA, MLS */
+ if (size == 3) {
+ unallocated_encoding(s);
+ return;
+ }
+ unsupported_encoding(s, insn);
+ return;
+ case 0x1: /* SQADD */
+ case 0x5: /* SQSUB */
+ case 0x8: /* SSHL, USHL */
+ case 0x9: /* SQSHL, UQSHL */
+ case 0xa: /* SRSHL, URSHL */
+ case 0xb: /* SQRSHL, UQRSHL */
+ if (size == 3 && !is_q) {
+ unallocated_encoding(s);
+ return;
+ }
+ unsupported_encoding(s, insn);
+ return;
+ case 0x16: /* SQDMULH, SQRDMULH */
+ if (size == 0 || size == 3) {
+ unallocated_encoding(s);
+ return;
+ }
+ unsupported_encoding(s, insn);
+ return;
+ default:
+ if (size == 3 && !is_q) {
+ unallocated_encoding(s);
+ return;
+ }
+ break;
+ }
+
+ if (size == 3) {
+ for (pass = 0; pass < (is_q ? 2 : 1); pass++) {
+ TCGv_i64 tcg_op1 = tcg_temp_new_i64();
+ TCGv_i64 tcg_op2 = tcg_temp_new_i64();
+ TCGv_i64 tcg_res = tcg_temp_new_i64();
+
+ read_vec_element(s, tcg_op1, rn, pass, MO_64);
+ read_vec_element(s, tcg_op2, rm, pass, MO_64);
+
+ handle_3same_64(s, opcode, u, tcg_res, tcg_op1, tcg_op2);
+
+ write_vec_element(s, tcg_res, rd, pass, MO_64);
+
+ tcg_temp_free_i64(tcg_res);
+ tcg_temp_free_i64(tcg_op1);
+ tcg_temp_free_i64(tcg_op2);
+ }
+ } else {
+ for (pass = 0; pass < (is_q ? 4 : 2); pass++) {
+ TCGv_i32 tcg_op1 = tcg_temp_new_i32();
+ TCGv_i32 tcg_op2 = tcg_temp_new_i32();
+ TCGv_i32 tcg_res = tcg_temp_new_i32();
+ NeonGenTwoOpFn *genfn;
+
+ read_vec_element_i32(s, tcg_op1, rn, pass, MO_32);
+ read_vec_element_i32(s, tcg_op2, rm, pass, MO_32);
+
+ switch (opcode) {
+ case 0x6: /* CMGT, CMHI */
+ {
+ static NeonGenTwoOpFn * const fns[3][2] = {
+ { gen_helper_neon_cgt_s8, gen_helper_neon_cgt_u8 },
+ { gen_helper_neon_cgt_s16, gen_helper_neon_cgt_u16 },
+ { gen_helper_neon_cgt_s32, gen_helper_neon_cgt_u32 },
+ };
+ genfn = fns[size][u];
+ break;
+ }
+ case 0x7: /* CMGE, CMHS */
+ {
+ static NeonGenTwoOpFn * const fns[3][2] = {
+ { gen_helper_neon_cge_s8, gen_helper_neon_cge_u8 },
+ { gen_helper_neon_cge_s16, gen_helper_neon_cge_u16 },
+ { gen_helper_neon_cge_s32, gen_helper_neon_cge_u32 },
+ };
+ genfn = fns[size][u];
+ break;
+ }
+ case 0x10: /* ADD, SUB */
+ {
+ static NeonGenTwoOpFn * const fns[3][2] = {
+ { gen_helper_neon_add_u8, gen_helper_neon_sub_u8 },
+ { gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
+ { tcg_gen_add_i32, tcg_gen_sub_i32 },
+ };
+ genfn = fns[size][u];
+ break;
+ }
+ case 0x11: /* CMTST, CMEQ */
+ {
+ static NeonGenTwoOpFn * const fns[3][2] = {
+ { gen_helper_neon_tst_u8, gen_helper_neon_ceq_u8 },
+ { gen_helper_neon_tst_u16, gen_helper_neon_ceq_u16 },
+ { gen_helper_neon_tst_u32, gen_helper_neon_ceq_u32 },
+ };
+ genfn = fns[size][u];
+ break;
+ }
+ default:
+ g_assert_not_reached();
+ }
+
+ genfn(tcg_res, tcg_op1, tcg_op2);
+
+ write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
+
+ tcg_temp_free_i32(tcg_res);
+ tcg_temp_free_i32(tcg_op1);
+ tcg_temp_free_i32(tcg_op2);
+ }
+ }
+
+ if (!is_q) {
+ clear_vec_high(s, rd);
+ }
}
/* C3.6.16 AdvSIMD three same
--
1.8.5
- [Qemu-devel] [PULL 16/38] target-arm: Add AArch32 FP VRINTA, VRINTN, VRINTP and VRINTM, (continued)
- [Qemu-devel] [PULL 16/38] target-arm: Add AArch32 FP VRINTA, VRINTN, VRINTP and VRINTM, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 33/38] linux-headers: Update from Linus' master ba635f8, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 09/38] target-arm: A64: Add SIMD modified immediate group, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 34/38] kvm: Introduce kvm_arch_irqchip_create, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 32/38] target-arm: A64: Add SIMD shift by immediate, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 24/38] target-arm: Add AArch32 SIMD VCVTA, VCVTN, VCVTP and VCVTM, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 27/38] target-arm: A64: Add SIMD scalar 3 same add, sub and compare ops, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 17/38] target-arm: Add support for AArch32 FP VRINTR, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 31/38] target-arm: A64: Add simple SIMD 3-same floating point ops, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 29/38] target-arm: A64: Add logic ops from SIMD 3 same group, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 30/38] target-arm: A64: Add integer ops from SIMD 3-same group,
Peter Maydell <=
- [Qemu-devel] [PULL 28/38] target-arm: A64: Add top level decode for SIMD 3-same group, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 18/38] target-arm: Add support for AArch32 FP VRINTZ, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 01/38] target-arm: A64: Add SIMD ld/st multiple, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 14/38] display: avoid multi-statement macro, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 13/38] ZYNQ: Implement board MIDR control for Zynq, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 19/38] target-arm: Add support for AArch32 FP VRINTX, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 21/38] target-arm: Add set_neon_rmode helper, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 26/38] target-arm: A64: Add SIMD three-different ABDL instructions, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 07/38] target-arm: A64: Add SIMD across-lanes instructions, Peter Maydell, 2014/01/29
- [Qemu-devel] [PULL 15/38] target-arm: Move arm_rmode_to_sf to a shared location., Peter Maydell, 2014/01/29