mirror of
https://github.com/qemu/qemu.git
synced 2024-12-14 15:03:33 +08:00
13b0228f77
Unfortunately, there is no easy way to avoid looping over all elements in v2. Provide specialized variants for !cc,!rt/!cc,rt/cc,!rt/cc,rt and all element types. Especially for different values of rt, the compiler might be able to optimize the code a lot. Add s390_vec_write_element(). Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: David Hildenbrand <david@redhat.com>
142 lines
3.8 KiB
C
142 lines
3.8 KiB
C
/*
|
|
* QEMU TCG support -- s390x vector utilitites
|
|
*
|
|
* Copyright (C) 2019 Red Hat Inc
|
|
*
|
|
* Authors:
|
|
* David Hildenbrand <david@redhat.com>
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
* See the COPYING file in the top-level directory.
|
|
*/
|
|
#ifndef S390X_VEC_H
|
|
#define S390X_VEC_H
|
|
|
|
#include "tcg/tcg.h"
|
|
|
|
typedef union S390Vector {
|
|
uint64_t doubleword[2];
|
|
uint32_t word[4];
|
|
uint16_t halfword[8];
|
|
uint8_t byte[16];
|
|
} S390Vector;
|
|
|
|
/*
|
|
* Each vector is stored as two 64bit host values. So when talking about
|
|
* byte/halfword/word numbers, we have to take care of proper translation
|
|
* between element numbers.
|
|
*
|
|
* Big Endian (target/possible host)
|
|
* B: [ 0][ 1][ 2][ 3][ 4][ 5][ 6][ 7] - [ 8][ 9][10][11][12][13][14][15]
|
|
* HW: [ 0][ 1][ 2][ 3] - [ 4][ 5][ 6][ 7]
|
|
* W: [ 0][ 1] - [ 2][ 3]
|
|
* DW: [ 0] - [ 1]
|
|
*
|
|
* Little Endian (possible host)
|
|
* B: [ 7][ 6][ 5][ 4][ 3][ 2][ 1][ 0] - [15][14][13][12][11][10][ 9][ 8]
|
|
* HW: [ 3][ 2][ 1][ 0] - [ 7][ 6][ 5][ 4]
|
|
* W: [ 1][ 0] - [ 3][ 2]
|
|
* DW: [ 0] - [ 1]
|
|
*/
|
|
#ifndef HOST_WORDS_BIGENDIAN
|
|
#define H1(x) ((x) ^ 7)
|
|
#define H2(x) ((x) ^ 3)
|
|
#define H4(x) ((x) ^ 1)
|
|
#else
|
|
#define H1(x) (x)
|
|
#define H2(x) (x)
|
|
#define H4(x) (x)
|
|
#endif
|
|
|
|
static inline uint8_t s390_vec_read_element8(const S390Vector *v, uint8_t enr)
|
|
{
|
|
g_assert(enr < 16);
|
|
return v->byte[H1(enr)];
|
|
}
|
|
|
|
static inline uint16_t s390_vec_read_element16(const S390Vector *v, uint8_t enr)
|
|
{
|
|
g_assert(enr < 8);
|
|
return v->halfword[H2(enr)];
|
|
}
|
|
|
|
static inline uint32_t s390_vec_read_element32(const S390Vector *v, uint8_t enr)
|
|
{
|
|
g_assert(enr < 4);
|
|
return v->word[H4(enr)];
|
|
}
|
|
|
|
static inline uint64_t s390_vec_read_element64(const S390Vector *v, uint8_t enr)
|
|
{
|
|
g_assert(enr < 2);
|
|
return v->doubleword[enr];
|
|
}
|
|
|
|
static inline uint64_t s390_vec_read_element(const S390Vector *v, uint8_t enr,
|
|
uint8_t es)
|
|
{
|
|
switch (es) {
|
|
case MO_8:
|
|
return s390_vec_read_element8(v, enr);
|
|
case MO_16:
|
|
return s390_vec_read_element16(v, enr);
|
|
case MO_32:
|
|
return s390_vec_read_element32(v, enr);
|
|
case MO_64:
|
|
return s390_vec_read_element64(v, enr);
|
|
default:
|
|
g_assert_not_reached();
|
|
}
|
|
}
|
|
|
|
static inline void s390_vec_write_element8(S390Vector *v, uint8_t enr,
|
|
uint8_t data)
|
|
{
|
|
g_assert(enr < 16);
|
|
v->byte[H1(enr)] = data;
|
|
}
|
|
|
|
static inline void s390_vec_write_element16(S390Vector *v, uint8_t enr,
|
|
uint16_t data)
|
|
{
|
|
g_assert(enr < 8);
|
|
v->halfword[H2(enr)] = data;
|
|
}
|
|
|
|
static inline void s390_vec_write_element32(S390Vector *v, uint8_t enr,
|
|
uint32_t data)
|
|
{
|
|
g_assert(enr < 4);
|
|
v->word[H4(enr)] = data;
|
|
}
|
|
|
|
static inline void s390_vec_write_element64(S390Vector *v, uint8_t enr,
|
|
uint64_t data)
|
|
{
|
|
g_assert(enr < 2);
|
|
v->doubleword[enr] = data;
|
|
}
|
|
|
|
static inline void s390_vec_write_element(S390Vector *v, uint8_t enr,
|
|
uint8_t es, uint64_t data)
|
|
{
|
|
switch (es) {
|
|
case MO_8:
|
|
s390_vec_write_element8(v, enr, data);
|
|
break;
|
|
case MO_16:
|
|
s390_vec_write_element16(v, enr, data);
|
|
break;
|
|
case MO_32:
|
|
s390_vec_write_element32(v, enr, data);
|
|
break;
|
|
case MO_64:
|
|
s390_vec_write_element64(v, enr, data);
|
|
break;
|
|
default:
|
|
g_assert_not_reached();
|
|
}
|
|
}
|
|
|
|
#endif /* S390X_VEC_H */
|