]> git.proxmox.com Git - mirror_qemu.git/blame - target/sparc/vis_helper.c
target/sparc: Split out do_ms16b
[mirror_qemu.git] / target / sparc / vis_helper.c
CommitLineData
1bccec25
BS
1/*
2 * VIS op helpers
3 *
4 * Copyright (c) 2003-2005 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
5650b549 9 * version 2.1 of the License, or (at your option) any later version.
1bccec25
BS
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
db5ebe5f 20#include "qemu/osdep.h"
1bccec25 21#include "cpu.h"
2ef6175a 22#include "exec/helper-proto.h"
1bccec25 23
1bccec25
BS
24/* This function uses non-native bit order */
25#define GET_FIELD(X, FROM, TO) \
26 ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
27
28/* This function uses the order in the manuals, i.e. bit 0 is 2^0 */
29#define GET_FIELD_SP(X, FROM, TO) \
30 GET_FIELD(X, 63 - (TO), 63 - (FROM))
31
f027c3b1 32target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
1bccec25
BS
33{
34 return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
35 (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
36 (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
37 (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
38 (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
39 (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
40 (((pixel_addr >> 55) & 1) << 4) |
41 (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
42 GET_FIELD_SP(pixel_addr, 11, 12);
43}
44
e03b5686 45#if HOST_BIG_ENDIAN
1bccec25 46#define VIS_B64(n) b[7 - (n)]
d6f898cf 47#define VIS_SB64(n) sb[7 - (n)]
1bccec25
BS
48#define VIS_W64(n) w[3 - (n)]
49#define VIS_SW64(n) sw[3 - (n)]
50#define VIS_L64(n) l[1 - (n)]
51#define VIS_B32(n) b[3 - (n)]
52#define VIS_W32(n) w[1 - (n)]
53#else
54#define VIS_B64(n) b[n]
d6f898cf 55#define VIS_SB64(n) sb[n]
1bccec25
BS
56#define VIS_W64(n) w[n]
57#define VIS_SW64(n) sw[n]
58#define VIS_L64(n) l[n]
59#define VIS_B32(n) b[n]
60#define VIS_W32(n) w[n]
61#endif
62
63typedef union {
64 uint8_t b[8];
d6f898cf 65 int8_t sb[8];
1bccec25
BS
66 uint16_t w[4];
67 int16_t sw[4];
68 uint32_t l[2];
69 uint64_t ll;
70 float64 d;
71} VIS64;
72
73typedef union {
74 uint8_t b[4];
75 uint16_t w[2];
76 uint32_t l;
77 float32 f;
78} VIS32;
79
d3ef26af 80uint64_t helper_fpmerge(uint32_t src1, uint32_t src2)
1bccec25 81{
d3ef26af
RH
82 VIS32 s1, s2;
83 VIS64 d;
1bccec25 84
d3ef26af
RH
85 s1.l = src1;
86 s2.l = src2;
87 d.ll = 0;
1bccec25 88
d3ef26af
RH
89 d.VIS_B64(7) = s1.VIS_B32(3);
90 d.VIS_B64(6) = s2.VIS_B32(3);
91 d.VIS_B64(5) = s1.VIS_B32(2);
92 d.VIS_B64(4) = s2.VIS_B32(2);
93 d.VIS_B64(3) = s1.VIS_B32(1);
94 d.VIS_B64(2) = s2.VIS_B32(1);
95 d.VIS_B64(1) = s1.VIS_B32(0);
96 d.VIS_B64(0) = s2.VIS_B32(0);
1bccec25 97
03fb8cfc 98 return d.ll;
1bccec25
BS
99}
100
d6f898cf
RH
101static inline int do_ms16b(int x, int y)
102{
103 return ((x * y) + 0x80) >> 8;
104}
105
9157dccc 106uint64_t helper_fmul8x16(uint32_t src1, uint64_t src2)
1bccec25 107{
9157dccc
RH
108 VIS64 d;
109 VIS32 s;
1bccec25 110
9157dccc 111 s.l = src1;
03fb8cfc 112 d.ll = src2;
1bccec25 113
d6f898cf
RH
114 d.VIS_W64(0) = do_ms16b(s.VIS_B32(0), d.VIS_SW64(0));
115 d.VIS_W64(1) = do_ms16b(s.VIS_B32(1), d.VIS_SW64(1));
116 d.VIS_W64(2) = do_ms16b(s.VIS_B32(2), d.VIS_SW64(2));
117 d.VIS_W64(3) = do_ms16b(s.VIS_B32(3), d.VIS_SW64(3));
1bccec25 118
03fb8cfc 119 return d.ll;
1bccec25
BS
120}
121
a859602c 122uint64_t helper_fmul8x16a(uint32_t src1, int32_t src2)
1bccec25 123{
a859602c
RH
124 VIS32 s;
125 VIS64 d;
1bccec25 126
a859602c
RH
127 s.l = src1;
128 d.ll = 0;
129
d6f898cf
RH
130 d.VIS_W64(0) = do_ms16b(s.VIS_B32(0), src2);
131 d.VIS_W64(1) = do_ms16b(s.VIS_B32(1), src2);
132 d.VIS_W64(2) = do_ms16b(s.VIS_B32(2), src2);
133 d.VIS_W64(3) = do_ms16b(s.VIS_B32(3), src2);
1bccec25 134
03fb8cfc 135 return d.ll;
1bccec25
BS
136}
137
f027c3b1 138uint64_t helper_fmul8sux16(uint64_t src1, uint64_t src2)
1bccec25
BS
139{
140 VIS64 s, d;
1bccec25 141
03fb8cfc
RH
142 s.ll = src1;
143 d.ll = src2;
1bccec25 144
d6f898cf
RH
145 d.VIS_W64(0) = do_ms16b(s.VIS_SB64(1), d.VIS_SW64(0));
146 d.VIS_W64(1) = do_ms16b(s.VIS_SB64(3), d.VIS_SW64(1));
147 d.VIS_W64(2) = do_ms16b(s.VIS_SB64(5), d.VIS_SW64(2));
148 d.VIS_W64(3) = do_ms16b(s.VIS_SB64(7), d.VIS_SW64(3));
1bccec25 149
03fb8cfc 150 return d.ll;
1bccec25
BS
151}
152
f027c3b1 153uint64_t helper_fmul8ulx16(uint64_t src1, uint64_t src2)
1bccec25
BS
154{
155 VIS64 s, d;
1bccec25 156
03fb8cfc
RH
157 s.ll = src1;
158 d.ll = src2;
1bccec25 159
d6f898cf
RH
160 d.VIS_W64(0) = do_ms16b(s.VIS_B64(0), d.VIS_SW64(0));
161 d.VIS_W64(1) = do_ms16b(s.VIS_B64(2), d.VIS_SW64(1));
162 d.VIS_W64(2) = do_ms16b(s.VIS_B64(4), d.VIS_SW64(2));
163 d.VIS_W64(3) = do_ms16b(s.VIS_B64(6), d.VIS_SW64(3));
1bccec25 164
03fb8cfc 165 return d.ll;
1bccec25
BS
166}
167
7b616f36 168uint64_t helper_fexpand(uint32_t src2)
1bccec25
BS
169{
170 VIS32 s;
171 VIS64 d;
172
7b616f36
RH
173 s.l = src2;
174 d.ll = 0;
1bccec25
BS
175 d.VIS_W64(0) = s.VIS_B32(0) << 4;
176 d.VIS_W64(1) = s.VIS_B32(1) << 4;
177 d.VIS_W64(2) = s.VIS_B32(2) << 4;
178 d.VIS_W64(3) = s.VIS_B32(3) << 4;
179
03fb8cfc 180 return d.ll;
1bccec25
BS
181}
182
1bccec25 183#define VIS_CMPHELPER(name, F) \
f027c3b1 184 uint64_t name##16(uint64_t src1, uint64_t src2) \
1bccec25
BS
185 { \
186 VIS64 s, d; \
187 \
03fb8cfc
RH
188 s.ll = src1; \
189 d.ll = src2; \
1bccec25
BS
190 \
191 d.VIS_W64(0) = F(s.VIS_W64(0), d.VIS_W64(0)) ? 1 : 0; \
192 d.VIS_W64(0) |= F(s.VIS_W64(1), d.VIS_W64(1)) ? 2 : 0; \
193 d.VIS_W64(0) |= F(s.VIS_W64(2), d.VIS_W64(2)) ? 4 : 0; \
194 d.VIS_W64(0) |= F(s.VIS_W64(3), d.VIS_W64(3)) ? 8 : 0; \
195 d.VIS_W64(1) = d.VIS_W64(2) = d.VIS_W64(3) = 0; \
196 \
197 return d.ll; \
198 } \
199 \
f027c3b1 200 uint64_t name##32(uint64_t src1, uint64_t src2) \
1bccec25
BS
201 { \
202 VIS64 s, d; \
203 \
03fb8cfc
RH
204 s.ll = src1; \
205 d.ll = src2; \
1bccec25
BS
206 \
207 d.VIS_L64(0) = F(s.VIS_L64(0), d.VIS_L64(0)) ? 1 : 0; \
208 d.VIS_L64(0) |= F(s.VIS_L64(1), d.VIS_L64(1)) ? 2 : 0; \
209 d.VIS_L64(1) = 0; \
210 \
211 return d.ll; \
212 }
213
214#define FCMPGT(a, b) ((a) > (b))
215#define FCMPEQ(a, b) ((a) == (b))
216#define FCMPLE(a, b) ((a) <= (b))
217#define FCMPNE(a, b) ((a) != (b))
218
219VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
220VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
221VIS_CMPHELPER(helper_fcmple, FCMPLE)
222VIS_CMPHELPER(helper_fcmpne, FCMPNE)
f888300b
RH
223
224uint64_t helper_pdist(uint64_t sum, uint64_t src1, uint64_t src2)
225{
226 int i;
227 for (i = 0; i < 8; i++) {
228 int s1, s2;
229
230 s1 = (src1 >> (56 - (i * 8))) & 0xff;
231 s2 = (src2 >> (56 - (i * 8))) & 0xff;
232
233 /* Absolute value of difference. */
234 s1 -= s2;
235 if (s1 < 0) {
236 s1 = -s1;
237 }
238
239 sum += s1;
240 }
241
242 return sum;
243}
2dedf314
RH
244
245uint32_t helper_fpack16(uint64_t gsr, uint64_t rs2)
246{
247 int scale = (gsr >> 3) & 0xf;
248 uint32_t ret = 0;
249 int byte;
250
251 for (byte = 0; byte < 4; byte++) {
252 uint32_t val;
253 int16_t src = rs2 >> (byte * 16);
254 int32_t scaled = src << scale;
255 int32_t from_fixed = scaled >> 7;
256
257 val = (from_fixed < 0 ? 0 :
258 from_fixed > 255 ? 255 : from_fixed);
259
260 ret |= val << (8 * byte);
261 }
262
263 return ret;
264}
265
266uint64_t helper_fpack32(uint64_t gsr, uint64_t rs1, uint64_t rs2)
267{
268 int scale = (gsr >> 3) & 0x1f;
269 uint64_t ret = 0;
270 int word;
271
272 ret = (rs1 << 8) & ~(0x000000ff000000ffULL);
273 for (word = 0; word < 2; word++) {
274 uint64_t val;
275 int32_t src = rs2 >> (word * 32);
276 int64_t scaled = (int64_t)src << scale;
277 int64_t from_fixed = scaled >> 23;
278
279 val = (from_fixed < 0 ? 0 :
280 (from_fixed > 255) ? 255 : from_fixed);
281
282 ret |= val << (32 * word);
283 }
284
285 return ret;
286}
287
288uint32_t helper_fpackfix(uint64_t gsr, uint64_t rs2)
289{
290 int scale = (gsr >> 3) & 0x1f;
291 uint32_t ret = 0;
292 int word;
293
294 for (word = 0; word < 2; word++) {
295 uint32_t val;
296 int32_t src = rs2 >> (word * 32);
12a3567c 297 int64_t scaled = (int64_t)src << scale;
2dedf314
RH
298 int64_t from_fixed = scaled >> 16;
299
300 val = (from_fixed < -32768 ? -32768 :
301 from_fixed > 32767 ? 32767 : from_fixed);
302
303 ret |= (val & 0xffff) << (word * 16);
304 }
305
306 return ret;
307}
793a137a 308
520c0d8d 309uint64_t helper_bshuffle(uint64_t gsr, uint64_t src1, uint64_t src2)
793a137a
RH
310{
311 union {
312 uint64_t ll[2];
313 uint8_t b[16];
314 } s;
315 VIS64 r;
316 uint32_t i, mask, host;
317
318 /* Set up S such that we can index across all of the bytes. */
e03b5686 319#if HOST_BIG_ENDIAN
793a137a
RH
320 s.ll[0] = src1;
321 s.ll[1] = src2;
322 host = 0;
323#else
324 s.ll[1] = src1;
325 s.ll[0] = src2;
326 host = 15;
327#endif
328 mask = gsr >> 32;
329
330 for (i = 0; i < 8; ++i) {
331 unsigned e = (mask >> (28 - i*4)) & 0xf;
332 r.VIS_B64(i) = s.b[e ^ host];
333 }
334
335 return r.ll;
336}