Modify Sparc32/64 to use TCG
[qemu/malc.git] / target-sparc / op_helper.c
blobf13a7b1d6edaf7dcd69ead93abb0af23a05d069a
1 #include "exec.h"
2 #include "host-utils.h"
3 #include "helper.h"
5 //#define DEBUG_PCALL
6 //#define DEBUG_MMU
7 //#define DEBUG_MXCC
8 //#define DEBUG_UNALIGNED
9 //#define DEBUG_UNASSIGNED
10 //#define DEBUG_ASI
12 #ifdef DEBUG_MMU
13 #define DPRINTF_MMU(fmt, args...) \
14 do { printf("MMU: " fmt , ##args); } while (0)
15 #else
16 #define DPRINTF_MMU(fmt, args...)
17 #endif
19 #ifdef DEBUG_MXCC
20 #define DPRINTF_MXCC(fmt, args...) \
21 do { printf("MXCC: " fmt , ##args); } while (0)
22 #else
23 #define DPRINTF_MXCC(fmt, args...)
24 #endif
26 #ifdef DEBUG_ASI
27 #define DPRINTF_ASI(fmt, args...) \
28 do { printf("ASI: " fmt , ##args); } while (0)
29 #else
30 #define DPRINTF_ASI(fmt, args...)
31 #endif
33 void raise_exception(int tt)
35 env->exception_index = tt;
36 cpu_loop_exit();
39 void helper_trap(target_ulong nb_trap)
41 env->exception_index = TT_TRAP + (nb_trap & 0x7f);
42 cpu_loop_exit();
45 void helper_trapcc(target_ulong nb_trap, target_ulong do_trap)
47 if (do_trap) {
48 env->exception_index = TT_TRAP + (nb_trap & 0x7f);
49 cpu_loop_exit();
53 void check_ieee_exceptions(void)
55 target_ulong status;
57 status = get_float_exception_flags(&env->fp_status);
58 if (status) {
59 /* Copy IEEE 754 flags into FSR */
60 if (status & float_flag_invalid)
61 env->fsr |= FSR_NVC;
62 if (status & float_flag_overflow)
63 env->fsr |= FSR_OFC;
64 if (status & float_flag_underflow)
65 env->fsr |= FSR_UFC;
66 if (status & float_flag_divbyzero)
67 env->fsr |= FSR_DZC;
68 if (status & float_flag_inexact)
69 env->fsr |= FSR_NXC;
71 if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
72 /* Unmasked exception, generate a trap */
73 env->fsr |= FSR_FTT_IEEE_EXCP;
74 raise_exception(TT_FP_EXCP);
75 } else {
76 /* Accumulate exceptions */
77 env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
82 #ifdef USE_INT_TO_FLOAT_HELPERS
83 void do_fitos(void)
85 set_float_exception_flags(0, &env->fp_status);
86 FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
87 check_ieee_exceptions();
90 void do_fitod(void)
92 DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
95 #if defined(CONFIG_USER_ONLY)
96 void do_fitoq(void)
98 QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
100 #endif
102 #ifdef TARGET_SPARC64
103 void do_fxtos(void)
105 set_float_exception_flags(0, &env->fp_status);
106 FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
107 check_ieee_exceptions();
110 void do_fxtod(void)
112 set_float_exception_flags(0, &env->fp_status);
113 DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
114 check_ieee_exceptions();
117 #if defined(CONFIG_USER_ONLY)
118 void do_fxtoq(void)
120 set_float_exception_flags(0, &env->fp_status);
121 QT0 = int64_to_float128(*((int32_t *)&DT1), &env->fp_status);
122 check_ieee_exceptions();
124 #endif
125 #endif
126 #endif
128 void do_fabss(void)
130 FT0 = float32_abs(FT1);
133 #ifdef TARGET_SPARC64
134 void do_fabsd(void)
136 DT0 = float64_abs(DT1);
139 #if defined(CONFIG_USER_ONLY)
140 void do_fabsq(void)
142 QT0 = float128_abs(QT1);
144 #endif
145 #endif
147 void do_fsqrts(void)
149 set_float_exception_flags(0, &env->fp_status);
150 FT0 = float32_sqrt(FT1, &env->fp_status);
151 check_ieee_exceptions();
154 void do_fsqrtd(void)
156 set_float_exception_flags(0, &env->fp_status);
157 DT0 = float64_sqrt(DT1, &env->fp_status);
158 check_ieee_exceptions();
161 #if defined(CONFIG_USER_ONLY)
162 void do_fsqrtq(void)
164 set_float_exception_flags(0, &env->fp_status);
165 QT0 = float128_sqrt(QT1, &env->fp_status);
166 check_ieee_exceptions();
168 #endif
170 #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
171 void glue(do_, name) (void) \
173 target_ulong new_fsr; \
175 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
176 switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
177 case float_relation_unordered: \
178 new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \
179 if ((env->fsr & FSR_NVM) || TRAP) { \
180 env->fsr |= new_fsr; \
181 env->fsr |= FSR_NVC; \
182 env->fsr |= FSR_FTT_IEEE_EXCP; \
183 raise_exception(TT_FP_EXCP); \
184 } else { \
185 env->fsr |= FSR_NVA; \
187 break; \
188 case float_relation_less: \
189 new_fsr = FSR_FCC0 << FS; \
190 break; \
191 case float_relation_greater: \
192 new_fsr = FSR_FCC1 << FS; \
193 break; \
194 default: \
195 new_fsr = 0; \
196 break; \
198 env->fsr |= new_fsr; \
201 GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
202 GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
204 GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
205 GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
207 #ifdef CONFIG_USER_ONLY
208 GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
209 GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
210 #endif
212 #ifdef TARGET_SPARC64
213 GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
214 GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
216 GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
217 GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
219 GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
220 GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
222 GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
223 GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
225 GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
226 GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
228 GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
229 GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
230 #ifdef CONFIG_USER_ONLY
231 GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
232 GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
233 GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
234 GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
235 GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
236 GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
237 #endif
238 #endif
240 #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && defined(DEBUG_MXCC)
241 static void dump_mxcc(CPUState *env)
243 printf("mxccdata: %016llx %016llx %016llx %016llx\n",
244 env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]);
245 printf("mxccregs: %016llx %016llx %016llx %016llx\n"
246 " %016llx %016llx %016llx %016llx\n",
247 env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3],
248 env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]);
250 #endif
252 #if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
253 && defined(DEBUG_ASI)
254 static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
255 uint64_t r1)
257 switch (size)
259 case 1:
260 DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
261 addr, asi, r1 & 0xff);
262 break;
263 case 2:
264 DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
265 addr, asi, r1 & 0xffff);
266 break;
267 case 4:
268 DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
269 addr, asi, r1 & 0xffffffff);
270 break;
271 case 8:
272 DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
273 addr, asi, r1);
274 break;
277 #endif
279 #ifndef TARGET_SPARC64
280 #ifndef CONFIG_USER_ONLY
281 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
283 uint64_t ret = 0;
284 #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
285 uint32_t last_addr = addr;
286 #endif
288 switch (asi) {
289 case 2: /* SuperSparc MXCC registers */
290 switch (addr) {
291 case 0x01c00a00: /* MXCC control register */
292 if (size == 8)
293 ret = env->mxccregs[3];
294 else
295 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
296 break;
297 case 0x01c00a04: /* MXCC control register */
298 if (size == 4)
299 ret = env->mxccregs[3];
300 else
301 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
302 break;
303 case 0x01c00c00: /* Module reset register */
304 if (size == 8) {
305 ret = env->mxccregs[5];
306 // should we do something here?
307 } else
308 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
309 break;
310 case 0x01c00f00: /* MBus port address register */
311 if (size == 8)
312 ret = env->mxccregs[7];
313 else
314 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
315 break;
316 default:
317 DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size);
318 break;
320 DPRINTF_MXCC("asi = %d, size = %d, sign = %d, addr = %08x -> ret = %08x,"
321 "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
322 #ifdef DEBUG_MXCC
323 dump_mxcc(env);
324 #endif
325 break;
326 case 3: /* MMU probe */
328 int mmulev;
330 mmulev = (addr >> 8) & 15;
331 if (mmulev > 4)
332 ret = 0;
333 else
334 ret = mmu_probe(env, addr, mmulev);
335 DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
336 addr, mmulev, ret);
338 break;
339 case 4: /* read MMU regs */
341 int reg = (addr >> 8) & 0x1f;
343 ret = env->mmuregs[reg];
344 if (reg == 3) /* Fault status cleared on read */
345 env->mmuregs[3] = 0;
346 else if (reg == 0x13) /* Fault status read */
347 ret = env->mmuregs[3];
348 else if (reg == 0x14) /* Fault address read */
349 ret = env->mmuregs[4];
350 DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
352 break;
353 case 5: // Turbosparc ITLB Diagnostic
354 case 6: // Turbosparc DTLB Diagnostic
355 case 7: // Turbosparc IOTLB Diagnostic
356 break;
357 case 9: /* Supervisor code access */
358 switch(size) {
359 case 1:
360 ret = ldub_code(addr);
361 break;
362 case 2:
363 ret = lduw_code(addr & ~1);
364 break;
365 default:
366 case 4:
367 ret = ldl_code(addr & ~3);
368 break;
369 case 8:
370 ret = ldq_code(addr & ~7);
371 break;
373 break;
374 case 0xa: /* User data access */
375 switch(size) {
376 case 1:
377 ret = ldub_user(addr);
378 break;
379 case 2:
380 ret = lduw_user(addr & ~1);
381 break;
382 default:
383 case 4:
384 ret = ldl_user(addr & ~3);
385 break;
386 case 8:
387 ret = ldq_user(addr & ~7);
388 break;
390 break;
391 case 0xb: /* Supervisor data access */
392 switch(size) {
393 case 1:
394 ret = ldub_kernel(addr);
395 break;
396 case 2:
397 ret = lduw_kernel(addr & ~1);
398 break;
399 default:
400 case 4:
401 ret = ldl_kernel(addr & ~3);
402 break;
403 case 8:
404 ret = ldq_kernel(addr & ~7);
405 break;
407 break;
408 case 0xc: /* I-cache tag */
409 case 0xd: /* I-cache data */
410 case 0xe: /* D-cache tag */
411 case 0xf: /* D-cache data */
412 break;
413 case 0x20: /* MMU passthrough */
414 switch(size) {
415 case 1:
416 ret = ldub_phys(addr);
417 break;
418 case 2:
419 ret = lduw_phys(addr & ~1);
420 break;
421 default:
422 case 4:
423 ret = ldl_phys(addr & ~3);
424 break;
425 case 8:
426 ret = ldq_phys(addr & ~7);
427 break;
429 break;
430 case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
431 switch(size) {
432 case 1:
433 ret = ldub_phys((target_phys_addr_t)addr
434 | ((target_phys_addr_t)(asi & 0xf) << 32));
435 break;
436 case 2:
437 ret = lduw_phys((target_phys_addr_t)(addr & ~1)
438 | ((target_phys_addr_t)(asi & 0xf) << 32));
439 break;
440 default:
441 case 4:
442 ret = ldl_phys((target_phys_addr_t)(addr & ~3)
443 | ((target_phys_addr_t)(asi & 0xf) << 32));
444 break;
445 case 8:
446 ret = ldq_phys((target_phys_addr_t)(addr & ~7)
447 | ((target_phys_addr_t)(asi & 0xf) << 32));
448 break;
450 break;
451 case 0x30: // Turbosparc secondary cache diagnostic
452 case 0x31: // Turbosparc RAM snoop
453 case 0x32: // Turbosparc page table descriptor diagnostic
454 case 0x39: /* data cache diagnostic register */
455 ret = 0;
456 break;
457 case 8: /* User code access, XXX */
458 default:
459 do_unassigned_access(addr, 0, 0, asi);
460 ret = 0;
461 break;
463 if (sign) {
464 switch(size) {
465 case 1:
466 ret = (int8_t) ret;
467 break;
468 case 2:
469 ret = (int16_t) ret;
470 break;
471 case 4:
472 ret = (int32_t) ret;
473 break;
474 default:
475 break;
478 #ifdef DEBUG_ASI
479 dump_asi("read ", last_addr, asi, size, ret);
480 #endif
481 return ret;
484 void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
486 switch(asi) {
487 case 2: /* SuperSparc MXCC registers */
488 switch (addr) {
489 case 0x01c00000: /* MXCC stream data register 0 */
490 if (size == 8)
491 env->mxccdata[0] = val;
492 else
493 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
494 break;
495 case 0x01c00008: /* MXCC stream data register 1 */
496 if (size == 8)
497 env->mxccdata[1] = val;
498 else
499 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
500 break;
501 case 0x01c00010: /* MXCC stream data register 2 */
502 if (size == 8)
503 env->mxccdata[2] = val;
504 else
505 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
506 break;
507 case 0x01c00018: /* MXCC stream data register 3 */
508 if (size == 8)
509 env->mxccdata[3] = val;
510 else
511 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
512 break;
513 case 0x01c00100: /* MXCC stream source */
514 if (size == 8)
515 env->mxccregs[0] = val;
516 else
517 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
518 env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 0);
519 env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 8);
520 env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16);
521 env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 24);
522 break;
523 case 0x01c00200: /* MXCC stream destination */
524 if (size == 8)
525 env->mxccregs[1] = val;
526 else
527 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
528 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0, env->mxccdata[0]);
529 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8, env->mxccdata[1]);
530 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]);
531 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, env->mxccdata[3]);
532 break;
533 case 0x01c00a00: /* MXCC control register */
534 if (size == 8)
535 env->mxccregs[3] = val;
536 else
537 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
538 break;
539 case 0x01c00a04: /* MXCC control register */
540 if (size == 4)
541 env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | val;
542 else
543 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
544 break;
545 case 0x01c00e00: /* MXCC error register */
546 // writing a 1 bit clears the error
547 if (size == 8)
548 env->mxccregs[6] &= ~val;
549 else
550 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
551 break;
552 case 0x01c00f00: /* MBus port address register */
553 if (size == 8)
554 env->mxccregs[7] = val;
555 else
556 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
557 break;
558 default:
559 DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size);
560 break;
562 DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %08x\n", asi, size, addr, val);
563 #ifdef DEBUG_MXCC
564 dump_mxcc(env);
565 #endif
566 break;
567 case 3: /* MMU flush */
569 int mmulev;
571 mmulev = (addr >> 8) & 15;
572 DPRINTF_MMU("mmu flush level %d\n", mmulev);
573 switch (mmulev) {
574 case 0: // flush page
575 tlb_flush_page(env, addr & 0xfffff000);
576 break;
577 case 1: // flush segment (256k)
578 case 2: // flush region (16M)
579 case 3: // flush context (4G)
580 case 4: // flush entire
581 tlb_flush(env, 1);
582 break;
583 default:
584 break;
586 #ifdef DEBUG_MMU
587 dump_mmu(env);
588 #endif
590 break;
591 case 4: /* write MMU regs */
593 int reg = (addr >> 8) & 0x1f;
594 uint32_t oldreg;
596 oldreg = env->mmuregs[reg];
597 switch(reg) {
598 case 0: // Control Register
599 env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
600 (val & 0x00ffffff);
601 // Mappings generated during no-fault mode or MMU
602 // disabled mode are invalid in normal mode
603 if ((oldreg & (MMU_E | MMU_NF | env->mmu_bm)) !=
604 (env->mmuregs[reg] & (MMU_E | MMU_NF | env->mmu_bm)))
605 tlb_flush(env, 1);
606 break;
607 case 1: // Context Table Pointer Register
608 env->mmuregs[reg] = val & env->mmu_ctpr_mask;
609 break;
610 case 2: // Context Register
611 env->mmuregs[reg] = val & env->mmu_cxr_mask;
612 if (oldreg != env->mmuregs[reg]) {
613 /* we flush when the MMU context changes because
614 QEMU has no MMU context support */
615 tlb_flush(env, 1);
617 break;
618 case 3: // Synchronous Fault Status Register with Clear
619 case 4: // Synchronous Fault Address Register
620 break;
621 case 0x10: // TLB Replacement Control Register
622 env->mmuregs[reg] = val & env->mmu_trcr_mask;
623 break;
624 case 0x13: // Synchronous Fault Status Register with Read and Clear
625 env->mmuregs[3] = val & env->mmu_sfsr_mask;
626 break;
627 case 0x14: // Synchronous Fault Address Register
628 env->mmuregs[4] = val;
629 break;
630 default:
631 env->mmuregs[reg] = val;
632 break;
634 if (oldreg != env->mmuregs[reg]) {
635 DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
637 #ifdef DEBUG_MMU
638 dump_mmu(env);
639 #endif
641 break;
642 case 5: // Turbosparc ITLB Diagnostic
643 case 6: // Turbosparc DTLB Diagnostic
644 case 7: // Turbosparc IOTLB Diagnostic
645 break;
646 case 0xa: /* User data access */
647 switch(size) {
648 case 1:
649 stb_user(addr, val);
650 break;
651 case 2:
652 stw_user(addr & ~1, val);
653 break;
654 default:
655 case 4:
656 stl_user(addr & ~3, val);
657 break;
658 case 8:
659 stq_user(addr & ~7, val);
660 break;
662 break;
663 case 0xb: /* Supervisor data access */
664 switch(size) {
665 case 1:
666 stb_kernel(addr, val);
667 break;
668 case 2:
669 stw_kernel(addr & ~1, val);
670 break;
671 default:
672 case 4:
673 stl_kernel(addr & ~3, val);
674 break;
675 case 8:
676 stq_kernel(addr & ~7, val);
677 break;
679 break;
680 case 0xc: /* I-cache tag */
681 case 0xd: /* I-cache data */
682 case 0xe: /* D-cache tag */
683 case 0xf: /* D-cache data */
684 case 0x10: /* I/D-cache flush page */
685 case 0x11: /* I/D-cache flush segment */
686 case 0x12: /* I/D-cache flush region */
687 case 0x13: /* I/D-cache flush context */
688 case 0x14: /* I/D-cache flush user */
689 break;
690 case 0x17: /* Block copy, sta access */
692 // val = src
693 // addr = dst
694 // copy 32 bytes
695 unsigned int i;
696 uint32_t src = val & ~3, dst = addr & ~3, temp;
698 for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
699 temp = ldl_kernel(src);
700 stl_kernel(dst, temp);
703 break;
704 case 0x1f: /* Block fill, stda access */
706 // addr = dst
707 // fill 32 bytes with val
708 unsigned int i;
709 uint32_t dst = addr & 7;
711 for (i = 0; i < 32; i += 8, dst += 8)
712 stq_kernel(dst, val);
714 break;
715 case 0x20: /* MMU passthrough */
717 switch(size) {
718 case 1:
719 stb_phys(addr, val);
720 break;
721 case 2:
722 stw_phys(addr & ~1, val);
723 break;
724 case 4:
725 default:
726 stl_phys(addr & ~3, val);
727 break;
728 case 8:
729 stq_phys(addr & ~7, val);
730 break;
733 break;
734 case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
736 switch(size) {
737 case 1:
738 stb_phys((target_phys_addr_t)addr
739 | ((target_phys_addr_t)(asi & 0xf) << 32), val);
740 break;
741 case 2:
742 stw_phys((target_phys_addr_t)(addr & ~1)
743 | ((target_phys_addr_t)(asi & 0xf) << 32), val);
744 break;
745 case 4:
746 default:
747 stl_phys((target_phys_addr_t)(addr & ~3)
748 | ((target_phys_addr_t)(asi & 0xf) << 32), val);
749 break;
750 case 8:
751 stq_phys((target_phys_addr_t)(addr & ~7)
752 | ((target_phys_addr_t)(asi & 0xf) << 32), val);
753 break;
756 break;
757 case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
758 case 0x31: // store buffer data, Ross RT620 I-cache flush or
759 // Turbosparc snoop RAM
760 case 0x32: // store buffer control or Turbosparc page table descriptor diagnostic
761 case 0x36: /* I-cache flash clear */
762 case 0x37: /* D-cache flash clear */
763 case 0x38: /* breakpoint diagnostics */
764 case 0x4c: /* breakpoint action */
765 break;
766 case 8: /* User code access, XXX */
767 case 9: /* Supervisor code access, XXX */
768 default:
769 do_unassigned_access(addr, 1, 0, asi);
770 break;
772 #ifdef DEBUG_ASI
773 dump_asi("write", addr, asi, size, val);
774 #endif
777 #endif /* CONFIG_USER_ONLY */
778 #else /* TARGET_SPARC64 */
780 #ifdef CONFIG_USER_ONLY
781 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
783 uint64_t ret = 0;
784 #if defined(DEBUG_ASI)
785 target_ulong last_addr = addr;
786 #endif
788 if (asi < 0x80)
789 raise_exception(TT_PRIV_ACT);
791 switch (asi) {
792 case 0x80: // Primary
793 case 0x82: // Primary no-fault
794 case 0x88: // Primary LE
795 case 0x8a: // Primary no-fault LE
797 switch(size) {
798 case 1:
799 ret = ldub_raw(addr);
800 break;
801 case 2:
802 ret = lduw_raw(addr & ~1);
803 break;
804 case 4:
805 ret = ldl_raw(addr & ~3);
806 break;
807 default:
808 case 8:
809 ret = ldq_raw(addr & ~7);
810 break;
813 break;
814 case 0x81: // Secondary
815 case 0x83: // Secondary no-fault
816 case 0x89: // Secondary LE
817 case 0x8b: // Secondary no-fault LE
818 // XXX
819 break;
820 default:
821 break;
824 /* Convert from little endian */
825 switch (asi) {
826 case 0x88: // Primary LE
827 case 0x89: // Secondary LE
828 case 0x8a: // Primary no-fault LE
829 case 0x8b: // Secondary no-fault LE
830 switch(size) {
831 case 2:
832 ret = bswap16(ret);
833 break;
834 case 4:
835 ret = bswap32(ret);
836 break;
837 case 8:
838 ret = bswap64(ret);
839 break;
840 default:
841 break;
843 default:
844 break;
847 /* Convert to signed number */
848 if (sign) {
849 switch(size) {
850 case 1:
851 ret = (int8_t) ret;
852 break;
853 case 2:
854 ret = (int16_t) ret;
855 break;
856 case 4:
857 ret = (int32_t) ret;
858 break;
859 default:
860 break;
863 #ifdef DEBUG_ASI
864 dump_asi("read ", last_addr, asi, size, ret);
865 #endif
866 return ret;
869 void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
871 #ifdef DEBUG_ASI
872 dump_asi("write", addr, asi, size, val);
873 #endif
874 if (asi < 0x80)
875 raise_exception(TT_PRIV_ACT);
877 /* Convert to little endian */
878 switch (asi) {
879 case 0x88: // Primary LE
880 case 0x89: // Secondary LE
881 switch(size) {
882 case 2:
883 addr = bswap16(addr);
884 break;
885 case 4:
886 addr = bswap32(addr);
887 break;
888 case 8:
889 addr = bswap64(addr);
890 break;
891 default:
892 break;
894 default:
895 break;
898 switch(asi) {
899 case 0x80: // Primary
900 case 0x88: // Primary LE
902 switch(size) {
903 case 1:
904 stb_raw(addr, val);
905 break;
906 case 2:
907 stw_raw(addr & ~1, val);
908 break;
909 case 4:
910 stl_raw(addr & ~3, val);
911 break;
912 case 8:
913 default:
914 stq_raw(addr & ~7, val);
915 break;
918 break;
919 case 0x81: // Secondary
920 case 0x89: // Secondary LE
921 // XXX
922 return;
924 case 0x82: // Primary no-fault, RO
925 case 0x83: // Secondary no-fault, RO
926 case 0x8a: // Primary no-fault LE, RO
927 case 0x8b: // Secondary no-fault LE, RO
928 default:
929 do_unassigned_access(addr, 1, 0, 1);
930 return;
934 #else /* CONFIG_USER_ONLY */
936 uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
938 uint64_t ret = 0;
939 #if defined(DEBUG_ASI)
940 target_ulong last_addr = addr;
941 #endif
943 if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
944 || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
945 raise_exception(TT_PRIV_ACT);
947 switch (asi) {
948 case 0x10: // As if user primary
949 case 0x18: // As if user primary LE
950 case 0x80: // Primary
951 case 0x82: // Primary no-fault
952 case 0x88: // Primary LE
953 case 0x8a: // Primary no-fault LE
954 if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
955 if (env->hpstate & HS_PRIV) {
956 switch(size) {
957 case 1:
958 ret = ldub_hypv(addr);
959 break;
960 case 2:
961 ret = lduw_hypv(addr & ~1);
962 break;
963 case 4:
964 ret = ldl_hypv(addr & ~3);
965 break;
966 default:
967 case 8:
968 ret = ldq_hypv(addr & ~7);
969 break;
971 } else {
972 switch(size) {
973 case 1:
974 ret = ldub_kernel(addr);
975 break;
976 case 2:
977 ret = lduw_kernel(addr & ~1);
978 break;
979 case 4:
980 ret = ldl_kernel(addr & ~3);
981 break;
982 default:
983 case 8:
984 ret = ldq_kernel(addr & ~7);
985 break;
988 } else {
989 switch(size) {
990 case 1:
991 ret = ldub_user(addr);
992 break;
993 case 2:
994 ret = lduw_user(addr & ~1);
995 break;
996 case 4:
997 ret = ldl_user(addr & ~3);
998 break;
999 default:
1000 case 8:
1001 ret = ldq_user(addr & ~7);
1002 break;
1005 break;
1006 case 0x14: // Bypass
1007 case 0x15: // Bypass, non-cacheable
1008 case 0x1c: // Bypass LE
1009 case 0x1d: // Bypass, non-cacheable LE
1011 switch(size) {
1012 case 1:
1013 ret = ldub_phys(addr);
1014 break;
1015 case 2:
1016 ret = lduw_phys(addr & ~1);
1017 break;
1018 case 4:
1019 ret = ldl_phys(addr & ~3);
1020 break;
1021 default:
1022 case 8:
1023 ret = ldq_phys(addr & ~7);
1024 break;
1026 break;
1028 case 0x04: // Nucleus
1029 case 0x0c: // Nucleus Little Endian (LE)
1030 case 0x11: // As if user secondary
1031 case 0x19: // As if user secondary LE
1032 case 0x24: // Nucleus quad LDD 128 bit atomic
1033 case 0x2c: // Nucleus quad LDD 128 bit atomic
1034 case 0x4a: // UPA config
1035 case 0x81: // Secondary
1036 case 0x83: // Secondary no-fault
1037 case 0x89: // Secondary LE
1038 case 0x8b: // Secondary no-fault LE
1039 // XXX
1040 break;
1041 case 0x45: // LSU
1042 ret = env->lsu;
1043 break;
1044 case 0x50: // I-MMU regs
1046 int reg = (addr >> 3) & 0xf;
1048 ret = env->immuregs[reg];
1049 break;
1051 case 0x51: // I-MMU 8k TSB pointer
1052 case 0x52: // I-MMU 64k TSB pointer
1053 case 0x55: // I-MMU data access
1054 // XXX
1055 break;
1056 case 0x56: // I-MMU tag read
1058 unsigned int i;
1060 for (i = 0; i < 64; i++) {
1061 // Valid, ctx match, vaddr match
1062 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1063 env->itlb_tag[i] == addr) {
1064 ret = env->itlb_tag[i];
1065 break;
1068 break;
1070 case 0x58: // D-MMU regs
1072 int reg = (addr >> 3) & 0xf;
1074 ret = env->dmmuregs[reg];
1075 break;
1077 case 0x5e: // D-MMU tag read
1079 unsigned int i;
1081 for (i = 0; i < 64; i++) {
1082 // Valid, ctx match, vaddr match
1083 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1084 env->dtlb_tag[i] == addr) {
1085 ret = env->dtlb_tag[i];
1086 break;
1089 break;
1091 case 0x59: // D-MMU 8k TSB pointer
1092 case 0x5a: // D-MMU 64k TSB pointer
1093 case 0x5b: // D-MMU data pointer
1094 case 0x5d: // D-MMU data access
1095 case 0x48: // Interrupt dispatch, RO
1096 case 0x49: // Interrupt data receive
1097 case 0x7f: // Incoming interrupt vector, RO
1098 // XXX
1099 break;
1100 case 0x54: // I-MMU data in, WO
1101 case 0x57: // I-MMU demap, WO
1102 case 0x5c: // D-MMU data in, WO
1103 case 0x5f: // D-MMU demap, WO
1104 case 0x77: // Interrupt vector, WO
1105 default:
1106 do_unassigned_access(addr, 0, 0, 1);
1107 ret = 0;
1108 break;
1111 /* Convert from little endian */
1112 switch (asi) {
1113 case 0x0c: // Nucleus Little Endian (LE)
1114 case 0x18: // As if user primary LE
1115 case 0x19: // As if user secondary LE
1116 case 0x1c: // Bypass LE
1117 case 0x1d: // Bypass, non-cacheable LE
1118 case 0x88: // Primary LE
1119 case 0x89: // Secondary LE
1120 case 0x8a: // Primary no-fault LE
1121 case 0x8b: // Secondary no-fault LE
1122 switch(size) {
1123 case 2:
1124 ret = bswap16(ret);
1125 break;
1126 case 4:
1127 ret = bswap32(ret);
1128 break;
1129 case 8:
1130 ret = bswap64(ret);
1131 break;
1132 default:
1133 break;
1135 default:
1136 break;
1139 /* Convert to signed number */
1140 if (sign) {
1141 switch(size) {
1142 case 1:
1143 ret = (int8_t) ret;
1144 break;
1145 case 2:
1146 ret = (int16_t) ret;
1147 break;
1148 case 4:
1149 ret = (int32_t) ret;
1150 break;
1151 default:
1152 break;
1155 #ifdef DEBUG_ASI
1156 dump_asi("read ", last_addr, asi, size, ret);
1157 #endif
1158 return ret;
1161 void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1163 #ifdef DEBUG_ASI
1164 dump_asi("write", addr, asi, size, val);
1165 #endif
1166 if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1167 || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1168 raise_exception(TT_PRIV_ACT);
1170 /* Convert to little endian */
1171 switch (asi) {
1172 case 0x0c: // Nucleus Little Endian (LE)
1173 case 0x18: // As if user primary LE
1174 case 0x19: // As if user secondary LE
1175 case 0x1c: // Bypass LE
1176 case 0x1d: // Bypass, non-cacheable LE
1177 case 0x88: // Primary LE
1178 case 0x89: // Secondary LE
1179 switch(size) {
1180 case 2:
1181 addr = bswap16(addr);
1182 break;
1183 case 4:
1184 addr = bswap32(addr);
1185 break;
1186 case 8:
1187 addr = bswap64(addr);
1188 break;
1189 default:
1190 break;
1192 default:
1193 break;
1196 switch(asi) {
1197 case 0x10: // As if user primary
1198 case 0x18: // As if user primary LE
1199 case 0x80: // Primary
1200 case 0x88: // Primary LE
1201 if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1202 if (env->hpstate & HS_PRIV) {
1203 switch(size) {
1204 case 1:
1205 stb_hypv(addr, val);
1206 break;
1207 case 2:
1208 stw_hypv(addr & ~1, val);
1209 break;
1210 case 4:
1211 stl_hypv(addr & ~3, val);
1212 break;
1213 case 8:
1214 default:
1215 stq_hypv(addr & ~7, val);
1216 break;
1218 } else {
1219 switch(size) {
1220 case 1:
1221 stb_kernel(addr, val);
1222 break;
1223 case 2:
1224 stw_kernel(addr & ~1, val);
1225 break;
1226 case 4:
1227 stl_kernel(addr & ~3, val);
1228 break;
1229 case 8:
1230 default:
1231 stq_kernel(addr & ~7, val);
1232 break;
1235 } else {
1236 switch(size) {
1237 case 1:
1238 stb_user(addr, val);
1239 break;
1240 case 2:
1241 stw_user(addr & ~1, val);
1242 break;
1243 case 4:
1244 stl_user(addr & ~3, val);
1245 break;
1246 case 8:
1247 default:
1248 stq_user(addr & ~7, val);
1249 break;
1252 break;
1253 case 0x14: // Bypass
1254 case 0x15: // Bypass, non-cacheable
1255 case 0x1c: // Bypass LE
1256 case 0x1d: // Bypass, non-cacheable LE
1258 switch(size) {
1259 case 1:
1260 stb_phys(addr, val);
1261 break;
1262 case 2:
1263 stw_phys(addr & ~1, val);
1264 break;
1265 case 4:
1266 stl_phys(addr & ~3, val);
1267 break;
1268 case 8:
1269 default:
1270 stq_phys(addr & ~7, val);
1271 break;
1274 return;
1275 case 0x04: // Nucleus
1276 case 0x0c: // Nucleus Little Endian (LE)
1277 case 0x11: // As if user secondary
1278 case 0x19: // As if user secondary LE
1279 case 0x24: // Nucleus quad LDD 128 bit atomic
1280 case 0x2c: // Nucleus quad LDD 128 bit atomic
1281 case 0x4a: // UPA config
1282 case 0x81: // Secondary
1283 case 0x89: // Secondary LE
1284 // XXX
1285 return;
1286 case 0x45: // LSU
1288 uint64_t oldreg;
1290 oldreg = env->lsu;
1291 env->lsu = val & (DMMU_E | IMMU_E);
1292 // Mappings generated during D/I MMU disabled mode are
1293 // invalid in normal mode
1294 if (oldreg != env->lsu) {
1295 DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
1296 #ifdef DEBUG_MMU
1297 dump_mmu(env);
1298 #endif
1299 tlb_flush(env, 1);
1301 return;
1303 case 0x50: // I-MMU regs
1305 int reg = (addr >> 3) & 0xf;
1306 uint64_t oldreg;
1308 oldreg = env->immuregs[reg];
1309 switch(reg) {
1310 case 0: // RO
1311 case 4:
1312 return;
1313 case 1: // Not in I-MMU
1314 case 2:
1315 case 7:
1316 case 8:
1317 return;
1318 case 3: // SFSR
1319 if ((val & 1) == 0)
1320 val = 0; // Clear SFSR
1321 break;
1322 case 5: // TSB access
1323 case 6: // Tag access
1324 default:
1325 break;
1327 env->immuregs[reg] = val;
1328 if (oldreg != env->immuregs[reg]) {
1329 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
1331 #ifdef DEBUG_MMU
1332 dump_mmu(env);
1333 #endif
1334 return;
1336 case 0x54: // I-MMU data in
1338 unsigned int i;
1340 // Try finding an invalid entry
1341 for (i = 0; i < 64; i++) {
1342 if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
1343 env->itlb_tag[i] = env->immuregs[6];
1344 env->itlb_tte[i] = val;
1345 return;
1348 // Try finding an unlocked entry
1349 for (i = 0; i < 64; i++) {
1350 if ((env->itlb_tte[i] & 0x40) == 0) {
1351 env->itlb_tag[i] = env->immuregs[6];
1352 env->itlb_tte[i] = val;
1353 return;
1356 // error state?
1357 return;
1359 case 0x55: // I-MMU data access
1361 unsigned int i = (addr >> 3) & 0x3f;
1363 env->itlb_tag[i] = env->immuregs[6];
1364 env->itlb_tte[i] = val;
1365 return;
1367 case 0x57: // I-MMU demap
1368 // XXX
1369 return;
1370 case 0x58: // D-MMU regs
1372 int reg = (addr >> 3) & 0xf;
1373 uint64_t oldreg;
1375 oldreg = env->dmmuregs[reg];
1376 switch(reg) {
1377 case 0: // RO
1378 case 4:
1379 return;
1380 case 3: // SFSR
1381 if ((val & 1) == 0) {
1382 val = 0; // Clear SFSR, Fault address
1383 env->dmmuregs[4] = 0;
1385 env->dmmuregs[reg] = val;
1386 break;
1387 case 1: // Primary context
1388 case 2: // Secondary context
1389 case 5: // TSB access
1390 case 6: // Tag access
1391 case 7: // Virtual Watchpoint
1392 case 8: // Physical Watchpoint
1393 default:
1394 break;
1396 env->dmmuregs[reg] = val;
1397 if (oldreg != env->dmmuregs[reg]) {
1398 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
1400 #ifdef DEBUG_MMU
1401 dump_mmu(env);
1402 #endif
1403 return;
1405 case 0x5c: // D-MMU data in
1407 unsigned int i;
1409 // Try finding an invalid entry
1410 for (i = 0; i < 64; i++) {
1411 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
1412 env->dtlb_tag[i] = env->dmmuregs[6];
1413 env->dtlb_tte[i] = val;
1414 return;
1417 // Try finding an unlocked entry
1418 for (i = 0; i < 64; i++) {
1419 if ((env->dtlb_tte[i] & 0x40) == 0) {
1420 env->dtlb_tag[i] = env->dmmuregs[6];
1421 env->dtlb_tte[i] = val;
1422 return;
1425 // error state?
1426 return;
1428 case 0x5d: // D-MMU data access
1430 unsigned int i = (addr >> 3) & 0x3f;
1432 env->dtlb_tag[i] = env->dmmuregs[6];
1433 env->dtlb_tte[i] = val;
1434 return;
1436 case 0x5f: // D-MMU demap
1437 case 0x49: // Interrupt data receive
1438 // XXX
1439 return;
1440 case 0x51: // I-MMU 8k TSB pointer, RO
1441 case 0x52: // I-MMU 64k TSB pointer, RO
1442 case 0x56: // I-MMU tag read, RO
1443 case 0x59: // D-MMU 8k TSB pointer, RO
1444 case 0x5a: // D-MMU 64k TSB pointer, RO
1445 case 0x5b: // D-MMU data pointer, RO
1446 case 0x5e: // D-MMU tag read, RO
1447 case 0x48: // Interrupt dispatch, RO
1448 case 0x7f: // Incoming interrupt vector, RO
1449 case 0x82: // Primary no-fault, RO
1450 case 0x83: // Secondary no-fault, RO
1451 case 0x8a: // Primary no-fault LE, RO
1452 case 0x8b: // Secondary no-fault LE, RO
1453 default:
1454 do_unassigned_access(addr, 1, 0, 1);
1455 return;
1458 #endif /* CONFIG_USER_ONLY */
1460 void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
1462 unsigned int i;
1463 target_ulong val;
1465 switch (asi) {
1466 case 0xf0: // Block load primary
1467 case 0xf1: // Block load secondary
1468 case 0xf8: // Block load primary LE
1469 case 0xf9: // Block load secondary LE
1470 if (rd & 7) {
1471 raise_exception(TT_ILL_INSN);
1472 return;
1474 if (addr & 0x3f) {
1475 raise_exception(TT_UNALIGNED);
1476 return;
1478 for (i = 0; i < 16; i++) {
1479 *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, 0);
1480 addr += 4;
1483 return;
1484 default:
1485 break;
1488 val = helper_ld_asi(addr, asi, size, 0);
1489 switch(size) {
1490 default:
1491 case 4:
1492 *((uint32_t *)&FT0) = val;
1493 break;
1494 case 8:
1495 *((int64_t *)&DT0) = val;
1496 break;
1497 #if defined(CONFIG_USER_ONLY)
1498 case 16:
1499 // XXX
1500 break;
1501 #endif
1505 void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
1507 unsigned int i;
1508 target_ulong val = 0;
1510 switch (asi) {
1511 case 0xf0: // Block store primary
1512 case 0xf1: // Block store secondary
1513 case 0xf8: // Block store primary LE
1514 case 0xf9: // Block store secondary LE
1515 if (rd & 7) {
1516 raise_exception(TT_ILL_INSN);
1517 return;
1519 if (addr & 0x3f) {
1520 raise_exception(TT_UNALIGNED);
1521 return;
1523 for (i = 0; i < 16; i++) {
1524 val = *(uint32_t *)&env->fpr[rd++];
1525 helper_st_asi(addr, val, asi & 0x8f, 4);
1526 addr += 4;
1529 return;
1530 default:
1531 break;
1534 switch(size) {
1535 default:
1536 case 4:
1537 val = *((uint32_t *)&FT0);
1538 break;
1539 case 8:
1540 val = *((int64_t *)&DT0);
1541 break;
1542 #if defined(CONFIG_USER_ONLY)
1543 case 16:
1544 // XXX
1545 break;
1546 #endif
1548 helper_st_asi(addr, val, asi, size);
1551 target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
1552 target_ulong val2, uint32_t asi)
1554 target_ulong ret;
1556 val1 &= 0xffffffffUL;
1557 ret = helper_ld_asi(addr, asi, 4, 0);
1558 ret &= 0xffffffffUL;
1559 if (val1 == ret)
1560 helper_st_asi(addr, val2 & 0xffffffffUL, asi, 4);
1561 return ret;
1564 target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
1565 target_ulong val2, uint32_t asi)
1567 target_ulong ret;
1569 ret = helper_ld_asi(addr, asi, 8, 0);
1570 if (val1 == ret)
1571 helper_st_asi(addr, val2, asi, 8);
1572 return ret;
1574 #endif /* TARGET_SPARC64 */
1576 #ifndef TARGET_SPARC64
1577 void helper_rett(void)
1579 unsigned int cwp;
1581 if (env->psret == 1)
1582 raise_exception(TT_ILL_INSN);
1584 env->psret = 1;
1585 cwp = (env->cwp + 1) & (NWINDOWS - 1);
1586 if (env->wim & (1 << cwp)) {
1587 raise_exception(TT_WIN_UNF);
1589 set_cwp(cwp);
1590 env->psrs = env->psrps;
1592 #endif
1594 uint64_t helper_pack64(target_ulong high, target_ulong low)
1596 return ((uint64_t)high << 32) | (uint64_t)(low & 0xffffffff);
1599 void helper_ldfsr(void)
1601 int rnd_mode;
1602 switch (env->fsr & FSR_RD_MASK) {
1603 case FSR_RD_NEAREST:
1604 rnd_mode = float_round_nearest_even;
1605 break;
1606 default:
1607 case FSR_RD_ZERO:
1608 rnd_mode = float_round_to_zero;
1609 break;
1610 case FSR_RD_POS:
1611 rnd_mode = float_round_up;
1612 break;
1613 case FSR_RD_NEG:
1614 rnd_mode = float_round_down;
1615 break;
1617 set_float_rounding_mode(rnd_mode, &env->fp_status);
1620 void helper_debug()
1622 env->exception_index = EXCP_DEBUG;
1623 cpu_loop_exit();
1626 #ifndef TARGET_SPARC64
1627 void helper_wrpsr(target_ulong new_psr)
1629 if ((new_psr & PSR_CWP) >= NWINDOWS)
1630 raise_exception(TT_ILL_INSN);
1631 else
1632 PUT_PSR(env, new_psr);
1635 target_ulong helper_rdpsr(void)
1637 return GET_PSR(env);
1640 #else
1642 target_ulong helper_popc(target_ulong val)
1644 return ctpop64(val);
1647 static inline uint64_t *get_gregset(uint64_t pstate)
1649 switch (pstate) {
1650 default:
1651 case 0:
1652 return env->bgregs;
1653 case PS_AG:
1654 return env->agregs;
1655 case PS_MG:
1656 return env->mgregs;
1657 case PS_IG:
1658 return env->igregs;
1662 static inline void change_pstate(uint64_t new_pstate)
1664 uint64_t pstate_regs, new_pstate_regs;
1665 uint64_t *src, *dst;
1667 pstate_regs = env->pstate & 0xc01;
1668 new_pstate_regs = new_pstate & 0xc01;
1669 if (new_pstate_regs != pstate_regs) {
1670 // Switch global register bank
1671 src = get_gregset(new_pstate_regs);
1672 dst = get_gregset(pstate_regs);
1673 memcpy32(dst, env->gregs);
1674 memcpy32(env->gregs, src);
1676 env->pstate = new_pstate;
1679 void helper_wrpstate(target_ulong new_state)
1681 change_pstate(new_state & 0xf3f);
1684 void helper_done(void)
1686 env->tl--;
1687 env->pc = env->tnpc[env->tl];
1688 env->npc = env->tnpc[env->tl] + 4;
1689 PUT_CCR(env, env->tstate[env->tl] >> 32);
1690 env->asi = (env->tstate[env->tl] >> 24) & 0xff;
1691 change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
1692 PUT_CWP64(env, env->tstate[env->tl] & 0xff);
1695 void helper_retry(void)
1697 env->tl--;
1698 env->pc = env->tpc[env->tl];
1699 env->npc = env->tnpc[env->tl];
1700 PUT_CCR(env, env->tstate[env->tl] >> 32);
1701 env->asi = (env->tstate[env->tl] >> 24) & 0xff;
1702 change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
1703 PUT_CWP64(env, env->tstate[env->tl] & 0xff);
1705 #endif
1707 void set_cwp(int new_cwp)
1709 /* put the modified wrap registers at their proper location */
1710 if (env->cwp == (NWINDOWS - 1))
1711 memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
1712 env->cwp = new_cwp;
1713 /* put the wrap registers at their temporary location */
1714 if (new_cwp == (NWINDOWS - 1))
1715 memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
1716 env->regwptr = env->regbase + (new_cwp * 16);
1717 REGWPTR = env->regwptr;
1720 void cpu_set_cwp(CPUState *env1, int new_cwp)
1722 CPUState *saved_env;
1723 #ifdef reg_REGWPTR
1724 target_ulong *saved_regwptr;
1725 #endif
1727 saved_env = env;
1728 #ifdef reg_REGWPTR
1729 saved_regwptr = REGWPTR;
1730 #endif
1731 env = env1;
1732 set_cwp(new_cwp);
1733 env = saved_env;
1734 #ifdef reg_REGWPTR
1735 REGWPTR = saved_regwptr;
1736 #endif
1739 #ifdef TARGET_SPARC64
1740 #ifdef DEBUG_PCALL
1741 static const char * const excp_names[0x50] = {
1742 [TT_TFAULT] = "Instruction Access Fault",
1743 [TT_TMISS] = "Instruction Access MMU Miss",
1744 [TT_CODE_ACCESS] = "Instruction Access Error",
1745 [TT_ILL_INSN] = "Illegal Instruction",
1746 [TT_PRIV_INSN] = "Privileged Instruction",
1747 [TT_NFPU_INSN] = "FPU Disabled",
1748 [TT_FP_EXCP] = "FPU Exception",
1749 [TT_TOVF] = "Tag Overflow",
1750 [TT_CLRWIN] = "Clean Windows",
1751 [TT_DIV_ZERO] = "Division By Zero",
1752 [TT_DFAULT] = "Data Access Fault",
1753 [TT_DMISS] = "Data Access MMU Miss",
1754 [TT_DATA_ACCESS] = "Data Access Error",
1755 [TT_DPROT] = "Data Protection Error",
1756 [TT_UNALIGNED] = "Unaligned Memory Access",
1757 [TT_PRIV_ACT] = "Privileged Action",
1758 [TT_EXTINT | 0x1] = "External Interrupt 1",
1759 [TT_EXTINT | 0x2] = "External Interrupt 2",
1760 [TT_EXTINT | 0x3] = "External Interrupt 3",
1761 [TT_EXTINT | 0x4] = "External Interrupt 4",
1762 [TT_EXTINT | 0x5] = "External Interrupt 5",
1763 [TT_EXTINT | 0x6] = "External Interrupt 6",
1764 [TT_EXTINT | 0x7] = "External Interrupt 7",
1765 [TT_EXTINT | 0x8] = "External Interrupt 8",
1766 [TT_EXTINT | 0x9] = "External Interrupt 9",
1767 [TT_EXTINT | 0xa] = "External Interrupt 10",
1768 [TT_EXTINT | 0xb] = "External Interrupt 11",
1769 [TT_EXTINT | 0xc] = "External Interrupt 12",
1770 [TT_EXTINT | 0xd] = "External Interrupt 13",
1771 [TT_EXTINT | 0xe] = "External Interrupt 14",
1772 [TT_EXTINT | 0xf] = "External Interrupt 15",
1774 #endif
1776 void do_interrupt(int intno)
1778 #ifdef DEBUG_PCALL
1779 if (loglevel & CPU_LOG_INT) {
1780 static int count;
1781 const char *name;
1783 if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80))
1784 name = "Unknown";
1785 else if (intno >= 0x100)
1786 name = "Trap Instruction";
1787 else if (intno >= 0xc0)
1788 name = "Window Fill";
1789 else if (intno >= 0x80)
1790 name = "Window Spill";
1791 else {
1792 name = excp_names[intno];
1793 if (!name)
1794 name = "Unknown";
1797 fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
1798 " SP=%016" PRIx64 "\n",
1799 count, name, intno,
1800 env->pc,
1801 env->npc, env->regwptr[6]);
1802 cpu_dump_state(env, logfile, fprintf, 0);
1803 #if 0
1805 int i;
1806 uint8_t *ptr;
1808 fprintf(logfile, " code=");
1809 ptr = (uint8_t *)env->pc;
1810 for(i = 0; i < 16; i++) {
1811 fprintf(logfile, " %02x", ldub(ptr + i));
1813 fprintf(logfile, "\n");
1815 #endif
1816 count++;
1818 #endif
1819 #if !defined(CONFIG_USER_ONLY)
1820 if (env->tl == MAXTL) {
1821 cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
1822 return;
1824 #endif
1825 env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
1826 ((env->pstate & 0xf3f) << 8) | GET_CWP64(env);
1827 env->tpc[env->tl] = env->pc;
1828 env->tnpc[env->tl] = env->npc;
1829 env->tt[env->tl] = intno;
1830 change_pstate(PS_PEF | PS_PRIV | PS_AG);
1832 if (intno == TT_CLRWIN)
1833 set_cwp((env->cwp - 1) & (NWINDOWS - 1));
1834 else if ((intno & 0x1c0) == TT_SPILL)
1835 set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1));
1836 else if ((intno & 0x1c0) == TT_FILL)
1837 set_cwp((env->cwp + 1) & (NWINDOWS - 1));
1838 env->tbr &= ~0x7fffULL;
1839 env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
1840 if (env->tl < MAXTL - 1) {
1841 env->tl++;
1842 } else {
1843 env->pstate |= PS_RED;
1844 if (env->tl != MAXTL)
1845 env->tl++;
1847 env->pc = env->tbr;
1848 env->npc = env->pc + 4;
1849 env->exception_index = 0;
1851 #else
1852 #ifdef DEBUG_PCALL
1853 static const char * const excp_names[0x80] = {
1854 [TT_TFAULT] = "Instruction Access Fault",
1855 [TT_ILL_INSN] = "Illegal Instruction",
1856 [TT_PRIV_INSN] = "Privileged Instruction",
1857 [TT_NFPU_INSN] = "FPU Disabled",
1858 [TT_WIN_OVF] = "Window Overflow",
1859 [TT_WIN_UNF] = "Window Underflow",
1860 [TT_UNALIGNED] = "Unaligned Memory Access",
1861 [TT_FP_EXCP] = "FPU Exception",
1862 [TT_DFAULT] = "Data Access Fault",
1863 [TT_TOVF] = "Tag Overflow",
1864 [TT_EXTINT | 0x1] = "External Interrupt 1",
1865 [TT_EXTINT | 0x2] = "External Interrupt 2",
1866 [TT_EXTINT | 0x3] = "External Interrupt 3",
1867 [TT_EXTINT | 0x4] = "External Interrupt 4",
1868 [TT_EXTINT | 0x5] = "External Interrupt 5",
1869 [TT_EXTINT | 0x6] = "External Interrupt 6",
1870 [TT_EXTINT | 0x7] = "External Interrupt 7",
1871 [TT_EXTINT | 0x8] = "External Interrupt 8",
1872 [TT_EXTINT | 0x9] = "External Interrupt 9",
1873 [TT_EXTINT | 0xa] = "External Interrupt 10",
1874 [TT_EXTINT | 0xb] = "External Interrupt 11",
1875 [TT_EXTINT | 0xc] = "External Interrupt 12",
1876 [TT_EXTINT | 0xd] = "External Interrupt 13",
1877 [TT_EXTINT | 0xe] = "External Interrupt 14",
1878 [TT_EXTINT | 0xf] = "External Interrupt 15",
1879 [TT_TOVF] = "Tag Overflow",
1880 [TT_CODE_ACCESS] = "Instruction Access Error",
1881 [TT_DATA_ACCESS] = "Data Access Error",
1882 [TT_DIV_ZERO] = "Division By Zero",
1883 [TT_NCP_INSN] = "Coprocessor Disabled",
1885 #endif
1887 void do_interrupt(int intno)
1889 int cwp;
1891 #ifdef DEBUG_PCALL
1892 if (loglevel & CPU_LOG_INT) {
1893 static int count;
1894 const char *name;
1896 if (intno < 0 || intno >= 0x100)
1897 name = "Unknown";
1898 else if (intno >= 0x80)
1899 name = "Trap Instruction";
1900 else {
1901 name = excp_names[intno];
1902 if (!name)
1903 name = "Unknown";
1906 fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
1907 count, name, intno,
1908 env->pc,
1909 env->npc, env->regwptr[6]);
1910 cpu_dump_state(env, logfile, fprintf, 0);
1911 #if 0
1913 int i;
1914 uint8_t *ptr;
1916 fprintf(logfile, " code=");
1917 ptr = (uint8_t *)env->pc;
1918 for(i = 0; i < 16; i++) {
1919 fprintf(logfile, " %02x", ldub(ptr + i));
1921 fprintf(logfile, "\n");
1923 #endif
1924 count++;
1926 #endif
1927 #if !defined(CONFIG_USER_ONLY)
1928 if (env->psret == 0) {
1929 cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
1930 return;
1932 #endif
1933 env->psret = 0;
1934 cwp = (env->cwp - 1) & (NWINDOWS - 1);
1935 set_cwp(cwp);
1936 env->regwptr[9] = env->pc;
1937 env->regwptr[10] = env->npc;
1938 env->psrps = env->psrs;
1939 env->psrs = 1;
1940 env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
1941 env->pc = env->tbr;
1942 env->npc = env->pc + 4;
1943 env->exception_index = 0;
1945 #endif
1947 #if !defined(CONFIG_USER_ONLY)
1949 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1950 void *retaddr);
1952 #define MMUSUFFIX _mmu
1953 #define ALIGNED_ONLY
1954 #ifdef __s390__
1955 # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
1956 #else
1957 # define GETPC() (__builtin_return_address(0))
1958 #endif
1960 #define SHIFT 0
1961 #include "softmmu_template.h"
1963 #define SHIFT 1
1964 #include "softmmu_template.h"
1966 #define SHIFT 2
1967 #include "softmmu_template.h"
1969 #define SHIFT 3
1970 #include "softmmu_template.h"
1972 static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1973 void *retaddr)
1975 #ifdef DEBUG_UNALIGNED
1976 printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
1977 #endif
1978 raise_exception(TT_UNALIGNED);
1981 /* try to fill the TLB and return an exception if error. If retaddr is
1982 NULL, it means that the function was called in C code (i.e. not
1983 from generated code or from helper.c) */
1984 /* XXX: fix it to restore all registers */
1985 void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1987 TranslationBlock *tb;
1988 int ret;
1989 unsigned long pc;
1990 CPUState *saved_env;
1992 /* XXX: hack to restore env in all cases, even if not called from
1993 generated code */
1994 saved_env = env;
1995 env = cpu_single_env;
1997 ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1998 if (ret) {
1999 if (retaddr) {
2000 /* now we have a real cpu fault */
2001 pc = (unsigned long)retaddr;
2002 tb = tb_find_pc(pc);
2003 if (tb) {
2004 /* the PC is inside the translated code. It means that we have
2005 a virtual CPU fault */
2006 cpu_restore_state(tb, env, pc, (void *)T2);
2009 cpu_loop_exit();
2011 env = saved_env;
2014 #endif
2016 #ifndef TARGET_SPARC64
2017 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2018 int is_asi)
2020 CPUState *saved_env;
2022 /* XXX: hack to restore env in all cases, even if not called from
2023 generated code */
2024 saved_env = env;
2025 env = cpu_single_env;
2026 #ifdef DEBUG_UNASSIGNED
2027 if (is_asi)
2028 printf("Unassigned mem %s access to " TARGET_FMT_plx " asi 0x%02x from "
2029 TARGET_FMT_lx "\n",
2030 is_exec ? "exec" : is_write ? "write" : "read", addr, is_asi,
2031 env->pc);
2032 else
2033 printf("Unassigned mem %s access to " TARGET_FMT_plx " from "
2034 TARGET_FMT_lx "\n",
2035 is_exec ? "exec" : is_write ? "write" : "read", addr, env->pc);
2036 #endif
2037 if (env->mmuregs[3]) /* Fault status register */
2038 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
2039 if (is_asi)
2040 env->mmuregs[3] |= 1 << 16;
2041 if (env->psrs)
2042 env->mmuregs[3] |= 1 << 5;
2043 if (is_exec)
2044 env->mmuregs[3] |= 1 << 6;
2045 if (is_write)
2046 env->mmuregs[3] |= 1 << 7;
2047 env->mmuregs[3] |= (5 << 2) | 2;
2048 env->mmuregs[4] = addr; /* Fault address register */
2049 if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
2050 if (is_exec)
2051 raise_exception(TT_CODE_ACCESS);
2052 else
2053 raise_exception(TT_DATA_ACCESS);
2055 env = saved_env;
2057 #else
2058 void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2059 int is_asi)
2061 #ifdef DEBUG_UNASSIGNED
2062 CPUState *saved_env;
2064 /* XXX: hack to restore env in all cases, even if not called from
2065 generated code */
2066 saved_env = env;
2067 env = cpu_single_env;
2068 printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n",
2069 addr, env->pc);
2070 env = saved_env;
2071 #endif
2072 if (is_exec)
2073 raise_exception(TT_CODE_ACCESS);
2074 else
2075 raise_exception(TT_DATA_ACCESS);
2077 #endif