Ignore reads to the EOI register.
[qemu-kvm/amd-iommu.git] / target-sparc / op.c
blob921699e4c0945853c9c851a9969869209daa9f2d
1 /*
2 SPARC micro operations
4 Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
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.
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.
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
21 #include "exec.h"
22 #include "helper.h"
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"
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
172 #define FLAG_SET(x) ((env->psr&x)?1:0)
174 void OPPROTO op_umul_T1_T0(void)
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;
186 void OPPROTO op_smul_T1_T0(void)
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;
198 void OPPROTO op_mulscc_T1_T0(void)
200 unsigned int b1, N, V, b2;
201 target_ulong src1;
203 N = FLAG_SET(PSR_NEG);
204 V = FLAG_SET(PSR_OVF);
205 b1 = N ^ V;
206 b2 = T0 & 1;
207 T0 = (b1 << 31) | (T0 >> 1);
208 if (!(env->y & 1))
209 T1 = 0;
210 /* do addition and update flags */
211 src1 = T0;
212 T0 += T1;
213 env->psr = 0;
214 if (!T0)
215 env->psr |= PSR_ZERO;
216 if ((int32_t) T0 < 0)
217 env->psr |= PSR_NEG;
218 if (T0 < src1)
219 env->psr |= PSR_CARRY;
220 if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
221 env->psr |= PSR_OVF;
222 env->y = (b2 << 31) | (env->y >> 1);
223 FORCE_RET();
226 void OPPROTO op_udiv_T1_T0(void)
228 uint64_t x0;
229 uint32_t x1;
231 x0 = T0 | ((uint64_t) (env->y) << 32);
232 x1 = T1;
234 if (x1 == 0) {
235 raise_exception(TT_DIV_ZERO);
238 x0 = x0 / x1;
239 if (x0 > 0xffffffff) {
240 T0 = 0xffffffff;
241 T1 = 1;
242 } else {
243 T0 = x0;
244 T1 = 0;
246 FORCE_RET();
249 void OPPROTO op_sdiv_T1_T0(void)
251 int64_t x0;
252 int32_t x1;
254 x0 = T0 | ((int64_t) (env->y) << 32);
255 x1 = T1;
257 if (x1 == 0) {
258 raise_exception(TT_DIV_ZERO);
261 x0 = x0 / x1;
262 if ((int32_t) x0 != x0) {
263 T0 = x0 < 0? 0x80000000: 0x7fffffff;
264 T1 = 1;
265 } else {
266 T0 = x0;
267 T1 = 0;
269 FORCE_RET();
272 /* Load and store */
273 #define MEMSUFFIX _raw
274 #include "op_mem.h"
275 #if !defined(CONFIG_USER_ONLY)
276 #define MEMSUFFIX _user
277 #include "op_mem.h"
279 #define MEMSUFFIX _kernel
280 #include "op_mem.h"
282 #ifdef TARGET_SPARC64
283 #define MEMSUFFIX _hypv
284 #include "op_mem.h"
285 #endif
286 #endif
288 #ifndef TARGET_SPARC64
289 /* XXX: use another pointer for %iN registers to avoid slow wrapping
290 handling ? */
291 void OPPROTO op_save(void)
293 uint32_t cwp;
294 cwp = (env->cwp - 1) & (NWINDOWS - 1);
295 if (env->wim & (1 << cwp)) {
296 raise_exception(TT_WIN_OVF);
298 set_cwp(cwp);
299 FORCE_RET();
302 void OPPROTO op_restore(void)
304 uint32_t cwp;
305 cwp = (env->cwp + 1) & (NWINDOWS - 1);
306 if (env->wim & (1 << cwp)) {
307 raise_exception(TT_WIN_UNF);
309 set_cwp(cwp);
310 FORCE_RET();
312 #else
313 void OPPROTO op_rdccr(void)
315 T0 = GET_CCR(env);
318 void OPPROTO op_wrccr(void)
320 PUT_CCR(env, T0);
323 // CWP handling is reversed in V9, but we still use the V8 register
324 // order.
325 void OPPROTO op_rdcwp(void)
327 T0 = GET_CWP64(env);
330 void OPPROTO op_wrcwp(void)
332 PUT_CWP64(env, T0);
335 /* XXX: use another pointer for %iN registers to avoid slow wrapping
336 handling ? */
337 void OPPROTO op_save(void)
339 uint32_t cwp;
340 cwp = (env->cwp - 1) & (NWINDOWS - 1);
341 if (env->cansave == 0) {
342 raise_exception(TT_SPILL | (env->otherwin != 0 ?
343 (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
344 ((env->wstate & 0x7) << 2)));
345 } else {
346 if (env->cleanwin - env->canrestore == 0) {
347 // XXX Clean windows without trap
348 raise_exception(TT_CLRWIN);
349 } else {
350 env->cansave--;
351 env->canrestore++;
352 set_cwp(cwp);
355 FORCE_RET();
358 void OPPROTO op_restore(void)
360 uint32_t cwp;
361 cwp = (env->cwp + 1) & (NWINDOWS - 1);
362 if (env->canrestore == 0) {
363 raise_exception(TT_FILL | (env->otherwin != 0 ?
364 (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
365 ((env->wstate & 0x7) << 2)));
366 } else {
367 env->cansave++;
368 env->canrestore--;
369 set_cwp(cwp);
371 FORCE_RET();
373 #endif
375 void OPPROTO op_jmp_label(void)
377 GOTO_LABEL_PARAM(1);
380 #define F_OP(name, p) void OPPROTO op_f##name##p(void)
382 #if defined(CONFIG_USER_ONLY)
383 #define F_BINOP(name) \
384 F_OP(name, s) \
386 FT0 = float32_ ## name (FT0, FT1, &env->fp_status); \
388 F_OP(name, d) \
390 DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
392 F_OP(name, q) \
394 QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \
396 #else
397 #define F_BINOP(name) \
398 F_OP(name, s) \
400 FT0 = float32_ ## name (FT0, FT1, &env->fp_status); \
402 F_OP(name, d) \
404 DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
406 #endif
408 F_BINOP(add);
409 F_BINOP(sub);
410 F_BINOP(mul);
411 F_BINOP(div);
412 #undef F_BINOP
414 void OPPROTO op_fsmuld(void)
416 DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
417 float32_to_float64(FT1, &env->fp_status),
418 &env->fp_status);
421 #if defined(CONFIG_USER_ONLY)
422 void OPPROTO op_fdmulq(void)
424 QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
425 float64_to_float128(DT1, &env->fp_status),
426 &env->fp_status);
428 #endif
430 #if defined(CONFIG_USER_ONLY)
431 #define F_HELPER(name) \
432 F_OP(name, s) \
434 do_f##name##s(); \
436 F_OP(name, d) \
438 do_f##name##d(); \
440 F_OP(name, q) \
442 do_f##name##q(); \
444 #else
445 #define F_HELPER(name) \
446 F_OP(name, s) \
448 do_f##name##s(); \
450 F_OP(name, d) \
452 do_f##name##d(); \
454 #endif
456 F_OP(neg, s)
458 FT0 = float32_chs(FT1);
461 #ifdef TARGET_SPARC64
462 F_OP(neg, d)
464 DT0 = float64_chs(DT1);
467 #if defined(CONFIG_USER_ONLY)
468 F_OP(neg, q)
470 QT0 = float128_chs(QT1);
473 #endif
475 #endif
477 /* Integer to float conversion. */
478 #ifdef USE_INT_TO_FLOAT_HELPERS
479 F_HELPER(ito);
480 #ifdef TARGET_SPARC64
481 F_HELPER(xto);
482 #endif
483 #else
484 F_OP(ito, s)
486 FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
489 F_OP(ito, d)
491 DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
494 #if defined(CONFIG_USER_ONLY)
495 F_OP(ito, q)
497 QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
499 #endif
501 #ifdef TARGET_SPARC64
502 F_OP(xto, s)
504 FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
507 F_OP(xto, d)
509 DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
511 #if defined(CONFIG_USER_ONLY)
512 F_OP(xto, q)
514 QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
516 #endif
517 #endif
518 #endif
519 #undef F_HELPER
521 /* floating point conversion */
522 void OPPROTO op_fdtos(void)
524 FT0 = float64_to_float32(DT1, &env->fp_status);
527 void OPPROTO op_fstod(void)
529 DT0 = float32_to_float64(FT1, &env->fp_status);
532 #if defined(CONFIG_USER_ONLY)
533 void OPPROTO op_fqtos(void)
535 FT0 = float128_to_float32(QT1, &env->fp_status);
538 void OPPROTO op_fstoq(void)
540 QT0 = float32_to_float128(FT1, &env->fp_status);
543 void OPPROTO op_fqtod(void)
545 DT0 = float128_to_float64(QT1, &env->fp_status);
548 void OPPROTO op_fdtoq(void)
550 QT0 = float64_to_float128(DT1, &env->fp_status);
552 #endif
554 /* Float to integer conversion. */
555 void OPPROTO op_fstoi(void)
557 *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
560 void OPPROTO op_fdtoi(void)
562 *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
565 #if defined(CONFIG_USER_ONLY)
566 void OPPROTO op_fqtoi(void)
568 *((int32_t *)&FT0) = float128_to_int32_round_to_zero(QT1, &env->fp_status);
570 #endif
572 #ifdef TARGET_SPARC64
573 void OPPROTO op_fstox(void)
575 *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
578 void OPPROTO op_fdtox(void)
580 *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
583 #if defined(CONFIG_USER_ONLY)
584 void OPPROTO op_fqtox(void)
586 *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
588 #endif
590 void OPPROTO op_flushw(void)
592 if (env->cansave != NWINDOWS - 2) {
593 raise_exception(TT_SPILL | (env->otherwin != 0 ?
594 (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
595 ((env->wstate & 0x7) << 2)));
599 void OPPROTO op_saved(void)
601 env->cansave++;
602 if (env->otherwin == 0)
603 env->canrestore--;
604 else
605 env->otherwin--;
606 FORCE_RET();
609 void OPPROTO op_restored(void)
611 env->canrestore++;
612 if (env->cleanwin < NWINDOWS - 1)
613 env->cleanwin++;
614 if (env->otherwin == 0)
615 env->cansave--;
616 else
617 env->otherwin--;
618 FORCE_RET();
620 #endif
622 #ifdef TARGET_SPARC64
623 // This function uses non-native bit order
624 #define GET_FIELD(X, FROM, TO) \
625 ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
627 // This function uses the order in the manuals, i.e. bit 0 is 2^0
628 #define GET_FIELD_SP(X, FROM, TO) \
629 GET_FIELD(X, 63 - (TO), 63 - (FROM))
631 void OPPROTO op_array8()
633 T0 = (GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
634 (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
635 (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
636 (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
637 (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
638 (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12);
641 void OPPROTO op_array16()
643 T0 = ((GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
644 (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
645 (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
646 (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
647 (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
648 (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12)) << 1;
651 void OPPROTO op_array32()
653 T0 = ((GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
654 (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
655 (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
656 (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
657 (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
658 (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12)) << 2;
661 void OPPROTO op_alignaddr()
663 uint64_t tmp;
665 tmp = T0 + T1;
666 env->gsr &= ~7ULL;
667 env->gsr |= tmp & 7ULL;
668 T0 = tmp & ~7ULL;
671 void OPPROTO op_faligndata()
673 uint64_t tmp;
675 tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
676 tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
677 *((uint64_t *)&DT0) = tmp;
680 void OPPROTO op_movl_FT0_0(void)
682 *((uint32_t *)&FT0) = 0;
685 void OPPROTO op_movl_DT0_0(void)
687 *((uint64_t *)&DT0) = 0;
690 void OPPROTO op_movl_FT0_1(void)
692 *((uint32_t *)&FT0) = 0xffffffff;
695 void OPPROTO op_movl_DT0_1(void)
697 *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
700 void OPPROTO op_fnot(void)
702 *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
705 void OPPROTO op_fnots(void)
707 *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
710 void OPPROTO op_fnor(void)
712 *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
715 void OPPROTO op_fnors(void)
717 *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
720 void OPPROTO op_for(void)
722 *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
725 void OPPROTO op_fors(void)
727 *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
730 void OPPROTO op_fxor(void)
732 *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
735 void OPPROTO op_fxors(void)
737 *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
740 void OPPROTO op_fand(void)
742 *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
745 void OPPROTO op_fands(void)
747 *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
750 void OPPROTO op_fornot(void)
752 *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
755 void OPPROTO op_fornots(void)
757 *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
760 void OPPROTO op_fandnot(void)
762 *(uint64_t *)&DT0 = *(uint64_t *)&DT0 & ~*(uint64_t *)&DT1;
765 void OPPROTO op_fandnots(void)
767 *(uint32_t *)&FT0 = *(uint32_t *)&FT0 & ~*(uint32_t *)&FT1;
770 void OPPROTO op_fnand(void)
772 *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 & *(uint64_t *)&DT1);
775 void OPPROTO op_fnands(void)
777 *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 & *(uint32_t *)&FT1);
780 void OPPROTO op_fxnor(void)
782 *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
785 void OPPROTO op_fxnors(void)
787 *(uint32_t *)&FT0 ^= ~*(uint32_t *)&FT1;
790 #ifdef WORDS_BIGENDIAN
791 #define VIS_B64(n) b[7 - (n)]
792 #define VIS_W64(n) w[3 - (n)]
793 #define VIS_SW64(n) sw[3 - (n)]
794 #define VIS_L64(n) l[1 - (n)]
795 #define VIS_B32(n) b[3 - (n)]
796 #define VIS_W32(n) w[1 - (n)]
797 #else
798 #define VIS_B64(n) b[n]
799 #define VIS_W64(n) w[n]
800 #define VIS_SW64(n) sw[n]
801 #define VIS_L64(n) l[n]
802 #define VIS_B32(n) b[n]
803 #define VIS_W32(n) w[n]
804 #endif
806 typedef union {
807 uint8_t b[8];
808 uint16_t w[4];
809 int16_t sw[4];
810 uint32_t l[2];
811 float64 d;
812 } vis64;
814 typedef union {
815 uint8_t b[4];
816 uint16_t w[2];
817 uint32_t l;
818 float32 f;
819 } vis32;
821 void OPPROTO op_fpmerge(void)
823 vis64 s, d;
825 s.d = DT0;
826 d.d = DT1;
828 // Reverse calculation order to handle overlap
829 d.VIS_B64(7) = s.VIS_B64(3);
830 d.VIS_B64(6) = d.VIS_B64(3);
831 d.VIS_B64(5) = s.VIS_B64(2);
832 d.VIS_B64(4) = d.VIS_B64(2);
833 d.VIS_B64(3) = s.VIS_B64(1);
834 d.VIS_B64(2) = d.VIS_B64(1);
835 d.VIS_B64(1) = s.VIS_B64(0);
836 //d.VIS_B64(0) = d.VIS_B64(0);
838 DT0 = d.d;
841 void OPPROTO op_fmul8x16(void)
843 vis64 s, d;
844 uint32_t tmp;
846 s.d = DT0;
847 d.d = DT1;
849 #define PMUL(r) \
850 tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r); \
851 if ((tmp & 0xff) > 0x7f) \
852 tmp += 0x100; \
853 d.VIS_W64(r) = tmp >> 8;
855 PMUL(0);
856 PMUL(1);
857 PMUL(2);
858 PMUL(3);
859 #undef PMUL
861 DT0 = d.d;
864 void OPPROTO op_fmul8x16al(void)
866 vis64 s, d;
867 uint32_t tmp;
869 s.d = DT0;
870 d.d = DT1;
872 #define PMUL(r) \
873 tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r); \
874 if ((tmp & 0xff) > 0x7f) \
875 tmp += 0x100; \
876 d.VIS_W64(r) = tmp >> 8;
878 PMUL(0);
879 PMUL(1);
880 PMUL(2);
881 PMUL(3);
882 #undef PMUL
884 DT0 = d.d;
887 void OPPROTO op_fmul8x16au(void)
889 vis64 s, d;
890 uint32_t tmp;
892 s.d = DT0;
893 d.d = DT1;
895 #define PMUL(r) \
896 tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r); \
897 if ((tmp & 0xff) > 0x7f) \
898 tmp += 0x100; \
899 d.VIS_W64(r) = tmp >> 8;
901 PMUL(0);
902 PMUL(1);
903 PMUL(2);
904 PMUL(3);
905 #undef PMUL
907 DT0 = d.d;
910 void OPPROTO op_fmul8sux16(void)
912 vis64 s, d;
913 uint32_t tmp;
915 s.d = DT0;
916 d.d = DT1;
918 #define PMUL(r) \
919 tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
920 if ((tmp & 0xff) > 0x7f) \
921 tmp += 0x100; \
922 d.VIS_W64(r) = tmp >> 8;
924 PMUL(0);
925 PMUL(1);
926 PMUL(2);
927 PMUL(3);
928 #undef PMUL
930 DT0 = d.d;
933 void OPPROTO op_fmul8ulx16(void)
935 vis64 s, d;
936 uint32_t tmp;
938 s.d = DT0;
939 d.d = DT1;
941 #define PMUL(r) \
942 tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
943 if ((tmp & 0xff) > 0x7f) \
944 tmp += 0x100; \
945 d.VIS_W64(r) = tmp >> 8;
947 PMUL(0);
948 PMUL(1);
949 PMUL(2);
950 PMUL(3);
951 #undef PMUL
953 DT0 = d.d;
956 void OPPROTO op_fmuld8sux16(void)
958 vis64 s, d;
959 uint32_t tmp;
961 s.d = DT0;
962 d.d = DT1;
964 #define PMUL(r) \
965 tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
966 if ((tmp & 0xff) > 0x7f) \
967 tmp += 0x100; \
968 d.VIS_L64(r) = tmp;
970 // Reverse calculation order to handle overlap
971 PMUL(1);
972 PMUL(0);
973 #undef PMUL
975 DT0 = d.d;
978 void OPPROTO op_fmuld8ulx16(void)
980 vis64 s, d;
981 uint32_t tmp;
983 s.d = DT0;
984 d.d = DT1;
986 #define PMUL(r) \
987 tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
988 if ((tmp & 0xff) > 0x7f) \
989 tmp += 0x100; \
990 d.VIS_L64(r) = tmp;
992 // Reverse calculation order to handle overlap
993 PMUL(1);
994 PMUL(0);
995 #undef PMUL
997 DT0 = d.d;
1000 void OPPROTO op_fexpand(void)
1002 vis32 s;
1003 vis64 d;
1005 s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
1006 d.d = DT1;
1007 d.VIS_L64(0) = s.VIS_W32(0) << 4;
1008 d.VIS_L64(1) = s.VIS_W32(1) << 4;
1009 d.VIS_L64(2) = s.VIS_W32(2) << 4;
1010 d.VIS_L64(3) = s.VIS_W32(3) << 4;
1012 DT0 = d.d;
1015 #define VIS_OP(name, F) \
1016 void OPPROTO name##16(void) \
1018 vis64 s, d; \
1020 s.d = DT0; \
1021 d.d = DT1; \
1023 d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0)); \
1024 d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1)); \
1025 d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2)); \
1026 d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3)); \
1028 DT0 = d.d; \
1031 void OPPROTO name##16s(void) \
1033 vis32 s, d; \
1035 s.f = FT0; \
1036 d.f = FT1; \
1038 d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0)); \
1039 d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1)); \
1041 FT0 = d.f; \
1044 void OPPROTO name##32(void) \
1046 vis64 s, d; \
1048 s.d = DT0; \
1049 d.d = DT1; \
1051 d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0)); \
1052 d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1)); \
1054 DT0 = d.d; \
1057 void OPPROTO name##32s(void) \
1059 vis32 s, d; \
1061 s.f = FT0; \
1062 d.f = FT1; \
1064 d.l = F(d.l, s.l); \
1066 FT0 = d.f; \
1069 #define FADD(a, b) ((a) + (b))
1070 #define FSUB(a, b) ((a) - (b))
1071 VIS_OP(op_fpadd, FADD)
1072 VIS_OP(op_fpsub, FSUB)
1074 #define VIS_CMPOP(name, F) \
1075 void OPPROTO name##16(void) \
1077 vis64 s, d; \
1079 s.d = DT0; \
1080 d.d = DT1; \
1082 d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0; \
1083 d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0; \
1084 d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0; \
1085 d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0; \
1087 DT0 = d.d; \
1090 void OPPROTO name##32(void) \
1092 vis64 s, d; \
1094 s.d = DT0; \
1095 d.d = DT1; \
1097 d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0; \
1098 d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0; \
1100 DT0 = d.d; \
1103 #define FCMPGT(a, b) ((a) > (b))
1104 #define FCMPEQ(a, b) ((a) == (b))
1105 #define FCMPLE(a, b) ((a) <= (b))
1106 #define FCMPNE(a, b) ((a) != (b))
1108 VIS_CMPOP(op_fcmpgt, FCMPGT)
1109 VIS_CMPOP(op_fcmpeq, FCMPEQ)
1110 VIS_CMPOP(op_fcmple, FCMPLE)
1111 VIS_CMPOP(op_fcmpne, FCMPNE)
1113 #endif
1115 #define CHECK_ALIGN_OP(align) \
1116 void OPPROTO op_check_align_T0_ ## align (void) \
1118 if (T0 & align) \
1119 raise_exception(TT_UNALIGNED); \
1120 FORCE_RET(); \
1123 CHECK_ALIGN_OP(1)
1124 CHECK_ALIGN_OP(3)
1125 CHECK_ALIGN_OP(7)