Code provision for hypervisor mode memory accesses.
[qemu] / 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
23  /*XXX*/
24 #define REGNAME g0
25 #define REG (env->gregs[0])
26 #include "op_template.h"
27 #define REGNAME g1
28 #define REG (env->gregs[1])
29 #include "op_template.h"
30 #define REGNAME g2
31 #define REG (env->gregs[2])
32 #include "op_template.h"
33 #define REGNAME g3
34 #define REG (env->gregs[3])
35 #include "op_template.h"
36 #define REGNAME g4
37 #define REG (env->gregs[4])
38 #include "op_template.h"
39 #define REGNAME g5
40 #define REG (env->gregs[5])
41 #include "op_template.h"
42 #define REGNAME g6
43 #define REG (env->gregs[6])
44 #include "op_template.h"
45 #define REGNAME g7
46 #define REG (env->gregs[7])
47 #include "op_template.h"
48 #define REGNAME i0
49 #define REG (REGWPTR[16])
50 #include "op_template.h"
51 #define REGNAME i1
52 #define REG (REGWPTR[17])
53 #include "op_template.h"
54 #define REGNAME i2
55 #define REG (REGWPTR[18])
56 #include "op_template.h"
57 #define REGNAME i3
58 #define REG (REGWPTR[19])
59 #include "op_template.h"
60 #define REGNAME i4
61 #define REG (REGWPTR[20])
62 #include "op_template.h"
63 #define REGNAME i5
64 #define REG (REGWPTR[21])
65 #include "op_template.h"
66 #define REGNAME i6
67 #define REG (REGWPTR[22])
68 #include "op_template.h"
69 #define REGNAME i7
70 #define REG (REGWPTR[23])
71 #include "op_template.h"
72 #define REGNAME l0
73 #define REG (REGWPTR[8])
74 #include "op_template.h"
75 #define REGNAME l1
76 #define REG (REGWPTR[9])
77 #include "op_template.h"
78 #define REGNAME l2
79 #define REG (REGWPTR[10])
80 #include "op_template.h"
81 #define REGNAME l3
82 #define REG (REGWPTR[11])
83 #include "op_template.h"
84 #define REGNAME l4
85 #define REG (REGWPTR[12])
86 #include "op_template.h"
87 #define REGNAME l5
88 #define REG (REGWPTR[13])
89 #include "op_template.h"
90 #define REGNAME l6
91 #define REG (REGWPTR[14])
92 #include "op_template.h"
93 #define REGNAME l7
94 #define REG (REGWPTR[15])
95 #include "op_template.h"
96 #define REGNAME o0
97 #define REG (REGWPTR[0])
98 #include "op_template.h"
99 #define REGNAME o1
100 #define REG (REGWPTR[1])
101 #include "op_template.h"
102 #define REGNAME o2
103 #define REG (REGWPTR[2])
104 #include "op_template.h"
105 #define REGNAME o3
106 #define REG (REGWPTR[3])
107 #include "op_template.h"
108 #define REGNAME o4
109 #define REG (REGWPTR[4])
110 #include "op_template.h"
111 #define REGNAME o5
112 #define REG (REGWPTR[5])
113 #include "op_template.h"
114 #define REGNAME o6
115 #define REG (REGWPTR[6])
116 #include "op_template.h"
117 #define REGNAME o7
118 #define REG (REGWPTR[7])
119 #include "op_template.h"
120
121 #define REGNAME f0
122 #define REG (env->fpr[0])
123 #include "fop_template.h"
124 #define REGNAME f1
125 #define REG (env->fpr[1])
126 #include "fop_template.h"
127 #define REGNAME f2
128 #define REG (env->fpr[2])
129 #include "fop_template.h"
130 #define REGNAME f3
131 #define REG (env->fpr[3])
132 #include "fop_template.h"
133 #define REGNAME f4
134 #define REG (env->fpr[4])
135 #include "fop_template.h"
136 #define REGNAME f5
137 #define REG (env->fpr[5])
138 #include "fop_template.h"
139 #define REGNAME f6
140 #define REG (env->fpr[6])
141 #include "fop_template.h"
142 #define REGNAME f7
143 #define REG (env->fpr[7])
144 #include "fop_template.h"
145 #define REGNAME f8
146 #define REG (env->fpr[8])
147 #include "fop_template.h"
148 #define REGNAME f9
149 #define REG (env->fpr[9])
150 #include "fop_template.h"
151 #define REGNAME f10
152 #define REG (env->fpr[10])
153 #include "fop_template.h"
154 #define REGNAME f11
155 #define REG (env->fpr[11])
156 #include "fop_template.h"
157 #define REGNAME f12
158 #define REG (env->fpr[12])
159 #include "fop_template.h"
160 #define REGNAME f13
161 #define REG (env->fpr[13])
162 #include "fop_template.h"
163 #define REGNAME f14
164 #define REG (env->fpr[14])
165 #include "fop_template.h"
166 #define REGNAME f15
167 #define REG (env->fpr[15])
168 #include "fop_template.h"
169 #define REGNAME f16
170 #define REG (env->fpr[16])
171 #include "fop_template.h"
172 #define REGNAME f17
173 #define REG (env->fpr[17])
174 #include "fop_template.h"
175 #define REGNAME f18
176 #define REG (env->fpr[18])
177 #include "fop_template.h"
178 #define REGNAME f19
179 #define REG (env->fpr[19])
180 #include "fop_template.h"
181 #define REGNAME f20
182 #define REG (env->fpr[20])
183 #include "fop_template.h"
184 #define REGNAME f21
185 #define REG (env->fpr[21])
186 #include "fop_template.h"
187 #define REGNAME f22
188 #define REG (env->fpr[22])
189 #include "fop_template.h"
190 #define REGNAME f23
191 #define REG (env->fpr[23])
192 #include "fop_template.h"
193 #define REGNAME f24
194 #define REG (env->fpr[24])
195 #include "fop_template.h"
196 #define REGNAME f25
197 #define REG (env->fpr[25])
198 #include "fop_template.h"
199 #define REGNAME f26
200 #define REG (env->fpr[26])
201 #include "fop_template.h"
202 #define REGNAME f27
203 #define REG (env->fpr[27])
204 #include "fop_template.h"
205 #define REGNAME f28
206 #define REG (env->fpr[28])
207 #include "fop_template.h"
208 #define REGNAME f29
209 #define REG (env->fpr[29])
210 #include "fop_template.h"
211 #define REGNAME f30
212 #define REG (env->fpr[30])
213 #include "fop_template.h"
214 #define REGNAME f31
215 #define REG (env->fpr[31])
216 #include "fop_template.h"
217
218 #ifdef TARGET_SPARC64
219 #define REGNAME f32
220 #define REG (env->fpr[32])
221 #include "fop_template.h"
222 #define REGNAME f34
223 #define REG (env->fpr[34])
224 #include "fop_template.h"
225 #define REGNAME f36
226 #define REG (env->fpr[36])
227 #include "fop_template.h"
228 #define REGNAME f38
229 #define REG (env->fpr[38])
230 #include "fop_template.h"
231 #define REGNAME f40
232 #define REG (env->fpr[40])
233 #include "fop_template.h"
234 #define REGNAME f42
235 #define REG (env->fpr[42])
236 #include "fop_template.h"
237 #define REGNAME f44
238 #define REG (env->fpr[44])
239 #include "fop_template.h"
240 #define REGNAME f46
241 #define REG (env->fpr[46])
242 #include "fop_template.h"
243 #define REGNAME f48
244 #define REG (env->fpr[47])
245 #include "fop_template.h"
246 #define REGNAME f50
247 #define REG (env->fpr[50])
248 #include "fop_template.h"
249 #define REGNAME f52
250 #define REG (env->fpr[52])
251 #include "fop_template.h"
252 #define REGNAME f54
253 #define REG (env->fpr[54])
254 #include "fop_template.h"
255 #define REGNAME f56
256 #define REG (env->fpr[56])
257 #include "fop_template.h"
258 #define REGNAME f58
259 #define REG (env->fpr[58])
260 #include "fop_template.h"
261 #define REGNAME f60
262 #define REG (env->fpr[60])
263 #include "fop_template.h"
264 #define REGNAME f62
265 #define REG (env->fpr[62])
266 #include "fop_template.h"
267 #endif
268
269 #ifdef TARGET_SPARC64
270 #ifdef WORDS_BIGENDIAN
271 typedef union UREG64 {
272     struct { uint16_t v3, v2, v1, v0; } w;
273     struct { uint32_t v1, v0; } l;
274     uint64_t q;
275 } UREG64;
276 #else
277 typedef union UREG64 {
278     struct { uint16_t v0, v1, v2, v3; } w;
279     struct { uint32_t v0, v1; } l;
280     uint64_t q;
281 } UREG64;
282 #endif
283
284 #define PARAMQ1 \
285 ({\
286     UREG64 __p;\
287     __p.l.v1 = PARAM1;\
288     __p.l.v0 = PARAM2;\
289     __p.q;\
290 })
291
292 void OPPROTO op_movq_T0_im64(void)
293 {
294     T0 = PARAMQ1;
295 }
296
297 void OPPROTO op_movq_T1_im64(void)
298 {
299     T1 = PARAMQ1;
300 }
301
302 #define XFLAG_SET(x) ((env->xcc&x)?1:0)
303
304 #else
305 #define EIP (env->pc)
306 #endif
307
308 #define FLAG_SET(x) ((env->psr&x)?1:0)
309
310 void OPPROTO op_movl_T0_0(void)
311 {
312     T0 = 0;
313 }
314
315 void OPPROTO op_movl_T0_im(void)
316 {
317     T0 = (uint32_t)PARAM1;
318 }
319
320 void OPPROTO op_movl_T1_im(void)
321 {
322     T1 = (uint32_t)PARAM1;
323 }
324
325 void OPPROTO op_movl_T2_im(void)
326 {
327     T2 = (uint32_t)PARAM1;
328 }
329
330 void OPPROTO op_movl_T0_sim(void)
331 {
332     T0 = (int32_t)PARAM1;
333 }
334
335 void OPPROTO op_movl_T1_sim(void)
336 {
337     T1 = (int32_t)PARAM1;
338 }
339
340 void OPPROTO op_movl_T2_sim(void)
341 {
342     T2 = (int32_t)PARAM1;
343 }
344
345 void OPPROTO op_movl_T0_env(void)
346 {
347     T0 = *(uint32_t *)((char *)env + PARAM1);
348 }
349
350 void OPPROTO op_movl_env_T0(void)
351 {
352     *(uint32_t *)((char *)env + PARAM1) = T0;
353 }
354
355 void OPPROTO op_movtl_T0_env(void)
356 {
357     T0 = *(target_ulong *)((char *)env + PARAM1);
358 }
359
360 void OPPROTO op_movtl_env_T0(void)
361 {
362     *(target_ulong *)((char *)env + PARAM1) = T0;
363 }
364
365 void OPPROTO op_add_T1_T0(void)
366 {
367     T0 += T1;
368 }
369
370 void OPPROTO op_add_T1_T0_cc(void)
371 {
372     target_ulong src1;
373
374     src1 = T0;
375     T0 += T1;
376     env->psr = 0;
377 #ifdef TARGET_SPARC64
378     if (!(T0 & 0xffffffff))
379         env->psr |= PSR_ZERO;
380     if ((int32_t) T0 < 0)
381         env->psr |= PSR_NEG;
382     if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
383         env->psr |= PSR_CARRY;
384     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
385          ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
386         env->psr |= PSR_OVF;
387
388     env->xcc = 0;
389     if (!T0)
390         env->xcc |= PSR_ZERO;
391     if ((int64_t) T0 < 0)
392         env->xcc |= PSR_NEG;
393     if (T0 < src1)
394         env->xcc |= PSR_CARRY;
395     if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63))
396         env->xcc |= PSR_OVF;
397 #else
398     if (!T0)
399         env->psr |= PSR_ZERO;
400     if ((int32_t) T0 < 0)
401         env->psr |= PSR_NEG;
402     if (T0 < src1)
403         env->psr |= PSR_CARRY;
404     if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
405         env->psr |= PSR_OVF;
406 #endif
407     FORCE_RET();
408 }
409
410 void OPPROTO op_addx_T1_T0(void)
411 {
412     T0 += T1 + FLAG_SET(PSR_CARRY);
413 }
414
415 void OPPROTO op_addx_T1_T0_cc(void)
416 {
417     target_ulong src1;
418     src1 = T0;
419     if (FLAG_SET(PSR_CARRY))
420     {
421       T0 += T1 + 1;
422       env->psr = 0;
423 #ifdef TARGET_SPARC64
424       if ((T0 & 0xffffffff) <= (src1 & 0xffffffff))
425         env->psr |= PSR_CARRY;
426       env->xcc = 0;
427       if (T0 <= src1)
428         env->xcc |= PSR_CARRY;
429 #else
430       if (T0 <= src1)
431         env->psr |= PSR_CARRY;
432 #endif
433     }
434     else
435     {
436       T0 += T1;
437       env->psr = 0;
438 #ifdef TARGET_SPARC64
439       if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
440         env->psr |= PSR_CARRY;
441       env->xcc = 0;
442       if (T0 < src1)
443         env->xcc |= PSR_CARRY;
444 #else
445       if (T0 < src1)
446         env->psr |= PSR_CARRY;
447 #endif
448     }
449 #ifdef TARGET_SPARC64
450     if (!(T0 & 0xffffffff))
451         env->psr |= PSR_ZERO;
452     if ((int32_t) T0 < 0)
453         env->psr |= PSR_NEG;
454     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
455          ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
456         env->psr |= PSR_OVF;
457
458     if (!T0)
459         env->xcc |= PSR_ZERO;
460     if ((int64_t) T0 < 0)
461         env->xcc |= PSR_NEG;
462     if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63))
463         env->xcc |= PSR_OVF;
464 #else
465     if (!T0)
466         env->psr |= PSR_ZERO;
467     if ((int32_t) T0 < 0)
468         env->psr |= PSR_NEG;
469     if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
470         env->psr |= PSR_OVF;
471 #endif
472     FORCE_RET();
473 }
474
475 void OPPROTO op_tadd_T1_T0_cc(void)
476 {
477     target_ulong src1;
478
479     src1 = T0;
480     T0 += T1;
481     env->psr = 0;
482 #ifdef TARGET_SPARC64
483     if (!(T0 & 0xffffffff))
484         env->psr |= PSR_ZERO;
485     if ((int32_t) T0 < 0)
486         env->psr |= PSR_NEG;
487     if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
488         env->psr |= PSR_CARRY;
489     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
490          ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
491         env->psr |= PSR_OVF;
492     if ((src1 & 0x03) || (T1 & 0x03))
493         env->psr |= PSR_OVF;
494
495     env->xcc = 0;
496     if (!T0)
497         env->xcc |= PSR_ZERO;
498     if ((int64_t) T0 < 0)
499         env->xcc |= PSR_NEG;
500     if (T0 < src1)
501         env->xcc |= PSR_CARRY;
502     if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63))
503         env->xcc |= PSR_OVF;
504 #else
505     if (!T0)
506         env->psr |= PSR_ZERO;
507     if ((int32_t) T0 < 0)
508         env->psr |= PSR_NEG;
509     if (T0 < src1)
510         env->psr |= PSR_CARRY;
511     if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
512         env->psr |= PSR_OVF;
513     if ((src1 & 0x03) || (T1 & 0x03))
514         env->psr |= PSR_OVF;
515 #endif
516     FORCE_RET();
517 }
518
519 void OPPROTO op_tadd_T1_T0_ccTV(void)
520 {
521     target_ulong src1;
522
523     if ((T0 & 0x03) || (T1 & 0x03)) {
524         raise_exception(TT_TOVF);
525         FORCE_RET();
526         return;
527     }
528
529     src1 = T0;
530     T0 += T1;
531
532 #ifdef TARGET_SPARC64
533     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) &
534          ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
535         raise_exception(TT_TOVF);
536 #else
537     if ((src1 & 0x03) || (T1 & 0x03))
538         raise_exception(TT_TOVF);
539 #endif
540
541     env->psr = 0;
542 #ifdef TARGET_SPARC64
543     if (!(T0 & 0xffffffff))
544         env->psr |= PSR_ZERO;
545     if ((int32_t) T0 < 0)
546         env->psr |= PSR_NEG;
547     if ((T0 & 0xffffffff) < (src1 & 0xffffffff))
548         env->psr |= PSR_CARRY;
549
550     env->xcc = 0;
551     if (!T0)
552         env->xcc |= PSR_ZERO;
553     if ((int64_t) T0 < 0)
554         env->xcc |= PSR_NEG;
555     if (T0 < src1)
556         env->xcc |= PSR_CARRY;
557 #else
558     if (!T0)
559         env->psr |= PSR_ZERO;
560     if ((int32_t) T0 < 0)
561         env->psr |= PSR_NEG;
562     if (T0 < src1)
563         env->psr |= PSR_CARRY;
564 #endif
565     FORCE_RET();
566 }
567
568 void OPPROTO op_sub_T1_T0(void)
569 {
570     T0 -= T1;
571 }
572
573 void OPPROTO op_sub_T1_T0_cc(void)
574 {
575     target_ulong src1;
576
577     src1 = T0;
578     T0 -= T1;
579     env->psr = 0;
580 #ifdef TARGET_SPARC64
581     if (!(T0 & 0xffffffff))
582         env->psr |= PSR_ZERO;
583     if ((int32_t) T0 < 0)
584         env->psr |= PSR_NEG;
585     if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
586         env->psr |= PSR_CARRY;
587     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
588          ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
589         env->psr |= PSR_OVF;
590
591     env->xcc = 0;
592     if (!T0)
593         env->xcc |= PSR_ZERO;
594     if ((int64_t) T0 < 0)
595         env->xcc |= PSR_NEG;
596     if (src1 < T1)
597         env->xcc |= PSR_CARRY;
598     if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63))
599         env->xcc |= PSR_OVF;
600 #else
601     if (!T0)
602         env->psr |= PSR_ZERO;
603     if ((int32_t) T0 < 0)
604         env->psr |= PSR_NEG;
605     if (src1 < T1)
606         env->psr |= PSR_CARRY;
607     if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
608         env->psr |= PSR_OVF;
609 #endif
610     FORCE_RET();
611 }
612
613 void OPPROTO op_subx_T1_T0(void)
614 {
615     T0 -= T1 + FLAG_SET(PSR_CARRY);
616 }
617
618 void OPPROTO op_subx_T1_T0_cc(void)
619 {
620     target_ulong src1;
621     src1 = T0;
622     if (FLAG_SET(PSR_CARRY))
623     {
624       T0 -= T1 + 1;
625       env->psr = 0;
626 #ifdef TARGET_SPARC64
627       if ((src1 & 0xffffffff) <= (T1 & 0xffffffff))
628         env->psr |= PSR_CARRY;
629       env->xcc = 0;
630       if (src1 <= T1)
631         env->xcc |= PSR_CARRY;
632 #else
633       if (src1 <= T1)
634         env->psr |= PSR_CARRY;
635 #endif
636     }
637     else
638     {
639       T0 -= T1;
640       env->psr = 0;
641 #ifdef TARGET_SPARC64
642       if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
643         env->psr |= PSR_CARRY;
644       env->xcc = 0;
645       if (src1 < T1)
646         env->xcc |= PSR_CARRY;
647 #else
648       if (src1 < T1)
649         env->psr |= PSR_CARRY;
650 #endif
651     }
652 #ifdef TARGET_SPARC64
653     if (!(T0 & 0xffffffff))
654         env->psr |= PSR_ZERO;
655     if ((int32_t) T0 < 0)
656         env->psr |= PSR_NEG;
657     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
658          ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
659         env->psr |= PSR_OVF;
660
661     if (!T0)
662         env->xcc |= PSR_ZERO;
663     if ((int64_t) T0 < 0)
664         env->xcc |= PSR_NEG;
665     if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63))
666         env->xcc |= PSR_OVF;
667 #else
668     if (!T0)
669         env->psr |= PSR_ZERO;
670     if ((int32_t) T0 < 0)
671         env->psr |= PSR_NEG;
672     if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
673         env->psr |= PSR_OVF;
674 #endif
675     FORCE_RET();
676 }
677
678 void OPPROTO op_tsub_T1_T0_cc(void)
679 {
680     target_ulong src1;
681
682     src1 = T0;
683     T0 -= T1;
684     env->psr = 0;
685 #ifdef TARGET_SPARC64
686     if (!(T0 & 0xffffffff))
687         env->psr |= PSR_ZERO;
688     if ((int32_t) T0 < 0)
689         env->psr |= PSR_NEG;
690     if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
691         env->psr |= PSR_CARRY;
692     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
693          ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
694         env->psr |= PSR_OVF;
695     if ((src1 & 0x03) || (T1 & 0x03))
696         env->psr |= PSR_OVF;
697
698     env->xcc = 0;
699     if (!T0)
700         env->xcc |= PSR_ZERO;
701     if ((int64_t) T0 < 0)
702         env->xcc |= PSR_NEG;
703     if (src1 < T1)
704         env->xcc |= PSR_CARRY;
705     if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63))
706         env->xcc |= PSR_OVF;
707 #else
708     if (!T0)
709         env->psr |= PSR_ZERO;
710     if ((int32_t) T0 < 0)
711         env->psr |= PSR_NEG;
712     if (src1 < T1)
713         env->psr |= PSR_CARRY;
714     if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
715         env->psr |= PSR_OVF;
716     if ((src1 & 0x03) || (T1 & 0x03))
717         env->psr |= PSR_OVF;
718 #endif
719     FORCE_RET();
720 }
721
722 void OPPROTO op_tsub_T1_T0_ccTV(void)
723 {
724     target_ulong src1;
725
726     if ((T0 & 0x03) || (T1 & 0x03))
727         raise_exception(TT_TOVF);
728
729     src1 = T0;
730     T0 -= T1;
731
732 #ifdef TARGET_SPARC64
733     if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) &
734          ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31))
735         raise_exception(TT_TOVF);
736 #else
737     if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31))
738         raise_exception(TT_TOVF);
739 #endif
740
741     env->psr = 0;
742 #ifdef TARGET_SPARC64
743     if (!(T0 & 0xffffffff))
744         env->psr |= PSR_ZERO;
745     if ((int32_t) T0 < 0)
746         env->psr |= PSR_NEG;
747     if ((src1 & 0xffffffff) < (T1 & 0xffffffff))
748         env->psr |= PSR_CARRY;
749
750     env->xcc = 0;
751     if (!T0)
752         env->xcc |= PSR_ZERO;
753     if ((int64_t) T0 < 0)
754         env->xcc |= PSR_NEG;
755     if (src1 < T1)
756         env->xcc |= PSR_CARRY;
757 #else
758     if (!T0)
759         env->psr |= PSR_ZERO;
760     if ((int32_t) T0 < 0)
761         env->psr |= PSR_NEG;
762     if (src1 < T1)
763         env->psr |= PSR_CARRY;
764 #endif
765     FORCE_RET();
766 }
767
768 void OPPROTO op_and_T1_T0(void)
769 {
770     T0 &= T1;
771 }
772
773 void OPPROTO op_or_T1_T0(void)
774 {
775     T0 |= T1;
776 }
777
778 void OPPROTO op_xor_T1_T0(void)
779 {
780     T0 ^= T1;
781 }
782
783 void OPPROTO op_andn_T1_T0(void)
784 {
785     T0 &= ~T1;
786 }
787
788 void OPPROTO op_orn_T1_T0(void)
789 {
790     T0 |= ~T1;
791 }
792
793 void OPPROTO op_xnor_T1_T0(void)
794 {
795     T0 ^= ~T1;
796 }
797
798 void OPPROTO op_umul_T1_T0(void)
799 {
800     uint64_t res;
801     res = (uint64_t) T0 * (uint64_t) T1;
802 #ifdef TARGET_SPARC64
803     T0 = res;
804 #else
805     T0 = res & 0xffffffff;
806 #endif
807     env->y = res >> 32;
808 }
809
810 void OPPROTO op_smul_T1_T0(void)
811 {
812     uint64_t res;
813     res = (int64_t) ((int32_t) T0) * (int64_t) ((int32_t) T1);
814 #ifdef TARGET_SPARC64
815     T0 = res;
816 #else
817     T0 = res & 0xffffffff;
818 #endif
819     env->y = res >> 32;
820 }
821
822 void OPPROTO op_mulscc_T1_T0(void)
823 {
824     unsigned int b1, N, V, b2;
825     target_ulong src1;
826
827     N = FLAG_SET(PSR_NEG);
828     V = FLAG_SET(PSR_OVF);
829     b1 = N ^ V;
830     b2 = T0 & 1;
831     T0 = (b1 << 31) | (T0 >> 1);
832     if (!(env->y & 1))
833         T1 = 0;
834     /* do addition and update flags */
835     src1 = T0;
836     T0 += T1;
837     env->psr = 0;
838     if (!T0)
839         env->psr |= PSR_ZERO;
840     if ((int32_t) T0 < 0)
841         env->psr |= PSR_NEG;
842     if (T0 < src1)
843         env->psr |= PSR_CARRY;
844     if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31))
845         env->psr |= PSR_OVF;
846     env->y = (b2 << 31) | (env->y >> 1);
847     FORCE_RET();
848 }
849
850 void OPPROTO op_udiv_T1_T0(void)
851 {
852     uint64_t x0;
853     uint32_t x1;
854
855     x0 = T0 | ((uint64_t) (env->y) << 32);
856     x1 = T1;
857
858     if (x1 == 0) {
859         raise_exception(TT_DIV_ZERO);
860     }
861
862     x0 = x0 / x1;
863     if (x0 > 0xffffffff) {
864         T0 = 0xffffffff;
865         T1 = 1;
866     } else {
867         T0 = x0;
868         T1 = 0;
869     }
870     FORCE_RET();
871 }
872
873 void OPPROTO op_sdiv_T1_T0(void)
874 {
875     int64_t x0;
876     int32_t x1;
877
878     x0 = T0 | ((int64_t) (env->y) << 32);
879     x1 = T1;
880
881     if (x1 == 0) {
882         raise_exception(TT_DIV_ZERO);
883     }
884
885     x0 = x0 / x1;
886     if ((int32_t) x0 != x0) {
887         T0 = x0 < 0? 0x80000000: 0x7fffffff;
888         T1 = 1;
889     } else {
890         T0 = x0;
891         T1 = 0;
892     }
893     FORCE_RET();
894 }
895
896 void OPPROTO op_div_cc(void)
897 {
898     env->psr = 0;
899 #ifdef TARGET_SPARC64
900     if (!T0)
901         env->psr |= PSR_ZERO;
902     if ((int32_t) T0 < 0)
903         env->psr |= PSR_NEG;
904     if (T1)
905         env->psr |= PSR_OVF;
906
907     env->xcc = 0;
908     if (!T0)
909         env->xcc |= PSR_ZERO;
910     if ((int64_t) T0 < 0)
911         env->xcc |= PSR_NEG;
912 #else
913     if (!T0)
914         env->psr |= PSR_ZERO;
915     if ((int32_t) T0 < 0)
916         env->psr |= PSR_NEG;
917     if (T1)
918         env->psr |= PSR_OVF;
919 #endif
920     FORCE_RET();
921 }
922
923 #ifdef TARGET_SPARC64
924 void OPPROTO op_mulx_T1_T0(void)
925 {
926     T0 *= T1;
927     FORCE_RET();
928 }
929
930 void OPPROTO op_udivx_T1_T0(void)
931 {
932     if (T1 == 0) {
933         raise_exception(TT_DIV_ZERO);
934     }
935     T0 /= T1;
936     FORCE_RET();
937 }
938
939 void OPPROTO op_sdivx_T1_T0(void)
940 {
941     if (T1 == 0) {
942         raise_exception(TT_DIV_ZERO);
943     }
944     if (T0 == INT64_MIN && T1 == -1)
945         T0 = INT64_MIN;
946     else
947         T0 /= (target_long) T1;
948     FORCE_RET();
949 }
950 #endif
951
952 void OPPROTO op_logic_T0_cc(void)
953 {
954     env->psr = 0;
955 #ifdef TARGET_SPARC64
956     if (!(T0 & 0xffffffff))
957         env->psr |= PSR_ZERO;
958     if ((int32_t) T0 < 0)
959         env->psr |= PSR_NEG;
960
961     env->xcc = 0;
962     if (!T0)
963         env->xcc |= PSR_ZERO;
964     if ((int64_t) T0 < 0)
965         env->xcc |= PSR_NEG;
966 #else
967     if (!T0)
968         env->psr |= PSR_ZERO;
969     if ((int32_t) T0 < 0)
970         env->psr |= PSR_NEG;
971 #endif
972     FORCE_RET();
973 }
974
975 void OPPROTO op_sll(void)
976 {
977     T0 <<= (T1 & 0x1f);
978 }
979
980 #ifdef TARGET_SPARC64
981 void OPPROTO op_sllx(void)
982 {
983     T0 <<= (T1 & 0x3f);
984 }
985
986 void OPPROTO op_srl(void)
987 {
988     T0 = (T0 & 0xffffffff) >> (T1 & 0x1f);
989 }
990
991 void OPPROTO op_srlx(void)
992 {
993     T0 >>= (T1 & 0x3f);
994 }
995
996 void OPPROTO op_sra(void)
997 {
998     T0 = ((int32_t) (T0 & 0xffffffff)) >> (T1 & 0x1f);
999 }
1000
1001 void OPPROTO op_srax(void)
1002 {
1003     T0 = ((int64_t) T0) >> (T1 & 0x3f);
1004 }
1005 #else
1006 void OPPROTO op_srl(void)
1007 {
1008     T0 >>= (T1 & 0x1f);
1009 }
1010
1011 void OPPROTO op_sra(void)
1012 {
1013     T0 = ((int32_t) T0) >> (T1 & 0x1f);
1014 }
1015 #endif
1016
1017 /* Load and store */
1018 #define MEMSUFFIX _raw
1019 #include "op_mem.h"
1020 #if !defined(CONFIG_USER_ONLY)
1021 #define MEMSUFFIX _user
1022 #include "op_mem.h"
1023
1024 #define MEMSUFFIX _kernel
1025 #include "op_mem.h"
1026 #endif
1027
1028 void OPPROTO op_ldfsr(void)
1029 {
1030     PUT_FSR32(env, *((uint32_t *) &FT0));
1031     helper_ldfsr();
1032 }
1033
1034 void OPPROTO op_stfsr(void)
1035 {
1036     *((uint32_t *) &FT0) = GET_FSR32(env);
1037 }
1038
1039 #ifndef TARGET_SPARC64
1040 void OPPROTO op_rdpsr(void)
1041 {
1042     do_rdpsr();
1043 }
1044
1045 void OPPROTO op_wrpsr(void)
1046 {
1047     do_wrpsr();
1048     FORCE_RET();
1049 }
1050
1051 void OPPROTO op_wrwim(void)
1052 {
1053 #if NWINDOWS == 32
1054     env->wim = T0;
1055 #else
1056     env->wim = T0 & ((1 << NWINDOWS) - 1);
1057 #endif
1058 }
1059
1060 void OPPROTO op_rett(void)
1061 {
1062     helper_rett();
1063     FORCE_RET();
1064 }
1065
1066 /* XXX: use another pointer for %iN registers to avoid slow wrapping
1067    handling ? */
1068 void OPPROTO op_save(void)
1069 {
1070     uint32_t cwp;
1071     cwp = (env->cwp - 1) & (NWINDOWS - 1);
1072     if (env->wim & (1 << cwp)) {
1073         raise_exception(TT_WIN_OVF);
1074     }
1075     set_cwp(cwp);
1076     FORCE_RET();
1077 }
1078
1079 void OPPROTO op_restore(void)
1080 {
1081     uint32_t cwp;
1082     cwp = (env->cwp + 1) & (NWINDOWS - 1);
1083     if (env->wim & (1 << cwp)) {
1084         raise_exception(TT_WIN_UNF);
1085     }
1086     set_cwp(cwp);
1087     FORCE_RET();
1088 }
1089 #else
1090 void OPPROTO op_rdccr(void)
1091 {
1092     T0 = GET_CCR(env);
1093 }
1094
1095 void OPPROTO op_wrccr(void)
1096 {
1097     PUT_CCR(env, T0);
1098 }
1099
1100 void OPPROTO op_rdtick(void)
1101 {
1102     T0 = do_tick_get_count(env->tick);
1103 }
1104
1105 void OPPROTO op_wrtick(void)
1106 {
1107     do_tick_set_count(env->tick, T0);
1108 }
1109
1110 void OPPROTO op_wrtick_cmpr(void)
1111 {
1112     do_tick_set_limit(env->tick, T0);
1113 }
1114
1115 void OPPROTO op_rdstick(void)
1116 {
1117     T0 = do_tick_get_count(env->stick);
1118 }
1119
1120 void OPPROTO op_wrstick(void)
1121 {
1122     do_tick_set_count(env->stick, T0);
1123     do_tick_set_count(env->hstick, T0);
1124 }
1125
1126 void OPPROTO op_wrstick_cmpr(void)
1127 {
1128     do_tick_set_limit(env->stick, T0);
1129 }
1130
1131 void OPPROTO op_wrhstick_cmpr(void)
1132 {
1133     do_tick_set_limit(env->hstick, T0);
1134 }
1135
1136 void OPPROTO op_rdtpc(void)
1137 {
1138     T0 = env->tpc[env->tl];
1139 }
1140
1141 void OPPROTO op_wrtpc(void)
1142 {
1143     env->tpc[env->tl] = T0;
1144 }
1145
1146 void OPPROTO op_rdtnpc(void)
1147 {
1148     T0 = env->tnpc[env->tl];
1149 }
1150
1151 void OPPROTO op_wrtnpc(void)
1152 {
1153     env->tnpc[env->tl] = T0;
1154 }
1155
1156 void OPPROTO op_rdtstate(void)
1157 {
1158     T0 = env->tstate[env->tl];
1159 }
1160
1161 void OPPROTO op_wrtstate(void)
1162 {
1163     env->tstate[env->tl] = T0;
1164 }
1165
1166 void OPPROTO op_rdtt(void)
1167 {
1168     T0 = env->tt[env->tl];
1169 }
1170
1171 void OPPROTO op_wrtt(void)
1172 {
1173     env->tt[env->tl] = T0;
1174 }
1175
1176 void OPPROTO op_rdpstate(void)
1177 {
1178     T0 = env->pstate;
1179 }
1180
1181 void OPPROTO op_wrpstate(void)
1182 {
1183     do_wrpstate();
1184 }
1185
1186 // CWP handling is reversed in V9, but we still use the V8 register
1187 // order.
1188 void OPPROTO op_rdcwp(void)
1189 {
1190     T0 = GET_CWP64(env);
1191 }
1192
1193 void OPPROTO op_wrcwp(void)
1194 {
1195     PUT_CWP64(env, T0);
1196 }
1197
1198 /* XXX: use another pointer for %iN registers to avoid slow wrapping
1199    handling ? */
1200 void OPPROTO op_save(void)
1201 {
1202     uint32_t cwp;
1203     cwp = (env->cwp - 1) & (NWINDOWS - 1);
1204     if (env->cansave == 0) {
1205         raise_exception(TT_SPILL | (env->otherwin != 0 ?
1206                                     (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
1207                                     ((env->wstate & 0x7) << 2)));
1208     } else {
1209         if (env->cleanwin - env->canrestore == 0) {
1210             // XXX Clean windows without trap
1211             raise_exception(TT_CLRWIN);
1212         } else {
1213             env->cansave--;
1214             env->canrestore++;
1215             set_cwp(cwp);
1216         }
1217     }
1218     FORCE_RET();
1219 }
1220
1221 void OPPROTO op_restore(void)
1222 {
1223     uint32_t cwp;
1224     cwp = (env->cwp + 1) & (NWINDOWS - 1);
1225     if (env->canrestore == 0) {
1226         raise_exception(TT_FILL | (env->otherwin != 0 ?
1227                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
1228                                    ((env->wstate & 0x7) << 2)));
1229     } else {
1230         env->cansave++;
1231         env->canrestore--;
1232         set_cwp(cwp);
1233     }
1234     FORCE_RET();
1235 }
1236 #endif
1237
1238 void OPPROTO op_exception(void)
1239 {
1240     env->exception_index = PARAM1;
1241     cpu_loop_exit();
1242 }
1243
1244 void OPPROTO op_trap_T0(void)
1245 {
1246     env->exception_index = TT_TRAP + (T0 & 0x7f);
1247     cpu_loop_exit();
1248 }
1249
1250 void OPPROTO op_trapcc_T0(void)
1251 {
1252     if (T2) {
1253         env->exception_index = TT_TRAP + (T0 & 0x7f);
1254         cpu_loop_exit();
1255     }
1256     FORCE_RET();
1257 }
1258
1259 void OPPROTO op_fpexception_im(void)
1260 {
1261     env->exception_index = TT_FP_EXCP;
1262     env->fsr &= ~FSR_FTT_MASK;
1263     env->fsr |= PARAM1;
1264     cpu_loop_exit();
1265     FORCE_RET();
1266 }
1267
1268 void OPPROTO op_debug(void)
1269 {
1270     helper_debug();
1271 }
1272
1273 void OPPROTO op_exit_tb(void)
1274 {
1275     EXIT_TB();
1276 }
1277
1278 void OPPROTO op_eval_ba(void)
1279 {
1280     T2 = 1;
1281 }
1282
1283 void OPPROTO op_eval_be(void)
1284 {
1285     T2 = FLAG_SET(PSR_ZERO);
1286 }
1287
1288 void OPPROTO op_eval_ble(void)
1289 {
1290     target_ulong Z = FLAG_SET(PSR_ZERO), N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF);
1291
1292     T2 = Z | (N ^ V);
1293 }
1294
1295 void OPPROTO op_eval_bl(void)
1296 {
1297     target_ulong N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF);
1298
1299     T2 = N ^ V;
1300 }
1301
1302 void OPPROTO op_eval_bleu(void)
1303 {
1304     target_ulong Z = FLAG_SET(PSR_ZERO), C = FLAG_SET(PSR_CARRY);
1305
1306     T2 = C | Z;
1307 }
1308
1309 void OPPROTO op_eval_bcs(void)
1310 {
1311     T2 = FLAG_SET(PSR_CARRY);
1312 }
1313
1314 void OPPROTO op_eval_bvs(void)
1315 {
1316     T2 = FLAG_SET(PSR_OVF);
1317 }
1318
1319 void OPPROTO op_eval_bn(void)
1320 {
1321     T2 = 0;
1322 }
1323
1324 void OPPROTO op_eval_bneg(void)
1325 {
1326     T2 = FLAG_SET(PSR_NEG);
1327 }
1328
1329 void OPPROTO op_eval_bne(void)
1330 {
1331     T2 = !FLAG_SET(PSR_ZERO);
1332 }
1333
1334 void OPPROTO op_eval_bg(void)
1335 {
1336     target_ulong Z = FLAG_SET(PSR_ZERO), N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF);
1337
1338     T2 = !(Z | (N ^ V));
1339 }
1340
1341 void OPPROTO op_eval_bge(void)
1342 {
1343     target_ulong N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF);
1344
1345     T2 = !(N ^ V);
1346 }
1347
1348 void OPPROTO op_eval_bgu(void)
1349 {
1350     target_ulong Z = FLAG_SET(PSR_ZERO), C = FLAG_SET(PSR_CARRY);
1351
1352     T2 = !(C | Z);
1353 }
1354
1355 void OPPROTO op_eval_bcc(void)
1356 {
1357     T2 = !FLAG_SET(PSR_CARRY);
1358 }
1359
1360 void OPPROTO op_eval_bpos(void)
1361 {
1362     T2 = !FLAG_SET(PSR_NEG);
1363 }
1364
1365 void OPPROTO op_eval_bvc(void)
1366 {
1367     T2 = !FLAG_SET(PSR_OVF);
1368 }
1369
1370 #ifdef TARGET_SPARC64
1371 void OPPROTO op_eval_xbe(void)
1372 {
1373     T2 = XFLAG_SET(PSR_ZERO);
1374 }
1375
1376 void OPPROTO op_eval_xble(void)
1377 {
1378     target_ulong Z = XFLAG_SET(PSR_ZERO), N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF);
1379
1380     T2 = Z | (N ^ V);
1381 }
1382
1383 void OPPROTO op_eval_xbl(void)
1384 {
1385     target_ulong N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF);
1386
1387     T2 = N ^ V;
1388 }
1389
1390 void OPPROTO op_eval_xbleu(void)
1391 {
1392     target_ulong Z = XFLAG_SET(PSR_ZERO), C = XFLAG_SET(PSR_CARRY);
1393
1394     T2 = C | Z;
1395 }
1396
1397 void OPPROTO op_eval_xbcs(void)
1398 {
1399     T2 = XFLAG_SET(PSR_CARRY);
1400 }
1401
1402 void OPPROTO op_eval_xbvs(void)
1403 {
1404     T2 = XFLAG_SET(PSR_OVF);
1405 }
1406
1407 void OPPROTO op_eval_xbneg(void)
1408 {
1409     T2 = XFLAG_SET(PSR_NEG);
1410 }
1411
1412 void OPPROTO op_eval_xbne(void)
1413 {
1414     T2 = !XFLAG_SET(PSR_ZERO);
1415 }
1416
1417 void OPPROTO op_eval_xbg(void)
1418 {
1419     target_ulong Z = XFLAG_SET(PSR_ZERO), N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF);
1420
1421     T2 = !(Z | (N ^ V));
1422 }
1423
1424 void OPPROTO op_eval_xbge(void)
1425 {
1426     target_ulong N = XFLAG_SET(PSR_NEG), V = XFLAG_SET(PSR_OVF);
1427
1428     T2 = !(N ^ V);
1429 }
1430
1431 void OPPROTO op_eval_xbgu(void)
1432 {
1433     target_ulong Z = XFLAG_SET(PSR_ZERO), C = XFLAG_SET(PSR_CARRY);
1434
1435     T2 = !(C | Z);
1436 }
1437
1438 void OPPROTO op_eval_xbcc(void)
1439 {
1440     T2 = !XFLAG_SET(PSR_CARRY);
1441 }
1442
1443 void OPPROTO op_eval_xbpos(void)
1444 {
1445     T2 = !XFLAG_SET(PSR_NEG);
1446 }
1447
1448 void OPPROTO op_eval_xbvc(void)
1449 {
1450     T2 = !XFLAG_SET(PSR_OVF);
1451 }
1452 #endif
1453
1454 #define FCC
1455 #define FFLAG_SET(x) (env->fsr & x? 1: 0)
1456 #include "fbranch_template.h"
1457
1458 #ifdef TARGET_SPARC64
1459 #define FCC _fcc1
1460 #define FFLAG_SET(x) ((env->fsr & ((uint64_t)x >> 32))? 1: 0)
1461 #include "fbranch_template.h"
1462 #define FCC _fcc2
1463 #define FFLAG_SET(x) ((env->fsr & ((uint64_t)x >> 34))? 1: 0)
1464 #include "fbranch_template.h"
1465 #define FCC _fcc3
1466 #define FFLAG_SET(x) ((env->fsr & ((uint64_t)x >> 36))? 1: 0)
1467 #include "fbranch_template.h"
1468 #endif
1469
1470 #ifdef TARGET_SPARC64
1471 void OPPROTO op_eval_brz(void)
1472 {
1473     T2 = (T0 == 0);
1474 }
1475
1476 void OPPROTO op_eval_brnz(void)
1477 {
1478     T2 = (T0 != 0);
1479 }
1480
1481 void OPPROTO op_eval_brlz(void)
1482 {
1483     T2 = ((int64_t)T0 < 0);
1484 }
1485
1486 void OPPROTO op_eval_brlez(void)
1487 {
1488     T2 = ((int64_t)T0 <= 0);
1489 }
1490
1491 void OPPROTO op_eval_brgz(void)
1492 {
1493     T2 = ((int64_t)T0 > 0);
1494 }
1495
1496 void OPPROTO op_eval_brgez(void)
1497 {
1498     T2 = ((int64_t)T0 >= 0);
1499 }
1500
1501 void OPPROTO op_jmp_im64(void)
1502 {
1503     env->pc = PARAMQ1;
1504 }
1505
1506 void OPPROTO op_movq_npc_im64(void)
1507 {
1508     env->npc = PARAMQ1;
1509 }
1510 #endif
1511
1512 void OPPROTO op_jmp_im(void)
1513 {
1514     env->pc = (uint32_t)PARAM1;
1515 }
1516
1517 void OPPROTO op_movl_npc_im(void)
1518 {
1519     env->npc = (uint32_t)PARAM1;
1520 }
1521
1522 void OPPROTO op_movl_npc_T0(void)
1523 {
1524     env->npc = T0;
1525 }
1526
1527 void OPPROTO op_mov_pc_npc(void)
1528 {
1529     env->pc = env->npc;
1530 }
1531
1532 void OPPROTO op_next_insn(void)
1533 {
1534     env->pc = env->npc;
1535     env->npc = env->npc + 4;
1536 }
1537
1538 void OPPROTO op_goto_tb0(void)
1539 {
1540     GOTO_TB(op_goto_tb0, PARAM1, 0);
1541 }
1542
1543 void OPPROTO op_goto_tb1(void)
1544 {
1545     GOTO_TB(op_goto_tb1, PARAM1, 1);
1546 }
1547
1548 void OPPROTO op_jmp_label(void)
1549 {
1550     GOTO_LABEL_PARAM(1);
1551 }
1552
1553 void OPPROTO op_jnz_T2_label(void)
1554 {
1555     if (T2)
1556         GOTO_LABEL_PARAM(1);
1557     FORCE_RET();
1558 }
1559
1560 void OPPROTO op_jz_T2_label(void)
1561 {
1562     if (!T2)
1563         GOTO_LABEL_PARAM(1);
1564     FORCE_RET();
1565 }
1566
1567 void OPPROTO op_flush_T0(void)
1568 {
1569     helper_flush(T0);
1570 }
1571
1572 void OPPROTO op_clear_ieee_excp_and_FTT(void)
1573 {
1574     env->fsr &= ~(FSR_FTT_MASK | FSR_CEXC_MASK);;
1575 }
1576
1577 #define F_OP(name, p) void OPPROTO op_f##name##p(void)
1578
1579 #define F_BINOP(name)                                           \
1580     F_OP(name, s)                                               \
1581     {                                                           \
1582         set_float_exception_flags(0, &env->fp_status);          \
1583         FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
1584         check_ieee_exceptions();                                \
1585     }                                                           \
1586     F_OP(name, d)                                               \
1587     {                                                           \
1588         set_float_exception_flags(0, &env->fp_status);          \
1589         DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
1590         check_ieee_exceptions();                                \
1591     }
1592
1593 F_BINOP(add);
1594 F_BINOP(sub);
1595 F_BINOP(mul);
1596 F_BINOP(div);
1597 #undef F_BINOP
1598
1599 void OPPROTO op_fsmuld(void)
1600 {
1601     set_float_exception_flags(0, &env->fp_status);
1602     DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
1603                       float32_to_float64(FT1, &env->fp_status),
1604                       &env->fp_status);
1605     check_ieee_exceptions();
1606 }
1607
1608 #define F_HELPER(name)    \
1609     F_OP(name, s)         \
1610     {                     \
1611         do_f##name##s();  \
1612     }                     \
1613     F_OP(name, d)         \
1614     {                     \
1615         do_f##name##d();  \
1616     }
1617
1618 F_HELPER(sqrt);
1619
1620 F_OP(neg, s)
1621 {
1622     FT0 = float32_chs(FT1);
1623 }
1624
1625 F_OP(abs, s)
1626 {
1627     do_fabss();
1628 }
1629
1630 F_HELPER(cmp);
1631 F_HELPER(cmpe);
1632
1633 #ifdef TARGET_SPARC64
1634 F_OP(neg, d)
1635 {
1636     DT0 = float64_chs(DT1);
1637 }
1638
1639 F_OP(abs, d)
1640 {
1641     do_fabsd();
1642 }
1643
1644 void OPPROTO op_fcmps_fcc1(void)
1645 {
1646     do_fcmps_fcc1();
1647 }
1648
1649 void OPPROTO op_fcmpd_fcc1(void)
1650 {
1651     do_fcmpd_fcc1();
1652 }
1653
1654 void OPPROTO op_fcmps_fcc2(void)
1655 {
1656     do_fcmps_fcc2();
1657 }
1658
1659 void OPPROTO op_fcmpd_fcc2(void)
1660 {
1661     do_fcmpd_fcc2();
1662 }
1663
1664 void OPPROTO op_fcmps_fcc3(void)
1665 {
1666     do_fcmps_fcc3();
1667 }
1668
1669 void OPPROTO op_fcmpd_fcc3(void)
1670 {
1671     do_fcmpd_fcc3();
1672 }
1673
1674 void OPPROTO op_fcmpes_fcc1(void)
1675 {
1676     do_fcmpes_fcc1();
1677 }
1678
1679 void OPPROTO op_fcmped_fcc1(void)
1680 {
1681     do_fcmped_fcc1();
1682 }
1683
1684 void OPPROTO op_fcmpes_fcc2(void)
1685 {
1686     do_fcmpes_fcc2();
1687 }
1688
1689 void OPPROTO op_fcmped_fcc2(void)
1690 {
1691     do_fcmped_fcc2();
1692 }
1693
1694 void OPPROTO op_fcmpes_fcc3(void)
1695 {
1696     do_fcmpes_fcc3();
1697 }
1698
1699 void OPPROTO op_fcmped_fcc3(void)
1700 {
1701     do_fcmped_fcc3();
1702 }
1703
1704 #endif
1705
1706 /* Integer to float conversion.  */
1707 #ifdef USE_INT_TO_FLOAT_HELPERS
1708 F_HELPER(ito);
1709 #else
1710 F_OP(ito, s)
1711 {
1712     set_float_exception_flags(0, &env->fp_status);
1713     FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
1714     check_ieee_exceptions();
1715 }
1716
1717 F_OP(ito, d)
1718 {
1719     set_float_exception_flags(0, &env->fp_status);
1720     DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
1721     check_ieee_exceptions();
1722 }
1723
1724 #ifdef TARGET_SPARC64
1725 F_OP(xto, s)
1726 {
1727     set_float_exception_flags(0, &env->fp_status);
1728     FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
1729     check_ieee_exceptions();
1730 }
1731
1732 F_OP(xto, d)
1733 {
1734     set_float_exception_flags(0, &env->fp_status);
1735     DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
1736     check_ieee_exceptions();
1737 }
1738 #endif
1739 #endif
1740 #undef F_HELPER
1741
1742 /* floating point conversion */
1743 void OPPROTO op_fdtos(void)
1744 {
1745     set_float_exception_flags(0, &env->fp_status);
1746     FT0 = float64_to_float32(DT1, &env->fp_status);
1747     check_ieee_exceptions();
1748 }
1749
1750 void OPPROTO op_fstod(void)
1751 {
1752     set_float_exception_flags(0, &env->fp_status);
1753     DT0 = float32_to_float64(FT1, &env->fp_status);
1754     check_ieee_exceptions();
1755 }
1756
1757 /* Float to integer conversion.  */
1758 void OPPROTO op_fstoi(void)
1759 {
1760     set_float_exception_flags(0, &env->fp_status);
1761     *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
1762     check_ieee_exceptions();
1763 }
1764
1765 void OPPROTO op_fdtoi(void)
1766 {
1767     set_float_exception_flags(0, &env->fp_status);
1768     *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
1769     check_ieee_exceptions();
1770 }
1771
1772 #ifdef TARGET_SPARC64
1773 void OPPROTO op_fstox(void)
1774 {
1775     set_float_exception_flags(0, &env->fp_status);
1776     *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
1777     check_ieee_exceptions();
1778 }
1779
1780 void OPPROTO op_fdtox(void)
1781 {
1782     set_float_exception_flags(0, &env->fp_status);
1783     *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
1784     check_ieee_exceptions();
1785 }
1786
1787 void OPPROTO op_fmovs_cc(void)
1788 {
1789     if (T2)
1790         FT0 = FT1;
1791 }
1792
1793 void OPPROTO op_fmovd_cc(void)
1794 {
1795     if (T2)
1796         DT0 = DT1;
1797 }
1798
1799 void OPPROTO op_mov_cc(void)
1800 {
1801     if (T2)
1802         T0 = T1;
1803 }
1804
1805 void OPPROTO op_flushw(void)
1806 {
1807     if (env->cansave != NWINDOWS - 2) {
1808         raise_exception(TT_SPILL | (env->otherwin != 0 ?
1809                                     (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
1810                                     ((env->wstate & 0x7) << 2)));
1811     }
1812 }
1813
1814 void OPPROTO op_saved(void)
1815 {
1816     env->cansave++;
1817     if (env->otherwin == 0)
1818         env->canrestore--;
1819     else
1820         env->otherwin--;
1821     FORCE_RET();
1822 }
1823
1824 void OPPROTO op_restored(void)
1825 {
1826     env->canrestore++;
1827     if (env->cleanwin < NWINDOWS - 1)
1828         env->cleanwin++;
1829     if (env->otherwin == 0)
1830         env->cansave--;
1831     else
1832         env->otherwin--;
1833     FORCE_RET();
1834 }
1835
1836 void OPPROTO op_popc(void)
1837 {
1838     do_popc();
1839 }
1840
1841 void OPPROTO op_done(void)
1842 {
1843     do_done();
1844 }
1845
1846 void OPPROTO op_retry(void)
1847 {
1848     do_retry();
1849 }
1850
1851 void OPPROTO op_sir(void)
1852 {
1853     T0 = 0;  // XXX
1854 }
1855
1856 void OPPROTO op_ld_asi_reg()
1857 {
1858     T0 += PARAM1;
1859     helper_ld_asi(env->asi, PARAM2, PARAM3);
1860 }
1861
1862 void OPPROTO op_st_asi_reg()
1863 {
1864     T0 += PARAM1;
1865     helper_st_asi(env->asi, PARAM2);
1866 }
1867
1868 void OPPROTO op_ldf_asi_reg()
1869 {
1870     T0 += PARAM1;
1871     helper_ldf_asi(env->asi, PARAM2, PARAM3);
1872 }
1873
1874 void OPPROTO op_stf_asi_reg()
1875 {
1876     T0 += PARAM1;
1877     helper_stf_asi(env->asi, PARAM2, PARAM3);
1878 }
1879
1880 void OPPROTO op_ldf_asi()
1881 {
1882     helper_ldf_asi(PARAM1, PARAM2, PARAM3);
1883 }
1884
1885 void OPPROTO op_stf_asi()
1886 {
1887     helper_stf_asi(PARAM1, PARAM2, PARAM3);
1888 }
1889
1890 void OPPROTO op_ldstub_asi_reg()             /* XXX: should be atomically */
1891 {
1892     target_ulong tmp;
1893
1894     T0 += PARAM1;
1895     helper_ld_asi(env->asi, 1, 0);
1896     tmp = T1;
1897     T1 = 0xff;
1898     helper_st_asi(env->asi, 1);
1899     T1 = tmp;
1900 }
1901
1902 void OPPROTO op_swap_asi_reg()               /* XXX: should be atomically */
1903 {
1904     target_ulong tmp1, tmp2;
1905
1906     T0 += PARAM1;
1907     tmp1 = T1;
1908     helper_ld_asi(env->asi, 4, 0);
1909     tmp2 = T1;
1910     T1 = tmp1;
1911     helper_st_asi(env->asi, 4);
1912     T1 = tmp2;
1913 }
1914
1915 void OPPROTO op_ldda_asi()
1916 {
1917     helper_ld_asi(PARAM1, 8, 0);
1918     T0 = T1 & 0xffffffffUL;
1919     T1 >>= 32;
1920 }
1921
1922 void OPPROTO op_ldda_asi_reg()
1923 {
1924     T0 += PARAM1;
1925     helper_ld_asi(env->asi, 8, 0);
1926     T0 = T1 & 0xffffffffUL;
1927     T1 >>= 32;
1928 }
1929
1930 void OPPROTO op_stda_asi()
1931 {
1932     T1 <<= 32;
1933     T1 += T2 & 0xffffffffUL;
1934     helper_st_asi(PARAM1, 8);
1935 }
1936
1937 void OPPROTO op_stda_asi_reg()
1938 {
1939     T0 += PARAM1;
1940     T1 <<= 32;
1941     T1 += T2 & 0xffffffffUL;
1942     helper_st_asi(env->asi, 8);
1943 }
1944
1945 void OPPROTO op_cas_asi()                    /* XXX: should be atomically */
1946 {
1947     target_ulong tmp;
1948
1949     tmp = T1 & 0xffffffffUL;
1950     helper_ld_asi(PARAM1, 4, 0);
1951     if (tmp == T1) {
1952         tmp = T1;
1953         T1 = T2 & 0xffffffffUL;
1954         helper_st_asi(PARAM1, 4);
1955         T1 = tmp;
1956     }
1957     T1 &= 0xffffffffUL;
1958 }
1959
1960 void OPPROTO op_cas_asi_reg()                /* XXX: should be atomically */
1961 {
1962     target_ulong tmp;
1963
1964     T0 += PARAM1;
1965     tmp = T1 & 0xffffffffUL;
1966     helper_ld_asi(env->asi, 4, 0);
1967     if (tmp == T1) {
1968         tmp = T1;
1969         T1 = T2 & 0xffffffffUL;
1970         helper_st_asi(env->asi, 4);
1971         T1 = tmp;
1972     }
1973     T1 &= 0xffffffffUL;
1974 }
1975
1976 void OPPROTO op_casx_asi()                   /* XXX: should be atomically */
1977 {
1978     target_ulong tmp;
1979
1980     tmp = T1;
1981     helper_ld_asi(PARAM1, 8, 0);
1982     if (tmp == T1) {
1983         tmp = T1;
1984         T1 = T2;
1985         helper_st_asi(PARAM1, 8);
1986         T1 = tmp;
1987     }
1988 }
1989
1990 void OPPROTO op_casx_asi_reg()               /* XXX: should be atomically */
1991 {
1992     target_ulong tmp;
1993
1994     T0 += PARAM1;
1995     tmp = T1;
1996     helper_ld_asi(env->asi, 8, 0);
1997     if (tmp == T1) {
1998         tmp = T1;
1999         T1 = T2;
2000         helper_st_asi(env->asi, 8);
2001         T1 = tmp;
2002     }
2003 }
2004 #endif
2005
2006 #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
2007 void OPPROTO op_ld_asi()
2008 {
2009     helper_ld_asi(PARAM1, PARAM2, PARAM3);
2010 }
2011
2012 void OPPROTO op_st_asi()
2013 {
2014     helper_st_asi(PARAM1, PARAM2);
2015 }
2016
2017 void OPPROTO op_ldstub_asi()                 /* XXX: should be atomically */
2018 {
2019     target_ulong tmp;
2020
2021     helper_ld_asi(PARAM1, 1, 0);
2022     tmp = T1;
2023     T1 = 0xff;
2024     helper_st_asi(PARAM1, 1);
2025     T1 = tmp;
2026 }
2027
2028 void OPPROTO op_swap_asi()                   /* XXX: should be atomically */
2029 {
2030     target_ulong tmp1, tmp2;
2031
2032     tmp1 = T1;
2033     helper_ld_asi(PARAM1, 4, 0);
2034     tmp2 = T1;
2035     T1 = tmp1;
2036     helper_st_asi(PARAM1, 4);
2037     T1 = tmp2;
2038 }
2039 #endif
2040
2041 #ifdef TARGET_SPARC64
2042 // This function uses non-native bit order
2043 #define GET_FIELD(X, FROM, TO)                                  \
2044     ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
2045
2046 // This function uses the order in the manuals, i.e. bit 0 is 2^0
2047 #define GET_FIELD_SP(X, FROM, TO)               \
2048     GET_FIELD(X, 63 - (TO), 63 - (FROM))
2049
2050 void OPPROTO op_array8()
2051 {
2052     T0 = (GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
2053         (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
2054         (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
2055         (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
2056         (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
2057         (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12);
2058 }
2059
2060 void OPPROTO op_array16()
2061 {
2062     T0 = ((GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
2063           (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
2064           (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
2065           (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
2066           (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
2067           (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12)) << 1;
2068 }
2069
2070 void OPPROTO op_array32()
2071 {
2072     T0 = ((GET_FIELD_SP(T0, 60, 63) << (17 + 2 * T1)) |
2073           (GET_FIELD_SP(T0, 39, 39 + T1 - 1) << (17 + T1)) |
2074           (GET_FIELD_SP(T0, 17 + T1 - 1, 17) << 17) |
2075           (GET_FIELD_SP(T0, 56, 59) << 13) | (GET_FIELD_SP(T0, 35, 38) << 9) |
2076           (GET_FIELD_SP(T0, 13, 16) << 5) | (((T0 >> 55) & 1) << 4) |
2077           (GET_FIELD_SP(T0, 33, 34) << 2) | GET_FIELD_SP(T0, 11, 12)) << 2;
2078 }
2079
2080 void OPPROTO op_alignaddr()
2081 {
2082     uint64_t tmp;
2083
2084     tmp = T0 + T1;
2085     env->gsr &= ~7ULL;
2086     env->gsr |= tmp & 7ULL;
2087     T0 = tmp & ~7ULL;
2088 }
2089
2090 void OPPROTO op_faligndata()
2091 {
2092     uint64_t tmp;
2093
2094     tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
2095     tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
2096     *((uint64_t *)&DT0) = tmp;
2097 }
2098
2099 void OPPROTO op_movl_FT0_0(void)
2100 {
2101     *((uint32_t *)&FT0) = 0;
2102 }
2103
2104 void OPPROTO op_movl_DT0_0(void)
2105 {
2106     *((uint64_t *)&DT0) = 0;
2107 }
2108
2109 void OPPROTO op_movl_FT0_1(void)
2110 {
2111     *((uint32_t *)&FT0) = 0xffffffff;
2112 }
2113
2114 void OPPROTO op_movl_DT0_1(void)
2115 {
2116     *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
2117 }
2118
2119 void OPPROTO op_fnot(void)
2120 {
2121     *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
2122 }
2123
2124 void OPPROTO op_fnots(void)
2125 {
2126     *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
2127 }
2128
2129 void OPPROTO op_fnor(void)
2130 {
2131     *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
2132 }
2133
2134 void OPPROTO op_fnors(void)
2135 {
2136     *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
2137 }
2138
2139 void OPPROTO op_for(void)
2140 {
2141     *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
2142 }
2143
2144 void OPPROTO op_fors(void)
2145 {
2146     *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
2147 }
2148
2149 void OPPROTO op_fxor(void)
2150 {
2151     *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
2152 }
2153
2154 void OPPROTO op_fxors(void)
2155 {
2156     *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
2157 }
2158
2159 void OPPROTO op_fand(void)
2160 {
2161     *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
2162 }
2163
2164 void OPPROTO op_fands(void)
2165 {
2166     *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
2167 }
2168
2169 void OPPROTO op_fornot(void)
2170 {
2171     *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
2172 }
2173
2174 void OPPROTO op_fornots(void)
2175 {
2176     *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
2177 }
2178
2179 void OPPROTO op_fandnot(void)
2180 {
2181     *(uint64_t *)&DT0 = *(uint64_t *)&DT0 & ~*(uint64_t *)&DT1;
2182 }
2183
2184 void OPPROTO op_fandnots(void)
2185 {
2186     *(uint32_t *)&FT0 = *(uint32_t *)&FT0 & ~*(uint32_t *)&FT1;
2187 }
2188
2189 void OPPROTO op_fnand(void)
2190 {
2191     *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 & *(uint64_t *)&DT1);
2192 }
2193
2194 void OPPROTO op_fnands(void)
2195 {
2196     *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 & *(uint32_t *)&FT1);
2197 }
2198
2199 void OPPROTO op_fxnor(void)
2200 {
2201     *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
2202 }
2203
2204 void OPPROTO op_fxnors(void)
2205 {
2206     *(uint32_t *)&FT0 ^= ~*(uint32_t *)&FT1;
2207 }
2208
2209 #ifdef WORDS_BIGENDIAN
2210 #define VIS_B64(n) b[7 - (n)]
2211 #define VIS_W64(n) w[3 - (n)]
2212 #define VIS_SW64(n) sw[3 - (n)]
2213 #define VIS_L64(n) l[1 - (n)]
2214 #define VIS_B32(n) b[3 - (n)]
2215 #define VIS_W32(n) w[1 - (n)]
2216 #else
2217 #define VIS_B64(n) b[n]
2218 #define VIS_W64(n) w[n]
2219 #define VIS_SW64(n) sw[n]
2220 #define VIS_L64(n) l[n]
2221 #define VIS_B32(n) b[n]
2222 #define VIS_W32(n) w[n]
2223 #endif
2224
2225 typedef union {
2226     uint8_t b[8];
2227     uint16_t w[4];
2228     int16_t sw[4];
2229     uint32_t l[2];
2230     float64 d;
2231 } vis64;
2232
2233 typedef union {
2234     uint8_t b[4];
2235     uint16_t w[2];
2236     uint32_t l;
2237     float32 f;
2238 } vis32;
2239
2240 void OPPROTO op_fpmerge(void)
2241 {
2242     vis64 s, d;
2243
2244     s.d = DT0;
2245     d.d = DT1;
2246
2247     // Reverse calculation order to handle overlap
2248     d.VIS_B64(7) = s.VIS_B64(3);
2249     d.VIS_B64(6) = d.VIS_B64(3);
2250     d.VIS_B64(5) = s.VIS_B64(2);
2251     d.VIS_B64(4) = d.VIS_B64(2);
2252     d.VIS_B64(3) = s.VIS_B64(1);
2253     d.VIS_B64(2) = d.VIS_B64(1);
2254     d.VIS_B64(1) = s.VIS_B64(0);
2255     //d.VIS_B64(0) = d.VIS_B64(0);
2256
2257     DT0 = d.d;
2258 }
2259
2260 void OPPROTO op_fmul8x16(void)
2261 {
2262     vis64 s, d;
2263     uint32_t tmp;
2264
2265     s.d = DT0;
2266     d.d = DT1;
2267
2268 #define PMUL(r)                                                 \
2269     tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
2270     if ((tmp & 0xff) > 0x7f)                                    \
2271         tmp += 0x100;                                           \
2272     d.VIS_W64(r) = tmp >> 8;
2273
2274     PMUL(0);
2275     PMUL(1);
2276     PMUL(2);
2277     PMUL(3);
2278 #undef PMUL
2279
2280     DT0 = d.d;
2281 }
2282
2283 void OPPROTO op_fmul8x16al(void)
2284 {
2285     vis64 s, d;
2286     uint32_t tmp;
2287
2288     s.d = DT0;
2289     d.d = DT1;
2290
2291 #define PMUL(r)                                                 \
2292     tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
2293     if ((tmp & 0xff) > 0x7f)                                    \
2294         tmp += 0x100;                                           \
2295     d.VIS_W64(r) = tmp >> 8;
2296
2297     PMUL(0);
2298     PMUL(1);
2299     PMUL(2);
2300     PMUL(3);
2301 #undef PMUL
2302
2303     DT0 = d.d;
2304 }
2305
2306 void OPPROTO op_fmul8x16au(void)
2307 {
2308     vis64 s, d;
2309     uint32_t tmp;
2310
2311     s.d = DT0;
2312     d.d = DT1;
2313
2314 #define PMUL(r)                                                 \
2315     tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
2316     if ((tmp & 0xff) > 0x7f)                                    \
2317         tmp += 0x100;                                           \
2318     d.VIS_W64(r) = tmp >> 8;
2319
2320     PMUL(0);
2321     PMUL(1);
2322     PMUL(2);
2323     PMUL(3);
2324 #undef PMUL
2325
2326     DT0 = d.d;
2327 }
2328
2329 void OPPROTO op_fmul8sux16(void)
2330 {
2331     vis64 s, d;
2332     uint32_t tmp;
2333
2334     s.d = DT0;
2335     d.d = DT1;
2336
2337 #define PMUL(r)                                                         \
2338     tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
2339     if ((tmp & 0xff) > 0x7f)                                            \
2340         tmp += 0x100;                                                   \
2341     d.VIS_W64(r) = tmp >> 8;
2342
2343     PMUL(0);
2344     PMUL(1);
2345     PMUL(2);
2346     PMUL(3);
2347 #undef PMUL
2348
2349     DT0 = d.d;
2350 }
2351
2352 void OPPROTO op_fmul8ulx16(void)
2353 {
2354     vis64 s, d;
2355     uint32_t tmp;
2356
2357     s.d = DT0;
2358     d.d = DT1;
2359
2360 #define PMUL(r)                                                         \
2361     tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
2362     if ((tmp & 0xff) > 0x7f)                                            \
2363         tmp += 0x100;                                                   \
2364     d.VIS_W64(r) = tmp >> 8;
2365
2366     PMUL(0);
2367     PMUL(1);
2368     PMUL(2);
2369     PMUL(3);
2370 #undef PMUL
2371
2372     DT0 = d.d;
2373 }
2374
2375 void OPPROTO op_fmuld8sux16(void)
2376 {
2377     vis64 s, d;
2378     uint32_t tmp;
2379
2380     s.d = DT0;
2381     d.d = DT1;
2382
2383 #define PMUL(r)                                                         \
2384     tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
2385     if ((tmp & 0xff) > 0x7f)                                            \
2386         tmp += 0x100;                                                   \
2387     d.VIS_L64(r) = tmp;
2388
2389     // Reverse calculation order to handle overlap
2390     PMUL(1);
2391     PMUL(0);
2392 #undef PMUL
2393
2394     DT0 = d.d;
2395 }
2396
2397 void OPPROTO op_fmuld8ulx16(void)
2398 {
2399     vis64 s, d;
2400     uint32_t tmp;
2401
2402     s.d = DT0;
2403     d.d = DT1;
2404
2405 #define PMUL(r)                                                         \
2406     tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
2407     if ((tmp & 0xff) > 0x7f)                                            \
2408         tmp += 0x100;                                                   \
2409     d.VIS_L64(r) = tmp;
2410
2411     // Reverse calculation order to handle overlap
2412     PMUL(1);
2413     PMUL(0);
2414 #undef PMUL
2415
2416     DT0 = d.d;
2417 }
2418
2419 void OPPROTO op_fexpand(void)
2420 {
2421     vis32 s;
2422     vis64 d;
2423
2424     s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
2425     d.d = DT1;
2426     d.VIS_L64(0) = s.VIS_W32(0) << 4;
2427     d.VIS_L64(1) = s.VIS_W32(1) << 4;
2428     d.VIS_L64(2) = s.VIS_W32(2) << 4;
2429     d.VIS_L64(3) = s.VIS_W32(3) << 4;
2430
2431     DT0 = d.d;
2432 }
2433
2434 #define VIS_OP(name, F)                                 \
2435     void OPPROTO name##16(void)                         \
2436     {                                                   \
2437         vis64 s, d;                                     \
2438                                                         \
2439         s.d = DT0;                                      \
2440         d.d = DT1;                                      \
2441                                                         \
2442         d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
2443         d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
2444         d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
2445         d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
2446                                                         \
2447         DT0 = d.d;                                      \
2448     }                                                   \
2449                                                         \
2450     void OPPROTO name##16s(void)                        \
2451     {                                                   \
2452         vis32 s, d;                                     \
2453                                                         \
2454         s.f = FT0;                                      \
2455         d.f = FT1;                                      \
2456                                                         \
2457         d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
2458         d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
2459                                                         \
2460         FT0 = d.f;                                      \
2461     }                                                   \
2462                                                         \
2463     void OPPROTO name##32(void)                         \
2464     {                                                   \
2465         vis64 s, d;                                     \
2466                                                         \
2467         s.d = DT0;                                      \
2468         d.d = DT1;                                      \
2469                                                         \
2470         d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
2471         d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
2472                                                         \
2473         DT0 = d.d;                                      \
2474     }                                                   \
2475                                                         \
2476     void OPPROTO name##32s(void)                        \
2477     {                                                   \
2478         vis32 s, d;                                     \
2479                                                         \
2480         s.f = FT0;                                      \
2481         d.f = FT1;                                      \
2482                                                         \
2483         d.l = F(d.l, s.l);                              \
2484                                                         \
2485         FT0 = d.f;                                      \
2486     }
2487
2488 #define FADD(a, b) ((a) + (b))
2489 #define FSUB(a, b) ((a) - (b))
2490 VIS_OP(op_fpadd, FADD)
2491 VIS_OP(op_fpsub, FSUB)
2492
2493 #define VIS_CMPOP(name, F)                                        \
2494     void OPPROTO name##16(void)                                   \
2495     {                                                             \
2496         vis64 s, d;                                               \
2497                                                                   \
2498         s.d = DT0;                                                \
2499         d.d = DT1;                                                \
2500                                                                   \
2501         d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
2502         d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
2503         d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
2504         d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
2505                                                                   \
2506         DT0 = d.d;                                                \
2507     }                                                             \
2508                                                                   \
2509     void OPPROTO name##32(void)                                   \
2510     {                                                             \
2511         vis64 s, d;                                               \
2512                                                                   \
2513         s.d = DT0;                                                \
2514         d.d = DT1;                                                \
2515                                                                   \
2516         d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
2517         d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
2518                                                                   \
2519         DT0 = d.d;                                                \
2520     }
2521
2522 #define FCMPGT(a, b) ((a) > (b))
2523 #define FCMPEQ(a, b) ((a) == (b))
2524 #define FCMPLE(a, b) ((a) <= (b))
2525 #define FCMPNE(a, b) ((a) != (b))
2526
2527 VIS_CMPOP(op_fcmpgt, FCMPGT)
2528 VIS_CMPOP(op_fcmpeq, FCMPEQ)
2529 VIS_CMPOP(op_fcmple, FCMPLE)
2530 VIS_CMPOP(op_fcmpne, FCMPNE)
2531
2532 #endif
2533
2534 #define CHECK_ALIGN_OP(align)                           \
2535     void OPPROTO op_check_align_T0_ ## align (void)     \
2536     {                                                   \
2537         if (T0 & align)                                 \
2538             raise_exception(TT_UNALIGNED);              \
2539         FORCE_RET();                                    \
2540     }
2541
2542 CHECK_ALIGN_OP(1)
2543 CHECK_ALIGN_OP(3)
2544 CHECK_ALIGN_OP(7)