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