]>
Commit | Line | Data |
---|---|---|
60e9e3f1 DH |
1 | /* |
2 | * QEMU TCG support -- s390x vector support instructions | |
3 | * | |
4 | * Copyright (C) 2019 Red Hat Inc | |
5 | * | |
6 | * Authors: | |
7 | * David Hildenbrand <[email protected]> | |
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" | |
73946f0d | 18 | #include "tcg/tcg-gvec-desc.h" |
60e9e3f1 DH |
19 | #include "exec/helper-proto.h" |
20 | #include "exec/cpu_ldst.h" | |
21 | #include "exec/exec-all.h" | |
22 | ||
23 | void HELPER(vll)(CPUS390XState *env, void *v1, uint64_t addr, uint64_t bytes) | |
24 | { | |
25 | if (likely(bytes >= 16)) { | |
26 | uint64_t t0, t1; | |
27 | ||
28 | t0 = cpu_ldq_data_ra(env, addr, GETPC()); | |
29 | addr = wrap_address(env, addr + 8); | |
30 | t1 = cpu_ldq_data_ra(env, addr, GETPC()); | |
31 | s390_vec_write_element64(v1, 0, t0); | |
32 | s390_vec_write_element64(v1, 1, t1); | |
33 | } else { | |
34 | S390Vector tmp = {}; | |
35 | int i; | |
36 | ||
37 | for (i = 0; i < bytes; i++) { | |
38 | uint8_t byte = cpu_ldub_data_ra(env, addr, GETPC()); | |
39 | ||
40 | s390_vec_write_element8(&tmp, i, byte); | |
41 | addr = wrap_address(env, addr + 1); | |
42 | } | |
43 | *(S390Vector *)v1 = tmp; | |
44 | } | |
45 | } | |
73946f0d DH |
46 | |
47 | #define DEF_VPK_HFN(BITS, TBITS) \ | |
48 | typedef uint##TBITS##_t (*vpk##BITS##_fn)(uint##BITS##_t, int *); \ | |
49 | static int vpk##BITS##_hfn(S390Vector *v1, const S390Vector *v2, \ | |
50 | const S390Vector *v3, vpk##BITS##_fn fn) \ | |
51 | { \ | |
52 | int i, saturated = 0; \ | |
53 | S390Vector tmp; \ | |
54 | \ | |
55 | for (i = 0; i < (128 / TBITS); i++) { \ | |
56 | uint##BITS##_t src; \ | |
57 | \ | |
58 | if (i < (128 / BITS)) { \ | |
59 | src = s390_vec_read_element##BITS(v2, i); \ | |
60 | } else { \ | |
61 | src = s390_vec_read_element##BITS(v3, i - (128 / BITS)); \ | |
62 | } \ | |
63 | s390_vec_write_element##TBITS(&tmp, i, fn(src, &saturated)); \ | |
64 | } \ | |
65 | *v1 = tmp; \ | |
66 | return saturated; \ | |
67 | } | |
68 | DEF_VPK_HFN(64, 32) | |
69 | DEF_VPK_HFN(32, 16) | |
70 | DEF_VPK_HFN(16, 8) | |
71 | ||
72 | #define DEF_VPK(BITS, TBITS) \ | |
73 | static uint##TBITS##_t vpk##BITS##e(uint##BITS##_t src, int *saturated) \ | |
74 | { \ | |
75 | return src; \ | |
76 | } \ | |
77 | void HELPER(gvec_vpk##BITS)(void *v1, const void *v2, const void *v3, \ | |
78 | uint32_t desc) \ | |
79 | { \ | |
80 | vpk##BITS##_hfn(v1, v2, v3, vpk##BITS##e); \ | |
81 | } | |
82 | DEF_VPK(64, 32) | |
83 | DEF_VPK(32, 16) | |
84 | DEF_VPK(16, 8) | |
85 | ||
86 | #define DEF_VPKS(BITS, TBITS) \ | |
87 | static uint##TBITS##_t vpks##BITS##e(uint##BITS##_t src, int *saturated) \ | |
88 | { \ | |
89 | if ((int##BITS##_t)src > INT##TBITS##_MAX) { \ | |
90 | (*saturated)++; \ | |
91 | return INT##TBITS##_MAX; \ | |
92 | } else if ((int##BITS##_t)src < INT##TBITS##_MIN) { \ | |
93 | (*saturated)++; \ | |
94 | return INT##TBITS##_MIN; \ | |
95 | } \ | |
96 | return src; \ | |
97 | } \ | |
98 | void HELPER(gvec_vpks##BITS)(void *v1, const void *v2, const void *v3, \ | |
99 | uint32_t desc) \ | |
100 | { \ | |
101 | vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e); \ | |
102 | } \ | |
103 | void HELPER(gvec_vpks_cc##BITS)(void *v1, const void *v2, const void *v3, \ | |
104 | CPUS390XState *env, uint32_t desc) \ | |
105 | { \ | |
106 | int saturated = vpk##BITS##_hfn(v1, v2, v3, vpks##BITS##e); \ | |
107 | \ | |
108 | if (saturated == (128 / TBITS)) { \ | |
109 | env->cc_op = 3; \ | |
110 | } else if (saturated) { \ | |
111 | env->cc_op = 1; \ | |
112 | } else { \ | |
113 | env->cc_op = 0; \ | |
114 | } \ | |
115 | } | |
116 | DEF_VPKS(64, 32) | |
117 | DEF_VPKS(32, 16) | |
118 | DEF_VPKS(16, 8) | |
119 | ||
120 | #define DEF_VPKLS(BITS, TBITS) \ | |
121 | static uint##TBITS##_t vpkls##BITS##e(uint##BITS##_t src, int *saturated) \ | |
122 | { \ | |
123 | if (src > UINT##TBITS##_MAX) { \ | |
124 | (*saturated)++; \ | |
125 | return UINT##TBITS##_MAX; \ | |
126 | } \ | |
127 | return src; \ | |
128 | } \ | |
129 | void HELPER(gvec_vpkls##BITS)(void *v1, const void *v2, const void *v3, \ | |
130 | uint32_t desc) \ | |
131 | { \ | |
132 | vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e); \ | |
133 | } \ | |
134 | void HELPER(gvec_vpkls_cc##BITS)(void *v1, const void *v2, const void *v3, \ | |
135 | CPUS390XState *env, uint32_t desc) \ | |
136 | { \ | |
137 | int saturated = vpk##BITS##_hfn(v1, v2, v3, vpkls##BITS##e); \ | |
138 | \ | |
139 | if (saturated == (128 / TBITS)) { \ | |
140 | env->cc_op = 3; \ | |
141 | } else if (saturated) { \ | |
142 | env->cc_op = 1; \ | |
143 | } else { \ | |
144 | env->cc_op = 0; \ | |
145 | } \ | |
146 | } | |
147 | DEF_VPKLS(64, 32) | |
148 | DEF_VPKLS(32, 16) | |
149 | DEF_VPKLS(16, 8) |