tcg: Adjust simd_desc size encoding
With larger vector sizes, it turns out oprsz == maxsz, and we only need to represent mismatch for oprsz <= 32. We do, however, need to represent larger oprsz and do so without reducing SIMD_DATA_BITS. Reduce the size of the oprsz field and increase the maxsz field. Steal the oprsz value of 24 to indicate equality with maxsz. Tested-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
6eeea6725a
commit
e2e7168a21
@ -20,29 +20,41 @@
|
|||||||
#ifndef TCG_TCG_GVEC_DESC_H
|
#ifndef TCG_TCG_GVEC_DESC_H
|
||||||
#define TCG_TCG_GVEC_DESC_H
|
#define TCG_TCG_GVEC_DESC_H
|
||||||
|
|
||||||
/* ??? These bit widths are set for ARM SVE, maxing out at 256 byte vectors. */
|
/*
|
||||||
#define SIMD_OPRSZ_SHIFT 0
|
* This configuration allows MAXSZ to represent 2048 bytes, and
|
||||||
#define SIMD_OPRSZ_BITS 5
|
* OPRSZ to match MAXSZ, or represent the smaller values 8, 16, or 32.
|
||||||
|
*
|
||||||
|
* Encode this with:
|
||||||
|
* 0, 1, 3 -> 8, 16, 32
|
||||||
|
* 2 -> maxsz
|
||||||
|
*
|
||||||
|
* This steals the input that would otherwise map to 24 to match maxsz.
|
||||||
|
*/
|
||||||
|
#define SIMD_MAXSZ_SHIFT 0
|
||||||
|
#define SIMD_MAXSZ_BITS 8
|
||||||
|
|
||||||
#define SIMD_MAXSZ_SHIFT (SIMD_OPRSZ_SHIFT + SIMD_OPRSZ_BITS)
|
#define SIMD_OPRSZ_SHIFT (SIMD_MAXSZ_SHIFT + SIMD_MAXSZ_BITS)
|
||||||
#define SIMD_MAXSZ_BITS 5
|
#define SIMD_OPRSZ_BITS 2
|
||||||
|
|
||||||
#define SIMD_DATA_SHIFT (SIMD_MAXSZ_SHIFT + SIMD_MAXSZ_BITS)
|
#define SIMD_DATA_SHIFT (SIMD_OPRSZ_SHIFT + SIMD_OPRSZ_BITS)
|
||||||
#define SIMD_DATA_BITS (32 - SIMD_DATA_SHIFT)
|
#define SIMD_DATA_BITS (32 - SIMD_DATA_SHIFT)
|
||||||
|
|
||||||
/* Create a descriptor from components. */
|
/* Create a descriptor from components. */
|
||||||
uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data);
|
uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data);
|
||||||
|
|
||||||
/* Extract the operation size from a descriptor. */
|
|
||||||
static inline intptr_t simd_oprsz(uint32_t desc)
|
|
||||||
{
|
|
||||||
return (extract32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS) + 1) * 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Extract the max vector size from a descriptor. */
|
/* Extract the max vector size from a descriptor. */
|
||||||
static inline intptr_t simd_maxsz(uint32_t desc)
|
static inline intptr_t simd_maxsz(uint32_t desc)
|
||||||
{
|
{
|
||||||
return (extract32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS) + 1) * 8;
|
return extract32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS) * 8 + 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extract the operation size from a descriptor. */
|
||||||
|
static inline intptr_t simd_oprsz(uint32_t desc)
|
||||||
|
{
|
||||||
|
uint32_t f = extract32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS);
|
||||||
|
intptr_t o = f * 8 + 8;
|
||||||
|
intptr_t m = simd_maxsz(desc);
|
||||||
|
return f == 2 ? m : o;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Extract the operation-specific data from a descriptor. */
|
/* Extract the operation-specific data from a descriptor. */
|
||||||
|
@ -37,11 +37,21 @@ static const TCGOpcode vecop_list_empty[1] = { 0 };
|
|||||||
of the operand offsets so that we can check them all at once. */
|
of the operand offsets so that we can check them all at once. */
|
||||||
static void check_size_align(uint32_t oprsz, uint32_t maxsz, uint32_t ofs)
|
static void check_size_align(uint32_t oprsz, uint32_t maxsz, uint32_t ofs)
|
||||||
{
|
{
|
||||||
uint32_t opr_align = oprsz >= 16 ? 15 : 7;
|
uint32_t max_align;
|
||||||
uint32_t max_align = maxsz >= 16 || oprsz >= 16 ? 15 : 7;
|
|
||||||
tcg_debug_assert(oprsz > 0);
|
switch (oprsz) {
|
||||||
tcg_debug_assert(oprsz <= maxsz);
|
case 8:
|
||||||
tcg_debug_assert((oprsz & opr_align) == 0);
|
case 16:
|
||||||
|
case 32:
|
||||||
|
tcg_debug_assert(oprsz <= maxsz);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tcg_debug_assert(oprsz == maxsz);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tcg_debug_assert(maxsz <= (8 << SIMD_MAXSZ_BITS));
|
||||||
|
|
||||||
|
max_align = maxsz >= 16 ? 15 : 7;
|
||||||
tcg_debug_assert((maxsz & max_align) == 0);
|
tcg_debug_assert((maxsz & max_align) == 0);
|
||||||
tcg_debug_assert((ofs & max_align) == 0);
|
tcg_debug_assert((ofs & max_align) == 0);
|
||||||
}
|
}
|
||||||
@ -77,12 +87,21 @@ uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data)
|
|||||||
{
|
{
|
||||||
uint32_t desc = 0;
|
uint32_t desc = 0;
|
||||||
|
|
||||||
assert(oprsz % 8 == 0 && oprsz <= (8 << SIMD_OPRSZ_BITS));
|
check_size_align(oprsz, maxsz, 0);
|
||||||
assert(maxsz % 8 == 0 && maxsz <= (8 << SIMD_MAXSZ_BITS));
|
tcg_debug_assert(data == sextract32(data, 0, SIMD_DATA_BITS));
|
||||||
assert(data == sextract32(data, 0, SIMD_DATA_BITS));
|
|
||||||
|
|
||||||
oprsz = (oprsz / 8) - 1;
|
oprsz = (oprsz / 8) - 1;
|
||||||
maxsz = (maxsz / 8) - 1;
|
maxsz = (maxsz / 8) - 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have just asserted in check_size_align that either
|
||||||
|
* oprsz is {8,16,32} or matches maxsz. Encode the final
|
||||||
|
* case with '2', as that would otherwise map to 24.
|
||||||
|
*/
|
||||||
|
if (oprsz == maxsz) {
|
||||||
|
oprsz = 2;
|
||||||
|
}
|
||||||
|
|
||||||
desc = deposit32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS, oprsz);
|
desc = deposit32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS, oprsz);
|
||||||
desc = deposit32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS, maxsz);
|
desc = deposit32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS, maxsz);
|
||||||
desc = deposit32(desc, SIMD_DATA_SHIFT, SIMD_DATA_BITS, data);
|
desc = deposit32(desc, SIMD_DATA_SHIFT, SIMD_DATA_BITS, data);
|
||||||
|
Loading…
Reference in New Issue
Block a user