vec_helper.c (10089B)
1/* 2 * QEMU TCG support -- s390x vector support instructions 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#include "qemu/osdep.h" 13#include "cpu.h" 14#include "s390x-internal.h" 15#include "vec.h" 16#include "tcg/tcg.h" 17#include "tcg/tcg-gvec-desc.h" 18#include "exec/helper-proto.h" 19#include "exec/cpu_ldst.h" 20#include "exec/exec-all.h" 21 22void HELPER(gvec_vbperm)(void *v1, const void *v2, const void *v3, 23 uint32_t desc) 24{ 25 S390Vector tmp = {}; 26 uint16_t result = 0; 27 int i; 28 29 for (i = 0; i < 16; i++) { 30 const uint8_t bit_nr = s390_vec_read_element8(v3, i); 31 uint16_t bit; 32 33 if (bit_nr >= 128) { 34 continue; 35 } 36 bit = (s390_vec_read_element8(v2, bit_nr / 8) 37 >> (7 - (bit_nr % 8))) & 1; 38 result |= (bit << (15 - i)); 39 } 40 s390_vec_write_element16(&tmp, 3, result); 41 *(S390Vector *)v1 = tmp; 42} 43 44void HELPER(vll)(CPUS390XState *env, void *v1, uint64_t addr, uint64_t bytes) 45{ 46 if (likely(bytes >= 16)) { 47 uint64_t t0, t1; 48 49 t0 = cpu_ldq_data_ra(env, addr, GETPC()); 50 addr = wrap_address(env, addr + 8); 51 t1 = cpu_ldq_data_ra(env, addr, GETPC()); 52 s390_vec_write_element64(v1, 0, t0); 53 s390_vec_write_element64(v1, 1, t1); 54 } else { 55 S390Vector tmp = {}; 56 int i; 57 58 for (i = 0; i < bytes; i++) { 59 uint8_t byte = cpu_ldub_data_ra(env, addr, GETPC()); 60 61 s390_vec_write_element8(&tmp, i, byte); 62 addr = wrap_address(env, addr + 1); 63 } 64 *(S390Vector *)v1 = tmp; 65 } 66} 67 68#define DEF_VPK_HFN(BITS, TBITS) \ 69typedef uint##TBITS##_t (*vpk##BITS##_fn)(uint##BITS##_t, int *); \ 70static int vpk##BITS##_hfn(S390Vector *v1, const S390Vector *v2, \ 71 const S390Vector *v3, vpk##BITS##_fn fn) \ 72{ \ 73 int i, saturated = 0; \ 74 S390Vector tmp; \ 75 \ 76 for (i = 0; i < (128 / TBITS); i++) { \ 77 uint##BITS##_t src; \ 78 \ 79 if (i < (128 / BITS)) { \ 80 src = s390_vec_read_element##BITS(v2, i); \ 81 } else { \ 82 src = s390_vec_read_element##BITS(v3, i - (128 / BITS)); \ 83 } \ 84 s390_vec_write_element##TBITS(&tmp, i, fn(src, &saturated)); \ 85 } \ 86 *v1 = tmp; \ 87 return saturated; \ 88} 89DEF_VPK_HFN(64, 32) 90DEF_VPK_HFN(32, 16) 91DEF_VPK_HFN(16, 8) 92 93#define DEF_VPK(BITS, TBITS) \ 94static uint##TBITS##_t vpk##BITS##e(uint##BITS##_t src, int *saturated) \ 95{ \ 96 return src; \ 97} \ 98void HELPER(gvec_vpk##BITS)(void *v1, const void *v2, const void *v3, \ 99 uint32_t desc) \ 100{ \ 101 vpk##BITS##_hfn(v1, v2, v3, vpk##BITS##e); \ 102} 103DEF_VPK(64, 32) 104DEF_VPK(32, 16) 105DEF_VPK(16, 8) 106 107#define DEF_VPKS(BITS, TBITS) \ 108static uint##TBITS##_t vpks##BITS##e(uint##BITS##_t src, int *saturated) \ 109{ \ 110 if ((int##BITS##_t)src > INT##TBITS##_MAX) { \ 111 (*saturated)++; \ 112 return INT##TBITS##_MAX; \ 113 } else if ((int##BITS##_t)src < INT##TBITS##_MIN) { \ 114 (*saturated)++; \ 115 return INT##TBITS##_MIN; \ 116 } \ 117 return src; \ 118} \ 119void HELPER(gvec_vpks##BITS)(void *v1, const void *v2, const void *v3, \ 120 uint32_t desc) \ 121{ \ 122 vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e); \ 123} \ 124void HELPER(gvec_vpks_cc##BITS)(void *v1, const void *v2, const void *v3, \ 125 CPUS390XState *env, uint32_t desc) \ 126{ \ 127 int saturated = vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e); \ 128 \ 129 if (saturated == (128 / TBITS)) { \ 130 env->cc_op = 3; \ 131 } else if (saturated) { \ 132 env->cc_op = 1; \ 133 } else { \ 134 env->cc_op = 0; \ 135 } \ 136} 137DEF_VPKS(64, 32) 138DEF_VPKS(32, 16) 139DEF_VPKS(16, 8) 140 141#define DEF_VPKLS(BITS, TBITS) \ 142static uint##TBITS##_t vpkls##BITS##e(uint##BITS##_t src, int *saturated) \ 143{ \ 144 if (src > UINT##TBITS##_MAX) { \ 145 (*saturated)++; \ 146 return UINT##TBITS##_MAX; \ 147 } \ 148 return src; \ 149} \ 150void HELPER(gvec_vpkls##BITS)(void *v1, const void *v2, const void *v3, \ 151 uint32_t desc) \ 152{ \ 153 vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e); \ 154} \ 155void HELPER(gvec_vpkls_cc##BITS)(void *v1, const void *v2, const void *v3, \ 156 CPUS390XState *env, uint32_t desc) \ 157{ \ 158 int saturated = vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e); \ 159 \ 160 if (saturated == (128 / TBITS)) { \ 161 env->cc_op = 3; \ 162 } else if (saturated) { \ 163 env->cc_op = 1; \ 164 } else { \ 165 env->cc_op = 0; \ 166 } \ 167} 168DEF_VPKLS(64, 32) 169DEF_VPKLS(32, 16) 170DEF_VPKLS(16, 8) 171 172void HELPER(gvec_vperm)(void *v1, const void *v2, const void *v3, 173 const void *v4, uint32_t desc) 174{ 175 S390Vector tmp; 176 int i; 177 178 for (i = 0; i < 16; i++) { 179 const uint8_t selector = s390_vec_read_element8(v4, i) & 0x1f; 180 uint8_t byte; 181 182 if (selector < 16) { 183 byte = s390_vec_read_element8(v2, selector); 184 } else { 185 byte = s390_vec_read_element8(v3, selector - 16); 186 } 187 s390_vec_write_element8(&tmp, i, byte); 188 } 189 *(S390Vector *)v1 = tmp; 190} 191 192void HELPER(vstl)(CPUS390XState *env, const void *v1, uint64_t addr, 193 uint64_t bytes) 194{ 195 /* Probe write access before actually modifying memory */ 196 probe_write_access(env, addr, bytes, GETPC()); 197 198 if (likely(bytes >= 16)) { 199 cpu_stq_data_ra(env, addr, s390_vec_read_element64(v1, 0), GETPC()); 200 addr = wrap_address(env, addr + 8); 201 cpu_stq_data_ra(env, addr, s390_vec_read_element64(v1, 1), GETPC()); 202 } else { 203 S390Vector tmp = {}; 204 int i; 205 206 for (i = 0; i < bytes; i++) { 207 uint8_t byte = s390_vec_read_element8(v1, i); 208 209 cpu_stb_data_ra(env, addr, byte, GETPC()); 210 addr = wrap_address(env, addr + 1); 211 } 212 *(S390Vector *)v1 = tmp; 213 } 214}