qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

vec_helper.c (10027B)


      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 
     22 void 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 
     44 void 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)                                               \
     69 typedef uint##TBITS##_t (*vpk##BITS##_fn)(uint##BITS##_t, int *);              \
     70 static 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 }
     89 DEF_VPK_HFN(64, 32)
     90 DEF_VPK_HFN(32, 16)
     91 DEF_VPK_HFN(16, 8)
     92 
     93 #define DEF_VPK(BITS, TBITS)                                                   \
     94 static uint##TBITS##_t vpk##BITS##e(uint##BITS##_t src, int *saturated)        \
     95 {                                                                              \
     96     return src;                                                                \
     97 }                                                                              \
     98 void 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 }
    103 DEF_VPK(64, 32)
    104 DEF_VPK(32, 16)
    105 DEF_VPK(16, 8)
    106 
    107 #define DEF_VPKS(BITS, TBITS)                                                  \
    108 static 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 }                                                                              \
    119 void 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 }                                                                              \
    124 void 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 }
    137 DEF_VPKS(64, 32)
    138 DEF_VPKS(32, 16)
    139 DEF_VPKS(16, 8)
    140 
    141 #define DEF_VPKLS(BITS, TBITS)                                                 \
    142 static 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 }                                                                              \
    150 void 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 }                                                                              \
    155 void 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 }
    168 DEF_VPKLS(64, 32)
    169 DEF_VPKLS(32, 16)
    170 DEF_VPKLS(16, 8)
    171 
    172 void 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 
    192 void 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         int i;
    204 
    205         for (i = 0; i < bytes; i++) {
    206             uint8_t byte = s390_vec_read_element8(v1, i);
    207 
    208             cpu_stb_data_ra(env, addr, byte, GETPC());
    209             addr = wrap_address(env, addr + 1);
    210         }
    211     }
    212 }