diff options
author | Juha Riihimäki <juha.riihimaki@nokia.com> | 2011-02-09 15:42:32 +0000 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2011-02-09 19:37:47 +0100 |
commit | af1bbf30c407cb194599a4e1724c38c7bf1d94b3 (patch) | |
tree | 3045df15e10ee27f990baad363d5763469df4e5f /target-arm/translate.c | |
parent | c0c1dc992584b8ccbae0e8f8b09124b76662633b (diff) |
target-arm: Fix VQMOVUN Neon instruction.
VQMOVUN does a signed-to-unsigned saturating conversion. This is
different from both the signed-to-signed and unsigned-to-unsigned
conversions already implemented, so we need a new set of helper
functions (neon_unarrow_sat*).
Signed-off-by: Juha Riihimäki <juha.riihimaki@nokia.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'target-arm/translate.c')
-rw-r--r-- | target-arm/translate.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c index e4649e6d54..89c916d3bc 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -4065,6 +4065,16 @@ static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src) } } +static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src) +{ + switch (size) { + case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break; + case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break; + case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break; + default: abort(); + } +} + static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift, int q, int u) { @@ -5461,12 +5471,18 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) for (pass = 0; pass < 2; pass++) { neon_load_reg64(cpu_V0, rm + pass); tmp = new_tmp(); - if (op == 36 && q == 0) { - gen_neon_narrow(size, tmp, cpu_V0); - } else if (q) { - gen_neon_narrow_satu(size, tmp, cpu_V0); - } else { - gen_neon_narrow_sats(size, tmp, cpu_V0); + if (op == 36) { + if (q) { /* VQMOVUN */ + gen_neon_unarrow_sats(size, tmp, cpu_V0); + } else { /* VMOVN */ + gen_neon_narrow(size, tmp, cpu_V0); + } + } else { /* VQMOVN */ + if (q) { + gen_neon_narrow_satu(size, tmp, cpu_V0); + } else { + gen_neon_narrow_sats(size, tmp, cpu_V0); + } } if (pass == 0) { tmp2 = tmp; |