Improved ASI debugging (Robert Reif)
[qemu] / target-sparc / op_helper.c
1 #include "exec.h"
2 #include "host-utils.h"
3
4 //#define DEBUG_PCALL
5 //#define DEBUG_MMU
6 //#define DEBUG_MXCC
7 //#define DEBUG_UNALIGNED
8 //#define DEBUG_UNASSIGNED
9 //#define DEBUG_ASI
10
11 #ifdef DEBUG_MMU
12 #define DPRINTF_MMU(fmt, args...) \
13 do { printf("MMU: " fmt , ##args); } while (0)
14 #else
15 #define DPRINTF_MMU(fmt, args...)
16 #endif
17
18 #ifdef DEBUG_MXCC
19 #define DPRINTF_MXCC(fmt, args...) \
20 do { printf("MXCC: " fmt , ##args); } while (0)
21 #else
22 #define DPRINTF_MXCC(fmt, args...)
23 #endif
24
25 #ifdef DEBUG_ASI
26 #define DPRINTF_ASI(fmt, args...) \
27 do { printf("ASI: " fmt , ##args); } while (0)
28 #else
29 #define DPRINTF_ASI(fmt, args...)
30 #endif
31
32 void raise_exception(int tt)
33 {
34     env->exception_index = tt;
35     cpu_loop_exit();
36 }
37
38 void check_ieee_exceptions()
39 {
40      T0 = get_float_exception_flags(&env->fp_status);
41      if (T0)
42      {
43         /* Copy IEEE 754 flags into FSR */
44         if (T0 & float_flag_invalid)
45             env->fsr |= FSR_NVC;
46         if (T0 & float_flag_overflow)
47             env->fsr |= FSR_OFC;
48         if (T0 & float_flag_underflow)
49             env->fsr |= FSR_UFC;
50         if (T0 & float_flag_divbyzero)
51             env->fsr |= FSR_DZC;
52         if (T0 & float_flag_inexact)
53             env->fsr |= FSR_NXC;
54
55         if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23))
56         {
57             /* Unmasked exception, generate a trap */
58             env->fsr |= FSR_FTT_IEEE_EXCP;
59             raise_exception(TT_FP_EXCP);
60         }
61         else
62         {
63             /* Accumulate exceptions */
64             env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
65         }
66      }
67 }
68
69 #ifdef USE_INT_TO_FLOAT_HELPERS
70 void do_fitos(void)
71 {
72     set_float_exception_flags(0, &env->fp_status);
73     FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
74     check_ieee_exceptions();
75 }
76
77 void do_fitod(void)
78 {
79     DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
80 }
81
82 #if defined(CONFIG_USER_ONLY)
83 void do_fitoq(void)
84 {
85     QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
86 }
87 #endif
88
89 #ifdef TARGET_SPARC64
90 void do_fxtos(void)
91 {
92     set_float_exception_flags(0, &env->fp_status);
93     FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
94     check_ieee_exceptions();
95 }
96
97 void do_fxtod(void)
98 {
99     set_float_exception_flags(0, &env->fp_status);
100     DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
101     check_ieee_exceptions();
102 }
103
104 #if defined(CONFIG_USER_ONLY)
105 void do_fxtoq(void)
106 {
107     set_float_exception_flags(0, &env->fp_status);
108     QT0 = int64_to_float128(*((int32_t *)&DT1), &env->fp_status);
109     check_ieee_exceptions();
110 }
111 #endif
112 #endif
113 #endif
114
115 void do_fabss(void)
116 {
117     FT0 = float32_abs(FT1);
118 }
119
120 #ifdef TARGET_SPARC64
121 void do_fabsd(void)
122 {
123     DT0 = float64_abs(DT1);
124 }
125
126 #if defined(CONFIG_USER_ONLY)
127 void do_fabsq(void)
128 {
129     QT0 = float128_abs(QT1);
130 }
131 #endif
132 #endif
133
134 void do_fsqrts(void)
135 {
136     set_float_exception_flags(0, &env->fp_status);
137     FT0 = float32_sqrt(FT1, &env->fp_status);
138     check_ieee_exceptions();
139 }
140
141 void do_fsqrtd(void)
142 {
143     set_float_exception_flags(0, &env->fp_status);
144     DT0 = float64_sqrt(DT1, &env->fp_status);
145     check_ieee_exceptions();
146 }
147
148 #if defined(CONFIG_USER_ONLY)
149 void do_fsqrtq(void)
150 {
151     set_float_exception_flags(0, &env->fp_status);
152     QT0 = float128_sqrt(QT1, &env->fp_status);
153     check_ieee_exceptions();
154 }
155 #endif
156
157 #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
158     void glue(do_, name) (void)                                         \
159     {                                                                   \
160         env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
161         switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
162         case float_relation_unordered:                                  \
163             T0 = (FSR_FCC1 | FSR_FCC0) << FS;                           \
164             if ((env->fsr & FSR_NVM) || TRAP) {                         \
165                 env->fsr |= T0;                                         \
166                 env->fsr |= FSR_NVC;                                    \
167                 env->fsr |= FSR_FTT_IEEE_EXCP;                          \
168                 raise_exception(TT_FP_EXCP);                            \
169             } else {                                                    \
170                 env->fsr |= FSR_NVA;                                    \
171             }                                                           \
172             break;                                                      \
173         case float_relation_less:                                       \
174             T0 = FSR_FCC0 << FS;                                        \
175             break;                                                      \
176         case float_relation_greater:                                    \
177             T0 = FSR_FCC1 << FS;                                        \
178             break;                                                      \
179         default:                                                        \
180             T0 = 0;                                                     \
181             break;                                                      \
182         }                                                               \
183         env->fsr |= T0;                                                 \
184     }
185
186 GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
187 GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
188
189 GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
190 GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
191
192 #ifdef CONFIG_USER_ONLY
193 GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
194 GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
195 #endif
196
197 #ifdef TARGET_SPARC64
198 GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
199 GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
200
201 GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
202 GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
203
204 GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
205 GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
206
207 GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
208 GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
209
210 GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
211 GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
212
213 GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
214 GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
215 #ifdef CONFIG_USER_ONLY
216 GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
217 GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
218 GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
219 GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
220 GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
221 GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
222 #endif
223 #endif
224
225 #ifndef TARGET_SPARC64
226 #ifndef CONFIG_USER_ONLY
227
228 #ifdef DEBUG_MXCC
229 static void dump_mxcc(CPUState *env)
230 {
231     printf("mxccdata: %016llx %016llx %016llx %016llx\n",
232         env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]);
233     printf("mxccregs: %016llx %016llx %016llx %016llx\n"
234            "          %016llx %016llx %016llx %016llx\n",
235         env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3],
236         env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]);
237 }
238 #endif
239
240 #ifdef DEBUG_ASI
241 static void dump_asi(const char * txt, uint32_t addr, int asi, int size,
242                      uint32_t r1, uint32_t r2)
243 {
244     switch (size)
245     {
246     case 1:
247         DPRINTF_ASI("%s %08x asi 0x%02x = %02x\n", txt, addr, asi, r1 & 0xff);
248         break;
249     case 2:
250         DPRINTF_ASI("%s %08x asi 0x%02x = %04x\n", txt, addr, asi, r1 & 0xffff);
251         break;
252     case 4:
253         DPRINTF_ASI("%s %08x asi 0x%02x = %08x\n", txt, addr, asi, r1);
254         break;
255     case 8:
256         DPRINTF_ASI("%s %08x asi 0x%02x = %016llx\n", txt, addr, asi,
257                     r2 | ((uint64_t)r1 << 32));
258         break;
259     }
260 }
261 #endif
262
263 void helper_ld_asi(int asi, int size, int sign)
264 {
265     uint32_t ret = 0;
266     uint64_t tmp;
267 #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
268     uint32_t last_T0 = T0;
269 #endif
270
271     switch (asi) {
272     case 2: /* SuperSparc MXCC registers */
273         switch (T0) {
274         case 0x01c00a00: /* MXCC control register */
275             if (size == 8) {
276                 ret = env->mxccregs[3] >> 32;
277                 T0 = env->mxccregs[3];
278             } else
279                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
280             break;
281         case 0x01c00a04: /* MXCC control register */
282             if (size == 4)
283                 ret = env->mxccregs[3];
284             else
285                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
286             break;
287         case 0x01c00c00: /* Module reset register */
288             if (size == 8) {
289                 ret = env->mxccregs[5] >> 32;
290                 T0 = env->mxccregs[5];
291                 // should we do something here?
292             } else
293                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
294             break;
295         case 0x01c00f00: /* MBus port address register */
296             if (size == 8) {
297                 ret = env->mxccregs[7] >> 32;
298                 T0 = env->mxccregs[7];
299             } else
300                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
301             break;
302         default:
303             DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size);
304             break;
305         }
306         DPRINTF_MXCC("asi = %d, size = %d, sign = %d, T0 = %08x -> ret = %08x,"
307                      "T0 = %08x\n", asi, size, sign, last_T0, ret, T0);
308 #ifdef DEBUG_MXCC
309         dump_mxcc(env);
310 #endif
311         break;
312     case 3: /* MMU probe */
313         {
314             int mmulev;
315
316             mmulev = (T0 >> 8) & 15;
317             if (mmulev > 4)
318                 ret = 0;
319             else {
320                 ret = mmu_probe(env, T0, mmulev);
321                 //bswap32s(&ret);
322             }
323             DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
324         }
325         break;
326     case 4: /* read MMU regs */
327         {
328             int reg = (T0 >> 8) & 0x1f;
329
330             ret = env->mmuregs[reg];
331             if (reg == 3) /* Fault status cleared on read */
332                 env->mmuregs[3] = 0;
333             else if (reg == 0x13) /* Fault status read */
334                 ret = env->mmuregs[3];
335             else if (reg == 0x14) /* Fault address read */
336                 ret = env->mmuregs[4];
337             DPRINTF_MMU("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
338         }
339         break;
340     case 9: /* Supervisor code access */
341         switch(size) {
342         case 1:
343             ret = ldub_code(T0);
344             break;
345         case 2:
346             ret = lduw_code(T0 & ~1);
347             break;
348         default:
349         case 4:
350             ret = ldl_code(T0 & ~3);
351             break;
352         case 8:
353             tmp = ldq_code(T0 & ~7);
354             ret = tmp >> 32;
355             T0 = tmp;
356             break;
357         }
358         break;
359     case 0xa: /* User data access */
360         switch(size) {
361         case 1:
362             ret = ldub_user(T0);
363             break;
364         case 2:
365             ret = lduw_user(T0 & ~1);
366             break;
367         default:
368         case 4:
369             ret = ldl_user(T0 & ~3);
370             break;
371         case 8:
372             tmp = ldq_user(T0 & ~7);
373             ret = tmp >> 32;
374             T0 = tmp;
375             break;
376         }
377         break;
378     case 0xb: /* Supervisor data access */
379         switch(size) {
380         case 1:
381             ret = ldub_kernel(T0);
382             break;
383         case 2:
384             ret = lduw_kernel(T0 & ~1);
385             break;
386         default:
387         case 4:
388             ret = ldl_kernel(T0 & ~3);
389             break;
390         case 8:
391             tmp = ldq_kernel(T0 & ~7);
392             ret = tmp >> 32;
393             T0 = tmp;
394             break;
395         }
396         break;
397     case 0xc: /* I-cache tag */
398     case 0xd: /* I-cache data */
399     case 0xe: /* D-cache tag */
400     case 0xf: /* D-cache data */
401         break;
402     case 0x20: /* MMU passthrough */
403         switch(size) {
404         case 1:
405             ret = ldub_phys(T0);
406             break;
407         case 2:
408             ret = lduw_phys(T0 & ~1);
409             break;
410         default:
411         case 4:
412             ret = ldl_phys(T0 & ~3);
413             break;
414         case 8:
415             tmp = ldq_phys(T0 & ~7);
416             ret = tmp >> 32;
417             T0 = tmp;
418             break;
419         }
420         break;
421     case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
422     case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
423         switch(size) {
424         case 1:
425             ret = ldub_phys((target_phys_addr_t)T0
426                             | ((target_phys_addr_t)(asi & 0xf) << 32));
427             break;
428         case 2:
429             ret = lduw_phys((target_phys_addr_t)(T0 & ~1)
430                             | ((target_phys_addr_t)(asi & 0xf) << 32));
431             break;
432         default:
433         case 4:
434             ret = ldl_phys((target_phys_addr_t)(T0 & ~3)
435                            | ((target_phys_addr_t)(asi & 0xf) << 32));
436             break;
437         case 8:
438             tmp = ldq_phys((target_phys_addr_t)(T0 & ~7)
439                            | ((target_phys_addr_t)(asi & 0xf) << 32));
440             ret = tmp >> 32;
441             T0 = tmp;
442             break;
443         }
444         break;
445     case 0x39: /* data cache diagnostic register */
446         ret = 0;
447         break;
448     case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
449     default:
450         do_unassigned_access(T0, 0, 0, asi);
451         ret = 0;
452         break;
453     }
454     if (sign) {
455         switch(size) {
456         case 1:
457             T1 = (int8_t) ret;
458             break;
459         case 2:
460             T1 = (int16_t) ret;
461             break;
462         default:
463             T1 = ret;
464             break;
465         }
466     }
467     else
468         T1 = ret;
469 #ifdef DEBUG_ASI
470     dump_asi("read ", last_T0, asi, size, T1, T0);
471 #endif
472 }
473
474 void helper_st_asi(int asi, int size)
475 {
476     switch(asi) {
477     case 2: /* SuperSparc MXCC registers */
478         switch (T0) {
479         case 0x01c00000: /* MXCC stream data register 0 */
480             if (size == 8)
481                 env->mxccdata[0] = ((uint64_t)T1 << 32) | T2;
482             else
483                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
484             break;
485         case 0x01c00008: /* MXCC stream data register 1 */
486             if (size == 8)
487                 env->mxccdata[1] = ((uint64_t)T1 << 32) | T2;
488             else
489                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
490             break;
491         case 0x01c00010: /* MXCC stream data register 2 */
492             if (size == 8)
493                 env->mxccdata[2] = ((uint64_t)T1 << 32) | T2;
494             else
495                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
496             break;
497         case 0x01c00018: /* MXCC stream data register 3 */
498             if (size == 8)
499                 env->mxccdata[3] = ((uint64_t)T1 << 32) | T2;
500             else
501                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
502             break;
503         case 0x01c00100: /* MXCC stream source */
504             if (size == 8)
505                 env->mxccregs[0] = ((uint64_t)T1 << 32) | T2;
506             else
507                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
508             env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +  0);
509             env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +  8);
510             env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16);
511             env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 24);
512             break;
513         case 0x01c00200: /* MXCC stream destination */
514             if (size == 8)
515                 env->mxccregs[1] = ((uint64_t)T1 << 32) | T2;
516             else
517                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
518             stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0, env->mxccdata[0]);
519             stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8, env->mxccdata[1]);
520             stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]);
521             stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, env->mxccdata[3]);
522             break;
523         case 0x01c00a00: /* MXCC control register */
524             if (size == 8)
525                 env->mxccregs[3] = ((uint64_t)T1 << 32) | T2;
526             else
527                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
528             break;
529         case 0x01c00a04: /* MXCC control register */
530             if (size == 4)
531                 env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | T1;
532             else
533                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
534             break;
535         case 0x01c00e00: /* MXCC error register  */
536             // writing a 1 bit clears the error
537             if (size == 8)
538                 env->mxccregs[6] &= ~(((uint64_t)T1 << 32) | T2);
539             else
540                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
541             break;
542         case 0x01c00f00: /* MBus port address register */
543             if (size == 8)
544                 env->mxccregs[7] = ((uint64_t)T1 << 32) | T2;
545             else
546                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
547             break;
548         default:
549             DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size);
550             break;
551         }
552         DPRINTF_MXCC("asi = %d, size = %d, T0 = %08x, T1 = %08x\n", asi, size, T0, T1);
553 #ifdef DEBUG_MXCC
554         dump_mxcc(env);
555 #endif
556         break;
557     case 3: /* MMU flush */
558         {
559             int mmulev;
560
561             mmulev = (T0 >> 8) & 15;
562             DPRINTF_MMU("mmu flush level %d\n", mmulev);
563             switch (mmulev) {
564             case 0: // flush page
565                 tlb_flush_page(env, T0 & 0xfffff000);
566                 break;
567             case 1: // flush segment (256k)
568             case 2: // flush region (16M)
569             case 3: // flush context (4G)
570             case 4: // flush entire
571                 tlb_flush(env, 1);
572                 break;
573             default:
574                 break;
575             }
576 #ifdef DEBUG_MMU
577             dump_mmu(env);
578 #endif
579         }
580         break;
581     case 4: /* write MMU regs */
582         {
583             int reg = (T0 >> 8) & 0x1f;
584             uint32_t oldreg;
585
586             oldreg = env->mmuregs[reg];
587             switch(reg) {
588             case 0:
589                 env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
590                                     (T1 & 0x00ffffff);
591                 // Mappings generated during no-fault mode or MMU
592                 // disabled mode are invalid in normal mode
593                 if ((oldreg & (MMU_E | MMU_NF | env->mmu_bm)) !=
594                     (env->mmuregs[reg] & (MMU_E | MMU_NF | env->mmu_bm)))
595                     tlb_flush(env, 1);
596                 break;
597             case 2:
598                 env->mmuregs[reg] = T1;
599                 if (oldreg != env->mmuregs[reg]) {
600                     /* we flush when the MMU context changes because
601                        QEMU has no MMU context support */
602                     tlb_flush(env, 1);
603                 }
604                 break;
605             case 3:
606             case 4:
607                 break;
608             case 0x13:
609                 env->mmuregs[3] = T1;
610                 break;
611             case 0x14:
612                 env->mmuregs[4] = T1;
613                 break;
614             default:
615                 env->mmuregs[reg] = T1;
616                 break;
617             }
618             if (oldreg != env->mmuregs[reg]) {
619                 DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
620             }
621 #ifdef DEBUG_MMU
622             dump_mmu(env);
623 #endif
624         }
625         break;
626     case 0xa: /* User data access */
627         switch(size) {
628         case 1:
629             stb_user(T0, T1);
630             break;
631         case 2:
632             stw_user(T0 & ~1, T1);
633             break;
634         default:
635         case 4:
636             stl_user(T0 & ~3, T1);
637             break;
638         case 8:
639             stq_user(T0 & ~7, ((uint64_t)T1 << 32) | T2);
640             break;
641         }
642         break;
643     case 0xb: /* Supervisor data access */
644         switch(size) {
645         case 1:
646             stb_kernel(T0, T1);
647             break;
648         case 2:
649             stw_kernel(T0 & ~1, T1);
650             break;
651         default:
652         case 4:
653             stl_kernel(T0 & ~3, T1);
654             break;
655         case 8:
656             stq_kernel(T0 & ~7, ((uint64_t)T1 << 32) | T2);
657             break;
658         }
659         break;
660     case 0xc: /* I-cache tag */
661     case 0xd: /* I-cache data */
662     case 0xe: /* D-cache tag */
663     case 0xf: /* D-cache data */
664     case 0x10: /* I/D-cache flush page */
665     case 0x11: /* I/D-cache flush segment */
666     case 0x12: /* I/D-cache flush region */
667     case 0x13: /* I/D-cache flush context */
668     case 0x14: /* I/D-cache flush user */
669         break;
670     case 0x17: /* Block copy, sta access */
671         {
672             // value (T1) = src
673             // address (T0) = dst
674             // copy 32 bytes
675             unsigned int i;
676             uint32_t src = T1 & ~3, dst = T0 & ~3, temp;
677
678             for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
679                 temp = ldl_kernel(src);
680                 stl_kernel(dst, temp);
681             }
682         }
683         break;
684     case 0x1f: /* Block fill, stda access */
685         {
686             // value (T1, T2)
687             // address (T0) = dst
688             // fill 32 bytes
689             unsigned int i;
690             uint32_t dst = T0 & 7;
691             uint64_t val;
692
693             val = (((uint64_t)T1) << 32) | T2;
694
695             for (i = 0; i < 32; i += 8, dst += 8)
696                 stq_kernel(dst, val);
697         }
698         break;
699     case 0x20: /* MMU passthrough */
700         {
701             switch(size) {
702             case 1:
703                 stb_phys(T0, T1);
704                 break;
705             case 2:
706                 stw_phys(T0 & ~1, T1);
707                 break;
708             case 4:
709             default:
710                 stl_phys(T0 & ~3, T1);
711                 break;
712             case 8:
713                 stq_phys(T0 & ~7, ((uint64_t)T1 << 32) | T2);
714                 break;
715             }
716         }
717         break;
718     case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
719     case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
720         {
721             switch(size) {
722             case 1:
723                 stb_phys((target_phys_addr_t)T0
724                          | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
725                 break;
726             case 2:
727                 stw_phys((target_phys_addr_t)(T0 & ~1)
728                             | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
729                 break;
730             case 4:
731             default:
732                 stl_phys((target_phys_addr_t)(T0 & ~3)
733                            | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
734                 break;
735             case 8:
736                 stq_phys((target_phys_addr_t)(T0 & ~7)
737                            | ((target_phys_addr_t)(asi & 0xf) << 32),
738                          ((uint64_t)T1 << 32) | T2);
739                 break;
740             }
741         }
742         break;
743     case 0x30: /* store buffer tags */
744     case 0x31: /* store buffer data or Ross RT620 I-cache flush */
745     case 0x32: /* store buffer control */
746     case 0x36: /* I-cache flash clear */
747     case 0x37: /* D-cache flash clear */
748     case 0x38: /* breakpoint diagnostics */
749     case 0x4c: /* breakpoint action */
750         break;
751     case 9: /* Supervisor code access, XXX */
752     case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
753     default:
754         do_unassigned_access(T0, 1, 0, asi);
755         break;
756     }
757 #ifdef DEBUG_ASI
758     dump_asi("write", T0, asi, size, T1, T2);
759 #endif
760 }
761
762 #endif /* CONFIG_USER_ONLY */
763 #else /* TARGET_SPARC64 */
764
765 #ifdef CONFIG_USER_ONLY
766 void helper_ld_asi(int asi, int size, int sign)
767 {
768     uint64_t ret = 0;
769
770     if (asi < 0x80)
771         raise_exception(TT_PRIV_ACT);
772
773     switch (asi) {
774     case 0x80: // Primary
775     case 0x82: // Primary no-fault
776     case 0x88: // Primary LE
777     case 0x8a: // Primary no-fault LE
778         {
779             switch(size) {
780             case 1:
781                 ret = ldub_raw(T0);
782                 break;
783             case 2:
784                 ret = lduw_raw(T0 & ~1);
785                 break;
786             case 4:
787                 ret = ldl_raw(T0 & ~3);
788                 break;
789             default:
790             case 8:
791                 ret = ldq_raw(T0 & ~7);
792                 break;
793             }
794         }
795         break;
796     case 0x81: // Secondary
797     case 0x83: // Secondary no-fault
798     case 0x89: // Secondary LE
799     case 0x8b: // Secondary no-fault LE
800         // XXX
801         break;
802     default:
803         break;
804     }
805
806     /* Convert from little endian */
807     switch (asi) {
808     case 0x88: // Primary LE
809     case 0x89: // Secondary LE
810     case 0x8a: // Primary no-fault LE
811     case 0x8b: // Secondary no-fault LE
812         switch(size) {
813         case 2:
814             ret = bswap16(ret);
815             break;
816         case 4:
817             ret = bswap32(ret);
818             break;
819         case 8:
820             ret = bswap64(ret);
821             break;
822         default:
823             break;
824         }
825     default:
826         break;
827     }
828
829     /* Convert to signed number */
830     if (sign) {
831         switch(size) {
832         case 1:
833             ret = (int8_t) ret;
834             break;
835         case 2:
836             ret = (int16_t) ret;
837             break;
838         case 4:
839             ret = (int32_t) ret;
840             break;
841         default:
842             break;
843         }
844     }
845     T1 = ret;
846 }
847
848 void helper_st_asi(int asi, int size)
849 {
850     if (asi < 0x80)
851         raise_exception(TT_PRIV_ACT);
852
853     /* Convert to little endian */
854     switch (asi) {
855     case 0x88: // Primary LE
856     case 0x89: // Secondary LE
857         switch(size) {
858         case 2:
859             T0 = bswap16(T0);
860             break;
861         case 4:
862             T0 = bswap32(T0);
863             break;
864         case 8:
865             T0 = bswap64(T0);
866             break;
867         default:
868             break;
869         }
870     default:
871         break;
872     }
873
874     switch(asi) {
875     case 0x80: // Primary
876     case 0x88: // Primary LE
877         {
878             switch(size) {
879             case 1:
880                 stb_raw(T0, T1);
881                 break;
882             case 2:
883                 stw_raw(T0 & ~1, T1);
884                 break;
885             case 4:
886                 stl_raw(T0 & ~3, T1);
887                 break;
888             case 8:
889             default:
890                 stq_raw(T0 & ~7, T1);
891                 break;
892             }
893         }
894         break;
895     case 0x81: // Secondary
896     case 0x89: // Secondary LE
897         // XXX
898         return;
899
900     case 0x82: // Primary no-fault, RO
901     case 0x83: // Secondary no-fault, RO
902     case 0x8a: // Primary no-fault LE, RO
903     case 0x8b: // Secondary no-fault LE, RO
904     default:
905         do_unassigned_access(T0, 1, 0, 1);
906         return;
907     }
908 }
909
910 #else /* CONFIG_USER_ONLY */
911
912 void helper_ld_asi(int asi, int size, int sign)
913 {
914     uint64_t ret = 0;
915
916     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
917         || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
918         raise_exception(TT_PRIV_ACT);
919
920     switch (asi) {
921     case 0x10: // As if user primary
922     case 0x18: // As if user primary LE
923     case 0x80: // Primary
924     case 0x82: // Primary no-fault
925     case 0x88: // Primary LE
926     case 0x8a: // Primary no-fault LE
927         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
928             if (env->hpstate & HS_PRIV) {
929                 switch(size) {
930                 case 1:
931                     ret = ldub_hypv(T0);
932                     break;
933                 case 2:
934                     ret = lduw_hypv(T0 & ~1);
935                     break;
936                 case 4:
937                     ret = ldl_hypv(T0 & ~3);
938                     break;
939                 default:
940                 case 8:
941                     ret = ldq_hypv(T0 & ~7);
942                     break;
943                 }
944             } else {
945                 switch(size) {
946                 case 1:
947                     ret = ldub_kernel(T0);
948                     break;
949                 case 2:
950                     ret = lduw_kernel(T0 & ~1);
951                     break;
952                 case 4:
953                     ret = ldl_kernel(T0 & ~3);
954                     break;
955                 default:
956                 case 8:
957                     ret = ldq_kernel(T0 & ~7);
958                     break;
959                 }
960             }
961         } else {
962             switch(size) {
963             case 1:
964                 ret = ldub_user(T0);
965                 break;
966             case 2:
967                 ret = lduw_user(T0 & ~1);
968                 break;
969             case 4:
970                 ret = ldl_user(T0 & ~3);
971                 break;
972             default:
973             case 8:
974                 ret = ldq_user(T0 & ~7);
975                 break;
976             }
977         }
978         break;
979     case 0x14: // Bypass
980     case 0x15: // Bypass, non-cacheable
981     case 0x1c: // Bypass LE
982     case 0x1d: // Bypass, non-cacheable LE
983         {
984             switch(size) {
985             case 1:
986                 ret = ldub_phys(T0);
987                 break;
988             case 2:
989                 ret = lduw_phys(T0 & ~1);
990                 break;
991             case 4:
992                 ret = ldl_phys(T0 & ~3);
993                 break;
994             default:
995             case 8:
996                 ret = ldq_phys(T0 & ~7);
997                 break;
998             }
999             break;
1000         }
1001     case 0x04: // Nucleus
1002     case 0x0c: // Nucleus Little Endian (LE)
1003     case 0x11: // As if user secondary
1004     case 0x19: // As if user secondary LE
1005     case 0x24: // Nucleus quad LDD 128 bit atomic
1006     case 0x2c: // Nucleus quad LDD 128 bit atomic
1007     case 0x4a: // UPA config
1008     case 0x81: // Secondary
1009     case 0x83: // Secondary no-fault
1010     case 0x89: // Secondary LE
1011     case 0x8b: // Secondary no-fault LE
1012         // XXX
1013         break;
1014     case 0x45: // LSU
1015         ret = env->lsu;
1016         break;
1017     case 0x50: // I-MMU regs
1018         {
1019             int reg = (T0 >> 3) & 0xf;
1020
1021             ret = env->immuregs[reg];
1022             break;
1023         }
1024     case 0x51: // I-MMU 8k TSB pointer
1025     case 0x52: // I-MMU 64k TSB pointer
1026     case 0x55: // I-MMU data access
1027         // XXX
1028         break;
1029     case 0x56: // I-MMU tag read
1030         {
1031             unsigned int i;
1032
1033             for (i = 0; i < 64; i++) {
1034                 // Valid, ctx match, vaddr match
1035                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1036                     env->itlb_tag[i] == T0) {
1037                     ret = env->itlb_tag[i];
1038                     break;
1039                 }
1040             }
1041             break;
1042         }
1043     case 0x58: // D-MMU regs
1044         {
1045             int reg = (T0 >> 3) & 0xf;
1046
1047             ret = env->dmmuregs[reg];
1048             break;
1049         }
1050     case 0x5e: // D-MMU tag read
1051         {
1052             unsigned int i;
1053
1054             for (i = 0; i < 64; i++) {
1055                 // Valid, ctx match, vaddr match
1056                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1057                     env->dtlb_tag[i] == T0) {
1058                     ret = env->dtlb_tag[i];
1059                     break;
1060                 }
1061             }
1062             break;
1063         }
1064     case 0x59: // D-MMU 8k TSB pointer
1065     case 0x5a: // D-MMU 64k TSB pointer
1066     case 0x5b: // D-MMU data pointer
1067     case 0x5d: // D-MMU data access
1068     case 0x48: // Interrupt dispatch, RO
1069     case 0x49: // Interrupt data receive
1070     case 0x7f: // Incoming interrupt vector, RO
1071         // XXX
1072         break;
1073     case 0x54: // I-MMU data in, WO
1074     case 0x57: // I-MMU demap, WO
1075     case 0x5c: // D-MMU data in, WO
1076     case 0x5f: // D-MMU demap, WO
1077     case 0x77: // Interrupt vector, WO
1078     default:
1079         do_unassigned_access(T0, 0, 0, 1);
1080         ret = 0;
1081         break;
1082     }
1083
1084     /* Convert from little endian */
1085     switch (asi) {
1086     case 0x0c: // Nucleus Little Endian (LE)
1087     case 0x18: // As if user primary LE
1088     case 0x19: // As if user secondary LE
1089     case 0x1c: // Bypass LE
1090     case 0x1d: // Bypass, non-cacheable LE
1091     case 0x88: // Primary LE
1092     case 0x89: // Secondary LE
1093     case 0x8a: // Primary no-fault LE
1094     case 0x8b: // Secondary no-fault LE
1095         switch(size) {
1096         case 2:
1097             ret = bswap16(ret);
1098             break;
1099         case 4:
1100             ret = bswap32(ret);
1101             break;
1102         case 8:
1103             ret = bswap64(ret);
1104             break;
1105         default:
1106             break;
1107         }
1108     default:
1109         break;
1110     }
1111
1112     /* Convert to signed number */
1113     if (sign) {
1114         switch(size) {
1115         case 1:
1116             ret = (int8_t) ret;
1117             break;
1118         case 2:
1119             ret = (int16_t) ret;
1120             break;
1121         case 4:
1122             ret = (int32_t) ret;
1123             break;
1124         default:
1125             break;
1126         }
1127     }
1128     T1 = ret;
1129 }
1130
1131 void helper_st_asi(int asi, int size)
1132 {
1133     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1134         || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1135         raise_exception(TT_PRIV_ACT);
1136
1137     /* Convert to little endian */
1138     switch (asi) {
1139     case 0x0c: // Nucleus Little Endian (LE)
1140     case 0x18: // As if user primary LE
1141     case 0x19: // As if user secondary LE
1142     case 0x1c: // Bypass LE
1143     case 0x1d: // Bypass, non-cacheable LE
1144     case 0x88: // Primary LE
1145     case 0x89: // Secondary LE
1146         switch(size) {
1147         case 2:
1148             T0 = bswap16(T0);
1149             break;
1150         case 4:
1151             T0 = bswap32(T0);
1152             break;
1153         case 8:
1154             T0 = bswap64(T0);
1155             break;
1156         default:
1157             break;
1158         }
1159     default:
1160         break;
1161     }
1162
1163     switch(asi) {
1164     case 0x10: // As if user primary
1165     case 0x18: // As if user primary LE
1166     case 0x80: // Primary
1167     case 0x88: // Primary LE
1168         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1169             if (env->hpstate & HS_PRIV) {
1170                 switch(size) {
1171                 case 1:
1172                     stb_hypv(T0, T1);
1173                     break;
1174                 case 2:
1175                     stw_hypv(T0 & ~1, T1);
1176                     break;
1177                 case 4:
1178                     stl_hypv(T0 & ~3, T1);
1179                     break;
1180                 case 8:
1181                 default:
1182                     stq_hypv(T0 & ~7, T1);
1183                     break;
1184                 }
1185             } else {
1186                 switch(size) {
1187                 case 1:
1188                     stb_kernel(T0, T1);
1189                     break;
1190                 case 2:
1191                     stw_kernel(T0 & ~1, T1);
1192                     break;
1193                 case 4:
1194                     stl_kernel(T0 & ~3, T1);
1195                     break;
1196                 case 8:
1197                 default:
1198                     stq_kernel(T0 & ~7, T1);
1199                     break;
1200                 }
1201             }
1202         } else {
1203             switch(size) {
1204             case 1:
1205                 stb_user(T0, T1);
1206                 break;
1207             case 2:
1208                 stw_user(T0 & ~1, T1);
1209                 break;
1210             case 4:
1211                 stl_user(T0 & ~3, T1);
1212                 break;
1213             case 8:
1214             default:
1215                 stq_user(T0 & ~7, T1);
1216                 break;
1217             }
1218         }
1219         break;
1220     case 0x14: // Bypass
1221     case 0x15: // Bypass, non-cacheable
1222     case 0x1c: // Bypass LE
1223     case 0x1d: // Bypass, non-cacheable LE
1224         {
1225             switch(size) {
1226             case 1:
1227                 stb_phys(T0, T1);
1228                 break;
1229             case 2:
1230                 stw_phys(T0 & ~1, T1);
1231                 break;
1232             case 4:
1233                 stl_phys(T0 & ~3, T1);
1234                 break;
1235             case 8:
1236             default:
1237                 stq_phys(T0 & ~7, T1);
1238                 break;
1239             }
1240         }
1241         return;
1242     case 0x04: // Nucleus
1243     case 0x0c: // Nucleus Little Endian (LE)
1244     case 0x11: // As if user secondary
1245     case 0x19: // As if user secondary LE
1246     case 0x24: // Nucleus quad LDD 128 bit atomic
1247     case 0x2c: // Nucleus quad LDD 128 bit atomic
1248     case 0x4a: // UPA config
1249     case 0x81: // Secondary
1250     case 0x89: // Secondary LE
1251         // XXX
1252         return;
1253     case 0x45: // LSU
1254         {
1255             uint64_t oldreg;
1256
1257             oldreg = env->lsu;
1258             env->lsu = T1 & (DMMU_E | IMMU_E);
1259             // Mappings generated during D/I MMU disabled mode are
1260             // invalid in normal mode
1261             if (oldreg != env->lsu) {
1262                 DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
1263 #ifdef DEBUG_MMU
1264                 dump_mmu(env);
1265 #endif
1266                 tlb_flush(env, 1);
1267             }
1268             return;
1269         }
1270     case 0x50: // I-MMU regs
1271         {
1272             int reg = (T0 >> 3) & 0xf;
1273             uint64_t oldreg;
1274
1275             oldreg = env->immuregs[reg];
1276             switch(reg) {
1277             case 0: // RO
1278             case 4:
1279                 return;
1280             case 1: // Not in I-MMU
1281             case 2:
1282             case 7:
1283             case 8:
1284                 return;
1285             case 3: // SFSR
1286                 if ((T1 & 1) == 0)
1287                     T1 = 0; // Clear SFSR
1288                 break;
1289             case 5: // TSB access
1290             case 6: // Tag access
1291             default:
1292                 break;
1293             }
1294             env->immuregs[reg] = T1;
1295             if (oldreg != env->immuregs[reg]) {
1296                 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
1297             }
1298 #ifdef DEBUG_MMU
1299             dump_mmu(env);
1300 #endif
1301             return;
1302         }
1303     case 0x54: // I-MMU data in
1304         {
1305             unsigned int i;
1306
1307             // Try finding an invalid entry
1308             for (i = 0; i < 64; i++) {
1309                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
1310                     env->itlb_tag[i] = env->immuregs[6];
1311                     env->itlb_tte[i] = T1;
1312                     return;
1313                 }
1314             }
1315             // Try finding an unlocked entry
1316             for (i = 0; i < 64; i++) {
1317                 if ((env->itlb_tte[i] & 0x40) == 0) {
1318                     env->itlb_tag[i] = env->immuregs[6];
1319                     env->itlb_tte[i] = T1;
1320                     return;
1321                 }
1322             }
1323             // error state?
1324             return;
1325         }
1326     case 0x55: // I-MMU data access
1327         {
1328             unsigned int i = (T0 >> 3) & 0x3f;
1329
1330             env->itlb_tag[i] = env->immuregs[6];
1331             env->itlb_tte[i] = T1;
1332             return;
1333         }
1334     case 0x57: // I-MMU demap
1335         // XXX
1336         return;
1337     case 0x58: // D-MMU regs
1338         {
1339             int reg = (T0 >> 3) & 0xf;
1340             uint64_t oldreg;
1341
1342             oldreg = env->dmmuregs[reg];
1343             switch(reg) {
1344             case 0: // RO
1345             case 4:
1346                 return;
1347             case 3: // SFSR
1348                 if ((T1 & 1) == 0) {
1349                     T1 = 0; // Clear SFSR, Fault address
1350                     env->dmmuregs[4] = 0;
1351                 }
1352                 env->dmmuregs[reg] = T1;
1353                 break;
1354             case 1: // Primary context
1355             case 2: // Secondary context
1356             case 5: // TSB access
1357             case 6: // Tag access
1358             case 7: // Virtual Watchpoint
1359             case 8: // Physical Watchpoint
1360             default:
1361                 break;
1362             }
1363             env->dmmuregs[reg] = T1;
1364             if (oldreg != env->dmmuregs[reg]) {
1365                 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
1366             }
1367 #ifdef DEBUG_MMU
1368             dump_mmu(env);
1369 #endif
1370             return;
1371         }
1372     case 0x5c: // D-MMU data in
1373         {
1374             unsigned int i;
1375
1376             // Try finding an invalid entry
1377             for (i = 0; i < 64; i++) {
1378                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
1379                     env->dtlb_tag[i] = env->dmmuregs[6];
1380                     env->dtlb_tte[i] = T1;
1381                     return;
1382                 }
1383             }
1384             // Try finding an unlocked entry
1385             for (i = 0; i < 64; i++) {
1386                 if ((env->dtlb_tte[i] & 0x40) == 0) {
1387                     env->dtlb_tag[i] = env->dmmuregs[6];
1388                     env->dtlb_tte[i] = T1;
1389                     return;
1390                 }
1391             }
1392             // error state?
1393             return;
1394         }
1395     case 0x5d: // D-MMU data access
1396         {
1397             unsigned int i = (T0 >> 3) & 0x3f;
1398
1399             env->dtlb_tag[i] = env->dmmuregs[6];
1400             env->dtlb_tte[i] = T1;
1401             return;
1402         }
1403     case 0x5f: // D-MMU demap
1404     case 0x49: // Interrupt data receive
1405         // XXX
1406         return;
1407     case 0x51: // I-MMU 8k TSB pointer, RO
1408     case 0x52: // I-MMU 64k TSB pointer, RO
1409     case 0x56: // I-MMU tag read, RO
1410     case 0x59: // D-MMU 8k TSB pointer, RO
1411     case 0x5a: // D-MMU 64k TSB pointer, RO
1412     case 0x5b: // D-MMU data pointer, RO
1413     case 0x5e: // D-MMU tag read, RO
1414     case 0x48: // Interrupt dispatch, RO
1415     case 0x7f: // Incoming interrupt vector, RO
1416     case 0x82: // Primary no-fault, RO
1417     case 0x83: // Secondary no-fault, RO
1418     case 0x8a: // Primary no-fault LE, RO
1419     case 0x8b: // Secondary no-fault LE, RO
1420     default:
1421         do_unassigned_access(T0, 1, 0, 1);
1422         return;
1423     }
1424 }
1425 #endif /* CONFIG_USER_ONLY */
1426
1427 void helper_ldf_asi(int asi, int size, int rd)
1428 {
1429     target_ulong tmp_T0 = T0, tmp_T1 = T1;
1430     unsigned int i;
1431
1432     switch (asi) {
1433     case 0xf0: // Block load primary
1434     case 0xf1: // Block load secondary
1435     case 0xf8: // Block load primary LE
1436     case 0xf9: // Block load secondary LE
1437         if (rd & 7) {
1438             raise_exception(TT_ILL_INSN);
1439             return;
1440         }
1441         if (T0 & 0x3f) {
1442             raise_exception(TT_UNALIGNED);
1443             return;
1444         }
1445         for (i = 0; i < 16; i++) {
1446             helper_ld_asi(asi & 0x8f, 4, 0);
1447             *(uint32_t *)&env->fpr[rd++] = T1;
1448             T0 += 4;
1449         }
1450         T0 = tmp_T0;
1451         T1 = tmp_T1;
1452
1453         return;
1454     default:
1455         break;
1456     }
1457
1458     helper_ld_asi(asi, size, 0);
1459     switch(size) {
1460     default:
1461     case 4:
1462         *((uint32_t *)&FT0) = T1;
1463         break;
1464     case 8:
1465         *((int64_t *)&DT0) = T1;
1466         break;
1467 #if defined(CONFIG_USER_ONLY)
1468     case 16:
1469         // XXX
1470         break;
1471 #endif
1472     }
1473     T1 = tmp_T1;
1474 }
1475
1476 void helper_stf_asi(int asi, int size, int rd)
1477 {
1478     target_ulong tmp_T0 = T0, tmp_T1 = T1;
1479     unsigned int i;
1480
1481     switch (asi) {
1482     case 0xf0: // Block store primary
1483     case 0xf1: // Block store secondary
1484     case 0xf8: // Block store primary LE
1485     case 0xf9: // Block store secondary LE
1486         if (rd & 7) {
1487             raise_exception(TT_ILL_INSN);
1488             return;
1489         }
1490         if (T0 & 0x3f) {
1491             raise_exception(TT_UNALIGNED);
1492             return;
1493         }
1494         for (i = 0; i < 16; i++) {
1495             T1 = *(uint32_t *)&env->fpr[rd++];
1496             helper_st_asi(asi & 0x8f, 4);
1497             T0 += 4;
1498         }
1499         T0 = tmp_T0;
1500         T1 = tmp_T1;
1501
1502         return;
1503     default:
1504         break;
1505     }
1506
1507     switch(size) {
1508     default:
1509     case 4:
1510         T1 = *((uint32_t *)&FT0);
1511         break;
1512     case 8:
1513         T1 = *((int64_t *)&DT0);
1514         break;
1515 #if defined(CONFIG_USER_ONLY)
1516     case 16:
1517         // XXX
1518         break;
1519 #endif
1520     }
1521     helper_st_asi(asi, size);
1522     T1 = tmp_T1;
1523 }
1524
1525 #endif /* TARGET_SPARC64 */
1526
1527 #ifndef TARGET_SPARC64
1528 void helper_rett()
1529 {
1530     unsigned int cwp;
1531
1532     if (env->psret == 1)
1533         raise_exception(TT_ILL_INSN);
1534
1535     env->psret = 1;
1536     cwp = (env->cwp + 1) & (NWINDOWS - 1);
1537     if (env->wim & (1 << cwp)) {
1538         raise_exception(TT_WIN_UNF);
1539     }
1540     set_cwp(cwp);
1541     env->psrs = env->psrps;
1542 }
1543 #endif
1544
1545 void helper_ldfsr(void)
1546 {
1547     int rnd_mode;
1548     switch (env->fsr & FSR_RD_MASK) {
1549     case FSR_RD_NEAREST:
1550         rnd_mode = float_round_nearest_even;
1551         break;
1552     default:
1553     case FSR_RD_ZERO:
1554         rnd_mode = float_round_to_zero;
1555         break;
1556     case FSR_RD_POS:
1557         rnd_mode = float_round_up;
1558         break;
1559     case FSR_RD_NEG:
1560         rnd_mode = float_round_down;
1561         break;
1562     }
1563     set_float_rounding_mode(rnd_mode, &env->fp_status);
1564 }
1565
1566 void helper_debug()
1567 {
1568     env->exception_index = EXCP_DEBUG;
1569     cpu_loop_exit();
1570 }
1571
1572 #ifndef TARGET_SPARC64
1573 void do_wrpsr()
1574 {
1575     if ((T0 & PSR_CWP) >= NWINDOWS)
1576         raise_exception(TT_ILL_INSN);
1577     else
1578         PUT_PSR(env, T0);
1579 }
1580
1581 void do_rdpsr()
1582 {
1583     T0 = GET_PSR(env);
1584 }
1585
1586 #else
1587
1588 void do_popc()
1589 {
1590     T0 = ctpop64(T1);
1591 }
1592
1593 static inline uint64_t *get_gregset(uint64_t pstate)
1594 {
1595     switch (pstate) {
1596     default:
1597     case 0:
1598         return env->bgregs;
1599     case PS_AG:
1600         return env->agregs;
1601     case PS_MG:
1602         return env->mgregs;
1603     case PS_IG:
1604         return env->igregs;
1605     }
1606 }
1607
1608 static inline void change_pstate(uint64_t new_pstate)
1609 {
1610     uint64_t pstate_regs, new_pstate_regs;
1611     uint64_t *src, *dst;
1612
1613     pstate_regs = env->pstate & 0xc01;
1614     new_pstate_regs = new_pstate & 0xc01;
1615     if (new_pstate_regs != pstate_regs) {
1616         // Switch global register bank
1617         src = get_gregset(new_pstate_regs);
1618         dst = get_gregset(pstate_regs);
1619         memcpy32(dst, env->gregs);
1620         memcpy32(env->gregs, src);
1621     }
1622     env->pstate = new_pstate;
1623 }
1624
1625 void do_wrpstate(void)
1626 {
1627     change_pstate(T0 & 0xf3f);
1628 }
1629
1630 void do_done(void)
1631 {
1632     env->tl--;
1633     env->pc = env->tnpc[env->tl];
1634     env->npc = env->tnpc[env->tl] + 4;
1635     PUT_CCR(env, env->tstate[env->tl] >> 32);
1636     env->asi = (env->tstate[env->tl] >> 24) & 0xff;
1637     change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
1638     PUT_CWP64(env, env->tstate[env->tl] & 0xff);
1639 }
1640
1641 void do_retry(void)
1642 {
1643     env->tl--;
1644     env->pc = env->tpc[env->tl];
1645     env->npc = env->tnpc[env->tl];
1646     PUT_CCR(env, env->tstate[env->tl] >> 32);
1647     env->asi = (env->tstate[env->tl] >> 24) & 0xff;
1648     change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
1649     PUT_CWP64(env, env->tstate[env->tl] & 0xff);
1650 }
1651 #endif
1652
1653 void set_cwp(int new_cwp)
1654 {
1655     /* put the modified wrap registers at their proper location */
1656     if (env->cwp == (NWINDOWS - 1))
1657         memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
1658     env->cwp = new_cwp;
1659     /* put the wrap registers at their temporary location */
1660     if (new_cwp == (NWINDOWS - 1))
1661         memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
1662     env->regwptr = env->regbase + (new_cwp * 16);
1663     REGWPTR = env->regwptr;
1664 }
1665
1666 void cpu_set_cwp(CPUState *env1, int new_cwp)
1667 {
1668     CPUState *saved_env;
1669 #ifdef reg_REGWPTR
1670     target_ulong *saved_regwptr;
1671 #endif
1672
1673     saved_env = env;
1674 #ifdef reg_REGWPTR
1675     saved_regwptr = REGWPTR;
1676 #endif
1677     env = env1;
1678     set_cwp(new_cwp);
1679     env = saved_env;
1680 #ifdef reg_REGWPTR
1681     REGWPTR = saved_regwptr;
1682 #endif
1683 }
1684
1685 #ifdef TARGET_SPARC64
1686 void do_interrupt(int intno)
1687 {
1688 #ifdef DEBUG_PCALL
1689     if (loglevel & CPU_LOG_INT) {
1690         static int count;
1691         fprintf(logfile, "%6d: v=%04x pc=%016" PRIx64 " npc=%016" PRIx64 " SP=%016" PRIx64 "\n",
1692                 count, intno,
1693                 env->pc,
1694                 env->npc, env->regwptr[6]);
1695         cpu_dump_state(env, logfile, fprintf, 0);
1696 #if 0
1697         {
1698             int i;
1699             uint8_t *ptr;
1700
1701             fprintf(logfile, "       code=");
1702             ptr = (uint8_t *)env->pc;
1703             for(i = 0; i < 16; i++) {
1704                 fprintf(logfile, " %02x", ldub(ptr + i));
1705             }
1706             fprintf(logfile, "\n");
1707         }
1708 #endif
1709         count++;
1710     }
1711 #endif
1712 #if !defined(CONFIG_USER_ONLY)
1713     if (env->tl == MAXTL) {
1714         cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
1715         return;
1716     }
1717 #endif
1718     env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
1719         ((env->pstate & 0xf3f) << 8) | GET_CWP64(env);
1720     env->tpc[env->tl] = env->pc;
1721     env->tnpc[env->tl] = env->npc;
1722     env->tt[env->tl] = intno;
1723     change_pstate(PS_PEF | PS_PRIV | PS_AG);
1724
1725     if (intno == TT_CLRWIN)
1726         set_cwp((env->cwp - 1) & (NWINDOWS - 1));
1727     else if ((intno & 0x1c0) == TT_SPILL)
1728         set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1));
1729     else if ((intno & 0x1c0) == TT_FILL)
1730         set_cwp((env->cwp + 1) & (NWINDOWS - 1));
1731     env->tbr &= ~0x7fffULL;
1732     env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
1733     if (env->tl < MAXTL - 1) {
1734         env->tl++;
1735     } else {
1736         env->pstate |= PS_RED;
1737         if (env->tl != MAXTL)
1738             env->tl++;
1739     }
1740     env->pc = env->tbr;
1741     env->npc = env->pc + 4;
1742     env->exception_index = 0;
1743 }
1744 #else
1745 void do_interrupt(int intno)
1746 {
1747     int cwp;
1748
1749 #ifdef DEBUG_PCALL
1750     if (loglevel & CPU_LOG_INT) {
1751         static int count;
1752         fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
1753                 count, intno,
1754                 env->pc,
1755                 env->npc, env->regwptr[6]);
1756         cpu_dump_state(env, logfile, fprintf, 0);
1757 #if 0
1758         {
1759             int i;
1760             uint8_t *ptr;
1761
1762             fprintf(logfile, "       code=");
1763             ptr = (uint8_t *)env->pc;
1764             for(i = 0; i < 16; i++) {
1765                 fprintf(logfile, " %02x", ldub(ptr + i));
1766             }
1767             fprintf(logfile, "\n");
1768         }
1769 #endif
1770         count++;
1771     }
1772 #endif
1773 #if !defined(CONFIG_USER_ONLY)
1774     if (env->psret == 0) {
1775         cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
1776         return;
1777     }
1778 #endif
1779     env->psret = 0;
1780     cwp = (env->cwp - 1) & (NWINDOWS - 1);
1781     set_cwp(cwp);
1782     env->regwptr[9] = env->pc;
1783     env->regwptr[10] = env->npc;
1784     env->psrps = env->psrs;
1785     env->psrs = 1;
1786     env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
1787     env->pc = env->tbr;
1788     env->npc = env->pc + 4;
1789     env->exception_index = 0;
1790 }
1791 #endif
1792
1793 #if !defined(CONFIG_USER_ONLY)
1794
1795 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1796                                 void *retaddr);
1797
1798 #define MMUSUFFIX _mmu
1799 #define ALIGNED_ONLY
1800 #ifdef __s390__
1801 # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
1802 #else
1803 # define GETPC() (__builtin_return_address(0))
1804 #endif
1805
1806 #define SHIFT 0
1807 #include "softmmu_template.h"
1808
1809 #define SHIFT 1
1810 #include "softmmu_template.h"
1811
1812 #define SHIFT 2
1813 #include "softmmu_template.h"
1814
1815 #define SHIFT 3
1816 #include "softmmu_template.h"
1817
1818 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1819                                 void *retaddr)
1820 {
1821 #ifdef DEBUG_UNALIGNED
1822     printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
1823 #endif
1824     raise_exception(TT_UNALIGNED);
1825 }
1826
1827 /* try to fill the TLB and return an exception if error. If retaddr is
1828    NULL, it means that the function was called in C code (i.e. not
1829    from generated code or from helper.c) */
1830 /* XXX: fix it to restore all registers */
1831 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1832 {
1833     TranslationBlock *tb;
1834     int ret;
1835     unsigned long pc;
1836     CPUState *saved_env;
1837
1838     /* XXX: hack to restore env in all cases, even if not called from
1839        generated code */
1840     saved_env = env;
1841     env = cpu_single_env;
1842
1843     ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1844     if (ret) {
1845         if (retaddr) {
1846             /* now we have a real cpu fault */
1847             pc = (unsigned long)retaddr;
1848             tb = tb_find_pc(pc);
1849             if (tb) {
1850                 /* the PC is inside the translated code. It means that we have
1851                    a virtual CPU fault */
1852                 cpu_restore_state(tb, env, pc, (void *)T2);
1853             }
1854         }
1855         cpu_loop_exit();
1856     }
1857     env = saved_env;
1858 }
1859
1860 #endif
1861
1862 #ifndef TARGET_SPARC64
1863 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1864                           int is_asi)
1865 {
1866     CPUState *saved_env;
1867
1868     /* XXX: hack to restore env in all cases, even if not called from
1869        generated code */
1870     saved_env = env;
1871     env = cpu_single_env;
1872 #ifdef DEBUG_UNASSIGNED
1873     if (is_asi)
1874         printf("Unassigned mem %s access to " TARGET_FMT_plx " asi 0x%02x from "
1875                TARGET_FMT_lx "\n",
1876                is_exec ? "exec" : is_write ? "write" : "read", addr, is_asi,
1877                env->pc);
1878     else
1879         printf("Unassigned mem %s access to " TARGET_FMT_plx " from "
1880                TARGET_FMT_lx "\n",
1881                is_exec ? "exec" : is_write ? "write" : "read", addr, env->pc);
1882 #endif
1883     if (env->mmuregs[3]) /* Fault status register */
1884         env->mmuregs[3] = 1; /* overflow (not read before another fault) */
1885     if (is_asi)
1886         env->mmuregs[3] |= 1 << 16;
1887     if (env->psrs)
1888         env->mmuregs[3] |= 1 << 5;
1889     if (is_exec)
1890         env->mmuregs[3] |= 1 << 6;
1891     if (is_write)
1892         env->mmuregs[3] |= 1 << 7;
1893     env->mmuregs[3] |= (5 << 2) | 2;
1894     env->mmuregs[4] = addr; /* Fault address register */
1895     if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
1896         if (is_exec)
1897             raise_exception(TT_CODE_ACCESS);
1898         else
1899             raise_exception(TT_DATA_ACCESS);
1900     }
1901     env = saved_env;
1902 }
1903 #else
1904 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1905                           int is_asi)
1906 {
1907 #ifdef DEBUG_UNASSIGNED
1908     CPUState *saved_env;
1909
1910     /* XXX: hack to restore env in all cases, even if not called from
1911        generated code */
1912     saved_env = env;
1913     env = cpu_single_env;
1914     printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n",
1915            addr, env->pc);
1916     env = saved_env;
1917 #endif
1918     if (is_exec)
1919         raise_exception(TT_CODE_ACCESS);
1920     else
1921         raise_exception(TT_DATA_ACCESS);
1922 }
1923 #endif
1924