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