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