]>
Commit | Line | Data |
---|---|---|
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 | |
9 | * version 2 of the License, or (at your option) any later version. | |
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 | ||
20 | #include "cpu.h" | |
1bccec25 BS |
21 | #include "helper.h" |
22 | ||
23 | #define DT0 (env->dt0) | |
24 | #define DT1 (env->dt1) | |
25 | #define QT0 (env->qt0) | |
26 | #define QT1 (env->qt1) | |
27 | ||
28 | /* This function uses non-native bit order */ | |
29 | #define GET_FIELD(X, FROM, TO) \ | |
30 | ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1)) | |
31 | ||
32 | /* This function uses the order in the manuals, i.e. bit 0 is 2^0 */ | |
33 | #define GET_FIELD_SP(X, FROM, TO) \ | |
34 | GET_FIELD(X, 63 - (TO), 63 - (FROM)) | |
35 | ||
2e2f4ade BS |
36 | target_ulong helper_array8(CPUState *env, target_ulong pixel_addr, |
37 | target_ulong cubesize) | |
1bccec25 BS |
38 | { |
39 | return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) | | |
40 | (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) | | |
41 | (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) | | |
42 | (GET_FIELD_SP(pixel_addr, 56, 59) << 13) | | |
43 | (GET_FIELD_SP(pixel_addr, 35, 38) << 9) | | |
44 | (GET_FIELD_SP(pixel_addr, 13, 16) << 5) | | |
45 | (((pixel_addr >> 55) & 1) << 4) | | |
46 | (GET_FIELD_SP(pixel_addr, 33, 34) << 2) | | |
47 | GET_FIELD_SP(pixel_addr, 11, 12); | |
48 | } | |
49 | ||
2e2f4ade BS |
50 | target_ulong helper_alignaddr(CPUState *env, target_ulong addr, |
51 | target_ulong offset) | |
1bccec25 BS |
52 | { |
53 | uint64_t tmp; | |
54 | ||
55 | tmp = addr + offset; | |
56 | env->gsr &= ~7ULL; | |
57 | env->gsr |= tmp & 7ULL; | |
58 | return tmp & ~7ULL; | |
59 | } | |
60 | ||
2e2f4ade | 61 | void helper_faligndata(CPUState *env) |
1bccec25 BS |
62 | { |
63 | uint64_t tmp; | |
64 | ||
65 | tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8); | |
66 | /* on many architectures a shift of 64 does nothing */ | |
67 | if ((env->gsr & 7) != 0) { | |
68 | tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8); | |
69 | } | |
70 | *((uint64_t *)&DT0) = tmp; | |
71 | } | |
72 | ||
73 | #ifdef HOST_WORDS_BIGENDIAN | |
74 | #define VIS_B64(n) b[7 - (n)] | |
75 | #define VIS_W64(n) w[3 - (n)] | |
76 | #define VIS_SW64(n) sw[3 - (n)] | |
77 | #define VIS_L64(n) l[1 - (n)] | |
78 | #define VIS_B32(n) b[3 - (n)] | |
79 | #define VIS_W32(n) w[1 - (n)] | |
80 | #else | |
81 | #define VIS_B64(n) b[n] | |
82 | #define VIS_W64(n) w[n] | |
83 | #define VIS_SW64(n) sw[n] | |
84 | #define VIS_L64(n) l[n] | |
85 | #define VIS_B32(n) b[n] | |
86 | #define VIS_W32(n) w[n] | |
87 | #endif | |
88 | ||
89 | typedef union { | |
90 | uint8_t b[8]; | |
91 | uint16_t w[4]; | |
92 | int16_t sw[4]; | |
93 | uint32_t l[2]; | |
94 | uint64_t ll; | |
95 | float64 d; | |
96 | } VIS64; | |
97 | ||
98 | typedef union { | |
99 | uint8_t b[4]; | |
100 | uint16_t w[2]; | |
101 | uint32_t l; | |
102 | float32 f; | |
103 | } VIS32; | |
104 | ||
2e2f4ade | 105 | void helper_fpmerge(CPUState *env) |
1bccec25 BS |
106 | { |
107 | VIS64 s, d; | |
108 | ||
109 | s.d = DT0; | |
110 | d.d = DT1; | |
111 | ||
112 | /* Reverse calculation order to handle overlap */ | |
113 | d.VIS_B64(7) = s.VIS_B64(3); | |
114 | d.VIS_B64(6) = d.VIS_B64(3); | |
115 | d.VIS_B64(5) = s.VIS_B64(2); | |
116 | d.VIS_B64(4) = d.VIS_B64(2); | |
117 | d.VIS_B64(3) = s.VIS_B64(1); | |
118 | d.VIS_B64(2) = d.VIS_B64(1); | |
119 | d.VIS_B64(1) = s.VIS_B64(0); | |
120 | /* d.VIS_B64(0) = d.VIS_B64(0); */ | |
121 | ||
122 | DT0 = d.d; | |
123 | } | |
124 | ||
2e2f4ade | 125 | void helper_fmul8x16(CPUState *env) |
1bccec25 BS |
126 | { |
127 | VIS64 s, d; | |
128 | uint32_t tmp; | |
129 | ||
130 | s.d = DT0; | |
131 | d.d = DT1; | |
132 | ||
133 | #define PMUL(r) \ | |
134 | tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r); \ | |
135 | if ((tmp & 0xff) > 0x7f) { \ | |
136 | tmp += 0x100; \ | |
137 | } \ | |
138 | d.VIS_W64(r) = tmp >> 8; | |
139 | ||
140 | PMUL(0); | |
141 | PMUL(1); | |
142 | PMUL(2); | |
143 | PMUL(3); | |
144 | #undef PMUL | |
145 | ||
146 | DT0 = d.d; | |
147 | } | |
148 | ||
2e2f4ade | 149 | void helper_fmul8x16al(CPUState *env) |
1bccec25 BS |
150 | { |
151 | VIS64 s, d; | |
152 | uint32_t tmp; | |
153 | ||
154 | s.d = DT0; | |
155 | d.d = DT1; | |
156 | ||
157 | #define PMUL(r) \ | |
158 | tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r); \ | |
159 | if ((tmp & 0xff) > 0x7f) { \ | |
160 | tmp += 0x100; \ | |
161 | } \ | |
162 | d.VIS_W64(r) = tmp >> 8; | |
163 | ||
164 | PMUL(0); | |
165 | PMUL(1); | |
166 | PMUL(2); | |
167 | PMUL(3); | |
168 | #undef PMUL | |
169 | ||
170 | DT0 = d.d; | |
171 | } | |
172 | ||
2e2f4ade | 173 | void helper_fmul8x16au(CPUState *env) |
1bccec25 BS |
174 | { |
175 | VIS64 s, d; | |
176 | uint32_t tmp; | |
177 | ||
178 | s.d = DT0; | |
179 | d.d = DT1; | |
180 | ||
181 | #define PMUL(r) \ | |
182 | tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r); \ | |
183 | if ((tmp & 0xff) > 0x7f) { \ | |
184 | tmp += 0x100; \ | |
185 | } \ | |
186 | d.VIS_W64(r) = tmp >> 8; | |
187 | ||
188 | PMUL(0); | |
189 | PMUL(1); | |
190 | PMUL(2); | |
191 | PMUL(3); | |
192 | #undef PMUL | |
193 | ||
194 | DT0 = d.d; | |
195 | } | |
196 | ||
2e2f4ade | 197 | void helper_fmul8sux16(CPUState *env) |
1bccec25 BS |
198 | { |
199 | VIS64 s, d; | |
200 | uint32_t tmp; | |
201 | ||
202 | s.d = DT0; | |
203 | d.d = DT1; | |
204 | ||
205 | #define PMUL(r) \ | |
206 | tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \ | |
207 | if ((tmp & 0xff) > 0x7f) { \ | |
208 | tmp += 0x100; \ | |
209 | } \ | |
210 | d.VIS_W64(r) = tmp >> 8; | |
211 | ||
212 | PMUL(0); | |
213 | PMUL(1); | |
214 | PMUL(2); | |
215 | PMUL(3); | |
216 | #undef PMUL | |
217 | ||
218 | DT0 = d.d; | |
219 | } | |
220 | ||
2e2f4ade | 221 | void helper_fmul8ulx16(CPUState *env) |
1bccec25 BS |
222 | { |
223 | VIS64 s, d; | |
224 | uint32_t tmp; | |
225 | ||
226 | s.d = DT0; | |
227 | d.d = DT1; | |
228 | ||
229 | #define PMUL(r) \ | |
230 | tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \ | |
231 | if ((tmp & 0xff) > 0x7f) { \ | |
232 | tmp += 0x100; \ | |
233 | } \ | |
234 | d.VIS_W64(r) = tmp >> 8; | |
235 | ||
236 | PMUL(0); | |
237 | PMUL(1); | |
238 | PMUL(2); | |
239 | PMUL(3); | |
240 | #undef PMUL | |
241 | ||
242 | DT0 = d.d; | |
243 | } | |
244 | ||
2e2f4ade | 245 | void helper_fmuld8sux16(CPUState *env) |
1bccec25 BS |
246 | { |
247 | VIS64 s, d; | |
248 | uint32_t tmp; | |
249 | ||
250 | s.d = DT0; | |
251 | d.d = DT1; | |
252 | ||
253 | #define PMUL(r) \ | |
254 | tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \ | |
255 | if ((tmp & 0xff) > 0x7f) { \ | |
256 | tmp += 0x100; \ | |
257 | } \ | |
258 | d.VIS_L64(r) = tmp; | |
259 | ||
260 | /* Reverse calculation order to handle overlap */ | |
261 | PMUL(1); | |
262 | PMUL(0); | |
263 | #undef PMUL | |
264 | ||
265 | DT0 = d.d; | |
266 | } | |
267 | ||
2e2f4ade | 268 | void helper_fmuld8ulx16(CPUState *env) |
1bccec25 BS |
269 | { |
270 | VIS64 s, d; | |
271 | uint32_t tmp; | |
272 | ||
273 | s.d = DT0; | |
274 | d.d = DT1; | |
275 | ||
276 | #define PMUL(r) \ | |
277 | tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \ | |
278 | if ((tmp & 0xff) > 0x7f) { \ | |
279 | tmp += 0x100; \ | |
280 | } \ | |
281 | d.VIS_L64(r) = tmp; | |
282 | ||
283 | /* Reverse calculation order to handle overlap */ | |
284 | PMUL(1); | |
285 | PMUL(0); | |
286 | #undef PMUL | |
287 | ||
288 | DT0 = d.d; | |
289 | } | |
290 | ||
2e2f4ade | 291 | void helper_fexpand(CPUState *env) |
1bccec25 BS |
292 | { |
293 | VIS32 s; | |
294 | VIS64 d; | |
295 | ||
296 | s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff); | |
297 | d.d = DT1; | |
298 | d.VIS_W64(0) = s.VIS_B32(0) << 4; | |
299 | d.VIS_W64(1) = s.VIS_B32(1) << 4; | |
300 | d.VIS_W64(2) = s.VIS_B32(2) << 4; | |
301 | d.VIS_W64(3) = s.VIS_B32(3) << 4; | |
302 | ||
303 | DT0 = d.d; | |
304 | } | |
305 | ||
306 | #define VIS_HELPER(name, F) \ | |
2e2f4ade | 307 | void name##16(CPUState *env) \ |
1bccec25 BS |
308 | { \ |
309 | VIS64 s, d; \ | |
310 | \ | |
311 | s.d = DT0; \ | |
312 | d.d = DT1; \ | |
313 | \ | |
314 | d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0)); \ | |
315 | d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1)); \ | |
316 | d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2)); \ | |
317 | d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3)); \ | |
318 | \ | |
319 | DT0 = d.d; \ | |
320 | } \ | |
321 | \ | |
2e2f4ade BS |
322 | uint32_t name##16s(CPUState *env, uint32_t src1, \ |
323 | uint32_t src2) \ | |
1bccec25 BS |
324 | { \ |
325 | VIS32 s, d; \ | |
326 | \ | |
327 | s.l = src1; \ | |
328 | d.l = src2; \ | |
329 | \ | |
330 | d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0)); \ | |
331 | d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1)); \ | |
332 | \ | |
333 | return d.l; \ | |
334 | } \ | |
335 | \ | |
2e2f4ade | 336 | void name##32(CPUState *env) \ |
1bccec25 BS |
337 | { \ |
338 | VIS64 s, d; \ | |
339 | \ | |
340 | s.d = DT0; \ | |
341 | d.d = DT1; \ | |
342 | \ | |
343 | d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0)); \ | |
344 | d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1)); \ | |
345 | \ | |
346 | DT0 = d.d; \ | |
347 | } \ | |
348 | \ | |
2e2f4ade BS |
349 | uint32_t name##32s(CPUState *env, uint32_t src1, \ |
350 | uint32_t src2) \ | |
1bccec25 BS |
351 | { \ |
352 | VIS32 s, d; \ | |
353 | \ | |
354 | s.l = src1; \ | |
355 | d.l = src2; \ | |
356 | \ | |
357 | d.l = F(d.l, s.l); \ | |
358 | \ | |
359 | return d.l; \ | |
360 | } | |
361 | ||
362 | #define FADD(a, b) ((a) + (b)) | |
363 | #define FSUB(a, b) ((a) - (b)) | |
364 | VIS_HELPER(helper_fpadd, FADD) | |
365 | VIS_HELPER(helper_fpsub, FSUB) | |
366 | ||
367 | #define VIS_CMPHELPER(name, F) \ | |
2e2f4ade | 368 | uint64_t name##16(CPUState *env) \ |
1bccec25 BS |
369 | { \ |
370 | VIS64 s, d; \ | |
371 | \ | |
372 | s.d = DT0; \ | |
373 | d.d = DT1; \ | |
374 | \ | |
375 | d.VIS_W64(0) = F(s.VIS_W64(0), d.VIS_W64(0)) ? 1 : 0; \ | |
376 | d.VIS_W64(0) |= F(s.VIS_W64(1), d.VIS_W64(1)) ? 2 : 0; \ | |
377 | d.VIS_W64(0) |= F(s.VIS_W64(2), d.VIS_W64(2)) ? 4 : 0; \ | |
378 | d.VIS_W64(0) |= F(s.VIS_W64(3), d.VIS_W64(3)) ? 8 : 0; \ | |
379 | d.VIS_W64(1) = d.VIS_W64(2) = d.VIS_W64(3) = 0; \ | |
380 | \ | |
381 | return d.ll; \ | |
382 | } \ | |
383 | \ | |
2e2f4ade | 384 | uint64_t name##32(CPUState *env) \ |
1bccec25 BS |
385 | { \ |
386 | VIS64 s, d; \ | |
387 | \ | |
388 | s.d = DT0; \ | |
389 | d.d = DT1; \ | |
390 | \ | |
391 | d.VIS_L64(0) = F(s.VIS_L64(0), d.VIS_L64(0)) ? 1 : 0; \ | |
392 | d.VIS_L64(0) |= F(s.VIS_L64(1), d.VIS_L64(1)) ? 2 : 0; \ | |
393 | d.VIS_L64(1) = 0; \ | |
394 | \ | |
395 | return d.ll; \ | |
396 | } | |
397 | ||
398 | #define FCMPGT(a, b) ((a) > (b)) | |
399 | #define FCMPEQ(a, b) ((a) == (b)) | |
400 | #define FCMPLE(a, b) ((a) <= (b)) | |
401 | #define FCMPNE(a, b) ((a) != (b)) | |
402 | ||
403 | VIS_CMPHELPER(helper_fcmpgt, FCMPGT) | |
404 | VIS_CMPHELPER(helper_fcmpeq, FCMPEQ) | |
405 | VIS_CMPHELPER(helper_fcmple, FCMPLE) | |
406 | VIS_CMPHELPER(helper_fcmpne, FCMPNE) |