From 72bcbbabb0295dbc47300702d4358d4cb9ecf5a9 Mon Sep 17 00:00:00 2001 From: Denis Drakhnya Date: Wed, 2 Dec 2020 20:38:14 +0200 Subject: [PATCH] target: e2k: Add pshufb instr. --- target/e2k/cpu.c | 2 +- target/e2k/helper.h | 1 + target/e2k/helper_vec.c | 89 ++++++++++++++++++++++++++++++++++++++ target/e2k/meson.build | 1 + target/e2k/translate/alc.c | 21 +++++++++ 5 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 target/e2k/helper_vec.c diff --git a/target/e2k/cpu.c b/target/e2k/cpu.c index fa95f4a4b5..a29c5a86f5 100644 --- a/target/e2k/cpu.c +++ b/target/e2k/cpu.c @@ -94,7 +94,7 @@ void cpu_e2k_set_id(CPUE2KState *env, unsigned int cpu) static const struct e2k_def_t e2k_defs[] = { { .name = "any", - .isa_version = 0xffffffff, + .isa_version = 4, } }; diff --git a/target/e2k/helper.h b/target/e2k/helper.h index b1f45103bb..ae10b2fa09 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -15,3 +15,4 @@ DEF_HELPER_1(break_restore_state, void, env) DEF_HELPER_2(setwd, void, env, i32) DEF_HELPER_2(probe_read_access, int, env, tl) DEF_HELPER_2(probe_write_access, int, env, tl) +DEF_HELPER_3(packed_shuffle_i64, i64, i64, i64, i64) diff --git a/target/e2k/helper_vec.c b/target/e2k/helper_vec.c new file mode 100644 index 0000000000..7700db564f --- /dev/null +++ b/target/e2k/helper_vec.c @@ -0,0 +1,89 @@ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "cpu.h" +#include "exec/exec-all.h" +#include "qemu/host-utils.h" +#include "exec/helper-proto.h" +#include "translate.h" + +static uint8_t reverse_bits(uint8_t b) +{ + b = ((b & 0xf0) >> 4) | ((b & 0x0f) << 4); + b = ((b & 0xcc) >> 2) | ((b & 0x33) << 2); + b = ((b & 0xaa) >> 1) | ((b & 0x55) << 1); + return b; +} + +typedef union { + uint64_t n; + uint8_t s[8]; +} u8x8; + +uint64_t HELPER(packed_shuffle_i64)(uint64_t src1, uint64_t src2, uint64_t src3) +{ + u8x8 ret, s1, s2, s3; + unsigned int i; + + s1.n = src1; + s2.n = src2; + s3.n = src3; + + for (i = 0; i < 8; i++) { + uint8_t desc = s3.s[i]; + int index = extract8(desc, 0, 3); + uint8_t byte; + + if (desc < 0x80) { + if (desc & 0x08) { + byte = s1.s[index]; + } else { + byte = s2.s[index]; + } + + switch(desc >> 5) { + case 0x1: + byte = reverse_bits(byte); + break; + case 0x2: + if ((byte & 0x80) != 0) { + byte = 0xff; + } else { + byte = 0; + } + break; + case 0x3: + if ((byte & 1) != 0) { + byte = 0xff; + } else { + byte = 0; + } + break; + default: + break; + } + + if (desc & 0x10) { + byte = ~byte; + } + } else { + switch(desc >> 6) { + case 0xa: + byte = 0x7f; + break; + case 0xc: + byte = 0x80; + break; + case 0xe: + byte = 0xff; + break; + default: + byte = 0; + break; + } + } + + ret.s[i] = byte; + } + + return ret.n; +} diff --git a/target/e2k/meson.build b/target/e2k/meson.build index 2cd476164c..6eb1ed13d1 100644 --- a/target/e2k/meson.build +++ b/target/e2k/meson.build @@ -5,6 +5,7 @@ e2k_ss.add(files( 'helper.c', 'helper_int.c', 'helper_sm.c', + 'helper_vec.c', 'translate.c', 'translate/state.c', 'translate/control.c', diff --git a/target/e2k/translate/alc.c b/target/e2k/translate/alc.c index 4d47de7410..8703953072 100644 --- a/target/e2k/translate/alc.c +++ b/target/e2k/translate/alc.c @@ -1530,6 +1530,24 @@ static void execute_ext_0b(DisasContext *ctx, int chan) } } +static void execute_ext_0f(DisasContext *ctx, int chan) +{ + uint8_t opc = GET_FIELD(ctx->bundle.als[chan], 24, 7); + + switch(opc) { + case 0x4d: + if (is_cmp_chan(chan) && ctx->version >= 2) { + gen_alopf21_i64(ctx, chan, gen_helper_packed_shuffle_i64); /* pshufb */ + } else { + e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC); + } + break; + default: + e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC); + break; + } +} + void e2k_alc_execute(DisasContext *ctx, int chan) { const UnpackedBundle *bundle = &ctx->bundle; @@ -1566,6 +1584,9 @@ void e2k_alc_execute(DisasContext *ctx, int chan) case 0x0b: execute_ext_0b(ctx, chan); break; + case 0x0f: + execute_ext_0f(ctx, chan); + break; default: e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC); break;