qemu/target/s390x/tcg/vec_helper.c
<<
>>
Prefs
   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}
 215