]> git.proxmox.com Git - qemu.git/blame - target-sparc/op_helper.c
fixed VIA irq register access
[qemu.git] / target-sparc / op_helper.c
CommitLineData
e8af50a3
FB
1#include "exec.h"
2
e80cfcfc
FB
3//#define DEBUG_MMU
4
9d893301
FB
5void raise_exception(int tt)
6{
7 env->exception_index = tt;
8 cpu_loop_exit();
9}
10
a0c4cb4a
FB
11#ifdef USE_INT_TO_FLOAT_HELPERS
12void do_fitos(void)
13{
14 FT0 = (float) *((int32_t *)&FT1);
15}
16
17void do_fitod(void)
18{
19 DT0 = (double) *((int32_t *)&FT1);
20}
21#endif
22
23void do_fabss(void)
e8af50a3 24{
7a0e1f41 25 FT0 = float32_abs(FT1);
e8af50a3
FB
26}
27
3475187d
FB
28#ifdef TARGET_SPARC64
29void do_fabsd(void)
30{
31 DT0 = float64_abs(DT1);
32}
33#endif
34
a0c4cb4a 35void do_fsqrts(void)
e8af50a3 36{
7a0e1f41 37 FT0 = float32_sqrt(FT1, &env->fp_status);
e8af50a3
FB
38}
39
a0c4cb4a 40void do_fsqrtd(void)
e8af50a3 41{
7a0e1f41 42 DT0 = float64_sqrt(DT1, &env->fp_status);
e8af50a3
FB
43}
44
3475187d 45#define FS 0
a0c4cb4a 46void do_fcmps (void)
e8af50a3 47{
3475187d 48 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
e8af50a3 49 if (isnan(FT0) || isnan(FT1)) {
3475187d 50 T0 = (FSR_FCC1 | FSR_FCC0) << FS;
e80cfcfc 51 if (env->fsr & FSR_NVM) {
3475187d 52 env->fsr |= T0;
e80cfcfc
FB
53 raise_exception(TT_FP_EXCP);
54 } else {
55 env->fsr |= FSR_NVA;
56 }
e8af50a3 57 } else if (FT0 < FT1) {
3475187d 58 T0 = FSR_FCC0 << FS;
e8af50a3 59 } else if (FT0 > FT1) {
3475187d 60 T0 = FSR_FCC1 << FS;
e8af50a3
FB
61 } else {
62 T0 = 0;
63 }
3475187d 64 env->fsr |= T0;
e8af50a3
FB
65}
66
a0c4cb4a 67void do_fcmpd (void)
e8af50a3 68{
3475187d
FB
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
91void 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
112void 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
135void 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
156void do_fcmpd_fcc2 (void)
157{
158 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
e8af50a3 159 if (isnan(DT0) || isnan(DT1)) {
3475187d 160 T0 = (FSR_FCC1 | FSR_FCC0) << FS;
e80cfcfc 161 if (env->fsr & FSR_NVM) {
3475187d 162 env->fsr |= T0;
e80cfcfc
FB
163 raise_exception(TT_FP_EXCP);
164 } else {
165 env->fsr |= FSR_NVA;
166 }
e8af50a3 167 } else if (DT0 < DT1) {
3475187d 168 T0 = FSR_FCC0 << FS;
e8af50a3 169 } else if (DT0 > DT1) {
3475187d
FB
170 T0 = FSR_FCC1 << FS;
171 } else {
172 T0 = 0;
173 }
174 env->fsr |= T0;
175}
176
177#undef FS
178#define FS 26
179void 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;
e8af50a3
FB
194 } else {
195 T0 = 0;
196 }
3475187d 197 env->fsr |= T0;
e8af50a3
FB
198}
199
3475187d
FB
200void 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
a0c4cb4a 224void helper_ld_asi(int asi, int size, int sign)
e8af50a3 225{
e80cfcfc
FB
226 uint32_t ret;
227
228 switch (asi) {
e8af50a3 229 case 3: /* MMU probe */
e80cfcfc
FB
230 {
231 int mmulev;
232
233 mmulev = (T0 >> 8) & 15;
234 if (mmulev > 4)
235 ret = 0;
236 else {
ee5bbe38 237 ret = mmu_probe(env, T0, mmulev);
e80cfcfc
FB
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;
e8af50a3
FB
245 case 4: /* read MMU regs */
246 {
e80cfcfc 247 int reg = (T0 >> 8) & 0xf;
e8af50a3 248
e80cfcfc 249 ret = env->mmuregs[reg];
55754d9e
FB
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
e8af50a3 255 }
e80cfcfc 256 break;
e8af50a3 257 case 0x20 ... 0x2f: /* MMU passthrough */
e80cfcfc
FB
258 cpu_physical_memory_read(T0, (void *) &ret, size);
259 if (size == 4)
49be8030
FB
260 tswap32s(&ret);
261 else if (size == 2)
262 tswap16s((uint16_t *)&ret);
e80cfcfc 263 break;
e8af50a3 264 default:
e80cfcfc
FB
265 ret = 0;
266 break;
e8af50a3 267 }
e80cfcfc 268 T1 = ret;
e8af50a3
FB
269}
270
a0c4cb4a 271void helper_st_asi(int asi, int size, int sign)
e8af50a3
FB
272{
273 switch(asi) {
274 case 3: /* MMU flush */
e80cfcfc
FB
275 {
276 int mmulev;
277
278 mmulev = (T0 >> 8) & 15;
55754d9e
FB
279#ifdef DEBUG_MMU
280 printf("mmu flush level %d\n", mmulev);
281#endif
e80cfcfc
FB
282 switch (mmulev) {
283 case 0: // flush page
55754d9e 284 tlb_flush_page(env, T0 & 0xfffff000);
e80cfcfc
FB
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
55754d9e 290 tlb_flush(env, 1);
e80cfcfc
FB
291 break;
292 default:
293 break;
294 }
55754d9e 295#ifdef DEBUG_MMU
ee5bbe38 296 dump_mmu(env);
55754d9e 297#endif
e80cfcfc
FB
298 return;
299 }
e8af50a3
FB
300 case 4: /* write MMU regs */
301 {
e80cfcfc
FB
302 int reg = (T0 >> 8) & 0xf, oldreg;
303
304 oldreg = env->mmuregs[reg];
55754d9e
FB
305 switch(reg) {
306 case 0:
e8af50a3
FB
307 env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
308 env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
6f7e9aec
FB
309 // Mappings generated during no-fault mode or MMU
310 // disabled mode are invalid in normal mode
311 if (oldreg != env->mmuregs[reg])
55754d9e
FB
312 tlb_flush(env, 1);
313 break;
314 case 2:
e8af50a3 315 env->mmuregs[reg] = T1;
55754d9e
FB
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 }
ee5bbe38 333 dump_mmu(env);
55754d9e 334#endif
e8af50a3
FB
335 return;
336 }
e80cfcfc
FB
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
49be8030 345 tswap32s(&src);
e80cfcfc
FB
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;
49be8030 360 tswap64s(&val);
e80cfcfc
FB
361
362 for (i = 0; i < 32; i += 8, dst += 8) {
363 cpu_physical_memory_write(dst, (void *) &val, 8);
364 }
365 }
366 return;
e8af50a3
FB
367 case 0x20 ... 0x2f: /* MMU passthrough */
368 {
369 int temp = T1;
e80cfcfc 370 if (size == 4)
49be8030 371 tswap32s(&temp);
e80cfcfc 372 else if (size == 2)
49be8030 373 tswap16s((uint16_t *)&temp);
e8af50a3
FB
374 cpu_physical_memory_write(T0, (void *) &temp, size);
375 }
376 return;
377 default:
378 return;
379 }
380}
381
3475187d
FB
382#else
383
384void 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
447void 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 }
ee5bbe38 511 dump_mmu(env);
3475187d
FB
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 }
ee5bbe38 579 dump_mmu(env);
3475187d
FB
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
a0c4cb4a 631void helper_rett()
e8af50a3 632{
af7bf89b
FB
633 unsigned int cwp;
634
e8af50a3
FB
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}
3475187d 643#endif
e8af50a3 644
8d5f07fa 645void helper_ldfsr(void)
e8af50a3 646{
7a0e1f41 647 int rnd_mode;
e8af50a3
FB
648 switch (env->fsr & FSR_RD_MASK) {
649 case FSR_RD_NEAREST:
7a0e1f41 650 rnd_mode = float_round_nearest_even;
e8af50a3 651 break;
ed910241 652 default:
e8af50a3 653 case FSR_RD_ZERO:
7a0e1f41 654 rnd_mode = float_round_to_zero;
e8af50a3
FB
655 break;
656 case FSR_RD_POS:
7a0e1f41 657 rnd_mode = float_round_up;
e8af50a3
FB
658 break;
659 case FSR_RD_NEG:
7a0e1f41 660 rnd_mode = float_round_down;
e8af50a3
FB
661 break;
662 }
7a0e1f41 663 set_float_rounding_mode(rnd_mode, &env->fp_status);
e8af50a3 664}
e80cfcfc
FB
665
666void 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
674double cpu_put_fp64(uint64_t mant, uint16_t exp)
675{
676 return ldexp((double) mant, exp - 53);
677}
678
679void helper_debug()
680{
681 env->exception_index = EXCP_DEBUG;
682 cpu_loop_exit();
683}
af7bf89b 684
3475187d 685#ifndef TARGET_SPARC64
af7bf89b
FB
686void do_wrpsr()
687{
688 PUT_PSR(env, T0);
689}
690
691void do_rdpsr()
692{
693 T0 = GET_PSR(env);
694}
3475187d
FB
695
696#else
697
698void 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
ee5bbe38
FB
708
709void 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
722void 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
742void 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
786void 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 */
856void 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