]> git.proxmox.com Git - qemu.git/blob - target-sparc/op.c
Convert mulscc to TCG, add cc_src2
[qemu.git] / target-sparc / op.c
1 /*
2 SPARC micro operations
3
4 Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
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, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include "exec.h"
22 #include "helper.h"
23
24 #define REGNAME f0
25 #define REG (env->fpr[0])
26 #include "fop_template.h"
27 #define REGNAME f1
28 #define REG (env->fpr[1])
29 #include "fop_template.h"
30 #define REGNAME f2
31 #define REG (env->fpr[2])
32 #include "fop_template.h"
33 #define REGNAME f3
34 #define REG (env->fpr[3])
35 #include "fop_template.h"
36 #define REGNAME f4
37 #define REG (env->fpr[4])
38 #include "fop_template.h"
39 #define REGNAME f5
40 #define REG (env->fpr[5])
41 #include "fop_template.h"
42 #define REGNAME f6
43 #define REG (env->fpr[6])
44 #include "fop_template.h"
45 #define REGNAME f7
46 #define REG (env->fpr[7])
47 #include "fop_template.h"
48 #define REGNAME f8
49 #define REG (env->fpr[8])
50 #include "fop_template.h"
51 #define REGNAME f9
52 #define REG (env->fpr[9])
53 #include "fop_template.h"
54 #define REGNAME f10
55 #define REG (env->fpr[10])
56 #include "fop_template.h"
57 #define REGNAME f11
58 #define REG (env->fpr[11])
59 #include "fop_template.h"
60 #define REGNAME f12
61 #define REG (env->fpr[12])
62 #include "fop_template.h"
63 #define REGNAME f13
64 #define REG (env->fpr[13])
65 #include "fop_template.h"
66 #define REGNAME f14
67 #define REG (env->fpr[14])
68 #include "fop_template.h"
69 #define REGNAME f15
70 #define REG (env->fpr[15])
71 #include "fop_template.h"
72 #define REGNAME f16
73 #define REG (env->fpr[16])
74 #include "fop_template.h"
75 #define REGNAME f17
76 #define REG (env->fpr[17])
77 #include "fop_template.h"
78 #define REGNAME f18
79 #define REG (env->fpr[18])
80 #include "fop_template.h"
81 #define REGNAME f19
82 #define REG (env->fpr[19])
83 #include "fop_template.h"
84 #define REGNAME f20
85 #define REG (env->fpr[20])
86 #include "fop_template.h"
87 #define REGNAME f21
88 #define REG (env->fpr[21])
89 #include "fop_template.h"
90 #define REGNAME f22
91 #define REG (env->fpr[22])
92 #include "fop_template.h"
93 #define REGNAME f23
94 #define REG (env->fpr[23])
95 #include "fop_template.h"
96 #define REGNAME f24
97 #define REG (env->fpr[24])
98 #include "fop_template.h"
99 #define REGNAME f25
100 #define REG (env->fpr[25])
101 #include "fop_template.h"
102 #define REGNAME f26
103 #define REG (env->fpr[26])
104 #include "fop_template.h"
105 #define REGNAME f27
106 #define REG (env->fpr[27])
107 #include "fop_template.h"
108 #define REGNAME f28
109 #define REG (env->fpr[28])
110 #include "fop_template.h"
111 #define REGNAME f29
112 #define REG (env->fpr[29])
113 #include "fop_template.h"
114 #define REGNAME f30
115 #define REG (env->fpr[30])
116 #include "fop_template.h"
117 #define REGNAME f31
118 #define REG (env->fpr[31])
119 #include "fop_template.h"
120
121 #ifdef TARGET_SPARC64
122 #define REGNAME f32
123 #define REG (env->fpr[32])
124 #include "fop_template.h"
125 #define REGNAME f34
126 #define REG (env->fpr[34])
127 #include "fop_template.h"
128 #define REGNAME f36
129 #define REG (env->fpr[36])
130 #include "fop_template.h"
131 #define REGNAME f38
132 #define REG (env->fpr[38])
133 #include "fop_template.h"
134 #define REGNAME f40
135 #define REG (env->fpr[40])
136 #include "fop_template.h"
137 #define REGNAME f42
138 #define REG (env->fpr[42])
139 #include "fop_template.h"
140 #define REGNAME f44
141 #define REG (env->fpr[44])
142 #include "fop_template.h"
143 #define REGNAME f46
144 #define REG (env->fpr[46])
145 #include "fop_template.h"
146 #define REGNAME f48
147 #define REG (env->fpr[47])
148 #include "fop_template.h"
149 #define REGNAME f50
150 #define REG (env->fpr[50])
151 #include "fop_template.h"
152 #define REGNAME f52
153 #define REG (env->fpr[52])
154 #include "fop_template.h"
155 #define REGNAME f54
156 #define REG (env->fpr[54])
157 #include "fop_template.h"
158 #define REGNAME f56
159 #define REG (env->fpr[56])
160 #include "fop_template.h"
161 #define REGNAME f58
162 #define REG (env->fpr[58])
163 #include "fop_template.h"
164 #define REGNAME f60
165 #define REG (env->fpr[60])
166 #include "fop_template.h"
167 #define REGNAME f62
168 #define REG (env->fpr[62])
169 #include "fop_template.h"
170 #endif
171
172 #define FLAG_SET(x) ((env->psr&x)?1:0)
173
174 void OPPROTO op_umul_T1_T0(void)
175 {
176 uint64_t res;
177 res = (uint64_t) T0 * (uint64_t) T1;
178 #ifdef TARGET_SPARC64
179 T0 = res;
180 #else
181 T0 = res & 0xffffffff;
182 #endif
183 env->y = res >> 32;
184 }
185
186 void OPPROTO op_smul_T1_T0(void)
187 {
188 uint64_t res;
189 res = (int64_t) ((int32_t) T0) * (int64_t) ((int32_t) T1);
190 #ifdef TARGET_SPARC64
191 T0 = res;
192 #else
193 T0 = res & 0xffffffff;
194 #endif
195 env->y = res >> 32;
196 }
197
198 void OPPROTO op_udiv_T1_T0(void)
199 {
200 uint64_t x0;
201 uint32_t x1;
202
203 x0 = T0 | ((uint64_t) (env->y) << 32);
204 x1 = T1;
205
206 if (x1 == 0) {
207 raise_exception(TT_DIV_ZERO);
208 }
209
210 x0 = x0 / x1;
211 if (x0 > 0xffffffff) {
212 T0 = 0xffffffff;
213 T1 = 1;
214 } else {
215 T0 = x0;
216 T1 = 0;
217 }
218 FORCE_RET();
219 }
220
221 void OPPROTO op_sdiv_T1_T0(void)
222 {
223 int64_t x0;
224 int32_t x1;
225
226 x0 = T0 | ((int64_t) (env->y) << 32);
227 x1 = T1;
228
229 if (x1 == 0) {
230 raise_exception(TT_DIV_ZERO);
231 }
232
233 x0 = x0 / x1;
234 if ((int32_t) x0 != x0) {
235 T0 = x0 < 0? 0x80000000: 0x7fffffff;
236 T1 = 1;
237 } else {
238 T0 = x0;
239 T1 = 0;
240 }
241 FORCE_RET();
242 }
243
244 /* Load and store */
245 #define MEMSUFFIX _raw
246 #include "op_mem.h"
247 #if !defined(CONFIG_USER_ONLY)
248 #define MEMSUFFIX _user
249 #include "op_mem.h"
250
251 #define MEMSUFFIX _kernel
252 #include "op_mem.h"
253
254 #ifdef TARGET_SPARC64
255 #define MEMSUFFIX _hypv
256 #include "op_mem.h"
257 #endif
258 #endif
259
260 #ifndef TARGET_SPARC64
261 /* XXX: use another pointer for %iN registers to avoid slow wrapping
262 handling ? */
263 void OPPROTO op_save(void)
264 {
265 uint32_t cwp;
266 cwp = (env->cwp - 1) & (NWINDOWS - 1);
267 if (env->wim & (1 << cwp)) {
268 raise_exception(TT_WIN_OVF);
269 }
270 set_cwp(cwp);
271 FORCE_RET();
272 }
273
274 void OPPROTO op_restore(void)
275 {
276 uint32_t cwp;
277 cwp = (env->cwp + 1) & (NWINDOWS - 1);
278 if (env->wim & (1 << cwp)) {
279 raise_exception(TT_WIN_UNF);
280 }
281 set_cwp(cwp);
282 FORCE_RET();
283 }
284 #else
285 void OPPROTO op_rdccr(void)
286 {
287 T0 = GET_CCR(env);
288 }
289
290 void OPPROTO op_wrccr(void)
291 {
292 PUT_CCR(env, T0);
293 }
294
295 // CWP handling is reversed in V9, but we still use the V8 register
296 // order.
297 void OPPROTO op_rdcwp(void)
298 {
299 T0 = GET_CWP64(env);
300 }
301
302 void OPPROTO op_wrcwp(void)
303 {
304 PUT_CWP64(env, T0);
305 }
306
307 /* XXX: use another pointer for %iN registers to avoid slow wrapping
308 handling ? */
309 void OPPROTO op_save(void)
310 {
311 uint32_t cwp;
312 cwp = (env->cwp - 1) & (NWINDOWS - 1);
313 if (env->cansave == 0) {
314 raise_exception(TT_SPILL | (env->otherwin != 0 ?
315 (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
316 ((env->wstate & 0x7) << 2)));
317 } else {
318 if (env->cleanwin - env->canrestore == 0) {
319 // XXX Clean windows without trap
320 raise_exception(TT_CLRWIN);
321 } else {
322 env->cansave--;
323 env->canrestore++;
324 set_cwp(cwp);
325 }
326 }
327 FORCE_RET();
328 }
329
330 void OPPROTO op_restore(void)
331 {
332 uint32_t cwp;
333 cwp = (env->cwp + 1) & (NWINDOWS - 1);
334 if (env->canrestore == 0) {
335 raise_exception(TT_FILL | (env->otherwin != 0 ?
336 (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
337 ((env->wstate & 0x7) << 2)));
338 } else {
339 env->cansave++;
340 env->canrestore--;
341 set_cwp(cwp);
342 }
343 FORCE_RET();
344 }
345 #endif
346
347 void OPPROTO op_jmp_label(void)
348 {
349 GOTO_LABEL_PARAM(1);
350 }
351
352 #define F_OP(name, p) void OPPROTO op_f##name##p(void)
353
354 #if defined(CONFIG_USER_ONLY)
355 #define F_BINOP(name) \
356 F_OP(name, s) \
357 { \
358 FT0 = float32_ ## name (FT0, FT1, &env->fp_status); \
359 } \
360 F_OP(name, d) \
361 { \
362 DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
363 } \
364 F_OP(name, q) \
365 { \
366 QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \
367 }
368 #else
369 #define F_BINOP(name) \
370 F_OP(name, s) \
371 { \
372 FT0 = float32_ ## name (FT0, FT1, &env->fp_status); \
373 } \
374 F_OP(name, d) \
375 { \
376 DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
377 }
378 #endif
379
380 F_BINOP(add);
381 F_BINOP(sub);
382 F_BINOP(mul);
383 F_BINOP(div);
384 #undef F_BINOP
385
386 void OPPROTO op_fsmuld(void)
387 {
388 DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
389 float32_to_float64(FT1, &env->fp_status),
390 &env->fp_status);
391 }
392
393 #if defined(CONFIG_USER_ONLY)
394 void OPPROTO op_fdmulq(void)
395 {
396 QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
397 float64_to_float128(DT1, &env->fp_status),
398 &env->fp_status);
399 }
400 #endif
401
402 #if defined(CONFIG_USER_ONLY)
403 #define F_HELPER(name) \
404 F_OP(name, s) \
405 { \
406 do_f##name##s(); \
407 } \
408 F_OP(name, d) \
409 { \
410 do_f##name##d(); \
411 } \
412 F_OP(name, q) \
413 { \
414 do_f##name##q(); \
415 }
416 #else
417 #define F_HELPER(name) \
418 F_OP(name, s) \
419 { \
420 do_f##name##s(); \
421 } \
422 F_OP(name, d) \
423 { \
424 do_f##name##d(); \
425 }
426 #endif
427
428 F_OP(neg, s)
429 {
430 FT0 = float32_chs(FT1);
431 }
432
433 #ifdef TARGET_SPARC64
434 F_OP(neg, d)
435 {
436 DT0 = float64_chs(DT1);
437 }
438
439 #if defined(CONFIG_USER_ONLY)
440 F_OP(neg, q)
441 {
442 QT0 = float128_chs(QT1);
443 }
444
445 #endif
446
447 #endif
448
449 /* Integer to float conversion. */
450 #ifdef USE_INT_TO_FLOAT_HELPERS
451 F_HELPER(ito);
452 #ifdef TARGET_SPARC64
453 F_HELPER(xto);
454 #endif
455 #else
456 F_OP(ito, s)
457 {
458 FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
459 }
460
461 F_OP(ito, d)
462 {
463 DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
464 }
465
466 #if defined(CONFIG_USER_ONLY)
467 F_OP(ito, q)
468 {
469 QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
470 }
471 #endif
472
473 #ifdef TARGET_SPARC64
474 F_OP(xto, s)
475 {
476 FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
477 }
478
479 F_OP(xto, d)
480 {
481 DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
482 }
483 #if defined(CONFIG_USER_ONLY)
484 F_OP(xto, q)
485 {
486 QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
487 }
488 #endif
489 #endif
490 #endif
491 #undef F_HELPER
492
493 /* floating point conversion */
494 void OPPROTO op_fdtos(void)
495 {
496 FT0 = float64_to_float32(DT1, &env->fp_status);
497 }
498
499 void OPPROTO op_fstod(void)
500 {
501 DT0 = float32_to_float64(FT1, &env->fp_status);
502 }
503
504 #if defined(CONFIG_USER_ONLY)
505 void OPPROTO op_fqtos(void)
506 {
507 FT0 = float128_to_float32(QT1, &env->fp_status);
508 }
509
510 void OPPROTO op_fstoq(void)
511 {
512 QT0 = float32_to_float128(FT1, &env->fp_status);
513 }
514
515 void OPPROTO op_fqtod(void)
516 {
517 DT0 = float128_to_float64(QT1, &env->fp_status);
518 }
519
520 void OPPROTO op_fdtoq(void)
521 {
522 QT0 = float64_to_float128(DT1, &env->fp_status);
523 }
524 #endif
525
526 /* Float to integer conversion. */
527 void OPPROTO op_fstoi(void)
528 {
529 *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
530 }
531
532 void OPPROTO op_fdtoi(void)
533 {
534 *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
535 }
536
537 #if defined(CONFIG_USER_ONLY)
538 void OPPROTO op_fqtoi(void)
539 {
540 *((int32_t *)&FT0) = float128_to_int32_round_to_zero(QT1, &env->fp_status);
541 }
542 #endif
543
544 #ifdef TARGET_SPARC64
545 void OPPROTO op_fstox(void)
546 {
547 *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
548 }
549
550 void OPPROTO op_fdtox(void)
551 {
552 *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
553 }
554
555 #if defined(CONFIG_USER_ONLY)
556 void OPPROTO op_fqtox(void)
557 {
558 *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
559 }
560 #endif
561
562 void OPPROTO op_flushw(void)
563 {
564 if (env->cansave != NWINDOWS - 2) {
565 raise_exception(TT_SPILL | (env->otherwin != 0 ?
566 (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
567 ((env->wstate & 0x7) << 2)));
568 }
569 }
570
571 void OPPROTO op_saved(void)
572 {
573 env->cansave++;
574 if (env->otherwin == 0)
575 env->canrestore--;
576 else
577 env->otherwin--;
578 FORCE_RET();
579 }
580
581 void OPPROTO op_restored(void)
582 {
583 env->canrestore++;
584 if (env->cleanwin < NWINDOWS - 1)
585 env->cleanwin++;
586 if (env->otherwin == 0)
587 env->cansave--;
588 else
589 env->otherwin--;
590 FORCE_RET();
591 }
592 #endif
593
594 #ifdef TARGET_SPARC64
595 // This function uses non-native bit order
596 #define GET_FIELD(X, FROM, TO) \
597 ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
598
599 // This function uses the order in the manuals, i.e. bit 0 is 2^0
600 #define GET_FIELD_SP(X, FROM, TO) \
601 GET_FIELD(X, 63 - (TO), 63 - (FROM))
602
603 void OPPROTO op_array8()
604 {
605 T0 = (GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
606 (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
607 (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
608 (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
609 (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
610 (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12);
611 }
612
613 void OPPROTO op_array16()
614 {
615 T0 = ((GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
616 (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
617 (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
618 (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
619 (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
620 (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12)) << 1;
621 }
622
623 void OPPROTO op_array32()
624 {
625 T0 = ((GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
626 (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
627 (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
628 (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
629 (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
630 (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12)) << 2;
631 }
632
633 void OPPROTO op_alignaddr()
634 {
635 uint64_t tmp;
636
637 tmp = T0 + T1;
638 env->gsr &= ~7ULL;
639 env->gsr |= tmp & 7ULL;
640 T0 = tmp & ~7ULL;
641 }
642
643 void OPPROTO op_faligndata()
644 {
645 uint64_t tmp;
646
647 tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
648 tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
649 *((uint64_t *)&DT0) = tmp;
650 }
651
652 void OPPROTO op_movl_FT0_0(void)
653 {
654 *((uint32_t *)&FT0) = 0;
655 }
656
657 void OPPROTO op_movl_DT0_0(void)
658 {
659 *((uint64_t *)&DT0) = 0;
660 }
661
662 void OPPROTO op_movl_FT0_1(void)
663 {
664 *((uint32_t *)&FT0) = 0xffffffff;
665 }
666
667 void OPPROTO op_movl_DT0_1(void)
668 {
669 *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
670 }
671
672 void OPPROTO op_fnot(void)
673 {
674 *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
675 }
676
677 void OPPROTO op_fnots(void)
678 {
679 *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
680 }
681
682 void OPPROTO op_fnor(void)
683 {
684 *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
685 }
686
687 void OPPROTO op_fnors(void)
688 {
689 *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
690 }
691
692 void OPPROTO op_for(void)
693 {
694 *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
695 }
696
697 void OPPROTO op_fors(void)
698 {
699 *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
700 }
701
702 void OPPROTO op_fxor(void)
703 {
704 *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
705 }
706
707 void OPPROTO op_fxors(void)
708 {
709 *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
710 }
711
712 void OPPROTO op_fand(void)
713 {
714 *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
715 }
716
717 void OPPROTO op_fands(void)
718 {
719 *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
720 }
721
722 void OPPROTO op_fornot(void)
723 {
724 *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
725 }
726
727 void OPPROTO op_fornots(void)
728 {
729 *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
730 }
731
732 void OPPROTO op_fandnot(void)
733 {
734 *(uint64_t *)&DT0 = *(uint64_t *)&DT0 & ~*(uint64_t *)&DT1;
735 }
736
737 void OPPROTO op_fandnots(void)
738 {
739 *(uint32_t *)&FT0 = *(uint32_t *)&FT0 & ~*(uint32_t *)&FT1;
740 }
741
742 void OPPROTO op_fnand(void)
743 {
744 *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 & *(uint64_t *)&DT1);
745 }
746
747 void OPPROTO op_fnands(void)
748 {
749 *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 & *(uint32_t *)&FT1);
750 }
751
752 void OPPROTO op_fxnor(void)
753 {
754 *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
755 }
756
757 void OPPROTO op_fxnors(void)
758 {
759 *(uint32_t *)&FT0 ^= ~*(uint32_t *)&FT1;
760 }
761
762 #ifdef WORDS_BIGENDIAN
763 #define VIS_B64(n) b[7 - (n)]
764 #define VIS_W64(n) w[3 - (n)]
765 #define VIS_SW64(n) sw[3 - (n)]
766 #define VIS_L64(n) l[1 - (n)]
767 #define VIS_B32(n) b[3 - (n)]
768 #define VIS_W32(n) w[1 - (n)]
769 #else
770 #define VIS_B64(n) b[n]
771 #define VIS_W64(n) w[n]
772 #define VIS_SW64(n) sw[n]
773 #define VIS_L64(n) l[n]
774 #define VIS_B32(n) b[n]
775 #define VIS_W32(n) w[n]
776 #endif
777
778 typedef union {
779 uint8_t b[8];
780 uint16_t w[4];
781 int16_t sw[4];
782 uint32_t l[2];
783 float64 d;
784 } vis64;
785
786 typedef union {
787 uint8_t b[4];
788 uint16_t w[2];
789 uint32_t l;
790 float32 f;
791 } vis32;
792
793 void OPPROTO op_fpmerge(void)
794 {
795 vis64 s, d;
796
797 s.d = DT0;
798 d.d = DT1;
799
800 // Reverse calculation order to handle overlap
801 d.VIS_B64(7) = s.VIS_B64(3);
802 d.VIS_B64(6) = d.VIS_B64(3);
803 d.VIS_B64(5) = s.VIS_B64(2);
804 d.VIS_B64(4) = d.VIS_B64(2);
805 d.VIS_B64(3) = s.VIS_B64(1);
806 d.VIS_B64(2) = d.VIS_B64(1);
807 d.VIS_B64(1) = s.VIS_B64(0);
808 //d.VIS_B64(0) = d.VIS_B64(0);
809
810 DT0 = d.d;
811 }
812
813 void OPPROTO op_fmul8x16(void)
814 {
815 vis64 s, d;
816 uint32_t tmp;
817
818 s.d = DT0;
819 d.d = DT1;
820
821 #define PMUL(r) \
822 tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r); \
823 if ((tmp & 0xff) > 0x7f) \
824 tmp += 0x100; \
825 d.VIS_W64(r) = tmp >> 8;
826
827 PMUL(0);
828 PMUL(1);
829 PMUL(2);
830 PMUL(3);
831 #undef PMUL
832
833 DT0 = d.d;
834 }
835
836 void OPPROTO op_fmul8x16al(void)
837 {
838 vis64 s, d;
839 uint32_t tmp;
840
841 s.d = DT0;
842 d.d = DT1;
843
844 #define PMUL(r) \
845 tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r); \
846 if ((tmp & 0xff) > 0x7f) \
847 tmp += 0x100; \
848 d.VIS_W64(r) = tmp >> 8;
849
850 PMUL(0);
851 PMUL(1);
852 PMUL(2);
853 PMUL(3);
854 #undef PMUL
855
856 DT0 = d.d;
857 }
858
859 void OPPROTO op_fmul8x16au(void)
860 {
861 vis64 s, d;
862 uint32_t tmp;
863
864 s.d = DT0;
865 d.d = DT1;
866
867 #define PMUL(r) \
868 tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r); \
869 if ((tmp & 0xff) > 0x7f) \
870 tmp += 0x100; \
871 d.VIS_W64(r) = tmp >> 8;
872
873 PMUL(0);
874 PMUL(1);
875 PMUL(2);
876 PMUL(3);
877 #undef PMUL
878
879 DT0 = d.d;
880 }
881
882 void OPPROTO op_fmul8sux16(void)
883 {
884 vis64 s, d;
885 uint32_t tmp;
886
887 s.d = DT0;
888 d.d = DT1;
889
890 #define PMUL(r) \
891 tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
892 if ((tmp & 0xff) > 0x7f) \
893 tmp += 0x100; \
894 d.VIS_W64(r) = tmp >> 8;
895
896 PMUL(0);
897 PMUL(1);
898 PMUL(2);
899 PMUL(3);
900 #undef PMUL
901
902 DT0 = d.d;
903 }
904
905 void OPPROTO op_fmul8ulx16(void)
906 {
907 vis64 s, d;
908 uint32_t tmp;
909
910 s.d = DT0;
911 d.d = DT1;
912
913 #define PMUL(r) \
914 tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
915 if ((tmp & 0xff) > 0x7f) \
916 tmp += 0x100; \
917 d.VIS_W64(r) = tmp >> 8;
918
919 PMUL(0);
920 PMUL(1);
921 PMUL(2);
922 PMUL(3);
923 #undef PMUL
924
925 DT0 = d.d;
926 }
927
928 void OPPROTO op_fmuld8sux16(void)
929 {
930 vis64 s, d;
931 uint32_t tmp;
932
933 s.d = DT0;
934 d.d = DT1;
935
936 #define PMUL(r) \
937 tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
938 if ((tmp & 0xff) > 0x7f) \
939 tmp += 0x100; \
940 d.VIS_L64(r) = tmp;
941
942 // Reverse calculation order to handle overlap
943 PMUL(1);
944 PMUL(0);
945 #undef PMUL
946
947 DT0 = d.d;
948 }
949
950 void OPPROTO op_fmuld8ulx16(void)
951 {
952 vis64 s, d;
953 uint32_t tmp;
954
955 s.d = DT0;
956 d.d = DT1;
957
958 #define PMUL(r) \
959 tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
960 if ((tmp & 0xff) > 0x7f) \
961 tmp += 0x100; \
962 d.VIS_L64(r) = tmp;
963
964 // Reverse calculation order to handle overlap
965 PMUL(1);
966 PMUL(0);
967 #undef PMUL
968
969 DT0 = d.d;
970 }
971
972 void OPPROTO op_fexpand(void)
973 {
974 vis32 s;
975 vis64 d;
976
977 s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
978 d.d = DT1;
979 d.VIS_L64(0) = s.VIS_W32(0) << 4;
980 d.VIS_L64(1) = s.VIS_W32(1) << 4;
981 d.VIS_L64(2) = s.VIS_W32(2) << 4;
982 d.VIS_L64(3) = s.VIS_W32(3) << 4;
983
984 DT0 = d.d;
985 }
986
987 #define VIS_OP(name, F) \
988 void OPPROTO name##16(void) \
989 { \
990 vis64 s, d; \
991 \
992 s.d = DT0; \
993 d.d = DT1; \
994 \
995 d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0)); \
996 d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1)); \
997 d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2)); \
998 d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3)); \
999 \
1000 DT0 = d.d; \
1001 } \
1002 \
1003 void OPPROTO name##16s(void) \
1004 { \
1005 vis32 s, d; \
1006 \
1007 s.f = FT0; \
1008 d.f = FT1; \
1009 \
1010 d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0)); \
1011 d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1)); \
1012 \
1013 FT0 = d.f; \
1014 } \
1015 \
1016 void OPPROTO name##32(void) \
1017 { \
1018 vis64 s, d; \
1019 \
1020 s.d = DT0; \
1021 d.d = DT1; \
1022 \
1023 d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0)); \
1024 d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1)); \
1025 \
1026 DT0 = d.d; \
1027 } \
1028 \
1029 void OPPROTO name##32s(void) \
1030 { \
1031 vis32 s, d; \
1032 \
1033 s.f = FT0; \
1034 d.f = FT1; \
1035 \
1036 d.l = F(d.l, s.l); \
1037 \
1038 FT0 = d.f; \
1039 }
1040
1041 #define FADD(a, b) ((a) + (b))
1042 #define FSUB(a, b) ((a) - (b))
1043 VIS_OP(op_fpadd, FADD)
1044 VIS_OP(op_fpsub, FSUB)
1045
1046 #define VIS_CMPOP(name, F) \
1047 void OPPROTO name##16(void) \
1048 { \
1049 vis64 s, d; \
1050 \
1051 s.d = DT0; \
1052 d.d = DT1; \
1053 \
1054 d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0; \
1055 d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0; \
1056 d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0; \
1057 d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0; \
1058 \
1059 DT0 = d.d; \
1060 } \
1061 \
1062 void OPPROTO name##32(void) \
1063 { \
1064 vis64 s, d; \
1065 \
1066 s.d = DT0; \
1067 d.d = DT1; \
1068 \
1069 d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0; \
1070 d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0; \
1071 \
1072 DT0 = d.d; \
1073 }
1074
1075 #define FCMPGT(a, b) ((a) > (b))
1076 #define FCMPEQ(a, b) ((a) == (b))
1077 #define FCMPLE(a, b) ((a) <= (b))
1078 #define FCMPNE(a, b) ((a) != (b))
1079
1080 VIS_CMPOP(op_fcmpgt, FCMPGT)
1081 VIS_CMPOP(op_fcmpeq, FCMPEQ)
1082 VIS_CMPOP(op_fcmple, FCMPLE)
1083 VIS_CMPOP(op_fcmpne, FCMPNE)
1084
1085 #endif
1086
1087 #define CHECK_ALIGN_OP(align) \
1088 void OPPROTO op_check_align_T0_ ## align (void) \
1089 { \
1090 if (T0 & align) \
1091 raise_exception(TT_UNALIGNED); \
1092 FORCE_RET(); \
1093 }
1094
1095 CHECK_ALIGN_OP(1)
1096 CHECK_ALIGN_OP(3)
1097 CHECK_ALIGN_OP(7)