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