mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 00:03:54 -06:00
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>
This commit is contained in:
parent
c0c1dc9925
commit
af1bbf30c4
3 changed files with 88 additions and 6 deletions
|
@ -1053,6 +1053,33 @@ uint32_t HELPER(neon_narrow_round_high_u16)(uint64_t x)
|
|||
return ((x >> 16) & 0xffff) | ((x >> 32) & 0xffff0000);
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_unarrow_sat8)(CPUState *env, uint64_t x)
|
||||
{
|
||||
uint16_t s;
|
||||
uint8_t d;
|
||||
uint32_t res = 0;
|
||||
#define SAT8(n) \
|
||||
s = x >> n; \
|
||||
if (s & 0x8000) { \
|
||||
SET_QC(); \
|
||||
} else { \
|
||||
if (s > 0xff) { \
|
||||
d = 0xff; \
|
||||
SET_QC(); \
|
||||
} else { \
|
||||
d = s; \
|
||||
} \
|
||||
res |= (uint32_t)d << (n / 2); \
|
||||
}
|
||||
|
||||
SAT8(0);
|
||||
SAT8(16);
|
||||
SAT8(32);
|
||||
SAT8(48);
|
||||
#undef SAT8
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_narrow_sat_u8)(CPUState *env, uint64_t x)
|
||||
{
|
||||
uint16_t s;
|
||||
|
@ -1099,6 +1126,29 @@ uint32_t HELPER(neon_narrow_sat_s8)(CPUState *env, uint64_t x)
|
|||
return res;
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_unarrow_sat16)(CPUState *env, uint64_t x)
|
||||
{
|
||||
uint32_t high;
|
||||
uint32_t low;
|
||||
low = x;
|
||||
if (low & 0x80000000) {
|
||||
low = 0;
|
||||
SET_QC();
|
||||
} else if (low > 0xffff) {
|
||||
low = 0xffff;
|
||||
SET_QC();
|
||||
}
|
||||
high = x >> 32;
|
||||
if (high & 0x80000000) {
|
||||
high = 0;
|
||||
SET_QC();
|
||||
} else if (high > 0xffff) {
|
||||
high = 0xffff;
|
||||
SET_QC();
|
||||
}
|
||||
return low | (high << 16);
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_narrow_sat_u16)(CPUState *env, uint64_t x)
|
||||
{
|
||||
uint32_t high;
|
||||
|
@ -1133,6 +1183,19 @@ uint32_t HELPER(neon_narrow_sat_s16)(CPUState *env, uint64_t x)
|
|||
return (uint16_t)low | (high << 16);
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_unarrow_sat32)(CPUState *env, uint64_t x)
|
||||
{
|
||||
if (x & 0x8000000000000000ull) {
|
||||
SET_QC();
|
||||
return 0;
|
||||
}
|
||||
if (x > 0xffffffffu) {
|
||||
SET_QC();
|
||||
return 0xffffffffu;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
uint32_t HELPER(neon_narrow_sat_u32)(CPUState *env, uint64_t x)
|
||||
{
|
||||
if (x > 0xffffffffu) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue