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