3665eea7c14f15aef2e9d5d1130f13db75be78c3
[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 static uint32_t compute_all_logic(void)
906 {
907     return get_NZ_icc(CC_DST);
908 }
909
910 static uint32_t compute_C_logic(void)
911 {
912     return 0;
913 }
914
915 #ifdef TARGET_SPARC64
916 static uint32_t compute_all_logic_xcc(void)
917 {
918     return get_NZ_xcc(CC_DST);
919 }
920 #endif
921
922 typedef struct CCTable {
923     uint32_t (*compute_all)(void); /* return all the flags */
924     uint32_t (*compute_c)(void);  /* return the C flag */
925 } CCTable;
926
927 static const CCTable icc_table[CC_OP_NB] = {
928     /* CC_OP_DYNAMIC should never happen */
929     [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
930     [CC_OP_ADD] = { compute_all_add, compute_C_add },
931     [CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
932     [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
933 };
934
935 #ifdef TARGET_SPARC64
936 static const CCTable xcc_table[CC_OP_NB] = {
937     /* CC_OP_DYNAMIC should never happen */
938     [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
939     [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
940     [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
941     [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
942 };
943 #endif
944
945 void helper_compute_psr(void)
946 {
947     uint32_t new_psr;
948
949     new_psr = icc_table[CC_OP].compute_all();
950     env->psr = new_psr;
951 #ifdef TARGET_SPARC64
952     new_psr = xcc_table[CC_OP].compute_all();
953     env->xcc = new_psr;
954 #endif
955     CC_OP = CC_OP_FLAGS;
956 }
957
958 uint32_t helper_compute_C_icc(void)
959 {
960     uint32_t ret;
961
962     ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
963     return ret;
964 }
965
966 #ifdef TARGET_SPARC64
967 GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
968 GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
969 GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
970
971 GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
972 GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
973 GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
974
975 GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
976 GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
977 GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
978
979 GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
980 GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
981 GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
982
983 GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
984 GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
985 GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
986
987 GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
988 GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
989 GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
990 #endif
991 #undef GEN_FCMPS
992
993 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
994     defined(DEBUG_MXCC)
995 static void dump_mxcc(CPUState *env)
996 {
997     printf("mxccdata: %016llx %016llx %016llx %016llx\n",
998            env->mxccdata[0], env->mxccdata[1],
999            env->mxccdata[2], env->mxccdata[3]);
1000     printf("mxccregs: %016llx %016llx %016llx %016llx\n"
1001            "          %016llx %016llx %016llx %016llx\n",
1002            env->mxccregs[0], env->mxccregs[1],
1003            env->mxccregs[2], env->mxccregs[3],
1004            env->mxccregs[4], env->mxccregs[5],
1005            env->mxccregs[6], env->mxccregs[7]);
1006 }
1007 #endif
1008
1009 #if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
1010     && defined(DEBUG_ASI)
1011 static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
1012                      uint64_t r1)
1013 {
1014     switch (size)
1015     {
1016     case 1:
1017         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
1018                     addr, asi, r1 & 0xff);
1019         break;
1020     case 2:
1021         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
1022                     addr, asi, r1 & 0xffff);
1023         break;
1024     case 4:
1025         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
1026                     addr, asi, r1 & 0xffffffff);
1027         break;
1028     case 8:
1029         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
1030                     addr, asi, r1);
1031         break;
1032     }
1033 }
1034 #endif
1035
1036 #ifndef TARGET_SPARC64
1037 #ifndef CONFIG_USER_ONLY
1038 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1039 {
1040     uint64_t ret = 0;
1041 #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
1042     uint32_t last_addr = addr;
1043 #endif
1044
1045     helper_check_align(addr, size - 1);
1046     switch (asi) {
1047     case 2: /* SuperSparc MXCC registers */
1048         switch (addr) {
1049         case 0x01c00a00: /* MXCC control register */
1050             if (size == 8)
1051                 ret = env->mxccregs[3];
1052             else
1053                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1054                              size);
1055             break;
1056         case 0x01c00a04: /* MXCC control register */
1057             if (size == 4)
1058                 ret = env->mxccregs[3];
1059             else
1060                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1061                              size);
1062             break;
1063         case 0x01c00c00: /* Module reset register */
1064             if (size == 8) {
1065                 ret = env->mxccregs[5];
1066                 // should we do something here?
1067             } else
1068                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1069                              size);
1070             break;
1071         case 0x01c00f00: /* MBus port address register */
1072             if (size == 8)
1073                 ret = env->mxccregs[7];
1074             else
1075                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1076                              size);
1077             break;
1078         default:
1079             DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1080                          size);
1081             break;
1082         }
1083         DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
1084                      "addr = %08x -> ret = %" PRIx64 ","
1085                      "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
1086 #ifdef DEBUG_MXCC
1087         dump_mxcc(env);
1088 #endif
1089         break;
1090     case 3: /* MMU probe */
1091         {
1092             int mmulev;
1093
1094             mmulev = (addr >> 8) & 15;
1095             if (mmulev > 4)
1096                 ret = 0;
1097             else
1098                 ret = mmu_probe(env, addr, mmulev);
1099             DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
1100                         addr, mmulev, ret);
1101         }
1102         break;
1103     case 4: /* read MMU regs */
1104         {
1105             int reg = (addr >> 8) & 0x1f;
1106
1107             ret = env->mmuregs[reg];
1108             if (reg == 3) /* Fault status cleared on read */
1109                 env->mmuregs[3] = 0;
1110             else if (reg == 0x13) /* Fault status read */
1111                 ret = env->mmuregs[3];
1112             else if (reg == 0x14) /* Fault address read */
1113                 ret = env->mmuregs[4];
1114             DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
1115         }
1116         break;
1117     case 5: // Turbosparc ITLB Diagnostic
1118     case 6: // Turbosparc DTLB Diagnostic
1119     case 7: // Turbosparc IOTLB Diagnostic
1120         break;
1121     case 9: /* Supervisor code access */
1122         switch(size) {
1123         case 1:
1124             ret = ldub_code(addr);
1125             break;
1126         case 2:
1127             ret = lduw_code(addr);
1128             break;
1129         default:
1130         case 4:
1131             ret = ldl_code(addr);
1132             break;
1133         case 8:
1134             ret = ldq_code(addr);
1135             break;
1136         }
1137         break;
1138     case 0xa: /* User data access */
1139         switch(size) {
1140         case 1:
1141             ret = ldub_user(addr);
1142             break;
1143         case 2:
1144             ret = lduw_user(addr);
1145             break;
1146         default:
1147         case 4:
1148             ret = ldl_user(addr);
1149             break;
1150         case 8:
1151             ret = ldq_user(addr);
1152             break;
1153         }
1154         break;
1155     case 0xb: /* Supervisor data access */
1156         switch(size) {
1157         case 1:
1158             ret = ldub_kernel(addr);
1159             break;
1160         case 2:
1161             ret = lduw_kernel(addr);
1162             break;
1163         default:
1164         case 4:
1165             ret = ldl_kernel(addr);
1166             break;
1167         case 8:
1168             ret = ldq_kernel(addr);
1169             break;
1170         }
1171         break;
1172     case 0xc: /* I-cache tag */
1173     case 0xd: /* I-cache data */
1174     case 0xe: /* D-cache tag */
1175     case 0xf: /* D-cache data */
1176         break;
1177     case 0x20: /* MMU passthrough */
1178         switch(size) {
1179         case 1:
1180             ret = ldub_phys(addr);
1181             break;
1182         case 2:
1183             ret = lduw_phys(addr);
1184             break;
1185         default:
1186         case 4:
1187             ret = ldl_phys(addr);
1188             break;
1189         case 8:
1190             ret = ldq_phys(addr);
1191             break;
1192         }
1193         break;
1194     case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1195         switch(size) {
1196         case 1:
1197             ret = ldub_phys((target_phys_addr_t)addr
1198                             | ((target_phys_addr_t)(asi & 0xf) << 32));
1199             break;
1200         case 2:
1201             ret = lduw_phys((target_phys_addr_t)addr
1202                             | ((target_phys_addr_t)(asi & 0xf) << 32));
1203             break;
1204         default:
1205         case 4:
1206             ret = ldl_phys((target_phys_addr_t)addr
1207                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1208             break;
1209         case 8:
1210             ret = ldq_phys((target_phys_addr_t)addr
1211                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1212             break;
1213         }
1214         break;
1215     case 0x30: // Turbosparc secondary cache diagnostic
1216     case 0x31: // Turbosparc RAM snoop
1217     case 0x32: // Turbosparc page table descriptor diagnostic
1218     case 0x39: /* data cache diagnostic register */
1219         ret = 0;
1220         break;
1221     case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
1222         {
1223             int reg = (addr >> 8) & 3;
1224
1225             switch(reg) {
1226             case 0: /* Breakpoint Value (Addr) */
1227                 ret = env->mmubpregs[reg];
1228                 break;
1229             case 1: /* Breakpoint Mask */
1230                 ret = env->mmubpregs[reg];
1231                 break;
1232             case 2: /* Breakpoint Control */
1233                 ret = env->mmubpregs[reg];
1234                 break;
1235             case 3: /* Breakpoint Status */
1236                 ret = env->mmubpregs[reg];
1237                 env->mmubpregs[reg] = 0ULL;
1238                 break;
1239             }
1240             DPRINTF_MMU("read breakpoint reg[%d] 0x%016llx\n", reg, ret);
1241         }
1242         break;
1243     case 8: /* User code access, XXX */
1244     default:
1245         do_unassigned_access(addr, 0, 0, asi, size);
1246         ret = 0;
1247         break;
1248     }
1249     if (sign) {
1250         switch(size) {
1251         case 1:
1252             ret = (int8_t) ret;
1253             break;
1254         case 2:
1255             ret = (int16_t) ret;
1256             break;
1257         case 4:
1258             ret = (int32_t) ret;
1259             break;
1260         default:
1261             break;
1262         }
1263     }
1264 #ifdef DEBUG_ASI
1265     dump_asi("read ", last_addr, asi, size, ret);
1266 #endif
1267     return ret;
1268 }
1269
1270 void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
1271 {
1272     helper_check_align(addr, size - 1);
1273     switch(asi) {
1274     case 2: /* SuperSparc MXCC registers */
1275         switch (addr) {
1276         case 0x01c00000: /* MXCC stream data register 0 */
1277             if (size == 8)
1278                 env->mxccdata[0] = val;
1279             else
1280                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1281                              size);
1282             break;
1283         case 0x01c00008: /* MXCC stream data register 1 */
1284             if (size == 8)
1285                 env->mxccdata[1] = val;
1286             else
1287                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1288                              size);
1289             break;
1290         case 0x01c00010: /* MXCC stream data register 2 */
1291             if (size == 8)
1292                 env->mxccdata[2] = val;
1293             else
1294                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1295                              size);
1296             break;
1297         case 0x01c00018: /* MXCC stream data register 3 */
1298             if (size == 8)
1299                 env->mxccdata[3] = val;
1300             else
1301                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1302                              size);
1303             break;
1304         case 0x01c00100: /* MXCC stream source */
1305             if (size == 8)
1306                 env->mxccregs[0] = val;
1307             else
1308                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1309                              size);
1310             env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1311                                         0);
1312             env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1313                                         8);
1314             env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1315                                         16);
1316             env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1317                                         24);
1318             break;
1319         case 0x01c00200: /* MXCC stream destination */
1320             if (size == 8)
1321                 env->mxccregs[1] = val;
1322             else
1323                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1324                              size);
1325             stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0,
1326                      env->mxccdata[0]);
1327             stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8,
1328                      env->mxccdata[1]);
1329             stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
1330                      env->mxccdata[2]);
1331             stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
1332                      env->mxccdata[3]);
1333             break;
1334         case 0x01c00a00: /* MXCC control register */
1335             if (size == 8)
1336                 env->mxccregs[3] = val;
1337             else
1338                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1339                              size);
1340             break;
1341         case 0x01c00a04: /* MXCC control register */
1342             if (size == 4)
1343                 env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
1344                     | val;
1345             else
1346                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1347                              size);
1348             break;
1349         case 0x01c00e00: /* MXCC error register  */
1350             // writing a 1 bit clears the error
1351             if (size == 8)
1352                 env->mxccregs[6] &= ~val;
1353             else
1354                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1355                              size);
1356             break;
1357         case 0x01c00f00: /* MBus port address register */
1358             if (size == 8)
1359                 env->mxccregs[7] = val;
1360             else
1361                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1362                              size);
1363             break;
1364         default:
1365             DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1366                          size);
1367             break;
1368         }
1369         DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
1370                      asi, size, addr, val);
1371 #ifdef DEBUG_MXCC
1372         dump_mxcc(env);
1373 #endif
1374         break;
1375     case 3: /* MMU flush */
1376         {
1377             int mmulev;
1378
1379             mmulev = (addr >> 8) & 15;
1380             DPRINTF_MMU("mmu flush level %d\n", mmulev);
1381             switch (mmulev) {
1382             case 0: // flush page
1383                 tlb_flush_page(env, addr & 0xfffff000);
1384                 break;
1385             case 1: // flush segment (256k)
1386             case 2: // flush region (16M)
1387             case 3: // flush context (4G)
1388             case 4: // flush entire
1389                 tlb_flush(env, 1);
1390                 break;
1391             default:
1392                 break;
1393             }
1394 #ifdef DEBUG_MMU
1395             dump_mmu(env);
1396 #endif
1397         }
1398         break;
1399     case 4: /* write MMU regs */
1400         {
1401             int reg = (addr >> 8) & 0x1f;
1402             uint32_t oldreg;
1403
1404             oldreg = env->mmuregs[reg];
1405             switch(reg) {
1406             case 0: // Control Register
1407                 env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
1408                                     (val & 0x00ffffff);
1409                 // Mappings generated during no-fault mode or MMU
1410                 // disabled mode are invalid in normal mode
1411                 if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
1412                     (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
1413                     tlb_flush(env, 1);
1414                 break;
1415             case 1: // Context Table Pointer Register
1416                 env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
1417                 break;
1418             case 2: // Context Register
1419                 env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
1420                 if (oldreg != env->mmuregs[reg]) {
1421                     /* we flush when the MMU context changes because
1422                        QEMU has no MMU context support */
1423                     tlb_flush(env, 1);
1424                 }
1425                 break;
1426             case 3: // Synchronous Fault Status Register with Clear
1427             case 4: // Synchronous Fault Address Register
1428                 break;
1429             case 0x10: // TLB Replacement Control Register
1430                 env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
1431                 break;
1432             case 0x13: // Synchronous Fault Status Register with Read and Clear
1433                 env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
1434                 break;
1435             case 0x14: // Synchronous Fault Address Register
1436                 env->mmuregs[4] = val;
1437                 break;
1438             default:
1439                 env->mmuregs[reg] = val;
1440                 break;
1441             }
1442             if (oldreg != env->mmuregs[reg]) {
1443                 DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
1444                             reg, oldreg, env->mmuregs[reg]);
1445             }
1446 #ifdef DEBUG_MMU
1447             dump_mmu(env);
1448 #endif
1449         }
1450         break;
1451     case 5: // Turbosparc ITLB Diagnostic
1452     case 6: // Turbosparc DTLB Diagnostic
1453     case 7: // Turbosparc IOTLB Diagnostic
1454         break;
1455     case 0xa: /* User data access */
1456         switch(size) {
1457         case 1:
1458             stb_user(addr, val);
1459             break;
1460         case 2:
1461             stw_user(addr, val);
1462             break;
1463         default:
1464         case 4:
1465             stl_user(addr, val);
1466             break;
1467         case 8:
1468             stq_user(addr, val);
1469             break;
1470         }
1471         break;
1472     case 0xb: /* Supervisor data access */
1473         switch(size) {
1474         case 1:
1475             stb_kernel(addr, val);
1476             break;
1477         case 2:
1478             stw_kernel(addr, val);
1479             break;
1480         default:
1481         case 4:
1482             stl_kernel(addr, val);
1483             break;
1484         case 8:
1485             stq_kernel(addr, val);
1486             break;
1487         }
1488         break;
1489     case 0xc: /* I-cache tag */
1490     case 0xd: /* I-cache data */
1491     case 0xe: /* D-cache tag */
1492     case 0xf: /* D-cache data */
1493     case 0x10: /* I/D-cache flush page */
1494     case 0x11: /* I/D-cache flush segment */
1495     case 0x12: /* I/D-cache flush region */
1496     case 0x13: /* I/D-cache flush context */
1497     case 0x14: /* I/D-cache flush user */
1498         break;
1499     case 0x17: /* Block copy, sta access */
1500         {
1501             // val = src
1502             // addr = dst
1503             // copy 32 bytes
1504             unsigned int i;
1505             uint32_t src = val & ~3, dst = addr & ~3, temp;
1506
1507             for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1508                 temp = ldl_kernel(src);
1509                 stl_kernel(dst, temp);
1510             }
1511         }
1512         break;
1513     case 0x1f: /* Block fill, stda access */
1514         {
1515             // addr = dst
1516             // fill 32 bytes with val
1517             unsigned int i;
1518             uint32_t dst = addr & 7;
1519
1520             for (i = 0; i < 32; i += 8, dst += 8)
1521                 stq_kernel(dst, val);
1522         }
1523         break;
1524     case 0x20: /* MMU passthrough */
1525         {
1526             switch(size) {
1527             case 1:
1528                 stb_phys(addr, val);
1529                 break;
1530             case 2:
1531                 stw_phys(addr, val);
1532                 break;
1533             case 4:
1534             default:
1535                 stl_phys(addr, val);
1536                 break;
1537             case 8:
1538                 stq_phys(addr, val);
1539                 break;
1540             }
1541         }
1542         break;
1543     case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1544         {
1545             switch(size) {
1546             case 1:
1547                 stb_phys((target_phys_addr_t)addr
1548                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1549                 break;
1550             case 2:
1551                 stw_phys((target_phys_addr_t)addr
1552                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1553                 break;
1554             case 4:
1555             default:
1556                 stl_phys((target_phys_addr_t)addr
1557                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1558                 break;
1559             case 8:
1560                 stq_phys((target_phys_addr_t)addr
1561                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1562                 break;
1563             }
1564         }
1565         break;
1566     case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
1567     case 0x31: // store buffer data, Ross RT620 I-cache flush or
1568                // Turbosparc snoop RAM
1569     case 0x32: // store buffer control or Turbosparc page table
1570                // descriptor diagnostic
1571     case 0x36: /* I-cache flash clear */
1572     case 0x37: /* D-cache flash clear */
1573     case 0x4c: /* breakpoint action */
1574         break;
1575     case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
1576         {
1577             int reg = (addr >> 8) & 3;
1578
1579             switch(reg) {
1580             case 0: /* Breakpoint Value (Addr) */
1581                 env->mmubpregs[reg] = (val & 0xfffffffffULL);
1582                 break;
1583             case 1: /* Breakpoint Mask */
1584                 env->mmubpregs[reg] = (val & 0xfffffffffULL);
1585                 break;
1586             case 2: /* Breakpoint Control */
1587                 env->mmubpregs[reg] = (val & 0x7fULL);
1588                 break;
1589             case 3: /* Breakpoint Status */
1590                 env->mmubpregs[reg] = (val & 0xfULL);
1591                 break;
1592             }
1593             DPRINTF_MMU("write breakpoint reg[%d] 0x%016llx\n", reg,
1594                         env->mmuregs[reg]);
1595         }
1596         break;
1597     case 8: /* User code access, XXX */
1598     case 9: /* Supervisor code access, XXX */
1599     default:
1600         do_unassigned_access(addr, 1, 0, asi, size);
1601         break;
1602     }
1603 #ifdef DEBUG_ASI
1604     dump_asi("write", addr, asi, size, val);
1605 #endif
1606 }
1607
1608 #endif /* CONFIG_USER_ONLY */
1609 #else /* TARGET_SPARC64 */
1610
1611 #ifdef CONFIG_USER_ONLY
1612 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1613 {
1614     uint64_t ret = 0;
1615 #if defined(DEBUG_ASI)
1616     target_ulong last_addr = addr;
1617 #endif
1618
1619     if (asi < 0x80)
1620         raise_exception(TT_PRIV_ACT);
1621
1622     helper_check_align(addr, size - 1);
1623     address_mask(env, &addr);
1624
1625     switch (asi) {
1626     case 0x82: // Primary no-fault
1627     case 0x8a: // Primary no-fault LE
1628         if (page_check_range(addr, size, PAGE_READ) == -1) {
1629 #ifdef DEBUG_ASI
1630             dump_asi("read ", last_addr, asi, size, ret);
1631 #endif
1632             return 0;
1633         }
1634         // Fall through
1635     case 0x80: // Primary
1636     case 0x88: // Primary LE
1637         {
1638             switch(size) {
1639             case 1:
1640                 ret = ldub_raw(addr);
1641                 break;
1642             case 2:
1643                 ret = lduw_raw(addr);
1644                 break;
1645             case 4:
1646                 ret = ldl_raw(addr);
1647                 break;
1648             default:
1649             case 8:
1650                 ret = ldq_raw(addr);
1651                 break;
1652             }
1653         }
1654         break;
1655     case 0x83: // Secondary no-fault
1656     case 0x8b: // Secondary no-fault LE
1657         if (page_check_range(addr, size, PAGE_READ) == -1) {
1658 #ifdef DEBUG_ASI
1659             dump_asi("read ", last_addr, asi, size, ret);
1660 #endif
1661             return 0;
1662         }
1663         // Fall through
1664     case 0x81: // Secondary
1665     case 0x89: // Secondary LE
1666         // XXX
1667         break;
1668     default:
1669         break;
1670     }
1671
1672     /* Convert from little endian */
1673     switch (asi) {
1674     case 0x88: // Primary LE
1675     case 0x89: // Secondary LE
1676     case 0x8a: // Primary no-fault LE
1677     case 0x8b: // Secondary no-fault LE
1678         switch(size) {
1679         case 2:
1680             ret = bswap16(ret);
1681             break;
1682         case 4:
1683             ret = bswap32(ret);
1684             break;
1685         case 8:
1686             ret = bswap64(ret);
1687             break;
1688         default:
1689             break;
1690         }
1691     default:
1692         break;
1693     }
1694
1695     /* Convert to signed number */
1696     if (sign) {
1697         switch(size) {
1698         case 1:
1699             ret = (int8_t) ret;
1700             break;
1701         case 2:
1702             ret = (int16_t) ret;
1703             break;
1704         case 4:
1705             ret = (int32_t) ret;
1706             break;
1707         default:
1708             break;
1709         }
1710     }
1711 #ifdef DEBUG_ASI
1712     dump_asi("read ", last_addr, asi, size, ret);
1713 #endif
1714     return ret;
1715 }
1716
1717 void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1718 {
1719 #ifdef DEBUG_ASI
1720     dump_asi("write", addr, asi, size, val);
1721 #endif
1722     if (asi < 0x80)
1723         raise_exception(TT_PRIV_ACT);
1724
1725     helper_check_align(addr, size - 1);
1726     address_mask(env, &addr);
1727
1728     /* Convert to little endian */
1729     switch (asi) {
1730     case 0x88: // Primary LE
1731     case 0x89: // Secondary LE
1732         switch(size) {
1733         case 2:
1734             addr = bswap16(addr);
1735             break;
1736         case 4:
1737             addr = bswap32(addr);
1738             break;
1739         case 8:
1740             addr = bswap64(addr);
1741             break;
1742         default:
1743             break;
1744         }
1745     default:
1746         break;
1747     }
1748
1749     switch(asi) {
1750     case 0x80: // Primary
1751     case 0x88: // Primary LE
1752         {
1753             switch(size) {
1754             case 1:
1755                 stb_raw(addr, val);
1756                 break;
1757             case 2:
1758                 stw_raw(addr, val);
1759                 break;
1760             case 4:
1761                 stl_raw(addr, val);
1762                 break;
1763             case 8:
1764             default:
1765                 stq_raw(addr, val);
1766                 break;
1767             }
1768         }
1769         break;
1770     case 0x81: // Secondary
1771     case 0x89: // Secondary LE
1772         // XXX
1773         return;
1774
1775     case 0x82: // Primary no-fault, RO
1776     case 0x83: // Secondary no-fault, RO
1777     case 0x8a: // Primary no-fault LE, RO
1778     case 0x8b: // Secondary no-fault LE, RO
1779     default:
1780         do_unassigned_access(addr, 1, 0, 1, size);
1781         return;
1782     }
1783 }
1784
1785 #else /* CONFIG_USER_ONLY */
1786
1787 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1788 {
1789     uint64_t ret = 0;
1790 #if defined(DEBUG_ASI)
1791     target_ulong last_addr = addr;
1792 #endif
1793
1794     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1795         || ((env->def->features & CPU_FEATURE_HYPV)
1796             && asi >= 0x30 && asi < 0x80
1797             && !(env->hpstate & HS_PRIV)))
1798         raise_exception(TT_PRIV_ACT);
1799
1800     helper_check_align(addr, size - 1);
1801     switch (asi) {
1802     case 0x82: // Primary no-fault
1803     case 0x8a: // Primary no-fault LE
1804         if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
1805 #ifdef DEBUG_ASI
1806             dump_asi("read ", last_addr, asi, size, ret);
1807 #endif
1808             return 0;
1809         }
1810         // Fall through
1811     case 0x10: // As if user primary
1812     case 0x18: // As if user primary LE
1813     case 0x80: // Primary
1814     case 0x88: // Primary LE
1815     case 0xe2: // UA2007 Primary block init
1816     case 0xe3: // UA2007 Secondary block init
1817         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1818             if ((env->def->features & CPU_FEATURE_HYPV)
1819                 && env->hpstate & HS_PRIV) {
1820                 switch(size) {
1821                 case 1:
1822                     ret = ldub_hypv(addr);
1823                     break;
1824                 case 2:
1825                     ret = lduw_hypv(addr);
1826                     break;
1827                 case 4:
1828                     ret = ldl_hypv(addr);
1829                     break;
1830                 default:
1831                 case 8:
1832                     ret = ldq_hypv(addr);
1833                     break;
1834                 }
1835             } else {
1836                 switch(size) {
1837                 case 1:
1838                     ret = ldub_kernel(addr);
1839                     break;
1840                 case 2:
1841                     ret = lduw_kernel(addr);
1842                     break;
1843                 case 4:
1844                     ret = ldl_kernel(addr);
1845                     break;
1846                 default:
1847                 case 8:
1848                     ret = ldq_kernel(addr);
1849                     break;
1850                 }
1851             }
1852         } else {
1853             switch(size) {
1854             case 1:
1855                 ret = ldub_user(addr);
1856                 break;
1857             case 2:
1858                 ret = lduw_user(addr);
1859                 break;
1860             case 4:
1861                 ret = ldl_user(addr);
1862                 break;
1863             default:
1864             case 8:
1865                 ret = ldq_user(addr);
1866                 break;
1867             }
1868         }
1869         break;
1870     case 0x14: // Bypass
1871     case 0x15: // Bypass, non-cacheable
1872     case 0x1c: // Bypass LE
1873     case 0x1d: // Bypass, non-cacheable LE
1874         {
1875             switch(size) {
1876             case 1:
1877                 ret = ldub_phys(addr);
1878                 break;
1879             case 2:
1880                 ret = lduw_phys(addr);
1881                 break;
1882             case 4:
1883                 ret = ldl_phys(addr);
1884                 break;
1885             default:
1886             case 8:
1887                 ret = ldq_phys(addr);
1888                 break;
1889             }
1890             break;
1891         }
1892     case 0x24: // Nucleus quad LDD 128 bit atomic
1893     case 0x2c: // Nucleus quad LDD 128 bit atomic LE
1894         //  Only ldda allowed
1895         raise_exception(TT_ILL_INSN);
1896         return 0;
1897     case 0x83: // Secondary no-fault
1898     case 0x8b: // Secondary no-fault LE
1899         if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
1900 #ifdef DEBUG_ASI
1901             dump_asi("read ", last_addr, asi, size, ret);
1902 #endif
1903             return 0;
1904         }
1905         // Fall through
1906     case 0x04: // Nucleus
1907     case 0x0c: // Nucleus Little Endian (LE)
1908     case 0x11: // As if user secondary
1909     case 0x19: // As if user secondary LE
1910     case 0x4a: // UPA config
1911     case 0x81: // Secondary
1912     case 0x89: // Secondary LE
1913         // XXX
1914         break;
1915     case 0x45: // LSU
1916         ret = env->lsu;
1917         break;
1918     case 0x50: // I-MMU regs
1919         {
1920             int reg = (addr >> 3) & 0xf;
1921
1922             if (reg == 0) {
1923                 // I-TSB Tag Target register
1924                 ret = ultrasparc_tag_target(env->immuregs[6]);
1925             } else {
1926                 ret = env->immuregs[reg];
1927             }
1928
1929             break;
1930         }
1931     case 0x51: // I-MMU 8k TSB pointer
1932         {
1933             // env->immuregs[5] holds I-MMU TSB register value
1934             // env->immuregs[6] holds I-MMU Tag Access register value
1935             ret = ultrasparc_tsb_pointer(env->immuregs[5], env->immuregs[6],
1936                                          8*1024);
1937             break;
1938         }
1939     case 0x52: // I-MMU 64k TSB pointer
1940         {
1941             // env->immuregs[5] holds I-MMU TSB register value
1942             // env->immuregs[6] holds I-MMU Tag Access register value
1943             ret = ultrasparc_tsb_pointer(env->immuregs[5], env->immuregs[6],
1944                                          64*1024);
1945             break;
1946         }
1947     case 0x55: // I-MMU data access
1948         {
1949             int reg = (addr >> 3) & 0x3f;
1950
1951             ret = env->itlb_tte[reg];
1952             break;
1953         }
1954     case 0x56: // I-MMU tag read
1955         {
1956             int reg = (addr >> 3) & 0x3f;
1957
1958             ret = env->itlb_tag[reg];
1959             break;
1960         }
1961     case 0x58: // D-MMU regs
1962         {
1963             int reg = (addr >> 3) & 0xf;
1964
1965             if (reg == 0) {
1966                 // D-TSB Tag Target register
1967                 ret = ultrasparc_tag_target(env->dmmuregs[6]);
1968             } else {
1969                 ret = env->dmmuregs[reg];
1970             }
1971             break;
1972         }
1973     case 0x59: // D-MMU 8k TSB pointer
1974         {
1975             // env->dmmuregs[5] holds D-MMU TSB register value
1976             // env->dmmuregs[6] holds D-MMU Tag Access register value
1977             ret = ultrasparc_tsb_pointer(env->dmmuregs[5], env->dmmuregs[6],
1978                                          8*1024);
1979             break;
1980         }
1981     case 0x5a: // D-MMU 64k TSB pointer
1982         {
1983             // env->dmmuregs[5] holds D-MMU TSB register value
1984             // env->dmmuregs[6] holds D-MMU Tag Access register value
1985             ret = ultrasparc_tsb_pointer(env->dmmuregs[5], env->dmmuregs[6],
1986                                          64*1024);
1987             break;
1988         }
1989     case 0x5d: // D-MMU data access
1990         {
1991             int reg = (addr >> 3) & 0x3f;
1992
1993             ret = env->dtlb_tte[reg];
1994             break;
1995         }
1996     case 0x5e: // D-MMU tag read
1997         {
1998             int reg = (addr >> 3) & 0x3f;
1999
2000             ret = env->dtlb_tag[reg];
2001             break;
2002         }
2003     case 0x46: // D-cache data
2004     case 0x47: // D-cache tag access
2005     case 0x4b: // E-cache error enable
2006     case 0x4c: // E-cache asynchronous fault status
2007     case 0x4d: // E-cache asynchronous fault address
2008     case 0x4e: // E-cache tag data
2009     case 0x66: // I-cache instruction access
2010     case 0x67: // I-cache tag access
2011     case 0x6e: // I-cache predecode
2012     case 0x6f: // I-cache LRU etc.
2013     case 0x76: // E-cache tag
2014     case 0x7e: // E-cache tag
2015         break;
2016     case 0x5b: // D-MMU data pointer
2017     case 0x48: // Interrupt dispatch, RO
2018     case 0x49: // Interrupt data receive
2019     case 0x7f: // Incoming interrupt vector, RO
2020         // XXX
2021         break;
2022     case 0x54: // I-MMU data in, WO
2023     case 0x57: // I-MMU demap, WO
2024     case 0x5c: // D-MMU data in, WO
2025     case 0x5f: // D-MMU demap, WO
2026     case 0x77: // Interrupt vector, WO
2027     default:
2028         do_unassigned_access(addr, 0, 0, 1, size);
2029         ret = 0;
2030         break;
2031     }
2032
2033     /* Convert from little endian */
2034     switch (asi) {
2035     case 0x0c: // Nucleus Little Endian (LE)
2036     case 0x18: // As if user primary LE
2037     case 0x19: // As if user secondary LE
2038     case 0x1c: // Bypass LE
2039     case 0x1d: // Bypass, non-cacheable LE
2040     case 0x88: // Primary LE
2041     case 0x89: // Secondary LE
2042     case 0x8a: // Primary no-fault LE
2043     case 0x8b: // Secondary no-fault LE
2044         switch(size) {
2045         case 2:
2046             ret = bswap16(ret);
2047             break;
2048         case 4:
2049             ret = bswap32(ret);
2050             break;
2051         case 8:
2052             ret = bswap64(ret);
2053             break;
2054         default:
2055             break;
2056         }
2057     default:
2058         break;
2059     }
2060
2061     /* Convert to signed number */
2062     if (sign) {
2063         switch(size) {
2064         case 1:
2065             ret = (int8_t) ret;
2066             break;
2067         case 2:
2068             ret = (int16_t) ret;
2069             break;
2070         case 4:
2071             ret = (int32_t) ret;
2072             break;
2073         default:
2074             break;
2075         }
2076     }
2077 #ifdef DEBUG_ASI
2078     dump_asi("read ", last_addr, asi, size, ret);
2079 #endif
2080     return ret;
2081 }
2082
2083 void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2084 {
2085 #ifdef DEBUG_ASI
2086     dump_asi("write", addr, asi, size, val);
2087 #endif
2088     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2089         || ((env->def->features & CPU_FEATURE_HYPV)
2090             && asi >= 0x30 && asi < 0x80
2091             && !(env->hpstate & HS_PRIV)))
2092         raise_exception(TT_PRIV_ACT);
2093
2094     helper_check_align(addr, size - 1);
2095     /* Convert to little endian */
2096     switch (asi) {
2097     case 0x0c: // Nucleus Little Endian (LE)
2098     case 0x18: // As if user primary LE
2099     case 0x19: // As if user secondary LE
2100     case 0x1c: // Bypass LE
2101     case 0x1d: // Bypass, non-cacheable LE
2102     case 0x88: // Primary LE
2103     case 0x89: // Secondary LE
2104         switch(size) {
2105         case 2:
2106             addr = bswap16(addr);
2107             break;
2108         case 4:
2109             addr = bswap32(addr);
2110             break;
2111         case 8:
2112             addr = bswap64(addr);
2113             break;
2114         default:
2115             break;
2116         }
2117     default:
2118         break;
2119     }
2120
2121     switch(asi) {
2122     case 0x10: // As if user primary
2123     case 0x18: // As if user primary LE
2124     case 0x80: // Primary
2125     case 0x88: // Primary LE
2126     case 0xe2: // UA2007 Primary block init
2127     case 0xe3: // UA2007 Secondary block init
2128         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
2129             if ((env->def->features & CPU_FEATURE_HYPV)
2130                 && env->hpstate & HS_PRIV) {
2131                 switch(size) {
2132                 case 1:
2133                     stb_hypv(addr, val);
2134                     break;
2135                 case 2:
2136                     stw_hypv(addr, val);
2137                     break;
2138                 case 4:
2139                     stl_hypv(addr, val);
2140                     break;
2141                 case 8:
2142                 default:
2143                     stq_hypv(addr, val);
2144                     break;
2145                 }
2146             } else {
2147                 switch(size) {
2148                 case 1:
2149                     stb_kernel(addr, val);
2150                     break;
2151                 case 2:
2152                     stw_kernel(addr, val);
2153                     break;
2154                 case 4:
2155                     stl_kernel(addr, val);
2156                     break;
2157                 case 8:
2158                 default:
2159                     stq_kernel(addr, val);
2160                     break;
2161                 }
2162             }
2163         } else {
2164             switch(size) {
2165             case 1:
2166                 stb_user(addr, val);
2167                 break;
2168             case 2:
2169                 stw_user(addr, val);
2170                 break;
2171             case 4:
2172                 stl_user(addr, val);
2173                 break;
2174             case 8:
2175             default:
2176                 stq_user(addr, val);
2177                 break;
2178             }
2179         }
2180         break;
2181     case 0x14: // Bypass
2182     case 0x15: // Bypass, non-cacheable
2183     case 0x1c: // Bypass LE
2184     case 0x1d: // Bypass, non-cacheable LE
2185         {
2186             switch(size) {
2187             case 1:
2188                 stb_phys(addr, val);
2189                 break;
2190             case 2:
2191                 stw_phys(addr, val);
2192                 break;
2193             case 4:
2194                 stl_phys(addr, val);
2195                 break;
2196             case 8:
2197             default:
2198                 stq_phys(addr, val);
2199                 break;
2200             }
2201         }
2202         return;
2203     case 0x24: // Nucleus quad LDD 128 bit atomic
2204     case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2205         //  Only ldda allowed
2206         raise_exception(TT_ILL_INSN);
2207         return;
2208     case 0x04: // Nucleus
2209     case 0x0c: // Nucleus Little Endian (LE)
2210     case 0x11: // As if user secondary
2211     case 0x19: // As if user secondary LE
2212     case 0x4a: // UPA config
2213     case 0x81: // Secondary
2214     case 0x89: // Secondary LE
2215         // XXX
2216         return;
2217     case 0x45: // LSU
2218         {
2219             uint64_t oldreg;
2220
2221             oldreg = env->lsu;
2222             env->lsu = val & (DMMU_E | IMMU_E);
2223             // Mappings generated during D/I MMU disabled mode are
2224             // invalid in normal mode
2225             if (oldreg != env->lsu) {
2226                 DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
2227                             oldreg, env->lsu);
2228 #ifdef DEBUG_MMU
2229                 dump_mmu(env);
2230 #endif
2231                 tlb_flush(env, 1);
2232             }
2233             return;
2234         }
2235     case 0x50: // I-MMU regs
2236         {
2237             int reg = (addr >> 3) & 0xf;
2238             uint64_t oldreg;
2239
2240             oldreg = env->immuregs[reg];
2241             switch(reg) {
2242             case 0: // RO
2243             case 4:
2244                 return;
2245             case 1: // Not in I-MMU
2246             case 2:
2247             case 7:
2248             case 8:
2249                 return;
2250             case 3: // SFSR
2251                 if ((val & 1) == 0)
2252                     val = 0; // Clear SFSR
2253                 break;
2254             case 5: // TSB access
2255             case 6: // Tag access
2256             default:
2257                 break;
2258             }
2259             env->immuregs[reg] = val;
2260             if (oldreg != env->immuregs[reg]) {
2261                 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
2262                             PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
2263             }
2264 #ifdef DEBUG_MMU
2265             dump_mmu(env);
2266 #endif
2267             return;
2268         }
2269     case 0x54: // I-MMU data in
2270         {
2271             unsigned int i;
2272
2273             // Try finding an invalid entry
2274             for (i = 0; i < 64; i++) {
2275                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
2276                     env->itlb_tag[i] = env->immuregs[6];
2277                     env->itlb_tte[i] = val;
2278                     return;
2279                 }
2280             }
2281             // Try finding an unlocked entry
2282             for (i = 0; i < 64; i++) {
2283                 if ((env->itlb_tte[i] & 0x40) == 0) {
2284                     env->itlb_tag[i] = env->immuregs[6];
2285                     env->itlb_tte[i] = val;
2286                     return;
2287                 }
2288             }
2289             // error state?
2290             return;
2291         }
2292     case 0x55: // I-MMU data access
2293         {
2294             // TODO: auto demap
2295
2296             unsigned int i = (addr >> 3) & 0x3f;
2297
2298             env->itlb_tag[i] = env->immuregs[6];
2299             env->itlb_tte[i] = val;
2300             return;
2301         }
2302     case 0x57: // I-MMU demap
2303         {
2304             unsigned int i;
2305
2306             for (i = 0; i < 64; i++) {
2307                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
2308                     target_ulong mask = 0xffffffffffffe000ULL;
2309
2310                     mask <<= 3 * ((env->itlb_tte[i] >> 61) & 3);
2311                     if ((val & mask) == (env->itlb_tag[i] & mask)) {
2312                         env->itlb_tag[i] = 0;
2313                         env->itlb_tte[i] = 0;
2314                     }
2315                     return;
2316                 }
2317             }
2318         }
2319         return;
2320     case 0x58: // D-MMU regs
2321         {
2322             int reg = (addr >> 3) & 0xf;
2323             uint64_t oldreg;
2324
2325             oldreg = env->dmmuregs[reg];
2326             switch(reg) {
2327             case 0: // RO
2328             case 4:
2329                 return;
2330             case 3: // SFSR
2331                 if ((val & 1) == 0) {
2332                     val = 0; // Clear SFSR, Fault address
2333                     env->dmmuregs[4] = 0;
2334                 }
2335                 env->dmmuregs[reg] = val;
2336                 break;
2337             case 1: // Primary context
2338             case 2: // Secondary context
2339             case 5: // TSB access
2340             case 6: // Tag access
2341             case 7: // Virtual Watchpoint
2342             case 8: // Physical Watchpoint
2343             default:
2344                 break;
2345             }
2346             env->dmmuregs[reg] = val;
2347             if (oldreg != env->dmmuregs[reg]) {
2348                 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
2349                             PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
2350             }
2351 #ifdef DEBUG_MMU
2352             dump_mmu(env);
2353 #endif
2354             return;
2355         }
2356     case 0x5c: // D-MMU data in
2357         {
2358             unsigned int i;
2359
2360             // Try finding an invalid entry
2361             for (i = 0; i < 64; i++) {
2362                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
2363                     env->dtlb_tag[i] = env->dmmuregs[6];
2364                     env->dtlb_tte[i] = val;
2365                     return;
2366                 }
2367             }
2368             // Try finding an unlocked entry
2369             for (i = 0; i < 64; i++) {
2370                 if ((env->dtlb_tte[i] & 0x40) == 0) {
2371                     env->dtlb_tag[i] = env->dmmuregs[6];
2372                     env->dtlb_tte[i] = val;
2373                     return;
2374                 }
2375             }
2376             // error state?
2377             return;
2378         }
2379     case 0x5d: // D-MMU data access
2380         {
2381             unsigned int i = (addr >> 3) & 0x3f;
2382
2383             env->dtlb_tag[i] = env->dmmuregs[6];
2384             env->dtlb_tte[i] = val;
2385             return;
2386         }
2387     case 0x5f: // D-MMU demap
2388         {
2389             unsigned int i;
2390
2391             for (i = 0; i < 64; i++) {
2392                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
2393                     target_ulong mask = 0xffffffffffffe000ULL;
2394
2395                     mask <<= 3 * ((env->dtlb_tte[i] >> 61) & 3);
2396                     if ((val & mask) == (env->dtlb_tag[i] & mask)) {
2397                         env->dtlb_tag[i] = 0;
2398                         env->dtlb_tte[i] = 0;
2399                     }
2400                     return;
2401                 }
2402             }
2403         }
2404         return;
2405     case 0x49: // Interrupt data receive
2406         // XXX
2407         return;
2408     case 0x46: // D-cache data
2409     case 0x47: // D-cache tag access
2410     case 0x4b: // E-cache error enable
2411     case 0x4c: // E-cache asynchronous fault status
2412     case 0x4d: // E-cache asynchronous fault address
2413     case 0x4e: // E-cache tag data
2414     case 0x66: // I-cache instruction access
2415     case 0x67: // I-cache tag access
2416     case 0x6e: // I-cache predecode
2417     case 0x6f: // I-cache LRU etc.
2418     case 0x76: // E-cache tag
2419     case 0x7e: // E-cache tag
2420         return;
2421     case 0x51: // I-MMU 8k TSB pointer, RO
2422     case 0x52: // I-MMU 64k TSB pointer, RO
2423     case 0x56: // I-MMU tag read, RO
2424     case 0x59: // D-MMU 8k TSB pointer, RO
2425     case 0x5a: // D-MMU 64k TSB pointer, RO
2426     case 0x5b: // D-MMU data pointer, RO
2427     case 0x5e: // D-MMU tag read, RO
2428     case 0x48: // Interrupt dispatch, RO
2429     case 0x7f: // Incoming interrupt vector, RO
2430     case 0x82: // Primary no-fault, RO
2431     case 0x83: // Secondary no-fault, RO
2432     case 0x8a: // Primary no-fault LE, RO
2433     case 0x8b: // Secondary no-fault LE, RO
2434     default:
2435         do_unassigned_access(addr, 1, 0, 1, size);
2436         return;
2437     }
2438 }
2439 #endif /* CONFIG_USER_ONLY */
2440
2441 void helper_ldda_asi(target_ulong addr, int asi, int rd)
2442 {
2443     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2444         || ((env->def->features & CPU_FEATURE_HYPV)
2445             && asi >= 0x30 && asi < 0x80
2446             && !(env->hpstate & HS_PRIV)))
2447         raise_exception(TT_PRIV_ACT);
2448
2449     switch (asi) {
2450     case 0x24: // Nucleus quad LDD 128 bit atomic
2451     case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2452         helper_check_align(addr, 0xf);
2453         if (rd == 0) {
2454             env->gregs[1] = ldq_kernel(addr + 8);
2455             if (asi == 0x2c)
2456                 bswap64s(&env->gregs[1]);
2457         } else if (rd < 8) {
2458             env->gregs[rd] = ldq_kernel(addr);
2459             env->gregs[rd + 1] = ldq_kernel(addr + 8);
2460             if (asi == 0x2c) {
2461                 bswap64s(&env->gregs[rd]);
2462                 bswap64s(&env->gregs[rd + 1]);
2463             }
2464         } else {
2465             env->regwptr[rd] = ldq_kernel(addr);
2466             env->regwptr[rd + 1] = ldq_kernel(addr + 8);
2467             if (asi == 0x2c) {
2468                 bswap64s(&env->regwptr[rd]);
2469                 bswap64s(&env->regwptr[rd + 1]);
2470             }
2471         }
2472         break;
2473     default:
2474         helper_check_align(addr, 0x3);
2475         if (rd == 0)
2476             env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
2477         else if (rd < 8) {
2478             env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
2479             env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2480         } else {
2481             env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
2482             env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2483         }
2484         break;
2485     }
2486 }
2487
2488 void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2489 {
2490     unsigned int i;
2491     target_ulong val;
2492
2493     helper_check_align(addr, 3);
2494     switch (asi) {
2495     case 0xf0: // Block load primary
2496     case 0xf1: // Block load secondary
2497     case 0xf8: // Block load primary LE
2498     case 0xf9: // Block load secondary LE
2499         if (rd & 7) {
2500             raise_exception(TT_ILL_INSN);
2501             return;
2502         }
2503         helper_check_align(addr, 0x3f);
2504         for (i = 0; i < 16; i++) {
2505             *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
2506                                                          0);
2507             addr += 4;
2508         }
2509
2510         return;
2511     default:
2512         break;
2513     }
2514
2515     val = helper_ld_asi(addr, asi, size, 0);
2516     switch(size) {
2517     default:
2518     case 4:
2519         *((uint32_t *)&env->fpr[rd]) = val;
2520         break;
2521     case 8:
2522         *((int64_t *)&DT0) = val;
2523         break;
2524     case 16:
2525         // XXX
2526         break;
2527     }
2528 }
2529
2530 void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2531 {
2532     unsigned int i;
2533     target_ulong val = 0;
2534
2535     helper_check_align(addr, 3);
2536     switch (asi) {
2537     case 0xe0: // UA2007 Block commit store primary (cache flush)
2538     case 0xe1: // UA2007 Block commit store secondary (cache flush)
2539     case 0xf0: // Block store primary
2540     case 0xf1: // Block store secondary
2541     case 0xf8: // Block store primary LE
2542     case 0xf9: // Block store secondary LE
2543         if (rd & 7) {
2544             raise_exception(TT_ILL_INSN);
2545             return;
2546         }
2547         helper_check_align(addr, 0x3f);
2548         for (i = 0; i < 16; i++) {
2549             val = *(uint32_t *)&env->fpr[rd++];
2550             helper_st_asi(addr, val, asi & 0x8f, 4);
2551             addr += 4;
2552         }
2553
2554         return;
2555     default:
2556         break;
2557     }
2558
2559     switch(size) {
2560     default:
2561     case 4:
2562         val = *((uint32_t *)&env->fpr[rd]);
2563         break;
2564     case 8:
2565         val = *((int64_t *)&DT0);
2566         break;
2567     case 16:
2568         // XXX
2569         break;
2570     }
2571     helper_st_asi(addr, val, asi, size);
2572 }
2573
2574 target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2575                             target_ulong val2, uint32_t asi)
2576 {
2577     target_ulong ret;
2578
2579     val2 &= 0xffffffffUL;
2580     ret = helper_ld_asi(addr, asi, 4, 0);
2581     ret &= 0xffffffffUL;
2582     if (val2 == ret)
2583         helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
2584     return ret;
2585 }
2586
2587 target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2588                              target_ulong val2, uint32_t asi)
2589 {
2590     target_ulong ret;
2591
2592     ret = helper_ld_asi(addr, asi, 8, 0);
2593     if (val2 == ret)
2594         helper_st_asi(addr, val1, asi, 8);
2595     return ret;
2596 }
2597 #endif /* TARGET_SPARC64 */
2598
2599 #ifndef TARGET_SPARC64
2600 void helper_rett(void)
2601 {
2602     unsigned int cwp;
2603
2604     if (env->psret == 1)
2605         raise_exception(TT_ILL_INSN);
2606
2607     env->psret = 1;
2608     cwp = cpu_cwp_inc(env, env->cwp + 1) ;
2609     if (env->wim & (1 << cwp)) {
2610         raise_exception(TT_WIN_UNF);
2611     }
2612     set_cwp(cwp);
2613     env->psrs = env->psrps;
2614 }
2615 #endif
2616
2617 target_ulong helper_udiv(target_ulong a, target_ulong b)
2618 {
2619     uint64_t x0;
2620     uint32_t x1;
2621
2622     x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2623     x1 = b;
2624
2625     if (x1 == 0) {
2626         raise_exception(TT_DIV_ZERO);
2627     }
2628
2629     x0 = x0 / x1;
2630     if (x0 > 0xffffffff) {
2631         env->cc_src2 = 1;
2632         return 0xffffffff;
2633     } else {
2634         env->cc_src2 = 0;
2635         return x0;
2636     }
2637 }
2638
2639 target_ulong helper_sdiv(target_ulong a, target_ulong b)
2640 {
2641     int64_t x0;
2642     int32_t x1;
2643
2644     x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2645     x1 = b;
2646
2647     if (x1 == 0) {
2648         raise_exception(TT_DIV_ZERO);
2649     }
2650
2651     x0 = x0 / x1;
2652     if ((int32_t) x0 != x0) {
2653         env->cc_src2 = 1;
2654         return x0 < 0? 0x80000000: 0x7fffffff;
2655     } else {
2656         env->cc_src2 = 0;
2657         return x0;
2658     }
2659 }
2660
2661 void helper_stdf(target_ulong addr, int mem_idx)
2662 {
2663     helper_check_align(addr, 7);
2664 #if !defined(CONFIG_USER_ONLY)
2665     switch (mem_idx) {
2666     case 0:
2667         stfq_user(addr, DT0);
2668         break;
2669     case 1:
2670         stfq_kernel(addr, DT0);
2671         break;
2672 #ifdef TARGET_SPARC64
2673     case 2:
2674         stfq_hypv(addr, DT0);
2675         break;
2676 #endif
2677     default:
2678         break;
2679     }
2680 #else
2681     address_mask(env, &addr);
2682     stfq_raw(addr, DT0);
2683 #endif
2684 }
2685
2686 void helper_lddf(target_ulong addr, int mem_idx)
2687 {
2688     helper_check_align(addr, 7);
2689 #if !defined(CONFIG_USER_ONLY)
2690     switch (mem_idx) {
2691     case 0:
2692         DT0 = ldfq_user(addr);
2693         break;
2694     case 1:
2695         DT0 = ldfq_kernel(addr);
2696         break;
2697 #ifdef TARGET_SPARC64
2698     case 2:
2699         DT0 = ldfq_hypv(addr);
2700         break;
2701 #endif
2702     default:
2703         break;
2704     }
2705 #else
2706     address_mask(env, &addr);
2707     DT0 = ldfq_raw(addr);
2708 #endif
2709 }
2710
2711 void helper_ldqf(target_ulong addr, int mem_idx)
2712 {
2713     // XXX add 128 bit load
2714     CPU_QuadU u;
2715
2716     helper_check_align(addr, 7);
2717 #if !defined(CONFIG_USER_ONLY)
2718     switch (mem_idx) {
2719     case 0:
2720         u.ll.upper = ldq_user(addr);
2721         u.ll.lower = ldq_user(addr + 8);
2722         QT0 = u.q;
2723         break;
2724     case 1:
2725         u.ll.upper = ldq_kernel(addr);
2726         u.ll.lower = ldq_kernel(addr + 8);
2727         QT0 = u.q;
2728         break;
2729 #ifdef TARGET_SPARC64
2730     case 2:
2731         u.ll.upper = ldq_hypv(addr);
2732         u.ll.lower = ldq_hypv(addr + 8);
2733         QT0 = u.q;
2734         break;
2735 #endif
2736     default:
2737         break;
2738     }
2739 #else
2740     address_mask(env, &addr);
2741     u.ll.upper = ldq_raw(addr);
2742     u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
2743     QT0 = u.q;
2744 #endif
2745 }
2746
2747 void helper_stqf(target_ulong addr, int mem_idx)
2748 {
2749     // XXX add 128 bit store
2750     CPU_QuadU u;
2751
2752     helper_check_align(addr, 7);
2753 #if !defined(CONFIG_USER_ONLY)
2754     switch (mem_idx) {
2755     case 0:
2756         u.q = QT0;
2757         stq_user(addr, u.ll.upper);
2758         stq_user(addr + 8, u.ll.lower);
2759         break;
2760     case 1:
2761         u.q = QT0;
2762         stq_kernel(addr, u.ll.upper);
2763         stq_kernel(addr + 8, u.ll.lower);
2764         break;
2765 #ifdef TARGET_SPARC64
2766     case 2:
2767         u.q = QT0;
2768         stq_hypv(addr, u.ll.upper);
2769         stq_hypv(addr + 8, u.ll.lower);
2770         break;
2771 #endif
2772     default:
2773         break;
2774     }
2775 #else
2776     u.q = QT0;
2777     address_mask(env, &addr);
2778     stq_raw(addr, u.ll.upper);
2779     stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
2780 #endif
2781 }
2782
2783 static inline void set_fsr(void)
2784 {
2785     int rnd_mode;
2786
2787     switch (env->fsr & FSR_RD_MASK) {
2788     case FSR_RD_NEAREST:
2789         rnd_mode = float_round_nearest_even;
2790         break;
2791     default:
2792     case FSR_RD_ZERO:
2793         rnd_mode = float_round_to_zero;
2794         break;
2795     case FSR_RD_POS:
2796         rnd_mode = float_round_up;
2797         break;
2798     case FSR_RD_NEG:
2799         rnd_mode = float_round_down;
2800         break;
2801     }
2802     set_float_rounding_mode(rnd_mode, &env->fp_status);
2803 }
2804
2805 void helper_ldfsr(uint32_t new_fsr)
2806 {
2807     env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
2808     set_fsr();
2809 }
2810
2811 #ifdef TARGET_SPARC64
2812 void helper_ldxfsr(uint64_t new_fsr)
2813 {
2814     env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
2815     set_fsr();
2816 }
2817 #endif
2818
2819 void helper_debug(void)
2820 {
2821     env->exception_index = EXCP_DEBUG;
2822     cpu_loop_exit();
2823 }
2824
2825 #ifndef TARGET_SPARC64
2826 /* XXX: use another pointer for %iN registers to avoid slow wrapping
2827    handling ? */
2828 void helper_save(void)
2829 {
2830     uint32_t cwp;
2831
2832     cwp = cpu_cwp_dec(env, env->cwp - 1);
2833     if (env->wim & (1 << cwp)) {
2834         raise_exception(TT_WIN_OVF);
2835     }
2836     set_cwp(cwp);
2837 }
2838
2839 void helper_restore(void)
2840 {
2841     uint32_t cwp;
2842
2843     cwp = cpu_cwp_inc(env, env->cwp + 1);
2844     if (env->wim & (1 << cwp)) {
2845         raise_exception(TT_WIN_UNF);
2846     }
2847     set_cwp(cwp);
2848 }
2849
2850 void helper_wrpsr(target_ulong new_psr)
2851 {
2852     if ((new_psr & PSR_CWP) >= env->nwindows)
2853         raise_exception(TT_ILL_INSN);
2854     else
2855         PUT_PSR(env, new_psr);
2856 }
2857
2858 target_ulong helper_rdpsr(void)
2859 {
2860     return GET_PSR(env);
2861 }
2862
2863 #else
2864 /* XXX: use another pointer for %iN registers to avoid slow wrapping
2865    handling ? */
2866 void helper_save(void)
2867 {
2868     uint32_t cwp;
2869
2870     cwp = cpu_cwp_dec(env, env->cwp - 1);
2871     if (env->cansave == 0) {
2872         raise_exception(TT_SPILL | (env->otherwin != 0 ?
2873                                     (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2874                                     ((env->wstate & 0x7) << 2)));
2875     } else {
2876         if (env->cleanwin - env->canrestore == 0) {
2877             // XXX Clean windows without trap
2878             raise_exception(TT_CLRWIN);
2879         } else {
2880             env->cansave--;
2881             env->canrestore++;
2882             set_cwp(cwp);
2883         }
2884     }
2885 }
2886
2887 void helper_restore(void)
2888 {
2889     uint32_t cwp;
2890
2891     cwp = cpu_cwp_inc(env, env->cwp + 1);
2892     if (env->canrestore == 0) {
2893         raise_exception(TT_FILL | (env->otherwin != 0 ?
2894                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2895                                    ((env->wstate & 0x7) << 2)));
2896     } else {
2897         env->cansave++;
2898         env->canrestore--;
2899         set_cwp(cwp);
2900     }
2901 }
2902
2903 void helper_flushw(void)
2904 {
2905     if (env->cansave != env->nwindows - 2) {
2906         raise_exception(TT_SPILL | (env->otherwin != 0 ?
2907                                     (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2908                                     ((env->wstate & 0x7) << 2)));
2909     }
2910 }
2911
2912 void helper_saved(void)
2913 {
2914     env->cansave++;
2915     if (env->otherwin == 0)
2916         env->canrestore--;
2917     else
2918         env->otherwin--;
2919 }
2920
2921 void helper_restored(void)
2922 {
2923     env->canrestore++;
2924     if (env->cleanwin < env->nwindows - 1)
2925         env->cleanwin++;
2926     if (env->otherwin == 0)
2927         env->cansave--;
2928     else
2929         env->otherwin--;
2930 }
2931
2932 target_ulong helper_rdccr(void)
2933 {
2934     return GET_CCR(env);
2935 }
2936
2937 void helper_wrccr(target_ulong new_ccr)
2938 {
2939     PUT_CCR(env, new_ccr);
2940 }
2941
2942 // CWP handling is reversed in V9, but we still use the V8 register
2943 // order.
2944 target_ulong helper_rdcwp(void)
2945 {
2946     return GET_CWP64(env);
2947 }
2948
2949 void helper_wrcwp(target_ulong new_cwp)
2950 {
2951     PUT_CWP64(env, new_cwp);
2952 }
2953
2954 // This function uses non-native bit order
2955 #define GET_FIELD(X, FROM, TO)                                  \
2956     ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
2957
2958 // This function uses the order in the manuals, i.e. bit 0 is 2^0
2959 #define GET_FIELD_SP(X, FROM, TO)               \
2960     GET_FIELD(X, 63 - (TO), 63 - (FROM))
2961
2962 target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
2963 {
2964     return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
2965         (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
2966         (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
2967         (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
2968         (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
2969         (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
2970         (((pixel_addr >> 55) & 1) << 4) |
2971         (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
2972         GET_FIELD_SP(pixel_addr, 11, 12);
2973 }
2974
2975 target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
2976 {
2977     uint64_t tmp;
2978
2979     tmp = addr + offset;
2980     env->gsr &= ~7ULL;
2981     env->gsr |= tmp & 7ULL;
2982     return tmp & ~7ULL;
2983 }
2984
2985 target_ulong helper_popc(target_ulong val)
2986 {
2987     return ctpop64(val);
2988 }
2989
2990 static inline uint64_t *get_gregset(uint64_t pstate)
2991 {
2992     switch (pstate) {
2993     default:
2994     case 0:
2995         return env->bgregs;
2996     case PS_AG:
2997         return env->agregs;
2998     case PS_MG:
2999         return env->mgregs;
3000     case PS_IG:
3001         return env->igregs;
3002     }
3003 }
3004
3005 static inline void change_pstate(uint64_t new_pstate)
3006 {
3007     uint64_t pstate_regs, new_pstate_regs;
3008     uint64_t *src, *dst;
3009
3010     pstate_regs = env->pstate & 0xc01;
3011     new_pstate_regs = new_pstate & 0xc01;
3012     if (new_pstate_regs != pstate_regs) {
3013         // Switch global register bank
3014         src = get_gregset(new_pstate_regs);
3015         dst = get_gregset(pstate_regs);
3016         memcpy32(dst, env->gregs);
3017         memcpy32(env->gregs, src);
3018     }
3019     env->pstate = new_pstate;
3020 }
3021
3022 void helper_wrpstate(target_ulong new_state)
3023 {
3024     if (!(env->def->features & CPU_FEATURE_GL))
3025         change_pstate(new_state & 0xf3f);
3026 }
3027
3028 void helper_done(void)
3029 {
3030     env->pc = env->tsptr->tpc;
3031     env->npc = env->tsptr->tnpc + 4;
3032     PUT_CCR(env, env->tsptr->tstate >> 32);
3033     env->asi = (env->tsptr->tstate >> 24) & 0xff;
3034     change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
3035     PUT_CWP64(env, env->tsptr->tstate & 0xff);
3036     env->tl--;
3037     env->tsptr = &env->ts[env->tl & MAXTL_MASK];
3038 }
3039
3040 void helper_retry(void)
3041 {
3042     env->pc = env->tsptr->tpc;
3043     env->npc = env->tsptr->tnpc;
3044     PUT_CCR(env, env->tsptr->tstate >> 32);
3045     env->asi = (env->tsptr->tstate >> 24) & 0xff;
3046     change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
3047     PUT_CWP64(env, env->tsptr->tstate & 0xff);
3048     env->tl--;
3049     env->tsptr = &env->ts[env->tl & MAXTL_MASK];
3050 }
3051
3052 void helper_set_softint(uint64_t value)
3053 {
3054     env->softint |= (uint32_t)value;
3055 }
3056
3057 void helper_clear_softint(uint64_t value)
3058 {
3059     env->softint &= (uint32_t)~value;
3060 }
3061
3062 void helper_write_softint(uint64_t value)
3063 {
3064     env->softint = (uint32_t)value;
3065 }
3066 #endif
3067
3068 void helper_flush(target_ulong addr)
3069 {
3070     addr &= ~7;
3071     tb_invalidate_page_range(addr, addr + 8);
3072 }
3073
3074 #ifdef TARGET_SPARC64
3075 #ifdef DEBUG_PCALL
3076 static const char * const excp_names[0x80] = {
3077     [TT_TFAULT] = "Instruction Access Fault",
3078     [TT_TMISS] = "Instruction Access MMU Miss",
3079     [TT_CODE_ACCESS] = "Instruction Access Error",
3080     [TT_ILL_INSN] = "Illegal Instruction",
3081     [TT_PRIV_INSN] = "Privileged Instruction",
3082     [TT_NFPU_INSN] = "FPU Disabled",
3083     [TT_FP_EXCP] = "FPU Exception",
3084     [TT_TOVF] = "Tag Overflow",
3085     [TT_CLRWIN] = "Clean Windows",
3086     [TT_DIV_ZERO] = "Division By Zero",
3087     [TT_DFAULT] = "Data Access Fault",
3088     [TT_DMISS] = "Data Access MMU Miss",
3089     [TT_DATA_ACCESS] = "Data Access Error",
3090     [TT_DPROT] = "Data Protection Error",
3091     [TT_UNALIGNED] = "Unaligned Memory Access",
3092     [TT_PRIV_ACT] = "Privileged Action",
3093     [TT_EXTINT | 0x1] = "External Interrupt 1",
3094     [TT_EXTINT | 0x2] = "External Interrupt 2",
3095     [TT_EXTINT | 0x3] = "External Interrupt 3",
3096     [TT_EXTINT | 0x4] = "External Interrupt 4",
3097     [TT_EXTINT | 0x5] = "External Interrupt 5",
3098     [TT_EXTINT | 0x6] = "External Interrupt 6",
3099     [TT_EXTINT | 0x7] = "External Interrupt 7",
3100     [TT_EXTINT | 0x8] = "External Interrupt 8",
3101     [TT_EXTINT | 0x9] = "External Interrupt 9",
3102     [TT_EXTINT | 0xa] = "External Interrupt 10",
3103     [TT_EXTINT | 0xb] = "External Interrupt 11",
3104     [TT_EXTINT | 0xc] = "External Interrupt 12",
3105     [TT_EXTINT | 0xd] = "External Interrupt 13",
3106     [TT_EXTINT | 0xe] = "External Interrupt 14",
3107     [TT_EXTINT | 0xf] = "External Interrupt 15",
3108 };
3109 #endif
3110
3111 void do_interrupt(CPUState *env)
3112 {
3113     int intno = env->exception_index;
3114
3115 #ifdef DEBUG_PCALL
3116     if (qemu_loglevel_mask(CPU_LOG_INT)) {
3117         static int count;
3118         const char *name;
3119
3120         if (intno < 0 || intno >= 0x180)
3121             name = "Unknown";
3122         else if (intno >= 0x100)
3123             name = "Trap Instruction";
3124         else if (intno >= 0xc0)
3125             name = "Window Fill";
3126         else if (intno >= 0x80)
3127             name = "Window Spill";
3128         else {
3129             name = excp_names[intno];
3130             if (!name)
3131                 name = "Unknown";
3132         }
3133
3134         qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
3135                 " SP=%016" PRIx64 "\n",
3136                 count, name, intno,
3137                 env->pc,
3138                 env->npc, env->regwptr[6]);
3139         log_cpu_state(env, 0);
3140 #if 0
3141         {
3142             int i;
3143             uint8_t *ptr;
3144
3145             qemu_log("       code=");
3146             ptr = (uint8_t *)env->pc;
3147             for(i = 0; i < 16; i++) {
3148                 qemu_log(" %02x", ldub(ptr + i));
3149             }
3150             qemu_log("\n");
3151         }
3152 #endif
3153         count++;
3154     }
3155 #endif
3156 #if !defined(CONFIG_USER_ONLY)
3157     if (env->tl >= env->maxtl) {
3158         cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
3159                   " Error state", env->exception_index, env->tl, env->maxtl);
3160         return;
3161     }
3162 #endif
3163     if (env->tl < env->maxtl - 1) {
3164         env->tl++;
3165     } else {
3166         env->pstate |= PS_RED;
3167         if (env->tl < env->maxtl)
3168             env->tl++;
3169     }
3170     env->tsptr = &env->ts[env->tl & MAXTL_MASK];
3171     env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
3172         ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
3173         GET_CWP64(env);
3174     env->tsptr->tpc = env->pc;
3175     env->tsptr->tnpc = env->npc;
3176     env->tsptr->tt = intno;
3177     if (!(env->def->features & CPU_FEATURE_GL)) {
3178         switch (intno) {
3179         case TT_IVEC:
3180             change_pstate(PS_PEF | PS_PRIV | PS_IG);
3181             break;
3182         case TT_TFAULT:
3183         case TT_TMISS:
3184         case TT_DFAULT:
3185         case TT_DMISS:
3186         case TT_DPROT:
3187             change_pstate(PS_PEF | PS_PRIV | PS_MG);
3188             break;
3189         default:
3190             change_pstate(PS_PEF | PS_PRIV | PS_AG);
3191             break;
3192         }
3193     }
3194     if (intno == TT_CLRWIN)
3195         cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
3196     else if ((intno & 0x1c0) == TT_SPILL)
3197         cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
3198     else if ((intno & 0x1c0) == TT_FILL)
3199         cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
3200     env->tbr &= ~0x7fffULL;
3201     env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
3202     env->pc = env->tbr;
3203     env->npc = env->pc + 4;
3204     env->exception_index = 0;
3205 }
3206 #else
3207 #ifdef DEBUG_PCALL
3208 static const char * const excp_names[0x80] = {
3209     [TT_TFAULT] = "Instruction Access Fault",
3210     [TT_ILL_INSN] = "Illegal Instruction",
3211     [TT_PRIV_INSN] = "Privileged Instruction",
3212     [TT_NFPU_INSN] = "FPU Disabled",
3213     [TT_WIN_OVF] = "Window Overflow",
3214     [TT_WIN_UNF] = "Window Underflow",
3215     [TT_UNALIGNED] = "Unaligned Memory Access",
3216     [TT_FP_EXCP] = "FPU Exception",
3217     [TT_DFAULT] = "Data Access Fault",
3218     [TT_TOVF] = "Tag Overflow",
3219     [TT_EXTINT | 0x1] = "External Interrupt 1",
3220     [TT_EXTINT | 0x2] = "External Interrupt 2",
3221     [TT_EXTINT | 0x3] = "External Interrupt 3",
3222     [TT_EXTINT | 0x4] = "External Interrupt 4",
3223     [TT_EXTINT | 0x5] = "External Interrupt 5",
3224     [TT_EXTINT | 0x6] = "External Interrupt 6",
3225     [TT_EXTINT | 0x7] = "External Interrupt 7",
3226     [TT_EXTINT | 0x8] = "External Interrupt 8",
3227     [TT_EXTINT | 0x9] = "External Interrupt 9",
3228     [TT_EXTINT | 0xa] = "External Interrupt 10",
3229     [TT_EXTINT | 0xb] = "External Interrupt 11",
3230     [TT_EXTINT | 0xc] = "External Interrupt 12",
3231     [TT_EXTINT | 0xd] = "External Interrupt 13",
3232     [TT_EXTINT | 0xe] = "External Interrupt 14",
3233     [TT_EXTINT | 0xf] = "External Interrupt 15",
3234     [TT_TOVF] = "Tag Overflow",
3235     [TT_CODE_ACCESS] = "Instruction Access Error",
3236     [TT_DATA_ACCESS] = "Data Access Error",
3237     [TT_DIV_ZERO] = "Division By Zero",
3238     [TT_NCP_INSN] = "Coprocessor Disabled",
3239 };
3240 #endif
3241
3242 void do_interrupt(CPUState *env)
3243 {
3244     int cwp, intno = env->exception_index;
3245
3246 #ifdef DEBUG_PCALL
3247     if (qemu_loglevel_mask(CPU_LOG_INT)) {
3248         static int count;
3249         const char *name;
3250
3251         if (intno < 0 || intno >= 0x100)
3252             name = "Unknown";
3253         else if (intno >= 0x80)
3254             name = "Trap Instruction";
3255         else {
3256             name = excp_names[intno];
3257             if (!name)
3258                 name = "Unknown";
3259         }
3260
3261         qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
3262                 count, name, intno,
3263                 env->pc,
3264                 env->npc, env->regwptr[6]);
3265         log_cpu_state(env, 0);
3266 #if 0
3267         {
3268             int i;
3269             uint8_t *ptr;
3270
3271             qemu_log("       code=");
3272             ptr = (uint8_t *)env->pc;
3273             for(i = 0; i < 16; i++) {
3274                 qemu_log(" %02x", ldub(ptr + i));
3275             }
3276             qemu_log("\n");
3277         }
3278 #endif
3279         count++;
3280     }
3281 #endif
3282 #if !defined(CONFIG_USER_ONLY)
3283     if (env->psret == 0) {
3284         cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
3285                   env->exception_index);
3286         return;
3287     }
3288 #endif
3289     env->psret = 0;
3290     cwp = cpu_cwp_dec(env, env->cwp - 1);
3291     cpu_set_cwp(env, cwp);
3292     env->regwptr[9] = env->pc;
3293     env->regwptr[10] = env->npc;
3294     env->psrps = env->psrs;
3295     env->psrs = 1;
3296     env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
3297     env->pc = env->tbr;
3298     env->npc = env->pc + 4;
3299     env->exception_index = 0;
3300 }
3301 #endif
3302
3303 #if !defined(CONFIG_USER_ONLY)
3304
3305 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3306                                 void *retaddr);
3307
3308 #define MMUSUFFIX _mmu
3309 #define ALIGNED_ONLY
3310
3311 #define SHIFT 0
3312 #include "softmmu_template.h"
3313
3314 #define SHIFT 1
3315 #include "softmmu_template.h"
3316
3317 #define SHIFT 2
3318 #include "softmmu_template.h"
3319
3320 #define SHIFT 3
3321 #include "softmmu_template.h"
3322
3323 /* XXX: make it generic ? */
3324 static void cpu_restore_state2(void *retaddr)
3325 {
3326     TranslationBlock *tb;
3327     unsigned long pc;
3328
3329     if (retaddr) {
3330         /* now we have a real cpu fault */
3331         pc = (unsigned long)retaddr;
3332         tb = tb_find_pc(pc);
3333         if (tb) {
3334             /* the PC is inside the translated code. It means that we have
3335                a virtual CPU fault */
3336             cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
3337         }
3338     }
3339 }
3340
3341 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3342                                 void *retaddr)
3343 {
3344 #ifdef DEBUG_UNALIGNED
3345     printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
3346            "\n", addr, env->pc);
3347 #endif
3348     cpu_restore_state2(retaddr);
3349     raise_exception(TT_UNALIGNED);
3350 }
3351
3352 /* try to fill the TLB and return an exception if error. If retaddr is
3353    NULL, it means that the function was called in C code (i.e. not
3354    from generated code or from helper.c) */
3355 /* XXX: fix it to restore all registers */
3356 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3357 {
3358     int ret;
3359     CPUState *saved_env;
3360
3361     /* XXX: hack to restore env in all cases, even if not called from
3362        generated code */
3363     saved_env = env;
3364     env = cpu_single_env;
3365
3366     ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3367     if (ret) {
3368         cpu_restore_state2(retaddr);
3369         cpu_loop_exit();
3370     }
3371     env = saved_env;
3372 }
3373
3374 #endif
3375
3376 #ifndef TARGET_SPARC64
3377 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3378                           int is_asi, int size)
3379 {
3380     CPUState *saved_env;
3381
3382     /* XXX: hack to restore env in all cases, even if not called from
3383        generated code */
3384     saved_env = env;
3385     env = cpu_single_env;
3386 #ifdef DEBUG_UNASSIGNED
3387     if (is_asi)
3388         printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3389                " asi 0x%02x from " TARGET_FMT_lx "\n",
3390                is_exec ? "exec" : is_write ? "write" : "read", size,
3391                size == 1 ? "" : "s", addr, is_asi, env->pc);
3392     else
3393         printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3394                " from " TARGET_FMT_lx "\n",
3395                is_exec ? "exec" : is_write ? "write" : "read", size,
3396                size == 1 ? "" : "s", addr, env->pc);
3397 #endif
3398     if (env->mmuregs[3]) /* Fault status register */
3399         env->mmuregs[3] = 1; /* overflow (not read before another fault) */
3400     if (is_asi)
3401         env->mmuregs[3] |= 1 << 16;
3402     if (env->psrs)
3403         env->mmuregs[3] |= 1 << 5;
3404     if (is_exec)
3405         env->mmuregs[3] |= 1 << 6;
3406     if (is_write)
3407         env->mmuregs[3] |= 1 << 7;
3408     env->mmuregs[3] |= (5 << 2) | 2;
3409     env->mmuregs[4] = addr; /* Fault address register */
3410     if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
3411         if (is_exec)
3412             raise_exception(TT_CODE_ACCESS);
3413         else
3414             raise_exception(TT_DATA_ACCESS);
3415     }
3416     env = saved_env;
3417 }
3418 #else
3419 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3420                           int is_asi, int size)
3421 {
3422 #ifdef DEBUG_UNASSIGNED
3423     CPUState *saved_env;
3424
3425     /* XXX: hack to restore env in all cases, even if not called from
3426        generated code */
3427     saved_env = env;
3428     env = cpu_single_env;
3429     printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
3430            "\n", addr, env->pc);
3431     env = saved_env;
3432 #endif
3433     if (is_exec)
3434         raise_exception(TT_CODE_ACCESS);
3435     else
3436         raise_exception(TT_DATA_ACCESS);
3437 }
3438 #endif
3439
3440 #ifdef TARGET_SPARC64
3441 void helper_tick_set_count(void *opaque, uint64_t count)
3442 {
3443 #if !defined(CONFIG_USER_ONLY)
3444     cpu_tick_set_count(opaque, count);
3445 #endif
3446 }
3447
3448 uint64_t helper_tick_get_count(void *opaque)
3449 {
3450 #if !defined(CONFIG_USER_ONLY)
3451     return cpu_tick_get_count(opaque);
3452 #else
3453     return 0;
3454 #endif
3455 }
3456
3457 void helper_tick_set_limit(void *opaque, uint64_t limit)
3458 {
3459 #if !defined(CONFIG_USER_ONLY)
3460     cpu_tick_set_limit(opaque, limit);
3461 #endif
3462 }
3463 #endif