Remove someexplicit alignment checks (initial patch by Fabrice Bellard)
[qemu] / target-sparc / op_helper.c
1 #include "exec.h"
2 #include "host-utils.h"
3 #include "helper.h"
4 #if !defined(CONFIG_USER_ONLY)
5 #include "softmmu_exec.h"
6 #endif /* !defined(CONFIG_USER_ONLY) */
7
8 //#define DEBUG_PCALL
9 //#define DEBUG_MMU
10 //#define DEBUG_MXCC
11 //#define DEBUG_UNALIGNED
12 //#define DEBUG_UNASSIGNED
13 //#define DEBUG_ASI
14
15 #ifdef DEBUG_MMU
16 #define DPRINTF_MMU(fmt, args...) \
17 do { printf("MMU: " fmt , ##args); } while (0)
18 #else
19 #define DPRINTF_MMU(fmt, args...) do {} while (0)
20 #endif
21
22 #ifdef DEBUG_MXCC
23 #define DPRINTF_MXCC(fmt, args...) \
24 do { printf("MXCC: " fmt , ##args); } while (0)
25 #else
26 #define DPRINTF_MXCC(fmt, args...) do {} while (0)
27 #endif
28
29 #ifdef DEBUG_ASI
30 #define DPRINTF_ASI(fmt, args...) \
31 do { printf("ASI: " fmt , ##args); } while (0)
32 #else
33 #define DPRINTF_ASI(fmt, args...) do {} while (0)
34 #endif
35
36 #ifdef TARGET_ABI32
37 #define ABI32_MASK(addr) do { (addr) &= 0xffffffffULL; } while (0)
38 #else
39 #define ABI32_MASK(addr) do {} while (0)
40 #endif
41
42 void raise_exception(int tt)
43 {
44     env->exception_index = tt;
45     cpu_loop_exit();
46 }
47
48 void helper_trap(target_ulong nb_trap)
49 {
50     env->exception_index = TT_TRAP + (nb_trap & 0x7f);
51     cpu_loop_exit();
52 }
53
54 void helper_trapcc(target_ulong nb_trap, target_ulong do_trap)
55 {
56     if (do_trap) {
57         env->exception_index = TT_TRAP + (nb_trap & 0x7f);
58         cpu_loop_exit();
59     }
60 }
61
62 void helper_check_align(target_ulong addr, uint32_t align)
63 {
64     if (addr & align) {
65 #ifdef DEBUG_UNALIGNED
66     printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
67            "\n", addr, env->pc);
68 #endif
69         raise_exception(TT_UNALIGNED);
70     }
71 }
72
73 #define F_HELPER(name, p) void helper_f##name##p(void)
74
75 #define F_BINOP(name)                                           \
76     F_HELPER(name, s)                                           \
77     {                                                           \
78         FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
79     }                                                           \
80     F_HELPER(name, d)                                           \
81     {                                                           \
82         DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
83     }                                                           \
84     F_HELPER(name, q)                                           \
85     {                                                           \
86         QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
87     }
88
89 F_BINOP(add);
90 F_BINOP(sub);
91 F_BINOP(mul);
92 F_BINOP(div);
93 #undef F_BINOP
94
95 void helper_fsmuld(void)
96 {
97     DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
98                       float32_to_float64(FT1, &env->fp_status),
99                       &env->fp_status);
100 }
101
102 void helper_fdmulq(void)
103 {
104     QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
105                        float64_to_float128(DT1, &env->fp_status),
106                        &env->fp_status);
107 }
108
109 F_HELPER(neg, s)
110 {
111     FT0 = float32_chs(FT1);
112 }
113
114 #ifdef TARGET_SPARC64
115 F_HELPER(neg, d)
116 {
117     DT0 = float64_chs(DT1);
118 }
119
120 F_HELPER(neg, q)
121 {
122     QT0 = float128_chs(QT1);
123 }
124 #endif
125
126 /* Integer to float conversion.  */
127 F_HELPER(ito, s)
128 {
129     FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
130 }
131
132 F_HELPER(ito, d)
133 {
134     DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
135 }
136
137 F_HELPER(ito, q)
138 {
139     QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
140 }
141
142 #ifdef TARGET_SPARC64
143 F_HELPER(xto, s)
144 {
145     FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
146 }
147
148 F_HELPER(xto, d)
149 {
150     DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
151 }
152
153 F_HELPER(xto, q)
154 {
155     QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
156 }
157 #endif
158 #undef F_HELPER
159
160 /* floating point conversion */
161 void helper_fdtos(void)
162 {
163     FT0 = float64_to_float32(DT1, &env->fp_status);
164 }
165
166 void helper_fstod(void)
167 {
168     DT0 = float32_to_float64(FT1, &env->fp_status);
169 }
170
171 void helper_fqtos(void)
172 {
173     FT0 = float128_to_float32(QT1, &env->fp_status);
174 }
175
176 void helper_fstoq(void)
177 {
178     QT0 = float32_to_float128(FT1, &env->fp_status);
179 }
180
181 void helper_fqtod(void)
182 {
183     DT0 = float128_to_float64(QT1, &env->fp_status);
184 }
185
186 void helper_fdtoq(void)
187 {
188     QT0 = float64_to_float128(DT1, &env->fp_status);
189 }
190
191 /* Float to integer conversion.  */
192 void helper_fstoi(void)
193 {
194     *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
195 }
196
197 void helper_fdtoi(void)
198 {
199     *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
200 }
201
202 void helper_fqtoi(void)
203 {
204     *((int32_t *)&FT0) = float128_to_int32_round_to_zero(QT1, &env->fp_status);
205 }
206
207 #ifdef TARGET_SPARC64
208 void helper_fstox(void)
209 {
210     *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
211 }
212
213 void helper_fdtox(void)
214 {
215     *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
216 }
217
218 void helper_fqtox(void)
219 {
220     *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
221 }
222
223 void helper_faligndata(void)
224 {
225     uint64_t tmp;
226
227     tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
228     tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
229     *((uint64_t *)&DT0) = tmp;
230 }
231
232 void helper_movl_FT0_0(void)
233 {
234     *((uint32_t *)&FT0) = 0;
235 }
236
237 void helper_movl_DT0_0(void)
238 {
239     *((uint64_t *)&DT0) = 0;
240 }
241
242 void helper_movl_FT0_1(void)
243 {
244     *((uint32_t *)&FT0) = 0xffffffff;
245 }
246
247 void helper_movl_DT0_1(void)
248 {
249     *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
250 }
251
252 void helper_fnot(void)
253 {
254     *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
255 }
256
257 void helper_fnots(void)
258 {
259     *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
260 }
261
262 void helper_fnor(void)
263 {
264     *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
265 }
266
267 void helper_fnors(void)
268 {
269     *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
270 }
271
272 void helper_for(void)
273 {
274     *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
275 }
276
277 void helper_fors(void)
278 {
279     *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
280 }
281
282 void helper_fxor(void)
283 {
284     *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
285 }
286
287 void helper_fxors(void)
288 {
289     *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
290 }
291
292 void helper_fand(void)
293 {
294     *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
295 }
296
297 void helper_fands(void)
298 {
299     *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
300 }
301
302 void helper_fornot(void)
303 {
304     *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
305 }
306
307 void helper_fornots(void)
308 {
309     *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
310 }
311
312 void helper_fandnot(void)
313 {
314     *(uint64_t *)&DT0 = *(uint64_t *)&DT0 & ~*(uint64_t *)&DT1;
315 }
316
317 void helper_fandnots(void)
318 {
319     *(uint32_t *)&FT0 = *(uint32_t *)&FT0 & ~*(uint32_t *)&FT1;
320 }
321
322 void helper_fnand(void)
323 {
324     *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 & *(uint64_t *)&DT1);
325 }
326
327 void helper_fnands(void)
328 {
329     *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 & *(uint32_t *)&FT1);
330 }
331
332 void helper_fxnor(void)
333 {
334     *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
335 }
336
337 void helper_fxnors(void)
338 {
339     *(uint32_t *)&FT0 ^= ~*(uint32_t *)&FT1;
340 }
341
342 #ifdef WORDS_BIGENDIAN
343 #define VIS_B64(n) b[7 - (n)]
344 #define VIS_W64(n) w[3 - (n)]
345 #define VIS_SW64(n) sw[3 - (n)]
346 #define VIS_L64(n) l[1 - (n)]
347 #define VIS_B32(n) b[3 - (n)]
348 #define VIS_W32(n) w[1 - (n)]
349 #else
350 #define VIS_B64(n) b[n]
351 #define VIS_W64(n) w[n]
352 #define VIS_SW64(n) sw[n]
353 #define VIS_L64(n) l[n]
354 #define VIS_B32(n) b[n]
355 #define VIS_W32(n) w[n]
356 #endif
357
358 typedef union {
359     uint8_t b[8];
360     uint16_t w[4];
361     int16_t sw[4];
362     uint32_t l[2];
363     float64 d;
364 } vis64;
365
366 typedef union {
367     uint8_t b[4];
368     uint16_t w[2];
369     uint32_t l;
370     float32 f;
371 } vis32;
372
373 void helper_fpmerge(void)
374 {
375     vis64 s, d;
376
377     s.d = DT0;
378     d.d = DT1;
379
380     // Reverse calculation order to handle overlap
381     d.VIS_B64(7) = s.VIS_B64(3);
382     d.VIS_B64(6) = d.VIS_B64(3);
383     d.VIS_B64(5) = s.VIS_B64(2);
384     d.VIS_B64(4) = d.VIS_B64(2);
385     d.VIS_B64(3) = s.VIS_B64(1);
386     d.VIS_B64(2) = d.VIS_B64(1);
387     d.VIS_B64(1) = s.VIS_B64(0);
388     //d.VIS_B64(0) = d.VIS_B64(0);
389
390     DT0 = d.d;
391 }
392
393 void helper_fmul8x16(void)
394 {
395     vis64 s, d;
396     uint32_t tmp;
397
398     s.d = DT0;
399     d.d = DT1;
400
401 #define PMUL(r)                                                 \
402     tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
403     if ((tmp & 0xff) > 0x7f)                                    \
404         tmp += 0x100;                                           \
405     d.VIS_W64(r) = tmp >> 8;
406
407     PMUL(0);
408     PMUL(1);
409     PMUL(2);
410     PMUL(3);
411 #undef PMUL
412
413     DT0 = d.d;
414 }
415
416 void helper_fmul8x16al(void)
417 {
418     vis64 s, d;
419     uint32_t tmp;
420
421     s.d = DT0;
422     d.d = DT1;
423
424 #define PMUL(r)                                                 \
425     tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
426     if ((tmp & 0xff) > 0x7f)                                    \
427         tmp += 0x100;                                           \
428     d.VIS_W64(r) = tmp >> 8;
429
430     PMUL(0);
431     PMUL(1);
432     PMUL(2);
433     PMUL(3);
434 #undef PMUL
435
436     DT0 = d.d;
437 }
438
439 void helper_fmul8x16au(void)
440 {
441     vis64 s, d;
442     uint32_t tmp;
443
444     s.d = DT0;
445     d.d = DT1;
446
447 #define PMUL(r)                                                 \
448     tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
449     if ((tmp & 0xff) > 0x7f)                                    \
450         tmp += 0x100;                                           \
451     d.VIS_W64(r) = tmp >> 8;
452
453     PMUL(0);
454     PMUL(1);
455     PMUL(2);
456     PMUL(3);
457 #undef PMUL
458
459     DT0 = d.d;
460 }
461
462 void helper_fmul8sux16(void)
463 {
464     vis64 s, d;
465     uint32_t tmp;
466
467     s.d = DT0;
468     d.d = DT1;
469
470 #define PMUL(r)                                                         \
471     tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
472     if ((tmp & 0xff) > 0x7f)                                            \
473         tmp += 0x100;                                                   \
474     d.VIS_W64(r) = tmp >> 8;
475
476     PMUL(0);
477     PMUL(1);
478     PMUL(2);
479     PMUL(3);
480 #undef PMUL
481
482     DT0 = d.d;
483 }
484
485 void helper_fmul8ulx16(void)
486 {
487     vis64 s, d;
488     uint32_t tmp;
489
490     s.d = DT0;
491     d.d = DT1;
492
493 #define PMUL(r)                                                         \
494     tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
495     if ((tmp & 0xff) > 0x7f)                                            \
496         tmp += 0x100;                                                   \
497     d.VIS_W64(r) = tmp >> 8;
498
499     PMUL(0);
500     PMUL(1);
501     PMUL(2);
502     PMUL(3);
503 #undef PMUL
504
505     DT0 = d.d;
506 }
507
508 void helper_fmuld8sux16(void)
509 {
510     vis64 s, d;
511     uint32_t tmp;
512
513     s.d = DT0;
514     d.d = DT1;
515
516 #define PMUL(r)                                                         \
517     tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
518     if ((tmp & 0xff) > 0x7f)                                            \
519         tmp += 0x100;                                                   \
520     d.VIS_L64(r) = tmp;
521
522     // Reverse calculation order to handle overlap
523     PMUL(1);
524     PMUL(0);
525 #undef PMUL
526
527     DT0 = d.d;
528 }
529
530 void helper_fmuld8ulx16(void)
531 {
532     vis64 s, d;
533     uint32_t tmp;
534
535     s.d = DT0;
536     d.d = DT1;
537
538 #define PMUL(r)                                                         \
539     tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
540     if ((tmp & 0xff) > 0x7f)                                            \
541         tmp += 0x100;                                                   \
542     d.VIS_L64(r) = tmp;
543
544     // Reverse calculation order to handle overlap
545     PMUL(1);
546     PMUL(0);
547 #undef PMUL
548
549     DT0 = d.d;
550 }
551
552 void helper_fexpand(void)
553 {
554     vis32 s;
555     vis64 d;
556
557     s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
558     d.d = DT1;
559     d.VIS_L64(0) = s.VIS_W32(0) << 4;
560     d.VIS_L64(1) = s.VIS_W32(1) << 4;
561     d.VIS_L64(2) = s.VIS_W32(2) << 4;
562     d.VIS_L64(3) = s.VIS_W32(3) << 4;
563
564     DT0 = d.d;
565 }
566
567 #define VIS_HELPER(name, F)                             \
568     void name##16(void)                                 \
569     {                                                   \
570         vis64 s, d;                                     \
571                                                         \
572         s.d = DT0;                                      \
573         d.d = DT1;                                      \
574                                                         \
575         d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
576         d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
577         d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
578         d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
579                                                         \
580         DT0 = d.d;                                      \
581     }                                                   \
582                                                         \
583     void name##16s(void)                                \
584     {                                                   \
585         vis32 s, d;                                     \
586                                                         \
587         s.f = FT0;                                      \
588         d.f = FT1;                                      \
589                                                         \
590         d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
591         d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
592                                                         \
593         FT0 = d.f;                                      \
594     }                                                   \
595                                                         \
596     void name##32(void)                                 \
597     {                                                   \
598         vis64 s, d;                                     \
599                                                         \
600         s.d = DT0;                                      \
601         d.d = DT1;                                      \
602                                                         \
603         d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
604         d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
605                                                         \
606         DT0 = d.d;                                      \
607     }                                                   \
608                                                         \
609     void name##32s(void)                                \
610     {                                                   \
611         vis32 s, d;                                     \
612                                                         \
613         s.f = FT0;                                      \
614         d.f = FT1;                                      \
615                                                         \
616         d.l = F(d.l, s.l);                              \
617                                                         \
618         FT0 = d.f;                                      \
619     }
620
621 #define FADD(a, b) ((a) + (b))
622 #define FSUB(a, b) ((a) - (b))
623 VIS_HELPER(helper_fpadd, FADD)
624 VIS_HELPER(helper_fpsub, FSUB)
625
626 #define VIS_CMPHELPER(name, F)                                        \
627     void name##16(void)                                           \
628     {                                                             \
629         vis64 s, d;                                               \
630                                                                   \
631         s.d = DT0;                                                \
632         d.d = DT1;                                                \
633                                                                   \
634         d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
635         d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
636         d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
637         d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
638                                                                   \
639         DT0 = d.d;                                                \
640     }                                                             \
641                                                                   \
642     void name##32(void)                                           \
643     {                                                             \
644         vis64 s, d;                                               \
645                                                                   \
646         s.d = DT0;                                                \
647         d.d = DT1;                                                \
648                                                                   \
649         d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
650         d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
651                                                                   \
652         DT0 = d.d;                                                \
653     }
654
655 #define FCMPGT(a, b) ((a) > (b))
656 #define FCMPEQ(a, b) ((a) == (b))
657 #define FCMPLE(a, b) ((a) <= (b))
658 #define FCMPNE(a, b) ((a) != (b))
659
660 VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
661 VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
662 VIS_CMPHELPER(helper_fcmple, FCMPLE)
663 VIS_CMPHELPER(helper_fcmpne, FCMPNE)
664 #endif
665
666 void helper_check_ieee_exceptions(void)
667 {
668     target_ulong status;
669
670     status = get_float_exception_flags(&env->fp_status);
671     if (status) {
672         /* Copy IEEE 754 flags into FSR */
673         if (status & float_flag_invalid)
674             env->fsr |= FSR_NVC;
675         if (status & float_flag_overflow)
676             env->fsr |= FSR_OFC;
677         if (status & float_flag_underflow)
678             env->fsr |= FSR_UFC;
679         if (status & float_flag_divbyzero)
680             env->fsr |= FSR_DZC;
681         if (status & float_flag_inexact)
682             env->fsr |= FSR_NXC;
683
684         if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
685             /* Unmasked exception, generate a trap */
686             env->fsr |= FSR_FTT_IEEE_EXCP;
687             raise_exception(TT_FP_EXCP);
688         } else {
689             /* Accumulate exceptions */
690             env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
691         }
692     }
693 }
694
695 void helper_clear_float_exceptions(void)
696 {
697     set_float_exception_flags(0, &env->fp_status);
698 }
699
700 void helper_fabss(void)
701 {
702     FT0 = float32_abs(FT1);
703 }
704
705 #ifdef TARGET_SPARC64
706 void helper_fabsd(void)
707 {
708     DT0 = float64_abs(DT1);
709 }
710
711 void helper_fabsq(void)
712 {
713     QT0 = float128_abs(QT1);
714 }
715 #endif
716
717 void helper_fsqrts(void)
718 {
719     FT0 = float32_sqrt(FT1, &env->fp_status);
720 }
721
722 void helper_fsqrtd(void)
723 {
724     DT0 = float64_sqrt(DT1, &env->fp_status);
725 }
726
727 void helper_fsqrtq(void)
728 {
729     QT0 = float128_sqrt(QT1, &env->fp_status);
730 }
731
732 #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
733     void glue(helper_, name) (void)                                     \
734     {                                                                   \
735         target_ulong new_fsr;                                           \
736                                                                         \
737         env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
738         switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
739         case float_relation_unordered:                                  \
740             new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
741             if ((env->fsr & FSR_NVM) || TRAP) {                         \
742                 env->fsr |= new_fsr;                                    \
743                 env->fsr |= FSR_NVC;                                    \
744                 env->fsr |= FSR_FTT_IEEE_EXCP;                          \
745                 raise_exception(TT_FP_EXCP);                            \
746             } else {                                                    \
747                 env->fsr |= FSR_NVA;                                    \
748             }                                                           \
749             break;                                                      \
750         case float_relation_less:                                       \
751             new_fsr = FSR_FCC0 << FS;                                   \
752             break;                                                      \
753         case float_relation_greater:                                    \
754             new_fsr = FSR_FCC1 << FS;                                   \
755             break;                                                      \
756         default:                                                        \
757             new_fsr = 0;                                                \
758             break;                                                      \
759         }                                                               \
760         env->fsr |= new_fsr;                                            \
761     }
762
763 GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
764 GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
765
766 GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
767 GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
768
769 GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
770 GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
771
772 #ifdef TARGET_SPARC64
773 GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
774 GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
775 GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
776
777 GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
778 GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
779 GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
780
781 GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
782 GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
783 GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
784
785 GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
786 GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
787 GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
788
789 GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
790 GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
791 GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
792
793 GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
794 GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
795 GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
796 #endif
797
798 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && defined(DEBUG_MXCC)
799 static void dump_mxcc(CPUState *env)
800 {
801     printf("mxccdata: %016llx %016llx %016llx %016llx\n",
802         env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]);
803     printf("mxccregs: %016llx %016llx %016llx %016llx\n"
804            "          %016llx %016llx %016llx %016llx\n",
805         env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3],
806         env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]);
807 }
808 #endif
809
810 #if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
811     && defined(DEBUG_ASI)
812 static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
813                      uint64_t r1)
814 {
815     switch (size)
816     {
817     case 1:
818         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
819                     addr, asi, r1 & 0xff);
820         break;
821     case 2:
822         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
823                     addr, asi, r1 & 0xffff);
824         break;
825     case 4:
826         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
827                     addr, asi, r1 & 0xffffffff);
828         break;
829     case 8:
830         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
831                     addr, asi, r1);
832         break;
833     }
834 }
835 #endif
836
837 #ifndef TARGET_SPARC64
838 #ifndef CONFIG_USER_ONLY
839 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
840 {
841     uint64_t ret = 0;
842 #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
843     uint32_t last_addr = addr;
844 #endif
845
846     helper_check_align(addr, size - 1);
847     switch (asi) {
848     case 2: /* SuperSparc MXCC registers */
849         switch (addr) {
850         case 0x01c00a00: /* MXCC control register */
851             if (size == 8)
852                 ret = env->mxccregs[3];
853             else
854                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
855             break;
856         case 0x01c00a04: /* MXCC control register */
857             if (size == 4)
858                 ret = env->mxccregs[3];
859             else
860                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
861             break;
862         case 0x01c00c00: /* Module reset register */
863             if (size == 8) {
864                 ret = env->mxccregs[5];
865                 // should we do something here?
866             } else
867                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
868             break;
869         case 0x01c00f00: /* MBus port address register */
870             if (size == 8)
871                 ret = env->mxccregs[7];
872             else
873                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
874             break;
875         default:
876             DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size);
877             break;
878         }
879         DPRINTF_MXCC("asi = %d, size = %d, sign = %d, addr = %08x -> ret = %08x,"
880                      "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
881 #ifdef DEBUG_MXCC
882         dump_mxcc(env);
883 #endif
884         break;
885     case 3: /* MMU probe */
886         {
887             int mmulev;
888
889             mmulev = (addr >> 8) & 15;
890             if (mmulev > 4)
891                 ret = 0;
892             else
893                 ret = mmu_probe(env, addr, mmulev);
894             DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
895                         addr, mmulev, ret);
896         }
897         break;
898     case 4: /* read MMU regs */
899         {
900             int reg = (addr >> 8) & 0x1f;
901
902             ret = env->mmuregs[reg];
903             if (reg == 3) /* Fault status cleared on read */
904                 env->mmuregs[3] = 0;
905             else if (reg == 0x13) /* Fault status read */
906                 ret = env->mmuregs[3];
907             else if (reg == 0x14) /* Fault address read */
908                 ret = env->mmuregs[4];
909             DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
910         }
911         break;
912     case 5: // Turbosparc ITLB Diagnostic
913     case 6: // Turbosparc DTLB Diagnostic
914     case 7: // Turbosparc IOTLB Diagnostic
915         break;
916     case 9: /* Supervisor code access */
917         switch(size) {
918         case 1:
919             ret = ldub_code(addr);
920             break;
921         case 2:
922             ret = lduw_code(addr & ~1);
923             break;
924         default:
925         case 4:
926             ret = ldl_code(addr & ~3);
927             break;
928         case 8:
929             ret = ldq_code(addr & ~7);
930             break;
931         }
932         break;
933     case 0xa: /* User data access */
934         switch(size) {
935         case 1:
936             ret = ldub_user(addr);
937             break;
938         case 2:
939             ret = lduw_user(addr & ~1);
940             break;
941         default:
942         case 4:
943             ret = ldl_user(addr & ~3);
944             break;
945         case 8:
946             ret = ldq_user(addr & ~7);
947             break;
948         }
949         break;
950     case 0xb: /* Supervisor data access */
951         switch(size) {
952         case 1:
953             ret = ldub_kernel(addr);
954             break;
955         case 2:
956             ret = lduw_kernel(addr & ~1);
957             break;
958         default:
959         case 4:
960             ret = ldl_kernel(addr & ~3);
961             break;
962         case 8:
963             ret = ldq_kernel(addr & ~7);
964             break;
965         }
966         break;
967     case 0xc: /* I-cache tag */
968     case 0xd: /* I-cache data */
969     case 0xe: /* D-cache tag */
970     case 0xf: /* D-cache data */
971         break;
972     case 0x20: /* MMU passthrough */
973         switch(size) {
974         case 1:
975             ret = ldub_phys(addr);
976             break;
977         case 2:
978             ret = lduw_phys(addr & ~1);
979             break;
980         default:
981         case 4:
982             ret = ldl_phys(addr & ~3);
983             break;
984         case 8:
985             ret = ldq_phys(addr & ~7);
986             break;
987         }
988         break;
989     case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
990         switch(size) {
991         case 1:
992             ret = ldub_phys((target_phys_addr_t)addr
993                             | ((target_phys_addr_t)(asi & 0xf) << 32));
994             break;
995         case 2:
996             ret = lduw_phys((target_phys_addr_t)(addr & ~1)
997                             | ((target_phys_addr_t)(asi & 0xf) << 32));
998             break;
999         default:
1000         case 4:
1001             ret = ldl_phys((target_phys_addr_t)(addr & ~3)
1002                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1003             break;
1004         case 8:
1005             ret = ldq_phys((target_phys_addr_t)(addr & ~7)
1006                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1007             break;
1008         }
1009         break;
1010     case 0x30: // Turbosparc secondary cache diagnostic
1011     case 0x31: // Turbosparc RAM snoop
1012     case 0x32: // Turbosparc page table descriptor diagnostic
1013     case 0x39: /* data cache diagnostic register */
1014         ret = 0;
1015         break;
1016     case 8: /* User code access, XXX */
1017     default:
1018         do_unassigned_access(addr, 0, 0, asi);
1019         ret = 0;
1020         break;
1021     }
1022     if (sign) {
1023         switch(size) {
1024         case 1:
1025             ret = (int8_t) ret;
1026             break;
1027         case 2:
1028             ret = (int16_t) ret;
1029             break;
1030         case 4:
1031             ret = (int32_t) ret;
1032             break;
1033         default:
1034             break;
1035         }
1036     }
1037 #ifdef DEBUG_ASI
1038     dump_asi("read ", last_addr, asi, size, ret);
1039 #endif
1040     return ret;
1041 }
1042
1043 void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
1044 {
1045     helper_check_align(addr, size - 1);
1046     switch(asi) {
1047     case 2: /* SuperSparc MXCC registers */
1048         switch (addr) {
1049         case 0x01c00000: /* MXCC stream data register 0 */
1050             if (size == 8)
1051                 env->mxccdata[0] = val;
1052             else
1053                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1054             break;
1055         case 0x01c00008: /* MXCC stream data register 1 */
1056             if (size == 8)
1057                 env->mxccdata[1] = val;
1058             else
1059                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1060             break;
1061         case 0x01c00010: /* MXCC stream data register 2 */
1062             if (size == 8)
1063                 env->mxccdata[2] = val;
1064             else
1065                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1066             break;
1067         case 0x01c00018: /* MXCC stream data register 3 */
1068             if (size == 8)
1069                 env->mxccdata[3] = val;
1070             else
1071                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1072             break;
1073         case 0x01c00100: /* MXCC stream source */
1074             if (size == 8)
1075                 env->mxccregs[0] = val;
1076             else
1077                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1078             env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +  0);
1079             env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +  8);
1080             env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16);
1081             env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 24);
1082             break;
1083         case 0x01c00200: /* MXCC stream destination */
1084             if (size == 8)
1085                 env->mxccregs[1] = val;
1086             else
1087                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1088             stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0, env->mxccdata[0]);
1089             stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8, env->mxccdata[1]);
1090             stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]);
1091             stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, env->mxccdata[3]);
1092             break;
1093         case 0x01c00a00: /* MXCC control register */
1094             if (size == 8)
1095                 env->mxccregs[3] = val;
1096             else
1097                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1098             break;
1099         case 0x01c00a04: /* MXCC control register */
1100             if (size == 4)
1101                 env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | val;
1102             else
1103                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1104             break;
1105         case 0x01c00e00: /* MXCC error register  */
1106             // writing a 1 bit clears the error
1107             if (size == 8)
1108                 env->mxccregs[6] &= ~val;
1109             else
1110                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1111             break;
1112         case 0x01c00f00: /* MBus port address register */
1113             if (size == 8)
1114                 env->mxccregs[7] = val;
1115             else
1116                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1117             break;
1118         default:
1119             DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size);
1120             break;
1121         }
1122         DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %08x\n", asi, size, addr, val);
1123 #ifdef DEBUG_MXCC
1124         dump_mxcc(env);
1125 #endif
1126         break;
1127     case 3: /* MMU flush */
1128         {
1129             int mmulev;
1130
1131             mmulev = (addr >> 8) & 15;
1132             DPRINTF_MMU("mmu flush level %d\n", mmulev);
1133             switch (mmulev) {
1134             case 0: // flush page
1135                 tlb_flush_page(env, addr & 0xfffff000);
1136                 break;
1137             case 1: // flush segment (256k)
1138             case 2: // flush region (16M)
1139             case 3: // flush context (4G)
1140             case 4: // flush entire
1141                 tlb_flush(env, 1);
1142                 break;
1143             default:
1144                 break;
1145             }
1146 #ifdef DEBUG_MMU
1147             dump_mmu(env);
1148 #endif
1149         }
1150         break;
1151     case 4: /* write MMU regs */
1152         {
1153             int reg = (addr >> 8) & 0x1f;
1154             uint32_t oldreg;
1155
1156             oldreg = env->mmuregs[reg];
1157             switch(reg) {
1158             case 0: // Control Register
1159                 env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
1160                                     (val & 0x00ffffff);
1161                 // Mappings generated during no-fault mode or MMU
1162                 // disabled mode are invalid in normal mode
1163                 if ((oldreg & (MMU_E | MMU_NF | env->mmu_bm)) !=
1164                     (env->mmuregs[reg] & (MMU_E | MMU_NF | env->mmu_bm)))
1165                     tlb_flush(env, 1);
1166                 break;
1167             case 1: // Context Table Pointer Register
1168                 env->mmuregs[reg] = val & env->mmu_ctpr_mask;
1169                 break;
1170             case 2: // Context Register
1171                 env->mmuregs[reg] = val & env->mmu_cxr_mask;
1172                 if (oldreg != env->mmuregs[reg]) {
1173                     /* we flush when the MMU context changes because
1174                        QEMU has no MMU context support */
1175                     tlb_flush(env, 1);
1176                 }
1177                 break;
1178             case 3: // Synchronous Fault Status Register with Clear
1179             case 4: // Synchronous Fault Address Register
1180                 break;
1181             case 0x10: // TLB Replacement Control Register
1182                 env->mmuregs[reg] = val & env->mmu_trcr_mask;
1183                 break;
1184             case 0x13: // Synchronous Fault Status Register with Read and Clear
1185                 env->mmuregs[3] = val & env->mmu_sfsr_mask;
1186                 break;
1187             case 0x14: // Synchronous Fault Address Register
1188                 env->mmuregs[4] = val;
1189                 break;
1190             default:
1191                 env->mmuregs[reg] = val;
1192                 break;
1193             }
1194             if (oldreg != env->mmuregs[reg]) {
1195                 DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
1196             }
1197 #ifdef DEBUG_MMU
1198             dump_mmu(env);
1199 #endif
1200         }
1201         break;
1202     case 5: // Turbosparc ITLB Diagnostic
1203     case 6: // Turbosparc DTLB Diagnostic
1204     case 7: // Turbosparc IOTLB Diagnostic
1205         break;
1206     case 0xa: /* User data access */
1207         switch(size) {
1208         case 1:
1209             stb_user(addr, val);
1210             break;
1211         case 2:
1212             stw_user(addr & ~1, val);
1213             break;
1214         default:
1215         case 4:
1216             stl_user(addr & ~3, val);
1217             break;
1218         case 8:
1219             stq_user(addr & ~7, val);
1220             break;
1221         }
1222         break;
1223     case 0xb: /* Supervisor data access */
1224         switch(size) {
1225         case 1:
1226             stb_kernel(addr, val);
1227             break;
1228         case 2:
1229             stw_kernel(addr & ~1, val);
1230             break;
1231         default:
1232         case 4:
1233             stl_kernel(addr & ~3, val);
1234             break;
1235         case 8:
1236             stq_kernel(addr & ~7, val);
1237             break;
1238         }
1239         break;
1240     case 0xc: /* I-cache tag */
1241     case 0xd: /* I-cache data */
1242     case 0xe: /* D-cache tag */
1243     case 0xf: /* D-cache data */
1244     case 0x10: /* I/D-cache flush page */
1245     case 0x11: /* I/D-cache flush segment */
1246     case 0x12: /* I/D-cache flush region */
1247     case 0x13: /* I/D-cache flush context */
1248     case 0x14: /* I/D-cache flush user */
1249         break;
1250     case 0x17: /* Block copy, sta access */
1251         {
1252             // val = src
1253             // addr = dst
1254             // copy 32 bytes
1255             unsigned int i;
1256             uint32_t src = val & ~3, dst = addr & ~3, temp;
1257
1258             for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1259                 temp = ldl_kernel(src);
1260                 stl_kernel(dst, temp);
1261             }
1262         }
1263         break;
1264     case 0x1f: /* Block fill, stda access */
1265         {
1266             // addr = dst
1267             // fill 32 bytes with val
1268             unsigned int i;
1269             uint32_t dst = addr & 7;
1270
1271             for (i = 0; i < 32; i += 8, dst += 8)
1272                 stq_kernel(dst, val);
1273         }
1274         break;
1275     case 0x20: /* MMU passthrough */
1276         {
1277             switch(size) {
1278             case 1:
1279                 stb_phys(addr, val);
1280                 break;
1281             case 2:
1282                 stw_phys(addr & ~1, val);
1283                 break;
1284             case 4:
1285             default:
1286                 stl_phys(addr & ~3, val);
1287                 break;
1288             case 8:
1289                 stq_phys(addr & ~7, val);
1290                 break;
1291             }
1292         }
1293         break;
1294     case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1295         {
1296             switch(size) {
1297             case 1:
1298                 stb_phys((target_phys_addr_t)addr
1299                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1300                 break;
1301             case 2:
1302                 stw_phys((target_phys_addr_t)(addr & ~1)
1303                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1304                 break;
1305             case 4:
1306             default:
1307                 stl_phys((target_phys_addr_t)(addr & ~3)
1308                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1309                 break;
1310             case 8:
1311                 stq_phys((target_phys_addr_t)(addr & ~7)
1312                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1313                 break;
1314             }
1315         }
1316         break;
1317     case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
1318     case 0x31: // store buffer data, Ross RT620 I-cache flush or
1319                // Turbosparc snoop RAM
1320     case 0x32: // store buffer control or Turbosparc page table descriptor diagnostic
1321     case 0x36: /* I-cache flash clear */
1322     case 0x37: /* D-cache flash clear */
1323     case 0x38: /* breakpoint diagnostics */
1324     case 0x4c: /* breakpoint action */
1325         break;
1326     case 8: /* User code access, XXX */
1327     case 9: /* Supervisor code access, XXX */
1328     default:
1329         do_unassigned_access(addr, 1, 0, asi);
1330         break;
1331     }
1332 #ifdef DEBUG_ASI
1333     dump_asi("write", addr, asi, size, val);
1334 #endif
1335 }
1336
1337 #endif /* CONFIG_USER_ONLY */
1338 #else /* TARGET_SPARC64 */
1339
1340 #ifdef CONFIG_USER_ONLY
1341 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1342 {
1343     uint64_t ret = 0;
1344 #if defined(DEBUG_ASI)
1345     target_ulong last_addr = addr;
1346 #endif
1347
1348     if (asi < 0x80)
1349         raise_exception(TT_PRIV_ACT);
1350
1351     helper_check_align(addr, size - 1);
1352     ABI32_MASK(addr);
1353
1354     switch (asi) {
1355     case 0x80: // Primary
1356     case 0x82: // Primary no-fault
1357     case 0x88: // Primary LE
1358     case 0x8a: // Primary no-fault LE
1359         {
1360             switch(size) {
1361             case 1:
1362                 ret = ldub_raw(addr);
1363                 break;
1364             case 2:
1365                 ret = lduw_raw(addr & ~1);
1366                 break;
1367             case 4:
1368                 ret = ldl_raw(addr & ~3);
1369                 break;
1370             default:
1371             case 8:
1372                 ret = ldq_raw(addr & ~7);
1373                 break;
1374             }
1375         }
1376         break;
1377     case 0x81: // Secondary
1378     case 0x83: // Secondary no-fault
1379     case 0x89: // Secondary LE
1380     case 0x8b: // Secondary no-fault LE
1381         // XXX
1382         break;
1383     default:
1384         break;
1385     }
1386
1387     /* Convert from little endian */
1388     switch (asi) {
1389     case 0x88: // Primary LE
1390     case 0x89: // Secondary LE
1391     case 0x8a: // Primary no-fault LE
1392     case 0x8b: // Secondary no-fault LE
1393         switch(size) {
1394         case 2:
1395             ret = bswap16(ret);
1396             break;
1397         case 4:
1398             ret = bswap32(ret);
1399             break;
1400         case 8:
1401             ret = bswap64(ret);
1402             break;
1403         default:
1404             break;
1405         }
1406     default:
1407         break;
1408     }
1409
1410     /* Convert to signed number */
1411     if (sign) {
1412         switch(size) {
1413         case 1:
1414             ret = (int8_t) ret;
1415             break;
1416         case 2:
1417             ret = (int16_t) ret;
1418             break;
1419         case 4:
1420             ret = (int32_t) ret;
1421             break;
1422         default:
1423             break;
1424         }
1425     }
1426 #ifdef DEBUG_ASI
1427     dump_asi("read ", last_addr, asi, size, ret);
1428 #endif
1429     return ret;
1430 }
1431
1432 void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1433 {
1434 #ifdef DEBUG_ASI
1435     dump_asi("write", addr, asi, size, val);
1436 #endif
1437     if (asi < 0x80)
1438         raise_exception(TT_PRIV_ACT);
1439
1440     helper_check_align(addr, size - 1);
1441     ABI32_MASK(addr);
1442
1443     /* Convert to little endian */
1444     switch (asi) {
1445     case 0x88: // Primary LE
1446     case 0x89: // Secondary LE
1447         switch(size) {
1448         case 2:
1449             addr = bswap16(addr);
1450             break;
1451         case 4:
1452             addr = bswap32(addr);
1453             break;
1454         case 8:
1455             addr = bswap64(addr);
1456             break;
1457         default:
1458             break;
1459         }
1460     default:
1461         break;
1462     }
1463
1464     switch(asi) {
1465     case 0x80: // Primary
1466     case 0x88: // Primary LE
1467         {
1468             switch(size) {
1469             case 1:
1470                 stb_raw(addr, val);
1471                 break;
1472             case 2:
1473                 stw_raw(addr & ~1, val);
1474                 break;
1475             case 4:
1476                 stl_raw(addr & ~3, val);
1477                 break;
1478             case 8:
1479             default:
1480                 stq_raw(addr & ~7, val);
1481                 break;
1482             }
1483         }
1484         break;
1485     case 0x81: // Secondary
1486     case 0x89: // Secondary LE
1487         // XXX
1488         return;
1489
1490     case 0x82: // Primary no-fault, RO
1491     case 0x83: // Secondary no-fault, RO
1492     case 0x8a: // Primary no-fault LE, RO
1493     case 0x8b: // Secondary no-fault LE, RO
1494     default:
1495         do_unassigned_access(addr, 1, 0, 1);
1496         return;
1497     }
1498 }
1499
1500 #else /* CONFIG_USER_ONLY */
1501
1502 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1503 {
1504     uint64_t ret = 0;
1505 #if defined(DEBUG_ASI)
1506     target_ulong last_addr = addr;
1507 #endif
1508
1509     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1510         || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1511         raise_exception(TT_PRIV_ACT);
1512
1513     helper_check_align(addr, size - 1);
1514     switch (asi) {
1515     case 0x10: // As if user primary
1516     case 0x18: // As if user primary LE
1517     case 0x80: // Primary
1518     case 0x82: // Primary no-fault
1519     case 0x88: // Primary LE
1520     case 0x8a: // Primary no-fault LE
1521         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1522             if (env->hpstate & HS_PRIV) {
1523                 switch(size) {
1524                 case 1:
1525                     ret = ldub_hypv(addr);
1526                     break;
1527                 case 2:
1528                     ret = lduw_hypv(addr & ~1);
1529                     break;
1530                 case 4:
1531                     ret = ldl_hypv(addr & ~3);
1532                     break;
1533                 default:
1534                 case 8:
1535                     ret = ldq_hypv(addr & ~7);
1536                     break;
1537                 }
1538             } else {
1539                 switch(size) {
1540                 case 1:
1541                     ret = ldub_kernel(addr);
1542                     break;
1543                 case 2:
1544                     ret = lduw_kernel(addr & ~1);
1545                     break;
1546                 case 4:
1547                     ret = ldl_kernel(addr & ~3);
1548                     break;
1549                 default:
1550                 case 8:
1551                     ret = ldq_kernel(addr & ~7);
1552                     break;
1553                 }
1554             }
1555         } else {
1556             switch(size) {
1557             case 1:
1558                 ret = ldub_user(addr);
1559                 break;
1560             case 2:
1561                 ret = lduw_user(addr & ~1);
1562                 break;
1563             case 4:
1564                 ret = ldl_user(addr & ~3);
1565                 break;
1566             default:
1567             case 8:
1568                 ret = ldq_user(addr & ~7);
1569                 break;
1570             }
1571         }
1572         break;
1573     case 0x14: // Bypass
1574     case 0x15: // Bypass, non-cacheable
1575     case 0x1c: // Bypass LE
1576     case 0x1d: // Bypass, non-cacheable LE
1577         {
1578             switch(size) {
1579             case 1:
1580                 ret = ldub_phys(addr);
1581                 break;
1582             case 2:
1583                 ret = lduw_phys(addr & ~1);
1584                 break;
1585             case 4:
1586                 ret = ldl_phys(addr & ~3);
1587                 break;
1588             default:
1589             case 8:
1590                 ret = ldq_phys(addr & ~7);
1591                 break;
1592             }
1593             break;
1594         }
1595     case 0x04: // Nucleus
1596     case 0x0c: // Nucleus Little Endian (LE)
1597     case 0x11: // As if user secondary
1598     case 0x19: // As if user secondary LE
1599     case 0x24: // Nucleus quad LDD 128 bit atomic
1600     case 0x2c: // Nucleus quad LDD 128 bit atomic
1601     case 0x4a: // UPA config
1602     case 0x81: // Secondary
1603     case 0x83: // Secondary no-fault
1604     case 0x89: // Secondary LE
1605     case 0x8b: // Secondary no-fault LE
1606         // XXX
1607         break;
1608     case 0x45: // LSU
1609         ret = env->lsu;
1610         break;
1611     case 0x50: // I-MMU regs
1612         {
1613             int reg = (addr >> 3) & 0xf;
1614
1615             ret = env->immuregs[reg];
1616             break;
1617         }
1618     case 0x51: // I-MMU 8k TSB pointer
1619     case 0x52: // I-MMU 64k TSB pointer
1620     case 0x55: // I-MMU data access
1621         // XXX
1622         break;
1623     case 0x56: // I-MMU tag read
1624         {
1625             unsigned int i;
1626
1627             for (i = 0; i < 64; i++) {
1628                 // Valid, ctx match, vaddr match
1629                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1630                     env->itlb_tag[i] == addr) {
1631                     ret = env->itlb_tag[i];
1632                     break;
1633                 }
1634             }
1635             break;
1636         }
1637     case 0x58: // D-MMU regs
1638         {
1639             int reg = (addr >> 3) & 0xf;
1640
1641             ret = env->dmmuregs[reg];
1642             break;
1643         }
1644     case 0x5e: // D-MMU tag read
1645         {
1646             unsigned int i;
1647
1648             for (i = 0; i < 64; i++) {
1649                 // Valid, ctx match, vaddr match
1650                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1651                     env->dtlb_tag[i] == addr) {
1652                     ret = env->dtlb_tag[i];
1653                     break;
1654                 }
1655             }
1656             break;
1657         }
1658     case 0x59: // D-MMU 8k TSB pointer
1659     case 0x5a: // D-MMU 64k TSB pointer
1660     case 0x5b: // D-MMU data pointer
1661     case 0x5d: // D-MMU data access
1662     case 0x48: // Interrupt dispatch, RO
1663     case 0x49: // Interrupt data receive
1664     case 0x7f: // Incoming interrupt vector, RO
1665         // XXX
1666         break;
1667     case 0x54: // I-MMU data in, WO
1668     case 0x57: // I-MMU demap, WO
1669     case 0x5c: // D-MMU data in, WO
1670     case 0x5f: // D-MMU demap, WO
1671     case 0x77: // Interrupt vector, WO
1672     default:
1673         do_unassigned_access(addr, 0, 0, 1);
1674         ret = 0;
1675         break;
1676     }
1677
1678     /* Convert from little endian */
1679     switch (asi) {
1680     case 0x0c: // Nucleus Little Endian (LE)
1681     case 0x18: // As if user primary LE
1682     case 0x19: // As if user secondary LE
1683     case 0x1c: // Bypass LE
1684     case 0x1d: // Bypass, non-cacheable LE
1685     case 0x88: // Primary LE
1686     case 0x89: // Secondary LE
1687     case 0x8a: // Primary no-fault LE
1688     case 0x8b: // Secondary no-fault LE
1689         switch(size) {
1690         case 2:
1691             ret = bswap16(ret);
1692             break;
1693         case 4:
1694             ret = bswap32(ret);
1695             break;
1696         case 8:
1697             ret = bswap64(ret);
1698             break;
1699         default:
1700             break;
1701         }
1702     default:
1703         break;
1704     }
1705
1706     /* Convert to signed number */
1707     if (sign) {
1708         switch(size) {
1709         case 1:
1710             ret = (int8_t) ret;
1711             break;
1712         case 2:
1713             ret = (int16_t) ret;
1714             break;
1715         case 4:
1716             ret = (int32_t) ret;
1717             break;
1718         default:
1719             break;
1720         }
1721     }
1722 #ifdef DEBUG_ASI
1723     dump_asi("read ", last_addr, asi, size, ret);
1724 #endif
1725     return ret;
1726 }
1727
1728 void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1729 {
1730 #ifdef DEBUG_ASI
1731     dump_asi("write", addr, asi, size, val);
1732 #endif
1733     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1734         || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1735         raise_exception(TT_PRIV_ACT);
1736
1737     helper_check_align(addr, size - 1);
1738     /* Convert to little endian */
1739     switch (asi) {
1740     case 0x0c: // Nucleus Little Endian (LE)
1741     case 0x18: // As if user primary LE
1742     case 0x19: // As if user secondary LE
1743     case 0x1c: // Bypass LE
1744     case 0x1d: // Bypass, non-cacheable LE
1745     case 0x88: // Primary LE
1746     case 0x89: // Secondary LE
1747         switch(size) {
1748         case 2:
1749             addr = bswap16(addr);
1750             break;
1751         case 4:
1752             addr = bswap32(addr);
1753             break;
1754         case 8:
1755             addr = bswap64(addr);
1756             break;
1757         default:
1758             break;
1759         }
1760     default:
1761         break;
1762     }
1763
1764     switch(asi) {
1765     case 0x10: // As if user primary
1766     case 0x18: // As if user primary LE
1767     case 0x80: // Primary
1768     case 0x88: // Primary LE
1769         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1770             if (env->hpstate & HS_PRIV) {
1771                 switch(size) {
1772                 case 1:
1773                     stb_hypv(addr, val);
1774                     break;
1775                 case 2:
1776                     stw_hypv(addr & ~1, val);
1777                     break;
1778                 case 4:
1779                     stl_hypv(addr & ~3, val);
1780                     break;
1781                 case 8:
1782                 default:
1783                     stq_hypv(addr & ~7, val);
1784                     break;
1785                 }
1786             } else {
1787                 switch(size) {
1788                 case 1:
1789                     stb_kernel(addr, val);
1790                     break;
1791                 case 2:
1792                     stw_kernel(addr & ~1, val);
1793                     break;
1794                 case 4:
1795                     stl_kernel(addr & ~3, val);
1796                     break;
1797                 case 8:
1798                 default:
1799                     stq_kernel(addr & ~7, val);
1800                     break;
1801                 }
1802             }
1803         } else {
1804             switch(size) {
1805             case 1:
1806                 stb_user(addr, val);
1807                 break;
1808             case 2:
1809                 stw_user(addr & ~1, val);
1810                 break;
1811             case 4:
1812                 stl_user(addr & ~3, val);
1813                 break;
1814             case 8:
1815             default:
1816                 stq_user(addr & ~7, val);
1817                 break;
1818             }
1819         }
1820         break;
1821     case 0x14: // Bypass
1822     case 0x15: // Bypass, non-cacheable
1823     case 0x1c: // Bypass LE
1824     case 0x1d: // Bypass, non-cacheable LE
1825         {
1826             switch(size) {
1827             case 1:
1828                 stb_phys(addr, val);
1829                 break;
1830             case 2:
1831                 stw_phys(addr & ~1, val);
1832                 break;
1833             case 4:
1834                 stl_phys(addr & ~3, val);
1835                 break;
1836             case 8:
1837             default:
1838                 stq_phys(addr & ~7, val);
1839                 break;
1840             }
1841         }
1842         return;
1843     case 0x04: // Nucleus
1844     case 0x0c: // Nucleus Little Endian (LE)
1845     case 0x11: // As if user secondary
1846     case 0x19: // As if user secondary LE
1847     case 0x24: // Nucleus quad LDD 128 bit atomic
1848     case 0x2c: // Nucleus quad LDD 128 bit atomic
1849     case 0x4a: // UPA config
1850     case 0x81: // Secondary
1851     case 0x89: // Secondary LE
1852         // XXX
1853         return;
1854     case 0x45: // LSU
1855         {
1856             uint64_t oldreg;
1857
1858             oldreg = env->lsu;
1859             env->lsu = val & (DMMU_E | IMMU_E);
1860             // Mappings generated during D/I MMU disabled mode are
1861             // invalid in normal mode
1862             if (oldreg != env->lsu) {
1863                 DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
1864 #ifdef DEBUG_MMU
1865                 dump_mmu(env);
1866 #endif
1867                 tlb_flush(env, 1);
1868             }
1869             return;
1870         }
1871     case 0x50: // I-MMU regs
1872         {
1873             int reg = (addr >> 3) & 0xf;
1874             uint64_t oldreg;
1875
1876             oldreg = env->immuregs[reg];
1877             switch(reg) {
1878             case 0: // RO
1879             case 4:
1880                 return;
1881             case 1: // Not in I-MMU
1882             case 2:
1883             case 7:
1884             case 8:
1885                 return;
1886             case 3: // SFSR
1887                 if ((val & 1) == 0)
1888                     val = 0; // Clear SFSR
1889                 break;
1890             case 5: // TSB access
1891             case 6: // Tag access
1892             default:
1893                 break;
1894             }
1895             env->immuregs[reg] = val;
1896             if (oldreg != env->immuregs[reg]) {
1897                 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
1898             }
1899 #ifdef DEBUG_MMU
1900             dump_mmu(env);
1901 #endif
1902             return;
1903         }
1904     case 0x54: // I-MMU data in
1905         {
1906             unsigned int i;
1907
1908             // Try finding an invalid entry
1909             for (i = 0; i < 64; i++) {
1910                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
1911                     env->itlb_tag[i] = env->immuregs[6];
1912                     env->itlb_tte[i] = val;
1913                     return;
1914                 }
1915             }
1916             // Try finding an unlocked entry
1917             for (i = 0; i < 64; i++) {
1918                 if ((env->itlb_tte[i] & 0x40) == 0) {
1919                     env->itlb_tag[i] = env->immuregs[6];
1920                     env->itlb_tte[i] = val;
1921                     return;
1922                 }
1923             }
1924             // error state?
1925             return;
1926         }
1927     case 0x55: // I-MMU data access
1928         {
1929             unsigned int i = (addr >> 3) & 0x3f;
1930
1931             env->itlb_tag[i] = env->immuregs[6];
1932             env->itlb_tte[i] = val;
1933             return;
1934         }
1935     case 0x57: // I-MMU demap
1936         // XXX
1937         return;
1938     case 0x58: // D-MMU regs
1939         {
1940             int reg = (addr >> 3) & 0xf;
1941             uint64_t oldreg;
1942
1943             oldreg = env->dmmuregs[reg];
1944             switch(reg) {
1945             case 0: // RO
1946             case 4:
1947                 return;
1948             case 3: // SFSR
1949                 if ((val & 1) == 0) {
1950                     val = 0; // Clear SFSR, Fault address
1951                     env->dmmuregs[4] = 0;
1952                 }
1953                 env->dmmuregs[reg] = val;
1954                 break;
1955             case 1: // Primary context
1956             case 2: // Secondary context
1957             case 5: // TSB access
1958             case 6: // Tag access
1959             case 7: // Virtual Watchpoint
1960             case 8: // Physical Watchpoint
1961             default:
1962                 break;
1963             }
1964             env->dmmuregs[reg] = val;
1965             if (oldreg != env->dmmuregs[reg]) {
1966                 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
1967             }
1968 #ifdef DEBUG_MMU
1969             dump_mmu(env);
1970 #endif
1971             return;
1972         }
1973     case 0x5c: // D-MMU data in
1974         {
1975             unsigned int i;
1976
1977             // Try finding an invalid entry
1978             for (i = 0; i < 64; i++) {
1979                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
1980                     env->dtlb_tag[i] = env->dmmuregs[6];
1981                     env->dtlb_tte[i] = val;
1982                     return;
1983                 }
1984             }
1985             // Try finding an unlocked entry
1986             for (i = 0; i < 64; i++) {
1987                 if ((env->dtlb_tte[i] & 0x40) == 0) {
1988                     env->dtlb_tag[i] = env->dmmuregs[6];
1989                     env->dtlb_tte[i] = val;
1990                     return;
1991                 }
1992             }
1993             // error state?
1994             return;
1995         }
1996     case 0x5d: // D-MMU data access
1997         {
1998             unsigned int i = (addr >> 3) & 0x3f;
1999
2000             env->dtlb_tag[i] = env->dmmuregs[6];
2001             env->dtlb_tte[i] = val;
2002             return;
2003         }
2004     case 0x5f: // D-MMU demap
2005     case 0x49: // Interrupt data receive
2006         // XXX
2007         return;
2008     case 0x51: // I-MMU 8k TSB pointer, RO
2009     case 0x52: // I-MMU 64k TSB pointer, RO
2010     case 0x56: // I-MMU tag read, RO
2011     case 0x59: // D-MMU 8k TSB pointer, RO
2012     case 0x5a: // D-MMU 64k TSB pointer, RO
2013     case 0x5b: // D-MMU data pointer, RO
2014     case 0x5e: // D-MMU tag read, RO
2015     case 0x48: // Interrupt dispatch, RO
2016     case 0x7f: // Incoming interrupt vector, RO
2017     case 0x82: // Primary no-fault, RO
2018     case 0x83: // Secondary no-fault, RO
2019     case 0x8a: // Primary no-fault LE, RO
2020     case 0x8b: // Secondary no-fault LE, RO
2021     default:
2022         do_unassigned_access(addr, 1, 0, 1);
2023         return;
2024     }
2025 }
2026 #endif /* CONFIG_USER_ONLY */
2027
2028 void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2029 {
2030     unsigned int i;
2031     target_ulong val;
2032
2033     helper_check_align(addr, 3);
2034     switch (asi) {
2035     case 0xf0: // Block load primary
2036     case 0xf1: // Block load secondary
2037     case 0xf8: // Block load primary LE
2038     case 0xf9: // Block load secondary LE
2039         if (rd & 7) {
2040             raise_exception(TT_ILL_INSN);
2041             return;
2042         }
2043         helper_check_align(addr, 0x3f);
2044         for (i = 0; i < 16; i++) {
2045             *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, 0);
2046             addr += 4;
2047         }
2048
2049         return;
2050     default:
2051         break;
2052     }
2053
2054     val = helper_ld_asi(addr, asi, size, 0);
2055     switch(size) {
2056     default:
2057     case 4:
2058         *((uint32_t *)&FT0) = val;
2059         break;
2060     case 8:
2061         *((int64_t *)&DT0) = val;
2062         break;
2063     case 16:
2064         // XXX
2065         break;
2066     }
2067 }
2068
2069 void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2070 {
2071     unsigned int i;
2072     target_ulong val = 0;
2073
2074     helper_check_align(addr, 3);
2075     switch (asi) {
2076     case 0xf0: // Block store primary
2077     case 0xf1: // Block store secondary
2078     case 0xf8: // Block store primary LE
2079     case 0xf9: // Block store secondary LE
2080         if (rd & 7) {
2081             raise_exception(TT_ILL_INSN);
2082             return;
2083         }
2084         helper_check_align(addr, 0x3f);
2085         for (i = 0; i < 16; i++) {
2086             val = *(uint32_t *)&env->fpr[rd++];
2087             helper_st_asi(addr, val, asi & 0x8f, 4);
2088             addr += 4;
2089         }
2090
2091         return;
2092     default:
2093         break;
2094     }
2095
2096     switch(size) {
2097     default:
2098     case 4:
2099         val = *((uint32_t *)&FT0);
2100         break;
2101     case 8:
2102         val = *((int64_t *)&DT0);
2103         break;
2104     case 16:
2105         // XXX
2106         break;
2107     }
2108     helper_st_asi(addr, val, asi, size);
2109 }
2110
2111 target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2112                             target_ulong val2, uint32_t asi)
2113 {
2114     target_ulong ret;
2115
2116     val1 &= 0xffffffffUL;
2117     ret = helper_ld_asi(addr, asi, 4, 0);
2118     ret &= 0xffffffffUL;
2119     if (val1 == ret)
2120         helper_st_asi(addr, val2 & 0xffffffffUL, asi, 4);
2121     return ret;
2122 }
2123
2124 target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2125                              target_ulong val2, uint32_t asi)
2126 {
2127     target_ulong ret;
2128
2129     ret = helper_ld_asi(addr, asi, 8, 0);
2130     if (val1 == ret)
2131         helper_st_asi(addr, val2, asi, 8);
2132     return ret;
2133 }
2134 #endif /* TARGET_SPARC64 */
2135
2136 #ifndef TARGET_SPARC64
2137 void helper_rett(void)
2138 {
2139     unsigned int cwp;
2140
2141     if (env->psret == 1)
2142         raise_exception(TT_ILL_INSN);
2143
2144     env->psret = 1;
2145     cwp = (env->cwp + 1) & (NWINDOWS - 1);
2146     if (env->wim & (1 << cwp)) {
2147         raise_exception(TT_WIN_UNF);
2148     }
2149     set_cwp(cwp);
2150     env->psrs = env->psrps;
2151 }
2152 #endif
2153
2154 target_ulong helper_udiv(target_ulong a, target_ulong b)
2155 {
2156     uint64_t x0;
2157     uint32_t x1;
2158
2159     x0 = a | ((uint64_t) (env->y) << 32);
2160     x1 = b;
2161
2162     if (x1 == 0) {
2163         raise_exception(TT_DIV_ZERO);
2164     }
2165
2166     x0 = x0 / x1;
2167     if (x0 > 0xffffffff) {
2168         env->cc_src2 = 1;
2169         return 0xffffffff;
2170     } else {
2171         env->cc_src2 = 0;
2172         return x0;
2173     }
2174 }
2175
2176 target_ulong helper_sdiv(target_ulong a, target_ulong b)
2177 {
2178     int64_t x0;
2179     int32_t x1;
2180
2181     x0 = a | ((int64_t) (env->y) << 32);
2182     x1 = b;
2183
2184     if (x1 == 0) {
2185         raise_exception(TT_DIV_ZERO);
2186     }
2187
2188     x0 = x0 / x1;
2189     if ((int32_t) x0 != x0) {
2190         env->cc_src2 = 1;
2191         return x0 < 0? 0x80000000: 0x7fffffff;
2192     } else {
2193         env->cc_src2 = 0;
2194         return x0;
2195     }
2196 }
2197
2198 uint64_t helper_pack64(target_ulong high, target_ulong low)
2199 {
2200     return ((uint64_t)high << 32) | (uint64_t)(low & 0xffffffff);
2201 }
2202
2203 void helper_stdf(target_ulong addr, int mem_idx)
2204 {
2205     helper_check_align(addr, 7);
2206 #if !defined(CONFIG_USER_ONLY)
2207     switch (mem_idx) {
2208     case 0:
2209         stfq_user(addr, DT0);
2210         break;
2211     case 1:
2212         stfq_kernel(addr, DT0);
2213         break;
2214 #ifdef TARGET_SPARC64
2215     case 2:
2216         stfq_hypv(addr, DT0);
2217         break;
2218 #endif
2219     default:
2220         break;
2221     }
2222 #else
2223     ABI32_MASK(addr);
2224     stfq_raw(addr, DT0);
2225 #endif
2226 }
2227
2228 void helper_lddf(target_ulong addr, int mem_idx)
2229 {
2230     helper_check_align(addr, 7);
2231 #if !defined(CONFIG_USER_ONLY)
2232     switch (mem_idx) {
2233     case 0:
2234         DT0 = ldfq_user(addr);
2235         break;
2236     case 1:
2237         DT0 = ldfq_kernel(addr);
2238         break;
2239 #ifdef TARGET_SPARC64
2240     case 2:
2241         DT0 = ldfq_hypv(addr);
2242         break;
2243 #endif
2244     default:
2245         break;
2246     }
2247 #else
2248     ABI32_MASK(addr);
2249     DT0 = ldfq_raw(addr);
2250 #endif
2251 }
2252
2253 void helper_ldqf(target_ulong addr, int mem_idx)
2254 {
2255     // XXX add 128 bit load
2256     CPU_QuadU u;
2257
2258     helper_check_align(addr, 7);
2259 #if !defined(CONFIG_USER_ONLY)
2260     switch (mem_idx) {
2261     case 0:
2262         u.ll.upper = ldq_user(addr);
2263         u.ll.lower = ldq_user(addr + 8);
2264         QT0 = u.q;
2265         break;
2266     case 1:
2267         u.ll.upper = ldq_kernel(addr);
2268         u.ll.lower = ldq_kernel(addr + 8);
2269         QT0 = u.q;
2270         break;
2271 #ifdef TARGET_SPARC64
2272     case 2:
2273         u.ll.upper = ldq_hypv(addr);
2274         u.ll.lower = ldq_hypv(addr + 8);
2275         QT0 = u.q;
2276         break;
2277 #endif
2278     default:
2279         break;
2280     }
2281 #else
2282     ABI32_MASK(addr);
2283     u.ll.upper = ldq_raw(addr);
2284     u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
2285     QT0 = u.q;
2286 #endif
2287 }
2288
2289 void helper_stqf(target_ulong addr, int mem_idx)
2290 {
2291     // XXX add 128 bit store
2292     CPU_QuadU u;
2293
2294     helper_check_align(addr, 7);
2295 #if !defined(CONFIG_USER_ONLY)
2296     switch (mem_idx) {
2297     case 0:
2298         u.q = QT0;
2299         stq_user(addr, u.ll.upper);
2300         stq_user(addr + 8, u.ll.lower);
2301         break;
2302     case 1:
2303         u.q = QT0;
2304         stq_kernel(addr, u.ll.upper);
2305         stq_kernel(addr + 8, u.ll.lower);
2306         break;
2307 #ifdef TARGET_SPARC64
2308     case 2:
2309         u.q = QT0;
2310         stq_hypv(addr, u.ll.upper);
2311         stq_hypv(addr + 8, u.ll.lower);
2312         break;
2313 #endif
2314     default:
2315         break;
2316     }
2317 #else
2318     u.q = QT0;
2319     ABI32_MASK(addr);
2320     stq_raw(addr, u.ll.upper);
2321     stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
2322 #endif
2323 }
2324
2325 void helper_ldfsr(void)
2326 {
2327     int rnd_mode;
2328
2329     PUT_FSR32(env, *((uint32_t *) &FT0));
2330     switch (env->fsr & FSR_RD_MASK) {
2331     case FSR_RD_NEAREST:
2332         rnd_mode = float_round_nearest_even;
2333         break;
2334     default:
2335     case FSR_RD_ZERO:
2336         rnd_mode = float_round_to_zero;
2337         break;
2338     case FSR_RD_POS:
2339         rnd_mode = float_round_up;
2340         break;
2341     case FSR_RD_NEG:
2342         rnd_mode = float_round_down;
2343         break;
2344     }
2345     set_float_rounding_mode(rnd_mode, &env->fp_status);
2346 }
2347
2348 void helper_stfsr(void)
2349 {
2350     *((uint32_t *) &FT0) = GET_FSR32(env);
2351 }
2352
2353 void helper_debug(void)
2354 {
2355     env->exception_index = EXCP_DEBUG;
2356     cpu_loop_exit();
2357 }
2358
2359 #ifndef TARGET_SPARC64
2360 /* XXX: use another pointer for %iN registers to avoid slow wrapping
2361    handling ? */
2362 void helper_save(void)
2363 {
2364     uint32_t cwp;
2365
2366     cwp = (env->cwp - 1) & (NWINDOWS - 1);
2367     if (env->wim & (1 << cwp)) {
2368         raise_exception(TT_WIN_OVF);
2369     }
2370     set_cwp(cwp);
2371 }
2372
2373 void helper_restore(void)
2374 {
2375     uint32_t cwp;
2376
2377     cwp = (env->cwp + 1) & (NWINDOWS - 1);
2378     if (env->wim & (1 << cwp)) {
2379         raise_exception(TT_WIN_UNF);
2380     }
2381     set_cwp(cwp);
2382 }
2383
2384 void helper_wrpsr(target_ulong new_psr)
2385 {
2386     if ((new_psr & PSR_CWP) >= NWINDOWS)
2387         raise_exception(TT_ILL_INSN);
2388     else
2389         PUT_PSR(env, new_psr);
2390 }
2391
2392 target_ulong helper_rdpsr(void)
2393 {
2394     return GET_PSR(env);
2395 }
2396
2397 #else
2398 /* XXX: use another pointer for %iN registers to avoid slow wrapping
2399    handling ? */
2400 void helper_save(void)
2401 {
2402     uint32_t cwp;
2403
2404     cwp = (env->cwp - 1) & (NWINDOWS - 1);
2405     if (env->cansave == 0) {
2406         raise_exception(TT_SPILL | (env->otherwin != 0 ?
2407                                     (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2408                                     ((env->wstate & 0x7) << 2)));
2409     } else {
2410         if (env->cleanwin - env->canrestore == 0) {
2411             // XXX Clean windows without trap
2412             raise_exception(TT_CLRWIN);
2413         } else {
2414             env->cansave--;
2415             env->canrestore++;
2416             set_cwp(cwp);
2417         }
2418     }
2419 }
2420
2421 void helper_restore(void)
2422 {
2423     uint32_t cwp;
2424
2425     cwp = (env->cwp + 1) & (NWINDOWS - 1);
2426     if (env->canrestore == 0) {
2427         raise_exception(TT_FILL | (env->otherwin != 0 ?
2428                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2429                                    ((env->wstate & 0x7) << 2)));
2430     } else {
2431         env->cansave++;
2432         env->canrestore--;
2433         set_cwp(cwp);
2434     }
2435 }
2436
2437 void helper_flushw(void)
2438 {
2439     if (env->cansave != NWINDOWS - 2) {
2440         raise_exception(TT_SPILL | (env->otherwin != 0 ?
2441                                     (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2442                                     ((env->wstate & 0x7) << 2)));
2443     }
2444 }
2445
2446 void helper_saved(void)
2447 {
2448     env->cansave++;
2449     if (env->otherwin == 0)
2450         env->canrestore--;
2451     else
2452         env->otherwin--;
2453 }
2454
2455 void helper_restored(void)
2456 {
2457     env->canrestore++;
2458     if (env->cleanwin < NWINDOWS - 1)
2459         env->cleanwin++;
2460     if (env->otherwin == 0)
2461         env->cansave--;
2462     else
2463         env->otherwin--;
2464 }
2465
2466 target_ulong helper_rdccr(void)
2467 {
2468     return GET_CCR(env);
2469 }
2470
2471 void helper_wrccr(target_ulong new_ccr)
2472 {
2473     PUT_CCR(env, new_ccr);
2474 }
2475
2476 // CWP handling is reversed in V9, but we still use the V8 register
2477 // order.
2478 target_ulong helper_rdcwp(void)
2479 {
2480     return GET_CWP64(env);
2481 }
2482
2483 void helper_wrcwp(target_ulong new_cwp)
2484 {
2485     PUT_CWP64(env, new_cwp);
2486 }
2487
2488 // This function uses non-native bit order
2489 #define GET_FIELD(X, FROM, TO)                                  \
2490     ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
2491
2492 // This function uses the order in the manuals, i.e. bit 0 is 2^0
2493 #define GET_FIELD_SP(X, FROM, TO)               \
2494     GET_FIELD(X, 63 - (TO), 63 - (FROM))
2495
2496 target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
2497 {
2498     return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
2499         (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
2500         (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
2501         (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
2502         (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
2503         (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
2504         (((pixel_addr >> 55) & 1) << 4) |
2505         (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
2506         GET_FIELD_SP(pixel_addr, 11, 12);
2507 }
2508
2509 target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
2510 {
2511     uint64_t tmp;
2512
2513     tmp = addr + offset;
2514     env->gsr &= ~7ULL;
2515     env->gsr |= tmp & 7ULL;
2516     return tmp & ~7ULL;
2517 }
2518
2519 target_ulong helper_popc(target_ulong val)
2520 {
2521     return ctpop64(val);
2522 }
2523
2524 static inline uint64_t *get_gregset(uint64_t pstate)
2525 {
2526     switch (pstate) {
2527     default:
2528     case 0:
2529         return env->bgregs;
2530     case PS_AG:
2531         return env->agregs;
2532     case PS_MG:
2533         return env->mgregs;
2534     case PS_IG:
2535         return env->igregs;
2536     }
2537 }
2538
2539 static inline void change_pstate(uint64_t new_pstate)
2540 {
2541     uint64_t pstate_regs, new_pstate_regs;
2542     uint64_t *src, *dst;
2543
2544     pstate_regs = env->pstate & 0xc01;
2545     new_pstate_regs = new_pstate & 0xc01;
2546     if (new_pstate_regs != pstate_regs) {
2547         // Switch global register bank
2548         src = get_gregset(new_pstate_regs);
2549         dst = get_gregset(pstate_regs);
2550         memcpy32(dst, env->gregs);
2551         memcpy32(env->gregs, src);
2552     }
2553     env->pstate = new_pstate;
2554 }
2555
2556 void helper_wrpstate(target_ulong new_state)
2557 {
2558     change_pstate(new_state & 0xf3f);
2559 }
2560
2561 void helper_done(void)
2562 {
2563     env->tl--;
2564     env->tsptr = &env->ts[env->tl];
2565     env->pc = env->tsptr->tpc;
2566     env->npc = env->tsptr->tnpc + 4;
2567     PUT_CCR(env, env->tsptr->tstate >> 32);
2568     env->asi = (env->tsptr->tstate >> 24) & 0xff;
2569     change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2570     PUT_CWP64(env, env->tsptr->tstate & 0xff);
2571 }
2572
2573 void helper_retry(void)
2574 {
2575     env->tl--;
2576     env->tsptr = &env->ts[env->tl];
2577     env->pc = env->tsptr->tpc;
2578     env->npc = env->tsptr->tnpc;
2579     PUT_CCR(env, env->tsptr->tstate >> 32);
2580     env->asi = (env->tsptr->tstate >> 24) & 0xff;
2581     change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2582     PUT_CWP64(env, env->tsptr->tstate & 0xff);
2583 }
2584 #endif
2585
2586 void set_cwp(int new_cwp)
2587 {
2588     /* put the modified wrap registers at their proper location */
2589     if (env->cwp == (NWINDOWS - 1))
2590         memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
2591     env->cwp = new_cwp;
2592     /* put the wrap registers at their temporary location */
2593     if (new_cwp == (NWINDOWS - 1))
2594         memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
2595     env->regwptr = env->regbase + (new_cwp * 16);
2596     REGWPTR = env->regwptr;
2597 }
2598
2599 void cpu_set_cwp(CPUState *env1, int new_cwp)
2600 {
2601     CPUState *saved_env;
2602 #ifdef reg_REGWPTR
2603     target_ulong *saved_regwptr;
2604 #endif
2605
2606     saved_env = env;
2607 #ifdef reg_REGWPTR
2608     saved_regwptr = REGWPTR;
2609 #endif
2610     env = env1;
2611     set_cwp(new_cwp);
2612     env = saved_env;
2613 #ifdef reg_REGWPTR
2614     REGWPTR = saved_regwptr;
2615 #endif
2616 }
2617
2618 #ifdef TARGET_SPARC64
2619 #ifdef DEBUG_PCALL
2620 static const char * const excp_names[0x50] = {
2621     [TT_TFAULT] = "Instruction Access Fault",
2622     [TT_TMISS] = "Instruction Access MMU Miss",
2623     [TT_CODE_ACCESS] = "Instruction Access Error",
2624     [TT_ILL_INSN] = "Illegal Instruction",
2625     [TT_PRIV_INSN] = "Privileged Instruction",
2626     [TT_NFPU_INSN] = "FPU Disabled",
2627     [TT_FP_EXCP] = "FPU Exception",
2628     [TT_TOVF] = "Tag Overflow",
2629     [TT_CLRWIN] = "Clean Windows",
2630     [TT_DIV_ZERO] = "Division By Zero",
2631     [TT_DFAULT] = "Data Access Fault",
2632     [TT_DMISS] = "Data Access MMU Miss",
2633     [TT_DATA_ACCESS] = "Data Access Error",
2634     [TT_DPROT] = "Data Protection Error",
2635     [TT_UNALIGNED] = "Unaligned Memory Access",
2636     [TT_PRIV_ACT] = "Privileged Action",
2637     [TT_EXTINT | 0x1] = "External Interrupt 1",
2638     [TT_EXTINT | 0x2] = "External Interrupt 2",
2639     [TT_EXTINT | 0x3] = "External Interrupt 3",
2640     [TT_EXTINT | 0x4] = "External Interrupt 4",
2641     [TT_EXTINT | 0x5] = "External Interrupt 5",
2642     [TT_EXTINT | 0x6] = "External Interrupt 6",
2643     [TT_EXTINT | 0x7] = "External Interrupt 7",
2644     [TT_EXTINT | 0x8] = "External Interrupt 8",
2645     [TT_EXTINT | 0x9] = "External Interrupt 9",
2646     [TT_EXTINT | 0xa] = "External Interrupt 10",
2647     [TT_EXTINT | 0xb] = "External Interrupt 11",
2648     [TT_EXTINT | 0xc] = "External Interrupt 12",
2649     [TT_EXTINT | 0xd] = "External Interrupt 13",
2650     [TT_EXTINT | 0xe] = "External Interrupt 14",
2651     [TT_EXTINT | 0xf] = "External Interrupt 15",
2652 };
2653 #endif
2654
2655 void do_interrupt(int intno)
2656 {
2657 #ifdef DEBUG_PCALL
2658     if (loglevel & CPU_LOG_INT) {
2659         static int count;
2660         const char *name;
2661
2662         if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80))
2663             name = "Unknown";
2664         else if (intno >= 0x100)
2665             name = "Trap Instruction";
2666         else if (intno >= 0xc0)
2667             name = "Window Fill";
2668         else if (intno >= 0x80)
2669             name = "Window Spill";
2670         else {
2671             name = excp_names[intno];
2672             if (!name)
2673                 name = "Unknown";
2674         }
2675
2676         fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
2677                 " SP=%016" PRIx64 "\n",
2678                 count, name, intno,
2679                 env->pc,
2680                 env->npc, env->regwptr[6]);
2681         cpu_dump_state(env, logfile, fprintf, 0);
2682 #if 0
2683         {
2684             int i;
2685             uint8_t *ptr;
2686
2687             fprintf(logfile, "       code=");
2688             ptr = (uint8_t *)env->pc;
2689             for(i = 0; i < 16; i++) {
2690                 fprintf(logfile, " %02x", ldub(ptr + i));
2691             }
2692             fprintf(logfile, "\n");
2693         }
2694 #endif
2695         count++;
2696     }
2697 #endif
2698 #if !defined(CONFIG_USER_ONLY)
2699     if (env->tl == MAXTL) {
2700         cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
2701         return;
2702     }
2703 #endif
2704     env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
2705         ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
2706         GET_CWP64(env);
2707     env->tsptr->tpc = env->pc;
2708     env->tsptr->tnpc = env->npc;
2709     env->tsptr->tt = intno;
2710     change_pstate(PS_PEF | PS_PRIV | PS_AG);
2711
2712     if (intno == TT_CLRWIN)
2713         set_cwp((env->cwp - 1) & (NWINDOWS - 1));
2714     else if ((intno & 0x1c0) == TT_SPILL)
2715         set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1));
2716     else if ((intno & 0x1c0) == TT_FILL)
2717         set_cwp((env->cwp + 1) & (NWINDOWS - 1));
2718     env->tbr &= ~0x7fffULL;
2719     env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
2720     if (env->tl < MAXTL - 1) {
2721         env->tl++;
2722     } else {
2723         env->pstate |= PS_RED;
2724         if (env->tl != MAXTL)
2725             env->tl++;
2726     }
2727     env->tsptr = &env->ts[env->tl];
2728     env->pc = env->tbr;
2729     env->npc = env->pc + 4;
2730     env->exception_index = 0;
2731 }
2732 #else
2733 #ifdef DEBUG_PCALL
2734 static const char * const excp_names[0x80] = {
2735     [TT_TFAULT] = "Instruction Access Fault",
2736     [TT_ILL_INSN] = "Illegal Instruction",
2737     [TT_PRIV_INSN] = "Privileged Instruction",
2738     [TT_NFPU_INSN] = "FPU Disabled",
2739     [TT_WIN_OVF] = "Window Overflow",
2740     [TT_WIN_UNF] = "Window Underflow",
2741     [TT_UNALIGNED] = "Unaligned Memory Access",
2742     [TT_FP_EXCP] = "FPU Exception",
2743     [TT_DFAULT] = "Data Access Fault",
2744     [TT_TOVF] = "Tag Overflow",
2745     [TT_EXTINT | 0x1] = "External Interrupt 1",
2746     [TT_EXTINT | 0x2] = "External Interrupt 2",
2747     [TT_EXTINT | 0x3] = "External Interrupt 3",
2748     [TT_EXTINT | 0x4] = "External Interrupt 4",
2749     [TT_EXTINT | 0x5] = "External Interrupt 5",
2750     [TT_EXTINT | 0x6] = "External Interrupt 6",
2751     [TT_EXTINT | 0x7] = "External Interrupt 7",
2752     [TT_EXTINT | 0x8] = "External Interrupt 8",
2753     [TT_EXTINT | 0x9] = "External Interrupt 9",
2754     [TT_EXTINT | 0xa] = "External Interrupt 10",
2755     [TT_EXTINT | 0xb] = "External Interrupt 11",
2756     [TT_EXTINT | 0xc] = "External Interrupt 12",
2757     [TT_EXTINT | 0xd] = "External Interrupt 13",
2758     [TT_EXTINT | 0xe] = "External Interrupt 14",
2759     [TT_EXTINT | 0xf] = "External Interrupt 15",
2760     [TT_TOVF] = "Tag Overflow",
2761     [TT_CODE_ACCESS] = "Instruction Access Error",
2762     [TT_DATA_ACCESS] = "Data Access Error",
2763     [TT_DIV_ZERO] = "Division By Zero",
2764     [TT_NCP_INSN] = "Coprocessor Disabled",
2765 };
2766 #endif
2767
2768 void do_interrupt(int intno)
2769 {
2770     int cwp;
2771
2772 #ifdef DEBUG_PCALL
2773     if (loglevel & CPU_LOG_INT) {
2774         static int count;
2775         const char *name;
2776
2777         if (intno < 0 || intno >= 0x100)
2778             name = "Unknown";
2779         else if (intno >= 0x80)
2780             name = "Trap Instruction";
2781         else {
2782             name = excp_names[intno];
2783             if (!name)
2784                 name = "Unknown";
2785         }
2786
2787         fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
2788                 count, name, intno,
2789                 env->pc,
2790                 env->npc, env->regwptr[6]);
2791         cpu_dump_state(env, logfile, fprintf, 0);
2792 #if 0
2793         {
2794             int i;
2795             uint8_t *ptr;
2796
2797             fprintf(logfile, "       code=");
2798             ptr = (uint8_t *)env->pc;
2799             for(i = 0; i < 16; i++) {
2800                 fprintf(logfile, " %02x", ldub(ptr + i));
2801             }
2802             fprintf(logfile, "\n");
2803         }
2804 #endif
2805         count++;
2806     }
2807 #endif
2808 #if !defined(CONFIG_USER_ONLY)
2809     if (env->psret == 0) {
2810         cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
2811         return;
2812     }
2813 #endif
2814     env->psret = 0;
2815     cwp = (env->cwp - 1) & (NWINDOWS - 1);
2816     set_cwp(cwp);
2817     env->regwptr[9] = env->pc;
2818     env->regwptr[10] = env->npc;
2819     env->psrps = env->psrs;
2820     env->psrs = 1;
2821     env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
2822     env->pc = env->tbr;
2823     env->npc = env->pc + 4;
2824     env->exception_index = 0;
2825 }
2826 #endif
2827
2828 #if !defined(CONFIG_USER_ONLY)
2829
2830 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
2831                                 void *retaddr);
2832
2833 #define MMUSUFFIX _mmu
2834 #define ALIGNED_ONLY
2835 #ifdef __s390__
2836 # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
2837 #else
2838 # define GETPC() (__builtin_return_address(0))
2839 #endif
2840
2841 #define SHIFT 0
2842 #include "softmmu_template.h"
2843
2844 #define SHIFT 1
2845 #include "softmmu_template.h"
2846
2847 #define SHIFT 2
2848 #include "softmmu_template.h"
2849
2850 #define SHIFT 3
2851 #include "softmmu_template.h"
2852
2853 /* XXX: make it generic ? */
2854 static void cpu_restore_state2(void *retaddr)
2855 {
2856     TranslationBlock *tb;
2857     unsigned long pc;
2858
2859     if (retaddr) {
2860         /* now we have a real cpu fault */
2861         pc = (unsigned long)retaddr;
2862         tb = tb_find_pc(pc);
2863         if (tb) {
2864             /* the PC is inside the translated code. It means that we have
2865                a virtual CPU fault */
2866             cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
2867         }
2868     }
2869 }
2870
2871 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
2872                                 void *retaddr)
2873 {
2874 #ifdef DEBUG_UNALIGNED
2875     printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
2876            "\n", addr, env->pc);
2877 #endif
2878     cpu_restore_state2(retaddr);
2879     raise_exception(TT_UNALIGNED);
2880 }
2881
2882 /* try to fill the TLB and return an exception if error. If retaddr is
2883    NULL, it means that the function was called in C code (i.e. not
2884    from generated code or from helper.c) */
2885 /* XXX: fix it to restore all registers */
2886 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
2887 {
2888     int ret;
2889     CPUState *saved_env;
2890
2891     /* XXX: hack to restore env in all cases, even if not called from
2892        generated code */
2893     saved_env = env;
2894     env = cpu_single_env;
2895
2896     ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
2897     if (ret) {
2898         cpu_restore_state2(retaddr);
2899         cpu_loop_exit();
2900     }
2901     env = saved_env;
2902 }
2903
2904 #endif
2905
2906 #ifndef TARGET_SPARC64
2907 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2908                           int is_asi)
2909 {
2910     CPUState *saved_env;
2911
2912     /* XXX: hack to restore env in all cases, even if not called from
2913        generated code */
2914     saved_env = env;
2915     env = cpu_single_env;
2916 #ifdef DEBUG_UNASSIGNED
2917     if (is_asi)
2918         printf("Unassigned mem %s access to " TARGET_FMT_plx " asi 0x%02x from "
2919                TARGET_FMT_lx "\n",
2920                is_exec ? "exec" : is_write ? "write" : "read", addr, is_asi,
2921                env->pc);
2922     else
2923         printf("Unassigned mem %s access to " TARGET_FMT_plx " from "
2924                TARGET_FMT_lx "\n",
2925                is_exec ? "exec" : is_write ? "write" : "read", addr, env->pc);
2926 #endif
2927     if (env->mmuregs[3]) /* Fault status register */
2928         env->mmuregs[3] = 1; /* overflow (not read before another fault) */
2929     if (is_asi)
2930         env->mmuregs[3] |= 1 << 16;
2931     if (env->psrs)
2932         env->mmuregs[3] |= 1 << 5;
2933     if (is_exec)
2934         env->mmuregs[3] |= 1 << 6;
2935     if (is_write)
2936         env->mmuregs[3] |= 1 << 7;
2937     env->mmuregs[3] |= (5 << 2) | 2;
2938     env->mmuregs[4] = addr; /* Fault address register */
2939     if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
2940         if (is_exec)
2941             raise_exception(TT_CODE_ACCESS);
2942         else
2943             raise_exception(TT_DATA_ACCESS);
2944     }
2945     env = saved_env;
2946 }
2947 #else
2948 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2949                           int is_asi)
2950 {
2951 #ifdef DEBUG_UNASSIGNED
2952     CPUState *saved_env;
2953
2954     /* XXX: hack to restore env in all cases, even if not called from
2955        generated code */
2956     saved_env = env;
2957     env = cpu_single_env;
2958     printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n",
2959            addr, env->pc);
2960     env = saved_env;
2961 #endif
2962     if (is_exec)
2963         raise_exception(TT_CODE_ACCESS);
2964     else
2965         raise_exception(TT_DATA_ACCESS);
2966 }
2967 #endif
2968