Enable faults for unassigned memory accesses and unimplemented ASIs
[qemu] / target-sparc / op_helper.c
1 #include "exec.h"
2
3 //#define DEBUG_PCALL
4 //#define DEBUG_MMU
5 //#define DEBUG_UNALIGNED
6 //#define DEBUG_UNASSIGNED
7
8 void raise_exception(int tt)
9 {
10     env->exception_index = tt;
11     cpu_loop_exit();
12 }   
13
14 void check_ieee_exceptions()
15 {
16      T0 = get_float_exception_flags(&env->fp_status);
17      if (T0)
18      {
19         /* Copy IEEE 754 flags into FSR */
20         if (T0 & float_flag_invalid)
21             env->fsr |= FSR_NVC;
22         if (T0 & float_flag_overflow)
23             env->fsr |= FSR_OFC;
24         if (T0 & float_flag_underflow)
25             env->fsr |= FSR_UFC;
26         if (T0 & float_flag_divbyzero)
27             env->fsr |= FSR_DZC;
28         if (T0 & float_flag_inexact)
29             env->fsr |= FSR_NXC;
30
31         if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23))
32         {
33             /* Unmasked exception, generate a trap */
34             env->fsr |= FSR_FTT_IEEE_EXCP;
35             raise_exception(TT_FP_EXCP);
36         }
37         else
38         {
39             /* Accumulate exceptions */
40             env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
41         }
42      }
43 }
44
45 #ifdef USE_INT_TO_FLOAT_HELPERS
46 void do_fitos(void)
47 {
48     set_float_exception_flags(0, &env->fp_status);
49     FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
50     check_ieee_exceptions();
51 }
52
53 void do_fitod(void)
54 {
55     DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
56 }
57 #endif
58
59 void do_fabss(void)
60 {
61     FT0 = float32_abs(FT1);
62 }
63
64 #ifdef TARGET_SPARC64
65 void do_fabsd(void)
66 {
67     DT0 = float64_abs(DT1);
68 }
69 #endif
70
71 void do_fsqrts(void)
72 {
73     set_float_exception_flags(0, &env->fp_status);
74     FT0 = float32_sqrt(FT1, &env->fp_status);
75     check_ieee_exceptions();
76 }
77
78 void do_fsqrtd(void)
79 {
80     set_float_exception_flags(0, &env->fp_status);
81     DT0 = float64_sqrt(DT1, &env->fp_status);
82     check_ieee_exceptions();
83 }
84
85 #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
86     void glue(do_, name) (void)                                         \
87     {                                                                   \
88         env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
89         switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
90         case float_relation_unordered:                                  \
91             T0 = (FSR_FCC1 | FSR_FCC0) << FS;                           \
92             if ((env->fsr & FSR_NVM) || TRAP) {                         \
93                 env->fsr |= T0;                                         \
94                 env->fsr |= FSR_NVC;                                    \
95                 env->fsr |= FSR_FTT_IEEE_EXCP;                          \
96                 raise_exception(TT_FP_EXCP);                            \
97             } else {                                                    \
98                 env->fsr |= FSR_NVA;                                    \
99             }                                                           \
100             break;                                                      \
101         case float_relation_less:                                       \
102             T0 = FSR_FCC0 << FS;                                        \
103             break;                                                      \
104         case float_relation_greater:                                    \
105             T0 = FSR_FCC1 << FS;                                        \
106             break;                                                      \
107         default:                                                        \
108             T0 = 0;                                                     \
109             break;                                                      \
110         }                                                               \
111         env->fsr |= T0;                                                 \
112     }
113
114 GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
115 GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
116
117 GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
118 GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
119
120 #ifdef TARGET_SPARC64
121 GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
122 GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
123
124 GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
125 GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
126
127 GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
128 GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
129
130 GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
131 GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
132
133 GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
134 GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
135
136 GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
137 GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
138 #endif
139
140 #if defined(CONFIG_USER_ONLY) 
141 void helper_ld_asi(int asi, int size, int sign)
142 {
143 }
144
145 void helper_st_asi(int asi, int size, int sign)
146 {
147 }
148 #else
149 #ifndef TARGET_SPARC64
150 void helper_ld_asi(int asi, int size, int sign)
151 {
152     uint32_t ret = 0;
153
154     switch (asi) {
155     case 2: /* SuperSparc MXCC registers */
156         break;
157     case 3: /* MMU probe */
158         {
159             int mmulev;
160
161             mmulev = (T0 >> 8) & 15;
162             if (mmulev > 4)
163                 ret = 0;
164             else {
165                 ret = mmu_probe(env, T0, mmulev);
166                 //bswap32s(&ret);
167             }
168 #ifdef DEBUG_MMU
169             printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
170 #endif
171         }
172         break;
173     case 4: /* read MMU regs */
174         {
175             int reg = (T0 >> 8) & 0xf;
176             
177             ret = env->mmuregs[reg];
178             if (reg == 3) /* Fault status cleared on read */
179                 env->mmuregs[reg] = 0;
180 #ifdef DEBUG_MMU
181             printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
182 #endif
183         }
184         break;
185     case 9: /* Supervisor code access */
186         switch(size) {
187         case 1:
188             ret = ldub_code(T0);
189             break;
190         case 2:
191             ret = lduw_code(T0 & ~1);
192             break;
193         default:
194         case 4:
195             ret = ldl_code(T0 & ~3);
196             break;
197         case 8:
198             ret = ldl_code(T0 & ~3);
199             T0 = ldl_code((T0 + 4) & ~3);
200             break;
201         }
202         break;
203     case 0xc: /* I-cache tag */
204     case 0xd: /* I-cache data */
205     case 0xe: /* D-cache tag */
206     case 0xf: /* D-cache data */
207         break;
208     case 0x20: /* MMU passthrough */
209         switch(size) {
210         case 1:
211             ret = ldub_phys(T0);
212             break;
213         case 2:
214             ret = lduw_phys(T0 & ~1);
215             break;
216         default:
217         case 4:
218             ret = ldl_phys(T0 & ~3);
219             break;
220         case 8:
221             ret = ldl_phys(T0 & ~3);
222             T0 = ldl_phys((T0 + 4) & ~3);
223             break;
224         }
225         break;
226     case 0x21 ... 0x2f: /* MMU passthrough, unassigned */
227     default:
228         do_unassigned_access(T0, 0, 0, 1);
229         ret = 0;
230         break;
231     }
232     T1 = ret;
233 }
234
235 void helper_st_asi(int asi, int size, int sign)
236 {
237     switch(asi) {
238     case 2: /* SuperSparc MXCC registers */
239         break;
240     case 3: /* MMU flush */
241         {
242             int mmulev;
243
244             mmulev = (T0 >> 8) & 15;
245 #ifdef DEBUG_MMU
246             printf("mmu flush level %d\n", mmulev);
247 #endif
248             switch (mmulev) {
249             case 0: // flush page
250                 tlb_flush_page(env, T0 & 0xfffff000);
251                 break;
252             case 1: // flush segment (256k)
253             case 2: // flush region (16M)
254             case 3: // flush context (4G)
255             case 4: // flush entire
256                 tlb_flush(env, 1);
257                 break;
258             default:
259                 break;
260             }
261 #ifdef DEBUG_MMU
262             dump_mmu(env);
263 #endif
264             return;
265         }
266     case 4: /* write MMU regs */
267         {
268             int reg = (T0 >> 8) & 0xf;
269             uint32_t oldreg;
270             
271             oldreg = env->mmuregs[reg];
272             switch(reg) {
273             case 0:
274                 env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
275                 env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
276                 // Mappings generated during no-fault mode or MMU
277                 // disabled mode are invalid in normal mode
278                 if (oldreg != env->mmuregs[reg])
279                     tlb_flush(env, 1);
280                 break;
281             case 2:
282                 env->mmuregs[reg] = T1;
283                 if (oldreg != env->mmuregs[reg]) {
284                     /* we flush when the MMU context changes because
285                        QEMU has no MMU context support */
286                     tlb_flush(env, 1);
287                 }
288                 break;
289             case 3:
290             case 4:
291                 break;
292             default:
293                 env->mmuregs[reg] = T1;
294                 break;
295             }
296 #ifdef DEBUG_MMU
297             if (oldreg != env->mmuregs[reg]) {
298                 printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
299             }
300             dump_mmu(env);
301 #endif
302             return;
303         }
304     case 0xc: /* I-cache tag */
305     case 0xd: /* I-cache data */
306     case 0xe: /* D-cache tag */
307     case 0xf: /* D-cache data */
308     case 0x10: /* I/D-cache flush page */
309     case 0x11: /* I/D-cache flush segment */
310     case 0x12: /* I/D-cache flush region */
311     case 0x13: /* I/D-cache flush context */
312     case 0x14: /* I/D-cache flush user */
313         break;
314     case 0x17: /* Block copy, sta access */
315         {
316             // value (T1) = src
317             // address (T0) = dst
318             // copy 32 bytes
319             unsigned int i;
320             uint32_t src = T1 & ~3, dst = T0 & ~3, temp;
321             
322             for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
323                 temp = ldl_kernel(src);
324                 stl_kernel(dst, temp);
325             }
326         }
327         return;
328     case 0x1f: /* Block fill, stda access */
329         {
330             // value (T1, T2)
331             // address (T0) = dst
332             // fill 32 bytes
333             unsigned int i;
334             uint32_t dst = T0 & 7;
335             uint64_t val;
336
337             val = (((uint64_t)T1) << 32) | T2;
338
339             for (i = 0; i < 32; i += 8, dst += 8)
340                 stq_kernel(dst, val);
341         }
342         return;
343     case 0x20: /* MMU passthrough */
344         {
345             switch(size) {
346             case 1:
347                 stb_phys(T0, T1);
348                 break;
349             case 2:
350                 stw_phys(T0 & ~1, T1);
351                 break;
352             case 4:
353             default:
354                 stl_phys(T0 & ~3, T1);
355                 break;
356             case 8:
357                 stl_phys(T0 & ~3, T1);
358                 stl_phys((T0 + 4) & ~3, T2);
359                 break;
360             }
361         }
362         return;
363     case 0x31: /* Ross RT620 I-cache flush */
364     case 0x36: /* I-cache flash clear */
365     case 0x37: /* D-cache flash clear */
366         break;
367     case 9: /* Supervisor code access, XXX */
368     case 0x21 ... 0x2f: /* MMU passthrough, unassigned */
369     default:
370         do_unassigned_access(T0, 1, 0, 1);
371         return;
372     }
373 }
374
375 #else
376
377 void helper_ld_asi(int asi, int size, int sign)
378 {
379     uint64_t ret = 0;
380
381     if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
382         raise_exception(TT_PRIV_ACT);
383
384     switch (asi) {
385     case 0x14: // Bypass
386     case 0x15: // Bypass, non-cacheable
387         {
388             switch(size) {
389             case 1:
390                 ret = ldub_phys(T0);
391                 break;
392             case 2:
393                 ret = lduw_phys(T0 & ~1);
394                 break;
395             case 4:
396                 ret = ldl_phys(T0 & ~3);
397                 break;
398             default:
399             case 8:
400                 ret = ldq_phys(T0 & ~7);
401                 break;
402             }
403             break;
404         }
405     case 0x04: // Nucleus
406     case 0x0c: // Nucleus Little Endian (LE)
407     case 0x10: // As if user primary
408     case 0x11: // As if user secondary
409     case 0x18: // As if user primary LE
410     case 0x19: // As if user secondary LE
411     case 0x1c: // Bypass LE
412     case 0x1d: // Bypass, non-cacheable LE
413     case 0x24: // Nucleus quad LDD 128 bit atomic
414     case 0x2c: // Nucleus quad LDD 128 bit atomic
415     case 0x4a: // UPA config
416     case 0x82: // Primary no-fault
417     case 0x83: // Secondary no-fault
418     case 0x88: // Primary LE
419     case 0x89: // Secondary LE
420     case 0x8a: // Primary no-fault LE
421     case 0x8b: // Secondary no-fault LE
422         // XXX
423         break;
424     case 0x45: // LSU
425         ret = env->lsu;
426         break;
427     case 0x50: // I-MMU regs
428         {
429             int reg = (T0 >> 3) & 0xf;
430
431             ret = env->immuregs[reg];
432             break;
433         }
434     case 0x51: // I-MMU 8k TSB pointer
435     case 0x52: // I-MMU 64k TSB pointer
436     case 0x55: // I-MMU data access
437         // XXX
438         break;
439     case 0x56: // I-MMU tag read
440         {
441             unsigned int i;
442             
443             for (i = 0; i < 64; i++) {
444                 // Valid, ctx match, vaddr match
445                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
446                     env->itlb_tag[i] == T0) {
447                     ret = env->itlb_tag[i];
448                     break;
449                 }
450             }
451             break;
452         }
453     case 0x58: // D-MMU regs
454         {
455             int reg = (T0 >> 3) & 0xf;
456
457             ret = env->dmmuregs[reg];
458             break;
459         }
460     case 0x5e: // D-MMU tag read
461         {
462             unsigned int i;
463             
464             for (i = 0; i < 64; i++) {
465                 // Valid, ctx match, vaddr match
466                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
467                     env->dtlb_tag[i] == T0) {
468                     ret = env->dtlb_tag[i];
469                     break;
470                 }
471             }
472             break;
473         }
474     case 0x59: // D-MMU 8k TSB pointer
475     case 0x5a: // D-MMU 64k TSB pointer
476     case 0x5b: // D-MMU data pointer
477     case 0x5d: // D-MMU data access
478     case 0x48: // Interrupt dispatch, RO
479     case 0x49: // Interrupt data receive
480     case 0x7f: // Incoming interrupt vector, RO
481         // XXX
482         break;
483     case 0x54: // I-MMU data in, WO
484     case 0x57: // I-MMU demap, WO
485     case 0x5c: // D-MMU data in, WO
486     case 0x5f: // D-MMU demap, WO
487     case 0x77: // Interrupt vector, WO
488     default:
489         do_unassigned_access(T0, 0, 0, 1);
490         ret = 0;
491         break;
492     }
493     T1 = ret;
494 }
495
496 void helper_st_asi(int asi, int size, int sign)
497 {
498     if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
499         raise_exception(TT_PRIV_ACT);
500
501     switch(asi) {
502     case 0x14: // Bypass
503     case 0x15: // Bypass, non-cacheable
504         {
505             switch(size) {
506             case 1:
507                 stb_phys(T0, T1);
508                 break;
509             case 2:
510                 stw_phys(T0 & ~1, T1);
511                 break;
512             case 4:
513                 stl_phys(T0 & ~3, T1);
514                 break;
515             case 8:
516             default:
517                 stq_phys(T0 & ~7, T1);
518                 break;
519             }
520         }
521         return;
522     case 0x04: // Nucleus
523     case 0x0c: // Nucleus Little Endian (LE)
524     case 0x10: // As if user primary
525     case 0x11: // As if user secondary
526     case 0x18: // As if user primary LE
527     case 0x19: // As if user secondary LE
528     case 0x1c: // Bypass LE
529     case 0x1d: // Bypass, non-cacheable LE
530     case 0x24: // Nucleus quad LDD 128 bit atomic
531     case 0x2c: // Nucleus quad LDD 128 bit atomic
532     case 0x4a: // UPA config
533     case 0x88: // Primary LE
534     case 0x89: // Secondary LE
535         // XXX
536         return;
537     case 0x45: // LSU
538         {
539             uint64_t oldreg;
540
541             oldreg = env->lsu;
542             env->lsu = T1 & (DMMU_E | IMMU_E);
543             // Mappings generated during D/I MMU disabled mode are
544             // invalid in normal mode
545             if (oldreg != env->lsu) {
546 #ifdef DEBUG_MMU
547                 printf("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
548                 dump_mmu(env);
549 #endif
550                 tlb_flush(env, 1);
551             }
552             return;
553         }
554     case 0x50: // I-MMU regs
555         {
556             int reg = (T0 >> 3) & 0xf;
557             uint64_t oldreg;
558             
559             oldreg = env->immuregs[reg];
560             switch(reg) {
561             case 0: // RO
562             case 4:
563                 return;
564             case 1: // Not in I-MMU
565             case 2:
566             case 7:
567             case 8:
568                 return;
569             case 3: // SFSR
570                 if ((T1 & 1) == 0)
571                     T1 = 0; // Clear SFSR
572                 break;
573             case 5: // TSB access
574             case 6: // Tag access
575             default:
576                 break;
577             }
578             env->immuregs[reg] = T1;
579 #ifdef DEBUG_MMU
580             if (oldreg != env->immuregs[reg]) {
581                 printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
582             }
583             dump_mmu(env);
584 #endif
585             return;
586         }
587     case 0x54: // I-MMU data in
588         {
589             unsigned int i;
590
591             // Try finding an invalid entry
592             for (i = 0; i < 64; i++) {
593                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
594                     env->itlb_tag[i] = env->immuregs[6];
595                     env->itlb_tte[i] = T1;
596                     return;
597                 }
598             }
599             // Try finding an unlocked entry
600             for (i = 0; i < 64; i++) {
601                 if ((env->itlb_tte[i] & 0x40) == 0) {
602                     env->itlb_tag[i] = env->immuregs[6];
603                     env->itlb_tte[i] = T1;
604                     return;
605                 }
606             }
607             // error state?
608             return;
609         }
610     case 0x55: // I-MMU data access
611         {
612             unsigned int i = (T0 >> 3) & 0x3f;
613
614             env->itlb_tag[i] = env->immuregs[6];
615             env->itlb_tte[i] = T1;
616             return;
617         }
618     case 0x57: // I-MMU demap
619         // XXX
620         return;
621     case 0x58: // D-MMU regs
622         {
623             int reg = (T0 >> 3) & 0xf;
624             uint64_t oldreg;
625             
626             oldreg = env->dmmuregs[reg];
627             switch(reg) {
628             case 0: // RO
629             case 4:
630                 return;
631             case 3: // SFSR
632                 if ((T1 & 1) == 0) {
633                     T1 = 0; // Clear SFSR, Fault address
634                     env->dmmuregs[4] = 0;
635                 }
636                 env->dmmuregs[reg] = T1;
637                 break;
638             case 1: // Primary context
639             case 2: // Secondary context
640             case 5: // TSB access
641             case 6: // Tag access
642             case 7: // Virtual Watchpoint
643             case 8: // Physical Watchpoint
644             default:
645                 break;
646             }
647             env->dmmuregs[reg] = T1;
648 #ifdef DEBUG_MMU
649             if (oldreg != env->dmmuregs[reg]) {
650                 printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
651             }
652             dump_mmu(env);
653 #endif
654             return;
655         }
656     case 0x5c: // D-MMU data in
657         {
658             unsigned int i;
659
660             // Try finding an invalid entry
661             for (i = 0; i < 64; i++) {
662                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
663                     env->dtlb_tag[i] = env->dmmuregs[6];
664                     env->dtlb_tte[i] = T1;
665                     return;
666                 }
667             }
668             // Try finding an unlocked entry
669             for (i = 0; i < 64; i++) {
670                 if ((env->dtlb_tte[i] & 0x40) == 0) {
671                     env->dtlb_tag[i] = env->dmmuregs[6];
672                     env->dtlb_tte[i] = T1;
673                     return;
674                 }
675             }
676             // error state?
677             return;
678         }
679     case 0x5d: // D-MMU data access
680         {
681             unsigned int i = (T0 >> 3) & 0x3f;
682
683             env->dtlb_tag[i] = env->dmmuregs[6];
684             env->dtlb_tte[i] = T1;
685             return;
686         }
687     case 0x5f: // D-MMU demap
688     case 0x49: // Interrupt data receive
689         // XXX
690         return;
691     case 0x51: // I-MMU 8k TSB pointer, RO
692     case 0x52: // I-MMU 64k TSB pointer, RO
693     case 0x56: // I-MMU tag read, RO
694     case 0x59: // D-MMU 8k TSB pointer, RO
695     case 0x5a: // D-MMU 64k TSB pointer, RO
696     case 0x5b: // D-MMU data pointer, RO
697     case 0x5e: // D-MMU tag read, RO
698     case 0x48: // Interrupt dispatch, RO
699     case 0x7f: // Incoming interrupt vector, RO
700     case 0x82: // Primary no-fault, RO
701     case 0x83: // Secondary no-fault, RO
702     case 0x8a: // Primary no-fault LE, RO
703     case 0x8b: // Secondary no-fault LE, RO
704     default:
705         do_unassigned_access(T0, 1, 0, 1);
706         return;
707     }
708 }
709 #endif
710 #endif /* !CONFIG_USER_ONLY */
711
712 #ifndef TARGET_SPARC64
713 void helper_rett()
714 {
715     unsigned int cwp;
716
717     if (env->psret == 1)
718         raise_exception(TT_ILL_INSN);
719
720     env->psret = 1;
721     cwp = (env->cwp + 1) & (NWINDOWS - 1); 
722     if (env->wim & (1 << cwp)) {
723         raise_exception(TT_WIN_UNF);
724     }
725     set_cwp(cwp);
726     env->psrs = env->psrps;
727 }
728 #endif
729
730 void helper_ldfsr(void)
731 {
732     int rnd_mode;
733     switch (env->fsr & FSR_RD_MASK) {
734     case FSR_RD_NEAREST:
735         rnd_mode = float_round_nearest_even;
736         break;
737     default:
738     case FSR_RD_ZERO:
739         rnd_mode = float_round_to_zero;
740         break;
741     case FSR_RD_POS:
742         rnd_mode = float_round_up;
743         break;
744     case FSR_RD_NEG:
745         rnd_mode = float_round_down;
746         break;
747     }
748     set_float_rounding_mode(rnd_mode, &env->fp_status);
749 }
750
751 void helper_debug()
752 {
753     env->exception_index = EXCP_DEBUG;
754     cpu_loop_exit();
755 }
756
757 #ifndef TARGET_SPARC64
758 void do_wrpsr()
759 {
760     if ((T0 & PSR_CWP) >= NWINDOWS)
761         raise_exception(TT_ILL_INSN);
762     else
763         PUT_PSR(env, T0);
764 }
765
766 void do_rdpsr()
767 {
768     T0 = GET_PSR(env);
769 }
770
771 #else
772
773 void do_popc()
774 {
775     T0 = (T1 & 0x5555555555555555ULL) + ((T1 >> 1) & 0x5555555555555555ULL);
776     T0 = (T0 & 0x3333333333333333ULL) + ((T0 >> 2) & 0x3333333333333333ULL);
777     T0 = (T0 & 0x0f0f0f0f0f0f0f0fULL) + ((T0 >> 4) & 0x0f0f0f0f0f0f0f0fULL);
778     T0 = (T0 & 0x00ff00ff00ff00ffULL) + ((T0 >> 8) & 0x00ff00ff00ff00ffULL);
779     T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);
780     T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);
781 }
782
783 static inline uint64_t *get_gregset(uint64_t pstate)
784 {
785     switch (pstate) {
786     default:
787     case 0:
788         return env->bgregs;
789     case PS_AG:
790         return env->agregs;
791     case PS_MG:
792         return env->mgregs;
793     case PS_IG:
794         return env->igregs;
795     }
796 }
797
798 void do_wrpstate()
799 {
800     uint64_t new_pstate, pstate_regs, new_pstate_regs;
801     uint64_t *src, *dst;
802
803     new_pstate = T0 & 0xf3f;
804     pstate_regs = env->pstate & 0xc01;
805     new_pstate_regs = new_pstate & 0xc01;
806     if (new_pstate_regs != pstate_regs) {
807         // Switch global register bank
808         src = get_gregset(new_pstate_regs);
809         dst = get_gregset(pstate_regs);
810         memcpy32(dst, env->gregs);
811         memcpy32(env->gregs, src);
812     }
813     env->pstate = new_pstate;
814 }
815
816 void do_done(void)
817 {
818     env->tl--;
819     env->pc = env->tnpc[env->tl];
820     env->npc = env->tnpc[env->tl] + 4;
821     PUT_CCR(env, env->tstate[env->tl] >> 32);
822     env->asi = (env->tstate[env->tl] >> 24) & 0xff;
823     env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
824     set_cwp(env->tstate[env->tl] & 0xff);
825 }
826
827 void do_retry(void)
828 {
829     env->tl--;
830     env->pc = env->tpc[env->tl];
831     env->npc = env->tnpc[env->tl];
832     PUT_CCR(env, env->tstate[env->tl] >> 32);
833     env->asi = (env->tstate[env->tl] >> 24) & 0xff;
834     env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
835     set_cwp(env->tstate[env->tl] & 0xff);
836 }
837 #endif
838
839 void set_cwp(int new_cwp)
840 {
841     /* put the modified wrap registers at their proper location */
842     if (env->cwp == (NWINDOWS - 1))
843         memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
844     env->cwp = new_cwp;
845     /* put the wrap registers at their temporary location */
846     if (new_cwp == (NWINDOWS - 1))
847         memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
848     env->regwptr = env->regbase + (new_cwp * 16);
849     REGWPTR = env->regwptr;
850 }
851
852 void cpu_set_cwp(CPUState *env1, int new_cwp)
853 {
854     CPUState *saved_env;
855 #ifdef reg_REGWPTR
856     target_ulong *saved_regwptr;
857 #endif
858
859     saved_env = env;
860 #ifdef reg_REGWPTR
861     saved_regwptr = REGWPTR;
862 #endif
863     env = env1;
864     set_cwp(new_cwp);
865     env = saved_env;
866 #ifdef reg_REGWPTR
867     REGWPTR = saved_regwptr;
868 #endif
869 }
870
871 #ifdef TARGET_SPARC64
872 void do_interrupt(int intno)
873 {
874 #ifdef DEBUG_PCALL
875     if (loglevel & CPU_LOG_INT) {
876         static int count;
877         fprintf(logfile, "%6d: v=%04x pc=%016" PRIx64 " npc=%016" PRIx64 " SP=%016" PRIx64 "\n",
878                 count, intno,
879                 env->pc,
880                 env->npc, env->regwptr[6]);
881         cpu_dump_state(env, logfile, fprintf, 0);
882 #if 0
883         {
884             int i;
885             uint8_t *ptr;
886
887             fprintf(logfile, "       code=");
888             ptr = (uint8_t *)env->pc;
889             for(i = 0; i < 16; i++) {
890                 fprintf(logfile, " %02x", ldub(ptr + i));
891             }
892             fprintf(logfile, "\n");
893         }
894 #endif
895         count++;
896     }
897 #endif
898 #if !defined(CONFIG_USER_ONLY) 
899     if (env->tl == MAXTL) {
900         cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
901         return;
902     }
903 #endif
904     env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
905         ((env->pstate & 0xfff) << 8) | (env->cwp & 0xff);
906     env->tpc[env->tl] = env->pc;
907     env->tnpc[env->tl] = env->npc;
908     env->tt[env->tl] = intno;
909     env->pstate = PS_PEF | PS_PRIV | PS_AG;
910     env->tbr &= ~0x7fffULL;
911     env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
912     if (env->tl < MAXTL - 1) {
913         env->tl++;
914     } else {
915         env->pstate |= PS_RED;
916         if (env->tl != MAXTL)
917             env->tl++;
918     }
919     env->pc = env->tbr;
920     env->npc = env->pc + 4;
921     env->exception_index = 0;
922 }
923 #else
924 void do_interrupt(int intno)
925 {
926     int cwp;
927
928 #ifdef DEBUG_PCALL
929     if (loglevel & CPU_LOG_INT) {
930         static int count;
931         fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
932                 count, intno,
933                 env->pc,
934                 env->npc, env->regwptr[6]);
935         cpu_dump_state(env, logfile, fprintf, 0);
936 #if 0
937         {
938             int i;
939             uint8_t *ptr;
940
941             fprintf(logfile, "       code=");
942             ptr = (uint8_t *)env->pc;
943             for(i = 0; i < 16; i++) {
944                 fprintf(logfile, " %02x", ldub(ptr + i));
945             }
946             fprintf(logfile, "\n");
947         }
948 #endif
949         count++;
950     }
951 #endif
952 #if !defined(CONFIG_USER_ONLY) 
953     if (env->psret == 0) {
954         cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
955         return;
956     }
957 #endif
958     env->psret = 0;
959     cwp = (env->cwp - 1) & (NWINDOWS - 1); 
960     set_cwp(cwp);
961     env->regwptr[9] = env->pc;
962     env->regwptr[10] = env->npc;
963     env->psrps = env->psrs;
964     env->psrs = 1;
965     env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
966     env->pc = env->tbr;
967     env->npc = env->pc + 4;
968     env->exception_index = 0;
969 }
970 #endif
971
972 #if !defined(CONFIG_USER_ONLY) 
973
974 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
975                                 void *retaddr);
976
977 #define MMUSUFFIX _mmu
978 #define ALIGNED_ONLY
979 #define GETPC() (__builtin_return_address(0))
980
981 #define SHIFT 0
982 #include "softmmu_template.h"
983
984 #define SHIFT 1
985 #include "softmmu_template.h"
986
987 #define SHIFT 2
988 #include "softmmu_template.h"
989
990 #define SHIFT 3
991 #include "softmmu_template.h"
992
993 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
994                                 void *retaddr)
995 {
996 #ifdef DEBUG_UNALIGNED
997     printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
998 #endif
999     raise_exception(TT_UNALIGNED);
1000 }
1001
1002 /* try to fill the TLB and return an exception if error. If retaddr is
1003    NULL, it means that the function was called in C code (i.e. not
1004    from generated code or from helper.c) */
1005 /* XXX: fix it to restore all registers */
1006 void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
1007 {
1008     TranslationBlock *tb;
1009     int ret;
1010     unsigned long pc;
1011     CPUState *saved_env;
1012
1013     /* XXX: hack to restore env in all cases, even if not called from
1014        generated code */
1015     saved_env = env;
1016     env = cpu_single_env;
1017
1018     ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
1019     if (ret) {
1020         if (retaddr) {
1021             /* now we have a real cpu fault */
1022             pc = (unsigned long)retaddr;
1023             tb = tb_find_pc(pc);
1024             if (tb) {
1025                 /* the PC is inside the translated code. It means that we have
1026                    a virtual CPU fault */
1027                 cpu_restore_state(tb, env, pc, (void *)T2);
1028             }
1029         }
1030         cpu_loop_exit();
1031     }
1032     env = saved_env;
1033 }
1034
1035 #endif
1036
1037 #ifndef TARGET_SPARC64
1038 void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
1039                           int is_asi)
1040 {
1041     CPUState *saved_env;
1042
1043     /* XXX: hack to restore env in all cases, even if not called from
1044        generated code */
1045     saved_env = env;
1046     env = cpu_single_env;
1047     if (env->mmuregs[3]) /* Fault status register */
1048         env->mmuregs[3] = 1; /* overflow (not read before another fault) */
1049     if (is_asi)
1050         env->mmuregs[3] |= 1 << 16;
1051     if (env->psrs)
1052         env->mmuregs[3] |= 1 << 5;
1053     if (is_exec)
1054         env->mmuregs[3] |= 1 << 6;
1055     if (is_write)
1056         env->mmuregs[3] |= 1 << 7;
1057     env->mmuregs[3] |= (5 << 2) | 2;
1058     env->mmuregs[4] = addr; /* Fault address register */
1059     if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
1060 #ifdef DEBUG_UNASSIGNED
1061         printf("Unassigned mem access to " TARGET_FMT_lx " from " TARGET_FMT_lx
1062                "\n", addr, env->pc);
1063 #endif
1064         raise_exception(TT_DATA_ACCESS);
1065     }
1066     env = saved_env;
1067 }
1068 #else
1069 void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
1070                           int is_asi)
1071 {
1072 #ifdef DEBUG_UNASSIGNED
1073     CPUState *saved_env;
1074
1075     /* XXX: hack to restore env in all cases, even if not called from
1076        generated code */
1077     saved_env = env;
1078     env = cpu_single_env;
1079     printf("Unassigned mem access to " TARGET_FMT_lx " from " TARGET_FMT_lx "\n",
1080            addr, env->pc);
1081     env = saved_env;
1082 #endif
1083     raise_exception(TT_DATA_ACCESS);
1084 }
1085 #endif