summaryrefslogtreecommitdiff
path: root/target-arm/translate-a64.c
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2014-01-31 14:47:31 +0000
committerPeter Maydell <peter.maydell@linaro.org>2014-01-31 14:47:31 +0000
commit7c51048fa918f64806adf0f76166e9940d772eb1 (patch)
tree7e1d5e1e727565a1c5b8d6368879f6c679f1b3d8 /target-arm/translate-a64.c
parent5c73747f3cc29471f9fbfe630ef15902e65f53b3 (diff)
downloadqemu-7c51048fa918f64806adf0f76166e9940d772eb1.tar.gz
target-arm: A64: Add SIMD TBL/TBLX
Add support for the SIMD TBL/TBLX instructions (group C3.6.2). Signed-off-by: Michael Matz <matz@suse.de> [PMM: rewritten to do more of the decode in translate-a64.c, and to do only one 64 bit pass at a time in the helper] Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'target-arm/translate-a64.c')
-rw-r--r--target-arm/translate-a64.c55
1 files changed, 54 insertions, 1 deletions
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index 75b00392bc..7a6b00a938 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -4742,7 +4742,60 @@ static void disas_simd_ext(DisasContext *s, uint32_t insn)
*/
static void disas_simd_tb(DisasContext *s, uint32_t insn)
{
- unsupported_encoding(s, insn);
+ int op2 = extract32(insn, 22, 2);
+ int is_q = extract32(insn, 30, 1);
+ int rm = extract32(insn, 16, 5);
+ int rn = extract32(insn, 5, 5);
+ int rd = extract32(insn, 0, 5);
+ int is_tblx = extract32(insn, 12, 1);
+ int len = extract32(insn, 13, 2);
+ TCGv_i64 tcg_resl, tcg_resh, tcg_idx;
+ TCGv_i32 tcg_regno, tcg_numregs;
+
+ if (op2 != 0) {
+ unallocated_encoding(s);
+ return;
+ }
+
+ /* This does a table lookup: for every byte element in the input
+ * we index into a table formed from up to four vector registers,
+ * and then the output is the result of the lookups. Our helper
+ * function does the lookup operation for a single 64 bit part of
+ * the input.
+ */
+ tcg_resl = tcg_temp_new_i64();
+ tcg_resh = tcg_temp_new_i64();
+
+ if (is_tblx) {
+ read_vec_element(s, tcg_resl, rd, 0, MO_64);
+ } else {
+ tcg_gen_movi_i64(tcg_resl, 0);
+ }
+ if (is_tblx && is_q) {
+ read_vec_element(s, tcg_resh, rd, 1, MO_64);
+ } else {
+ tcg_gen_movi_i64(tcg_resh, 0);
+ }
+
+ tcg_idx = tcg_temp_new_i64();
+ tcg_regno = tcg_const_i32(rn);
+ tcg_numregs = tcg_const_i32(len + 1);
+ read_vec_element(s, tcg_idx, rm, 0, MO_64);
+ gen_helper_simd_tbl(tcg_resl, cpu_env, tcg_resl, tcg_idx,
+ tcg_regno, tcg_numregs);
+ if (is_q) {
+ read_vec_element(s, tcg_idx, rm, 1, MO_64);
+ gen_helper_simd_tbl(tcg_resh, cpu_env, tcg_resh, tcg_idx,
+ tcg_regno, tcg_numregs);
+ }
+ tcg_temp_free_i64(tcg_idx);
+ tcg_temp_free_i32(tcg_regno);
+ tcg_temp_free_i32(tcg_numregs);
+
+ write_vec_element(s, tcg_resl, rd, 0, MO_64);
+ tcg_temp_free_i64(tcg_resl);
+ write_vec_element(s, tcg_resh, rd, 1, MO_64);
+ tcg_temp_free_i64(tcg_resh);
}
/* C3.6.3 ZIP/UZP/TRN