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