mirror of
https://github.com/qemu/qemu.git
synced 2024-11-24 19:33:39 +08:00
target/arm: Implement SVE Permute - Extract Group
Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20180516223007.10256-26-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
f25a236153
commit
b94f8f60bd
@ -414,6 +414,8 @@ DEF_HELPER_FLAGS_4(sve_cpy_z_h, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_cpy_z_s, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
DEF_HELPER_FLAGS_4(sve_cpy_z_d, TCG_CALL_NO_RWG, void, ptr, ptr, i64, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_4(sve_ext, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_5(sve_and_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_5(sve_bic_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_5(sve_eor_pppp, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
%imm4_16_p1 16:4 !function=plus1
|
||||
%imm6_22_5 22:1 5:5
|
||||
%imm8_16_10 16:5 10:3
|
||||
%imm9_16_10 16:s6 10:3
|
||||
|
||||
# A combination of tsz:imm3 -- extract esize.
|
||||
@ -362,6 +363,12 @@ FCPY 00000101 .. 01 .... 110 imm:8 ..... @rdn_pg4
|
||||
CPY_m_i 00000101 .. 01 .... 01 . ........ ..... @rdn_pg4 imm=%sh8_i8s
|
||||
CPY_z_i 00000101 .. 01 .... 00 . ........ ..... @rdn_pg4 imm=%sh8_i8s
|
||||
|
||||
### SVE Permute - Extract Group
|
||||
|
||||
# SVE extract vector (immediate offset)
|
||||
EXT 00000101 001 ..... 000 ... rm:5 rd:5 \
|
||||
&rrri rn=%reg_movprfx imm=%imm8_16_10
|
||||
|
||||
### SVE Predicate Logical Operations Group
|
||||
|
||||
# SVE predicate logical operations
|
||||
|
@ -1479,3 +1479,84 @@ void HELPER(sve_cpy_z_d)(void *vd, void *vg, uint64_t val, uint32_t desc)
|
||||
d[i] = (pg[H1(i)] & 1 ? val : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Big-endian hosts need to frob the byte indicies. If the copy
|
||||
* happens to be 8-byte aligned, then no frobbing necessary.
|
||||
*/
|
||||
static void swap_memmove(void *vd, void *vs, size_t n)
|
||||
{
|
||||
uintptr_t d = (uintptr_t)vd;
|
||||
uintptr_t s = (uintptr_t)vs;
|
||||
uintptr_t o = (d | s | n) & 7;
|
||||
size_t i;
|
||||
|
||||
#ifndef HOST_WORDS_BIGENDIAN
|
||||
o = 0;
|
||||
#endif
|
||||
switch (o) {
|
||||
case 0:
|
||||
memmove(vd, vs, n);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (d < s || d >= s + n) {
|
||||
for (i = 0; i < n; i += 4) {
|
||||
*(uint32_t *)H1_4(d + i) = *(uint32_t *)H1_4(s + i);
|
||||
}
|
||||
} else {
|
||||
for (i = n; i > 0; ) {
|
||||
i -= 4;
|
||||
*(uint32_t *)H1_4(d + i) = *(uint32_t *)H1_4(s + i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 6:
|
||||
if (d < s || d >= s + n) {
|
||||
for (i = 0; i < n; i += 2) {
|
||||
*(uint16_t *)H1_2(d + i) = *(uint16_t *)H1_2(s + i);
|
||||
}
|
||||
} else {
|
||||
for (i = n; i > 0; ) {
|
||||
i -= 2;
|
||||
*(uint16_t *)H1_2(d + i) = *(uint16_t *)H1_2(s + i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (d < s || d >= s + n) {
|
||||
for (i = 0; i < n; i++) {
|
||||
*(uint8_t *)H1(d + i) = *(uint8_t *)H1(s + i);
|
||||
}
|
||||
} else {
|
||||
for (i = n; i > 0; ) {
|
||||
i -= 1;
|
||||
*(uint8_t *)H1(d + i) = *(uint8_t *)H1(s + i);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HELPER(sve_ext)(void *vd, void *vn, void *vm, uint32_t desc)
|
||||
{
|
||||
intptr_t opr_sz = simd_oprsz(desc);
|
||||
size_t n_ofs = simd_data(desc);
|
||||
size_t n_siz = opr_sz - n_ofs;
|
||||
|
||||
if (vd != vm) {
|
||||
swap_memmove(vd, vn + n_ofs, n_siz);
|
||||
swap_memmove(vd + n_siz, vm, n_ofs);
|
||||
} else if (vd != vn) {
|
||||
swap_memmove(vd + n_siz, vd, n_ofs);
|
||||
swap_memmove(vd, vn + n_ofs, n_siz);
|
||||
} else {
|
||||
/* vd == vn == vm. Need temp space. */
|
||||
ARMVectorReg tmp;
|
||||
swap_memmove(&tmp, vm, n_ofs);
|
||||
swap_memmove(vd, vd + n_ofs, n_siz);
|
||||
memcpy(vd + n_siz, &tmp, n_ofs);
|
||||
}
|
||||
}
|
||||
|
@ -1922,6 +1922,40 @@ static bool trans_CPY_z_i(DisasContext *s, arg_CPY_z_i *a, uint32_t insn)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
*** SVE Permute Extract Group
|
||||
*/
|
||||
|
||||
static bool trans_EXT(DisasContext *s, arg_EXT *a, uint32_t insn)
|
||||
{
|
||||
if (!sve_access_check(s)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned vsz = vec_full_reg_size(s);
|
||||
unsigned n_ofs = a->imm >= vsz ? 0 : a->imm;
|
||||
unsigned n_siz = vsz - n_ofs;
|
||||
unsigned d = vec_full_reg_offset(s, a->rd);
|
||||
unsigned n = vec_full_reg_offset(s, a->rn);
|
||||
unsigned m = vec_full_reg_offset(s, a->rm);
|
||||
|
||||
/* Use host vector move insns if we have appropriate sizes
|
||||
* and no unfortunate overlap.
|
||||
*/
|
||||
if (m != d
|
||||
&& n_ofs == size_for_gvec(n_ofs)
|
||||
&& n_siz == size_for_gvec(n_siz)
|
||||
&& (d != n || n_siz <= n_ofs)) {
|
||||
tcg_gen_gvec_mov(0, d, n + n_ofs, n_siz, n_siz);
|
||||
if (n_ofs != 0) {
|
||||
tcg_gen_gvec_mov(0, d + n_siz, m, n_ofs, n_ofs);
|
||||
}
|
||||
} else {
|
||||
tcg_gen_gvec_3_ool(d, n, m, vsz, vsz, n_ofs, gen_helper_sve_ext);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
*** SVE Memory - 32-bit Gather and Unsized Contiguous Group
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user