1 /* 2 * QEMU TCG support -- s390x vector utilitites 3 * 4 * Copyright (C) 2019 Red Hat Inc 5 * 6 * Authors: 7 * David Hildenbrand <david@redhat.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 #ifndef S390X_VEC_H 13 #define S390X_VEC_H 14 15 #include "tcg/tcg.h" 16 17 typedef union S390Vector { 18 uint64_t doubleword[2]; 19 uint32_t word[4]; 20 uint16_t halfword[8]; 21 uint8_t byte[16]; 22 } S390Vector; 23 24 /* 25 * Each vector is stored as two 64bit host values. So when talking about 26 * byte/halfword/word numbers, we have to take care of proper translation 27 * between element numbers. 28 * 29 * Big Endian (target/possible host) 30 * B: [ 0][ 1][ 2][ 3][ 4][ 5][ 6][ 7] - [ 8][ 9][10][11][12][13][14][15] 31 * HW: [ 0][ 1][ 2][ 3] - [ 4][ 5][ 6][ 7] 32 * W: [ 0][ 1] - [ 2][ 3] 33 * DW: [ 0] - [ 1] 34 * 35 * Little Endian (possible host) 36 * B: [ 7][ 6][ 5][ 4][ 3][ 2][ 1][ 0] - [15][14][13][12][11][10][ 9][ 8] 37 * HW: [ 3][ 2][ 1][ 0] - [ 7][ 6][ 5][ 4] 38 * W: [ 1][ 0] - [ 3][ 2] 39 * DW: [ 0] - [ 1] 40 */ 41 #if !HOST_BIG_ENDIAN 42 #define H1(x) ((x) ^ 7) 43 #define H2(x) ((x) ^ 3) 44 #define H4(x) ((x) ^ 1) 45 #else 46 #define H1(x) (x) 47 #define H2(x) (x) 48 #define H4(x) (x) 49 #endif 50 51 static inline uint8_t s390_vec_read_element8(const S390Vector *v, uint8_t enr) 52 { 53 g_assert(enr < 16); 54 return v->byte[H1(enr)]; 55 } 56 57 static inline uint16_t s390_vec_read_element16(const S390Vector *v, uint8_t enr) 58 { 59 g_assert(enr < 8); 60 return v->halfword[H2(enr)]; 61 } 62 63 static inline uint32_t s390_vec_read_element32(const S390Vector *v, uint8_t enr) 64 { 65 g_assert(enr < 4); 66 return v->word[H4(enr)]; 67 } 68 69 static inline uint64_t s390_vec_read_element64(const S390Vector *v, uint8_t enr) 70 { 71 g_assert(enr < 2); 72 return v->doubleword[enr]; 73 } 74 75 static inline uint64_t s390_vec_read_element(const S390Vector *v, uint8_t enr, 76 uint8_t es) 77 { 78 switch (es) { 79 case MO_8: 80 return s390_vec_read_element8(v, enr); 81 case MO_16: 82 return s390_vec_read_element16(v, enr); 83 case MO_32: 84 return s390_vec_read_element32(v, enr); 85 case MO_64: 86 return s390_vec_read_element64(v, enr); 87 default: 88 g_assert_not_reached(); 89 } 90 } 91 92 static inline void s390_vec_write_element8(S390Vector *v, uint8_t enr, 93 uint8_t data) 94 { 95 g_assert(enr < 16); 96 v->byte[H1(enr)] = data; 97 } 98 99 static inline void s390_vec_write_element16(S390Vector *v, uint8_t enr, 100 uint16_t data) 101 { 102 g_assert(enr < 8); 103 v->halfword[H2(enr)] = data; 104 } 105 106 static inline void s390_vec_write_element32(S390Vector *v, uint8_t enr, 107 uint32_t data) 108 { 109 g_assert(enr < 4); 110 v->word[H4(enr)] = data; 111 } 112 113 static inline void s390_vec_write_element64(S390Vector *v, uint8_t enr, 114 uint64_t data) 115 { 116 g_assert(enr < 2); 117 v->doubleword[enr] = data; 118 } 119 120 static inline void s390_vec_write_element(S390Vector *v, uint8_t enr, 121 uint8_t es, uint64_t data) 122 { 123 switch (es) { 124 case MO_8: 125 s390_vec_write_element8(v, enr, data); 126 break; 127 case MO_16: 128 s390_vec_write_element16(v, enr, data); 129 break; 130 case MO_32: 131 s390_vec_write_element32(v, enr, data); 132 break; 133 case MO_64: 134 s390_vec_write_element64(v, enr, data); 135 break; 136 default: 137 g_assert_not_reached(); 138 } 139 } 140 141 #endif /* S390X_VEC_H */ 142