| /* |
| * 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] |
| */ |
| #if !HOST_BIG_ENDIAN |
| #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 */ |