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