]> git.proxmox.com Git - mirror_qemu.git/blame - target/s390x/vec_string_helper.c
s390x/tcg: Implement VECTOR FIND ANY ELEMENT EQUAL
[mirror_qemu.git] / target / s390x / vec_string_helper.c
CommitLineData
1fd28638
DH
1/*
2 * QEMU TCG support -- s390x vector string instruction support
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 "qemu-common.h"
14#include "cpu.h"
15#include "internal.h"
16#include "vec.h"
17#include "tcg/tcg.h"
18#include "tcg/tcg-gvec-desc.h"
19#include "exec/helper-proto.h"
20
21/*
22 * Returns a bit set in the MSB of each element that is zero,
23 * as defined by the mask.
24 */
25static inline uint64_t zero_search(uint64_t a, uint64_t mask)
26{
27 return ~(((a & mask) + mask) | a | mask);
28}
29
30/*
31 * Returns the byte offset for the first match, or 16 for no match.
32 */
33static inline int match_index(uint64_t c0, uint64_t c1)
34{
35 return (c0 ? clz64(c0) : clz64(c1) + 64) >> 3;
36}
37
38/*
39 * Returns the number of bits composing one element.
40 */
41static uint8_t get_element_bits(uint8_t es)
42{
43 return (1 << es) * BITS_PER_BYTE;
44}
45
46/*
47 * Returns the bitmask for a single element.
48 */
49static uint64_t get_single_element_mask(uint8_t es)
50{
51 return -1ull >> (64 - get_element_bits(es));
52}
53
54/*
55 * Returns the bitmask for a single element (excluding the MSB).
56 */
57static uint64_t get_single_element_lsbs_mask(uint8_t es)
58{
59 return -1ull >> (65 - get_element_bits(es));
60}
61
62/*
63 * Returns the bitmasks for multiple elements (excluding the MSBs).
64 */
65static uint64_t get_element_lsbs_mask(uint8_t es)
66{
67 return dup_const(es, get_single_element_lsbs_mask(es));
68}
69
70static int vfae(void *v1, const void *v2, const void *v3, bool in,
71 bool rt, bool zs, uint8_t es)
72{
73 const uint64_t mask = get_element_lsbs_mask(es);
74 const int bits = get_element_bits(es);
75 uint64_t a0, a1, b0, b1, e0, e1, t0, t1, z0, z1;
76 uint64_t first_zero = 16;
77 uint64_t first_equal;
78 int i;
79
80 a0 = s390_vec_read_element64(v2, 0);
81 a1 = s390_vec_read_element64(v2, 1);
82 b0 = s390_vec_read_element64(v3, 0);
83 b1 = s390_vec_read_element64(v3, 1);
84 e0 = 0;
85 e1 = 0;
86 /* compare against equality with every other element */
87 for (i = 0; i < 64; i += bits) {
88 t0 = rol64(b0, i);
89 t1 = rol64(b1, i);
90 e0 |= zero_search(a0 ^ t0, mask);
91 e0 |= zero_search(a0 ^ t1, mask);
92 e1 |= zero_search(a1 ^ t0, mask);
93 e1 |= zero_search(a1 ^ t1, mask);
94 }
95 /* invert the result if requested - invert only the MSBs */
96 if (in) {
97 e0 = ~e0 & ~mask;
98 e1 = ~e1 & ~mask;
99 }
100 first_equal = match_index(e0, e1);
101
102 if (zs) {
103 z0 = zero_search(a0, mask);
104 z1 = zero_search(a1, mask);
105 first_zero = match_index(z0, z1);
106 }
107
108 if (rt) {
109 e0 = (e0 >> (bits - 1)) * get_single_element_mask(es);
110 e1 = (e1 >> (bits - 1)) * get_single_element_mask(es);
111 s390_vec_write_element64(v1, 0, e0);
112 s390_vec_write_element64(v1, 1, e1);
113 } else {
114 s390_vec_write_element64(v1, 0, MIN(first_equal, first_zero));
115 s390_vec_write_element64(v1, 1, 0);
116 }
117
118 if (first_zero == 16 && first_equal == 16) {
119 return 3; /* no match */
120 } else if (first_zero == 16) {
121 return 1; /* matching elements, no match for zero */
122 } else if (first_equal < first_zero) {
123 return 2; /* matching elements before match for zero */
124 }
125 return 0; /* match for zero */
126}
127
128#define DEF_VFAE_HELPER(BITS) \
129void HELPER(gvec_vfae##BITS)(void *v1, const void *v2, const void *v3, \
130 uint32_t desc) \
131{ \
132 const bool in = extract32(simd_data(desc), 3, 1); \
133 const bool rt = extract32(simd_data(desc), 2, 1); \
134 const bool zs = extract32(simd_data(desc), 1, 1); \
135 \
136 vfae(v1, v2, v3, in, rt, zs, MO_##BITS); \
137}
138DEF_VFAE_HELPER(8)
139DEF_VFAE_HELPER(16)
140DEF_VFAE_HELPER(32)
141
142#define DEF_VFAE_CC_HELPER(BITS) \
143void HELPER(gvec_vfae_cc##BITS)(void *v1, const void *v2, const void *v3, \
144 CPUS390XState *env, uint32_t desc) \
145{ \
146 const bool in = extract32(simd_data(desc), 3, 1); \
147 const bool rt = extract32(simd_data(desc), 2, 1); \
148 const bool zs = extract32(simd_data(desc), 1, 1); \
149 \
150 env->cc_op = vfae(v1, v2, v3, in, rt, zs, MO_##BITS); \
151}
152DEF_VFAE_CC_HELPER(8)
153DEF_VFAE_CC_HELPER(16)
154DEF_VFAE_CC_HELPER(32)