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