]> git.proxmox.com Git - qemu.git/blame - target-sparc/op_helper.c
sparc64: fix TT_WOTHER value
[qemu.git] / target-sparc / op_helper.c
CommitLineData
e8af50a3 1#include "exec.h"
eed152bb 2#include "host-utils.h"
1a2fb1c0 3#include "helper.h"
e8af50a3 4
e80cfcfc 5//#define DEBUG_MMU
952a328f 6//#define DEBUG_MXCC
94554550 7//#define DEBUG_UNALIGNED
6c36d3fa 8//#define DEBUG_UNASSIGNED
8543e2cf 9//#define DEBUG_ASI
d81fd722 10//#define DEBUG_PCALL
7e8695ed 11//#define DEBUG_PSTATE
e80cfcfc 12
952a328f 13#ifdef DEBUG_MMU
001faf32
BS
14#define DPRINTF_MMU(fmt, ...) \
15 do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0)
952a328f 16#else
001faf32 17#define DPRINTF_MMU(fmt, ...) do {} while (0)
952a328f
BS
18#endif
19
20#ifdef DEBUG_MXCC
001faf32
BS
21#define DPRINTF_MXCC(fmt, ...) \
22 do { printf("MXCC: " fmt , ## __VA_ARGS__); } while (0)
952a328f 23#else
001faf32 24#define DPRINTF_MXCC(fmt, ...) do {} while (0)
952a328f
BS
25#endif
26
8543e2cf 27#ifdef DEBUG_ASI
001faf32
BS
28#define DPRINTF_ASI(fmt, ...) \
29 do { printf("ASI: " fmt , ## __VA_ARGS__); } while (0)
8543e2cf
BS
30#endif
31
7e8695ed
IK
32#ifdef DEBUG_PSTATE
33#define DPRINTF_PSTATE(fmt, ...) \
34 do { printf("PSTATE: " fmt , ## __VA_ARGS__); } while (0)
35#else
36#define DPRINTF_PSTATE(fmt, ...) do {} while (0)
37#endif
38
2cade6a3
BS
39#ifdef TARGET_SPARC64
40#ifndef TARGET_ABI32
41#define AM_CHECK(env1) ((env1)->pstate & PS_AM)
c2bc0e38 42#else
2cade6a3
BS
43#define AM_CHECK(env1) (1)
44#endif
c2bc0e38
BS
45#endif
46
3c7b48b7
PB
47#if defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
48static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
49 int is_asi, int size);
50#endif
51
9c22a623 52#if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
697a77e6
IK
53// Calculates TSB pointer value for fault page size 8k or 64k
54static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
55 uint64_t tag_access_register,
56 int page_size)
57{
58 uint64_t tsb_base = tsb_register & ~0x1fffULL;
6e8e7d4c
IK
59 int tsb_split = (tsb_register & 0x1000ULL) ? 1 : 0;
60 int tsb_size = tsb_register & 0xf;
697a77e6
IK
61
62 // discard lower 13 bits which hold tag access context
63 uint64_t tag_access_va = tag_access_register & ~0x1fffULL;
64
65 // now reorder bits
66 uint64_t tsb_base_mask = ~0x1fffULL;
67 uint64_t va = tag_access_va;
68
69 // move va bits to correct position
70 if (page_size == 8*1024) {
71 va >>= 9;
72 } else if (page_size == 64*1024) {
73 va >>= 12;
74 }
75
76 if (tsb_size) {
77 tsb_base_mask <<= tsb_size;
78 }
79
80 // calculate tsb_base mask and adjust va if split is in use
81 if (tsb_split) {
82 if (page_size == 8*1024) {
83 va &= ~(1ULL << (13 + tsb_size));
84 } else if (page_size == 64*1024) {
85 va |= (1ULL << (13 + tsb_size));
86 }
87 tsb_base_mask <<= 1;
88 }
89
90 return ((tsb_base & tsb_base_mask) | (va & ~tsb_base_mask)) & ~0xfULL;
91}
92
93// Calculates tag target register value by reordering bits
94// in tag access register
95static uint64_t ultrasparc_tag_target(uint64_t tag_access_register)
96{
97 return ((tag_access_register & 0x1fff) << 48) | (tag_access_register >> 22);
98}
99
f707726e
IK
100static void replace_tlb_entry(SparcTLBEntry *tlb,
101 uint64_t tlb_tag, uint64_t tlb_tte,
102 CPUState *env1)
6e8e7d4c
IK
103{
104 target_ulong mask, size, va, offset;
105
106 // flush page range if translation is valid
f707726e 107 if (TTE_IS_VALID(tlb->tte)) {
6e8e7d4c
IK
108
109 mask = 0xffffffffffffe000ULL;
110 mask <<= 3 * ((tlb->tte >> 61) & 3);
111 size = ~mask + 1;
112
113 va = tlb->tag & mask;
114
115 for (offset = 0; offset < size; offset += TARGET_PAGE_SIZE) {
116 tlb_flush_page(env1, va + offset);
117 }
118 }
119
120 tlb->tag = tlb_tag;
121 tlb->tte = tlb_tte;
122}
123
124static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
f707726e 125 const char* strmmu, CPUState *env1)
6e8e7d4c
IK
126{
127 unsigned int i;
128 target_ulong mask;
299b520c
IK
129 uint64_t context;
130
131 int is_demap_context = (demap_addr >> 6) & 1;
132
133 // demap context
134 switch ((demap_addr >> 4) & 3) {
135 case 0: // primary
136 context = env1->dmmu.mmu_primary_context;
137 break;
138 case 1: // secondary
139 context = env1->dmmu.mmu_secondary_context;
140 break;
141 case 2: // nucleus
142 context = 0;
143 break;
144 case 3: // reserved
145 default:
146 return;
147 }
6e8e7d4c
IK
148
149 for (i = 0; i < 64; i++) {
f707726e 150 if (TTE_IS_VALID(tlb[i].tte)) {
6e8e7d4c 151
299b520c
IK
152 if (is_demap_context) {
153 // will remove non-global entries matching context value
154 if (TTE_IS_GLOBAL(tlb[i].tte) ||
155 !tlb_compare_context(&tlb[i], context)) {
156 continue;
157 }
158 } else {
159 // demap page
160 // will remove any entry matching VA
161 mask = 0xffffffffffffe000ULL;
162 mask <<= 3 * ((tlb[i].tte >> 61) & 3);
163
164 if (!compare_masked(demap_addr, tlb[i].tag, mask)) {
165 continue;
166 }
167
168 // entry should be global or matching context value
169 if (!TTE_IS_GLOBAL(tlb[i].tte) &&
170 !tlb_compare_context(&tlb[i], context)) {
171 continue;
172 }
173 }
6e8e7d4c 174
299b520c 175 replace_tlb_entry(&tlb[i], 0, 0, env1);
6e8e7d4c 176#ifdef DEBUG_MMU
299b520c
IK
177 DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
178 dump_mmu(env1);
6e8e7d4c 179#endif
6e8e7d4c
IK
180 }
181 }
6e8e7d4c
IK
182}
183
f707726e
IK
184static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
185 uint64_t tlb_tag, uint64_t tlb_tte,
186 const char* strmmu, CPUState *env1)
187{
188 unsigned int i, replace_used;
189
190 // Try replacing invalid entry
191 for (i = 0; i < 64; i++) {
192 if (!TTE_IS_VALID(tlb[i].tte)) {
193 replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
194#ifdef DEBUG_MMU
195 DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu, i);
196 dump_mmu(env1);
197#endif
198 return;
199 }
200 }
201
202 // All entries are valid, try replacing unlocked entry
203
204 for (replace_used = 0; replace_used < 2; ++replace_used) {
205
206 // Used entries are not replaced on first pass
207
208 for (i = 0; i < 64; i++) {
209 if (!TTE_IS_LOCKED(tlb[i].tte) && !TTE_IS_USED(tlb[i].tte)) {
210
211 replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
212#ifdef DEBUG_MMU
213 DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
214 strmmu, (replace_used?"used":"unused"), i);
215 dump_mmu(env1);
216#endif
217 return;
218 }
219 }
220
221 // Now reset used bit and search for unused entries again
222
223 for (i = 0; i < 64; i++) {
224 TTE_SET_UNUSED(tlb[i].tte);
225 }
226 }
227
228#ifdef DEBUG_MMU
229 DPRINTF_MMU("%s lru replacement failed: no entries available\n", strmmu);
230#endif
231 // error state?
232}
233
697a77e6
IK
234#endif
235
41db525e 236static inline target_ulong address_mask(CPUState *env1, target_ulong addr)
2cade6a3
BS
237{
238#ifdef TARGET_SPARC64
239 if (AM_CHECK(env1))
41db525e 240 addr &= 0xffffffffULL;
2cade6a3 241#endif
41db525e 242 return addr;
2cade6a3
BS
243}
244
f4a5a5ba 245static void raise_exception(int tt)
9d893301
FB
246{
247 env->exception_index = tt;
248 cpu_loop_exit();
3b46e624 249}
9d893301 250
a7812ae4
PB
251void HELPER(raise_exception)(int tt)
252{
253 raise_exception(tt);
254}
255
2b29924f
BS
256void helper_check_align(target_ulong addr, uint32_t align)
257{
c2bc0e38
BS
258 if (addr & align) {
259#ifdef DEBUG_UNALIGNED
260 printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
261 "\n", addr, env->pc);
262#endif
2b29924f 263 raise_exception(TT_UNALIGNED);
c2bc0e38 264 }
2b29924f
BS
265}
266
44e7757c
BS
267#define F_HELPER(name, p) void helper_f##name##p(void)
268
44e7757c 269#define F_BINOP(name) \
714547bb 270 float32 helper_f ## name ## s (float32 src1, float32 src2) \
44e7757c 271 { \
714547bb 272 return float32_ ## name (src1, src2, &env->fp_status); \
44e7757c
BS
273 } \
274 F_HELPER(name, d) \
275 { \
276 DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \
4e14008f
BS
277 } \
278 F_HELPER(name, q) \
279 { \
280 QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \
44e7757c 281 }
44e7757c
BS
282
283F_BINOP(add);
284F_BINOP(sub);
285F_BINOP(mul);
286F_BINOP(div);
287#undef F_BINOP
288
d84763bc 289void helper_fsmuld(float32 src1, float32 src2)
1a2fb1c0 290{
d84763bc
BS
291 DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
292 float32_to_float64(src2, &env->fp_status),
44e7757c
BS
293 &env->fp_status);
294}
1a2fb1c0 295
4e14008f
BS
296void helper_fdmulq(void)
297{
298 QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
299 float64_to_float128(DT1, &env->fp_status),
300 &env->fp_status);
301}
4e14008f 302
714547bb 303float32 helper_fnegs(float32 src)
44e7757c 304{
714547bb 305 return float32_chs(src);
417454b0
BS
306}
307
44e7757c
BS
308#ifdef TARGET_SPARC64
309F_HELPER(neg, d)
7e8c2b6c 310{
44e7757c 311 DT0 = float64_chs(DT1);
7e8c2b6c 312}
4e14008f 313
4e14008f
BS
314F_HELPER(neg, q)
315{
316 QT0 = float128_chs(QT1);
317}
318#endif
44e7757c
BS
319
320/* Integer to float conversion. */
714547bb 321float32 helper_fitos(int32_t src)
a0c4cb4a 322{
714547bb 323 return int32_to_float32(src, &env->fp_status);
a0c4cb4a
FB
324}
325
d84763bc 326void helper_fitod(int32_t src)
a0c4cb4a 327{
d84763bc 328 DT0 = int32_to_float64(src, &env->fp_status);
a0c4cb4a 329}
9c2b428e 330
c5d04e99 331void helper_fitoq(int32_t src)
4e14008f 332{
c5d04e99 333 QT0 = int32_to_float128(src, &env->fp_status);
4e14008f 334}
4e14008f 335
1e64e78d 336#ifdef TARGET_SPARC64
d84763bc 337float32 helper_fxtos(void)
1e64e78d 338{
d84763bc 339 return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
1e64e78d
BS
340}
341
44e7757c 342F_HELPER(xto, d)
1e64e78d 343{
1e64e78d 344 DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
1e64e78d 345}
64a88d5d 346
4e14008f
BS
347F_HELPER(xto, q)
348{
349 QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
350}
351#endif
44e7757c
BS
352#undef F_HELPER
353
354/* floating point conversion */
d84763bc 355float32 helper_fdtos(void)
44e7757c 356{
d84763bc 357 return float64_to_float32(DT1, &env->fp_status);
44e7757c
BS
358}
359
d84763bc 360void helper_fstod(float32 src)
44e7757c 361{
d84763bc 362 DT0 = float32_to_float64(src, &env->fp_status);
44e7757c 363}
9c2b428e 364
c5d04e99 365float32 helper_fqtos(void)
4e14008f 366{
c5d04e99 367 return float128_to_float32(QT1, &env->fp_status);
4e14008f
BS
368}
369
c5d04e99 370void helper_fstoq(float32 src)
4e14008f 371{
c5d04e99 372 QT0 = float32_to_float128(src, &env->fp_status);
4e14008f
BS
373}
374
375void helper_fqtod(void)
376{
377 DT0 = float128_to_float64(QT1, &env->fp_status);
378}
379
380void helper_fdtoq(void)
381{
382 QT0 = float64_to_float128(DT1, &env->fp_status);
383}
4e14008f 384
44e7757c 385/* Float to integer conversion. */
714547bb 386int32_t helper_fstoi(float32 src)
44e7757c 387{
714547bb 388 return float32_to_int32_round_to_zero(src, &env->fp_status);
44e7757c
BS
389}
390
d84763bc 391int32_t helper_fdtoi(void)
44e7757c 392{
d84763bc 393 return float64_to_int32_round_to_zero(DT1, &env->fp_status);
44e7757c
BS
394}
395
c5d04e99 396int32_t helper_fqtoi(void)
4e14008f 397{
c5d04e99 398 return float128_to_int32_round_to_zero(QT1, &env->fp_status);
4e14008f 399}
4e14008f 400
44e7757c 401#ifdef TARGET_SPARC64
d84763bc 402void helper_fstox(float32 src)
44e7757c 403{
d84763bc 404 *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
44e7757c
BS
405}
406
407void helper_fdtox(void)
408{
409 *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
410}
411
4e14008f
BS
412void helper_fqtox(void)
413{
414 *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
415}
4e14008f 416
44e7757c
BS
417void helper_faligndata(void)
418{
419 uint64_t tmp;
420
421 tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
06057e6f
BS
422 /* on many architectures a shift of 64 does nothing */
423 if ((env->gsr & 7) != 0) {
424 tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
425 }
44e7757c
BS
426 *((uint64_t *)&DT0) = tmp;
427}
428
e2542fe2 429#ifdef HOST_WORDS_BIGENDIAN
44e7757c
BS
430#define VIS_B64(n) b[7 - (n)]
431#define VIS_W64(n) w[3 - (n)]
432#define VIS_SW64(n) sw[3 - (n)]
433#define VIS_L64(n) l[1 - (n)]
434#define VIS_B32(n) b[3 - (n)]
435#define VIS_W32(n) w[1 - (n)]
436#else
437#define VIS_B64(n) b[n]
438#define VIS_W64(n) w[n]
439#define VIS_SW64(n) sw[n]
440#define VIS_L64(n) l[n]
441#define VIS_B32(n) b[n]
442#define VIS_W32(n) w[n]
443#endif
444
445typedef union {
446 uint8_t b[8];
447 uint16_t w[4];
448 int16_t sw[4];
449 uint32_t l[2];
450 float64 d;
451} vis64;
452
453typedef union {
454 uint8_t b[4];
455 uint16_t w[2];
456 uint32_t l;
457 float32 f;
458} vis32;
459
460void helper_fpmerge(void)
461{
462 vis64 s, d;
463
464 s.d = DT0;
465 d.d = DT1;
466
467 // Reverse calculation order to handle overlap
468 d.VIS_B64(7) = s.VIS_B64(3);
469 d.VIS_B64(6) = d.VIS_B64(3);
470 d.VIS_B64(5) = s.VIS_B64(2);
471 d.VIS_B64(4) = d.VIS_B64(2);
472 d.VIS_B64(3) = s.VIS_B64(1);
473 d.VIS_B64(2) = d.VIS_B64(1);
474 d.VIS_B64(1) = s.VIS_B64(0);
475 //d.VIS_B64(0) = d.VIS_B64(0);
476
477 DT0 = d.d;
478}
479
480void helper_fmul8x16(void)
481{
482 vis64 s, d;
483 uint32_t tmp;
484
485 s.d = DT0;
486 d.d = DT1;
487
488#define PMUL(r) \
489 tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r); \
490 if ((tmp & 0xff) > 0x7f) \
491 tmp += 0x100; \
492 d.VIS_W64(r) = tmp >> 8;
493
494 PMUL(0);
495 PMUL(1);
496 PMUL(2);
497 PMUL(3);
498#undef PMUL
499
500 DT0 = d.d;
501}
502
503void helper_fmul8x16al(void)
504{
505 vis64 s, d;
506 uint32_t tmp;
507
508 s.d = DT0;
509 d.d = DT1;
510
511#define PMUL(r) \
512 tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r); \
513 if ((tmp & 0xff) > 0x7f) \
514 tmp += 0x100; \
515 d.VIS_W64(r) = tmp >> 8;
516
517 PMUL(0);
518 PMUL(1);
519 PMUL(2);
520 PMUL(3);
521#undef PMUL
522
523 DT0 = d.d;
524}
525
526void helper_fmul8x16au(void)
527{
528 vis64 s, d;
529 uint32_t tmp;
530
531 s.d = DT0;
532 d.d = DT1;
533
534#define PMUL(r) \
535 tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r); \
536 if ((tmp & 0xff) > 0x7f) \
537 tmp += 0x100; \
538 d.VIS_W64(r) = tmp >> 8;
539
540 PMUL(0);
541 PMUL(1);
542 PMUL(2);
543 PMUL(3);
544#undef PMUL
545
546 DT0 = d.d;
547}
548
549void helper_fmul8sux16(void)
550{
551 vis64 s, d;
552 uint32_t tmp;
553
554 s.d = DT0;
555 d.d = DT1;
556
557#define PMUL(r) \
558 tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
559 if ((tmp & 0xff) > 0x7f) \
560 tmp += 0x100; \
561 d.VIS_W64(r) = tmp >> 8;
562
563 PMUL(0);
564 PMUL(1);
565 PMUL(2);
566 PMUL(3);
567#undef PMUL
568
569 DT0 = d.d;
570}
571
572void helper_fmul8ulx16(void)
573{
574 vis64 s, d;
575 uint32_t tmp;
576
577 s.d = DT0;
578 d.d = DT1;
579
580#define PMUL(r) \
581 tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
582 if ((tmp & 0xff) > 0x7f) \
583 tmp += 0x100; \
584 d.VIS_W64(r) = tmp >> 8;
585
586 PMUL(0);
587 PMUL(1);
588 PMUL(2);
589 PMUL(3);
590#undef PMUL
591
592 DT0 = d.d;
593}
594
595void helper_fmuld8sux16(void)
596{
597 vis64 s, d;
598 uint32_t tmp;
599
600 s.d = DT0;
601 d.d = DT1;
602
603#define PMUL(r) \
604 tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
605 if ((tmp & 0xff) > 0x7f) \
606 tmp += 0x100; \
607 d.VIS_L64(r) = tmp;
608
609 // Reverse calculation order to handle overlap
610 PMUL(1);
611 PMUL(0);
612#undef PMUL
613
614 DT0 = d.d;
615}
616
617void helper_fmuld8ulx16(void)
618{
619 vis64 s, d;
620 uint32_t tmp;
621
622 s.d = DT0;
623 d.d = DT1;
624
625#define PMUL(r) \
626 tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
627 if ((tmp & 0xff) > 0x7f) \
628 tmp += 0x100; \
629 d.VIS_L64(r) = tmp;
630
631 // Reverse calculation order to handle overlap
632 PMUL(1);
633 PMUL(0);
634#undef PMUL
635
636 DT0 = d.d;
637}
638
639void helper_fexpand(void)
640{
641 vis32 s;
642 vis64 d;
643
644 s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
645 d.d = DT1;
c55bda30
BS
646 d.VIS_W64(0) = s.VIS_B32(0) << 4;
647 d.VIS_W64(1) = s.VIS_B32(1) << 4;
648 d.VIS_W64(2) = s.VIS_B32(2) << 4;
649 d.VIS_W64(3) = s.VIS_B32(3) << 4;
44e7757c
BS
650
651 DT0 = d.d;
652}
653
654#define VIS_HELPER(name, F) \
655 void name##16(void) \
656 { \
657 vis64 s, d; \
658 \
659 s.d = DT0; \
660 d.d = DT1; \
661 \
662 d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0)); \
663 d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1)); \
664 d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2)); \
665 d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3)); \
666 \
667 DT0 = d.d; \
668 } \
669 \
1d01299d 670 uint32_t name##16s(uint32_t src1, uint32_t src2) \
44e7757c
BS
671 { \
672 vis32 s, d; \
673 \
1d01299d
BS
674 s.l = src1; \
675 d.l = src2; \
44e7757c
BS
676 \
677 d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0)); \
678 d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1)); \
679 \
1d01299d 680 return d.l; \
44e7757c
BS
681 } \
682 \
683 void name##32(void) \
684 { \
685 vis64 s, d; \
686 \
687 s.d = DT0; \
688 d.d = DT1; \
689 \
690 d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0)); \
691 d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1)); \
692 \
693 DT0 = d.d; \
694 } \
695 \
1d01299d 696 uint32_t name##32s(uint32_t src1, uint32_t src2) \
44e7757c
BS
697 { \
698 vis32 s, d; \
699 \
1d01299d
BS
700 s.l = src1; \
701 d.l = src2; \
44e7757c
BS
702 \
703 d.l = F(d.l, s.l); \
704 \
1d01299d 705 return d.l; \
44e7757c
BS
706 }
707
708#define FADD(a, b) ((a) + (b))
709#define FSUB(a, b) ((a) - (b))
710VIS_HELPER(helper_fpadd, FADD)
711VIS_HELPER(helper_fpsub, FSUB)
712
713#define VIS_CMPHELPER(name, F) \
714 void name##16(void) \
715 { \
716 vis64 s, d; \
717 \
718 s.d = DT0; \
719 d.d = DT1; \
720 \
721 d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0; \
722 d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0; \
723 d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0; \
724 d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0; \
725 \
726 DT0 = d.d; \
727 } \
728 \
729 void name##32(void) \
730 { \
731 vis64 s, d; \
732 \
733 s.d = DT0; \
734 d.d = DT1; \
735 \
736 d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0; \
737 d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0; \
738 \
739 DT0 = d.d; \
740 }
741
742#define FCMPGT(a, b) ((a) > (b))
743#define FCMPEQ(a, b) ((a) == (b))
744#define FCMPLE(a, b) ((a) <= (b))
745#define FCMPNE(a, b) ((a) != (b))
746
747VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
748VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
749VIS_CMPHELPER(helper_fcmple, FCMPLE)
750VIS_CMPHELPER(helper_fcmpne, FCMPNE)
751#endif
752
753void helper_check_ieee_exceptions(void)
754{
755 target_ulong status;
756
757 status = get_float_exception_flags(&env->fp_status);
758 if (status) {
759 /* Copy IEEE 754 flags into FSR */
760 if (status & float_flag_invalid)
761 env->fsr |= FSR_NVC;
762 if (status & float_flag_overflow)
763 env->fsr |= FSR_OFC;
764 if (status & float_flag_underflow)
765 env->fsr |= FSR_UFC;
766 if (status & float_flag_divbyzero)
767 env->fsr |= FSR_DZC;
768 if (status & float_flag_inexact)
769 env->fsr |= FSR_NXC;
770
771 if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
772 /* Unmasked exception, generate a trap */
773 env->fsr |= FSR_FTT_IEEE_EXCP;
774 raise_exception(TT_FP_EXCP);
775 } else {
776 /* Accumulate exceptions */
777 env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
778 }
779 }
780}
781
782void helper_clear_float_exceptions(void)
783{
784 set_float_exception_flags(0, &env->fp_status);
785}
786
714547bb 787float32 helper_fabss(float32 src)
e8af50a3 788{
714547bb 789 return float32_abs(src);
e8af50a3
FB
790}
791
3475187d 792#ifdef TARGET_SPARC64
7e8c2b6c 793void helper_fabsd(void)
3475187d
FB
794{
795 DT0 = float64_abs(DT1);
796}
4e14008f 797
4e14008f
BS
798void helper_fabsq(void)
799{
800 QT0 = float128_abs(QT1);
801}
802#endif
3475187d 803
714547bb 804float32 helper_fsqrts(float32 src)
e8af50a3 805{
714547bb 806 return float32_sqrt(src, &env->fp_status);
e8af50a3
FB
807}
808
7e8c2b6c 809void helper_fsqrtd(void)
e8af50a3 810{
7a0e1f41 811 DT0 = float64_sqrt(DT1, &env->fp_status);
e8af50a3
FB
812}
813
4e14008f
BS
814void helper_fsqrtq(void)
815{
816 QT0 = float128_sqrt(QT1, &env->fp_status);
817}
4e14008f 818
417454b0 819#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
7e8c2b6c 820 void glue(helper_, name) (void) \
65ce8c2f 821 { \
1a2fb1c0
BS
822 target_ulong new_fsr; \
823 \
65ce8c2f
FB
824 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
825 switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
826 case float_relation_unordered: \
1a2fb1c0 827 new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \
417454b0 828 if ((env->fsr & FSR_NVM) || TRAP) { \
1a2fb1c0 829 env->fsr |= new_fsr; \
417454b0
BS
830 env->fsr |= FSR_NVC; \
831 env->fsr |= FSR_FTT_IEEE_EXCP; \
65ce8c2f
FB
832 raise_exception(TT_FP_EXCP); \
833 } else { \
834 env->fsr |= FSR_NVA; \
835 } \
836 break; \
837 case float_relation_less: \
1a2fb1c0 838 new_fsr = FSR_FCC0 << FS; \
65ce8c2f
FB
839 break; \
840 case float_relation_greater: \
1a2fb1c0 841 new_fsr = FSR_FCC1 << FS; \
65ce8c2f
FB
842 break; \
843 default: \
1a2fb1c0 844 new_fsr = 0; \
65ce8c2f
FB
845 break; \
846 } \
1a2fb1c0 847 env->fsr |= new_fsr; \
e8af50a3 848 }
714547bb
BS
849#define GEN_FCMPS(name, size, FS, TRAP) \
850 void glue(helper_, name)(float32 src1, float32 src2) \
851 { \
852 target_ulong new_fsr; \
853 \
854 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
855 switch (glue(size, _compare) (src1, src2, &env->fp_status)) { \
856 case float_relation_unordered: \
857 new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \
858 if ((env->fsr & FSR_NVM) || TRAP) { \
859 env->fsr |= new_fsr; \
860 env->fsr |= FSR_NVC; \
861 env->fsr |= FSR_FTT_IEEE_EXCP; \
862 raise_exception(TT_FP_EXCP); \
863 } else { \
864 env->fsr |= FSR_NVA; \
865 } \
866 break; \
867 case float_relation_less: \
868 new_fsr = FSR_FCC0 << FS; \
869 break; \
870 case float_relation_greater: \
871 new_fsr = FSR_FCC1 << FS; \
872 break; \
873 default: \
874 new_fsr = 0; \
875 break; \
876 } \
877 env->fsr |= new_fsr; \
878 }
e8af50a3 879
714547bb 880GEN_FCMPS(fcmps, float32, 0, 0);
417454b0
BS
881GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
882
714547bb 883GEN_FCMPS(fcmpes, float32, 0, 1);
417454b0 884GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
3475187d 885
4e14008f
BS
886GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
887GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
4e14008f 888
8393617c
BS
889static uint32_t compute_all_flags(void)
890{
891 return env->psr & PSR_ICC;
892}
893
894static uint32_t compute_C_flags(void)
895{
896 return env->psr & PSR_CARRY;
897}
898
bdf9f35d
BS
899static inline uint32_t get_NZ_icc(target_ulong dst)
900{
901 uint32_t ret = 0;
902
903 if (!(dst & 0xffffffffULL))
904 ret |= PSR_ZERO;
905 if ((int32_t) (dst & 0xffffffffULL) < 0)
906 ret |= PSR_NEG;
907 return ret;
908}
909
8393617c
BS
910#ifdef TARGET_SPARC64
911static uint32_t compute_all_flags_xcc(void)
912{
913 return env->xcc & PSR_ICC;
914}
915
916static uint32_t compute_C_flags_xcc(void)
917{
918 return env->xcc & PSR_CARRY;
919}
920
bdf9f35d
BS
921static inline uint32_t get_NZ_xcc(target_ulong dst)
922{
923 uint32_t ret = 0;
924
925 if (!dst)
926 ret |= PSR_ZERO;
927 if ((int64_t)dst < 0)
928 ret |= PSR_NEG;
929 return ret;
930}
931#endif
932
6c78ea32
BS
933static inline uint32_t get_V_div_icc(target_ulong src2)
934{
935 uint32_t ret = 0;
936
937 if (src2 != 0)
938 ret |= PSR_OVF;
939 return ret;
940}
941
942static uint32_t compute_all_div(void)
943{
944 uint32_t ret;
945
946 ret = get_NZ_icc(CC_DST);
947 ret |= get_V_div_icc(CC_SRC2);
948 return ret;
949}
950
951static uint32_t compute_C_div(void)
952{
953 return 0;
954}
955
3e6ba503
AT
956/* carry = (src1[31] & src2[31]) | ( ~dst[31] & (src1[31] | src2[31])) */
957static inline uint32_t get_C_add_icc(target_ulong dst, target_ulong src1,
958 target_ulong src2)
bdf9f35d
BS
959{
960 uint32_t ret = 0;
961
3e6ba503
AT
962 if (((src1 & (1ULL << 31)) & (src2 & (1ULL << 31)))
963 | ((~(dst & (1ULL << 31)))
964 & ((src1 & (1ULL << 31)) | (src2 & (1ULL << 31)))))
bdf9f35d
BS
965 ret |= PSR_CARRY;
966 return ret;
967}
968
969static inline uint32_t get_V_add_icc(target_ulong dst, target_ulong src1,
970 target_ulong src2)
971{
972 uint32_t ret = 0;
973
974 if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 31))
975 ret |= PSR_OVF;
976 return ret;
977}
978
bdf9f35d
BS
979#ifdef TARGET_SPARC64
980static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
981{
982 uint32_t ret = 0;
983
984 if (dst < src1)
985 ret |= PSR_CARRY;
986 return ret;
987}
988
989static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
990 target_ulong src2)
991{
992 uint32_t ret = 0;
993
994 if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63))
995 ret |= PSR_OVF;
996 return ret;
997}
998
999static uint32_t compute_all_add_xcc(void)
1000{
1001 uint32_t ret;
1002
1003 ret = get_NZ_xcc(CC_DST);
1004 ret |= get_C_add_xcc(CC_DST, CC_SRC);
1005 ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
1006 return ret;
1007}
1008
1009static uint32_t compute_C_add_xcc(void)
1010{
1011 return get_C_add_xcc(CC_DST, CC_SRC);
1012}
8393617c
BS
1013#endif
1014
3e6ba503 1015static uint32_t compute_all_add(void)
789c91ef
BS
1016{
1017 uint32_t ret;
1018
1019 ret = get_NZ_icc(CC_DST);
3e6ba503 1020 ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
789c91ef
BS
1021 ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
1022 return ret;
1023}
1024
3e6ba503 1025static uint32_t compute_C_add(void)
789c91ef 1026{
3e6ba503 1027 return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
789c91ef
BS
1028}
1029
1030#ifdef TARGET_SPARC64
1031static uint32_t compute_all_addx_xcc(void)
1032{
1033 uint32_t ret;
1034
1035 ret = get_NZ_xcc(CC_DST);
1036 ret |= get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
1037 ret |= get_C_add_xcc(CC_DST, CC_SRC);
1038 ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
1039 return ret;
1040}
1041
1042static uint32_t compute_C_addx_xcc(void)
1043{
1044 uint32_t ret;
1045
1046 ret = get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
1047 ret |= get_C_add_xcc(CC_DST, CC_SRC);
1048 return ret;
1049}
1050#endif
1051
3b2d1e92
BS
1052static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
1053{
1054 uint32_t ret = 0;
1055
1056 if ((src1 | src2) & 0x3)
1057 ret |= PSR_OVF;
1058 return ret;
1059}
1060
1061static uint32_t compute_all_tadd(void)
1062{
1063 uint32_t ret;
1064
1065 ret = get_NZ_icc(CC_DST);
3e6ba503 1066 ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
3b2d1e92
BS
1067 ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
1068 ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1069 return ret;
1070}
1071
1072static uint32_t compute_C_tadd(void)
1073{
3e6ba503 1074 return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
3b2d1e92
BS
1075}
1076
1077static uint32_t compute_all_taddtv(void)
1078{
1079 uint32_t ret;
1080
1081 ret = get_NZ_icc(CC_DST);
3e6ba503 1082 ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
3b2d1e92
BS
1083 return ret;
1084}
1085
1086static uint32_t compute_C_taddtv(void)
1087{
3e6ba503 1088 return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
3b2d1e92
BS
1089}
1090
3e6ba503
AT
1091/* carry = (~src1[31] & src2[31]) | ( dst[31] & (~src1[31] | src2[31])) */
1092static inline uint32_t get_C_sub_icc(target_ulong dst, target_ulong src1,
1093 target_ulong src2)
d4b0d468
BS
1094{
1095 uint32_t ret = 0;
1096
3e6ba503
AT
1097 if (((~(src1 & (1ULL << 31))) & (src2 & (1ULL << 31)))
1098 | ((dst & (1ULL << 31)) & (( ~(src1 & (1ULL << 31)))
1099 | (src2 & (1ULL << 31)))))
d4b0d468
BS
1100 ret |= PSR_CARRY;
1101 return ret;
1102}
1103
1104static inline uint32_t get_V_sub_icc(target_ulong dst, target_ulong src1,
1105 target_ulong src2)
1106{
1107 uint32_t ret = 0;
1108
1109 if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 31))
1110 ret |= PSR_OVF;
1111 return ret;
1112}
1113
d4b0d468
BS
1114
1115#ifdef TARGET_SPARC64
1116static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
1117{
1118 uint32_t ret = 0;
1119
1120 if (src1 < src2)
1121 ret |= PSR_CARRY;
1122 return ret;
1123}
1124
1125static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
1126 target_ulong src2)
1127{
1128 uint32_t ret = 0;
1129
1130 if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63))
1131 ret |= PSR_OVF;
1132 return ret;
1133}
1134
1135static uint32_t compute_all_sub_xcc(void)
1136{
1137 uint32_t ret;
1138
1139 ret = get_NZ_xcc(CC_DST);
1140 ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
1141 ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1142 return ret;
1143}
1144
1145static uint32_t compute_C_sub_xcc(void)
1146{
1147 return get_C_sub_xcc(CC_SRC, CC_SRC2);
1148}
1149#endif
1150
3e6ba503 1151static uint32_t compute_all_sub(void)
2ca1d92b
BS
1152{
1153 uint32_t ret;
1154
1155 ret = get_NZ_icc(CC_DST);
3e6ba503 1156 ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
2ca1d92b
BS
1157 ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1158 return ret;
1159}
1160
3e6ba503 1161static uint32_t compute_C_sub(void)
2ca1d92b 1162{
3e6ba503 1163 return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
2ca1d92b
BS
1164}
1165
1166#ifdef TARGET_SPARC64
1167static uint32_t compute_all_subx_xcc(void)
1168{
1169 uint32_t ret;
1170
1171 ret = get_NZ_xcc(CC_DST);
1172 ret |= get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
1173 ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
1174 ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1175 return ret;
1176}
1177
1178static uint32_t compute_C_subx_xcc(void)
1179{
1180 uint32_t ret;
1181
1182 ret = get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
1183 ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
1184 return ret;
1185}
1186#endif
1187
3b2d1e92
BS
1188static uint32_t compute_all_tsub(void)
1189{
1190 uint32_t ret;
1191
1192 ret = get_NZ_icc(CC_DST);
3e6ba503 1193 ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
3b2d1e92
BS
1194 ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1195 ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1196 return ret;
1197}
1198
1199static uint32_t compute_C_tsub(void)
1200{
3e6ba503 1201 return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
3b2d1e92
BS
1202}
1203
1204static uint32_t compute_all_tsubtv(void)
1205{
1206 uint32_t ret;
1207
1208 ret = get_NZ_icc(CC_DST);
3e6ba503 1209 ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
3b2d1e92
BS
1210 return ret;
1211}
1212
1213static uint32_t compute_C_tsubtv(void)
1214{
3e6ba503 1215 return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
3b2d1e92
BS
1216}
1217
38482a77
BS
1218static uint32_t compute_all_logic(void)
1219{
1220 return get_NZ_icc(CC_DST);
1221}
1222
1223static uint32_t compute_C_logic(void)
1224{
1225 return 0;
1226}
1227
1228#ifdef TARGET_SPARC64
1229static uint32_t compute_all_logic_xcc(void)
1230{
1231 return get_NZ_xcc(CC_DST);
1232}
1233#endif
1234
8393617c
BS
1235typedef struct CCTable {
1236 uint32_t (*compute_all)(void); /* return all the flags */
1237 uint32_t (*compute_c)(void); /* return the C flag */
1238} CCTable;
1239
1240static const CCTable icc_table[CC_OP_NB] = {
1241 /* CC_OP_DYNAMIC should never happen */
1242 [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
6c78ea32 1243 [CC_OP_DIV] = { compute_all_div, compute_C_div },
bdf9f35d 1244 [CC_OP_ADD] = { compute_all_add, compute_C_add },
3e6ba503 1245 [CC_OP_ADDX] = { compute_all_add, compute_C_add },
3b2d1e92
BS
1246 [CC_OP_TADD] = { compute_all_tadd, compute_C_tadd },
1247 [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_taddtv },
d4b0d468 1248 [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
3e6ba503 1249 [CC_OP_SUBX] = { compute_all_sub, compute_C_sub },
3b2d1e92
BS
1250 [CC_OP_TSUB] = { compute_all_tsub, compute_C_tsub },
1251 [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_tsubtv },
38482a77 1252 [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
8393617c
BS
1253};
1254
1255#ifdef TARGET_SPARC64
1256static const CCTable xcc_table[CC_OP_NB] = {
1257 /* CC_OP_DYNAMIC should never happen */
1258 [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
6c78ea32 1259 [CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
bdf9f35d 1260 [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
789c91ef 1261 [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
3b2d1e92
BS
1262 [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
1263 [CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
d4b0d468 1264 [CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
2ca1d92b 1265 [CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
3b2d1e92
BS
1266 [CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
1267 [CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
38482a77 1268 [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
8393617c
BS
1269};
1270#endif
1271
1272void helper_compute_psr(void)
1273{
1274 uint32_t new_psr;
1275
1276 new_psr = icc_table[CC_OP].compute_all();
1277 env->psr = new_psr;
1278#ifdef TARGET_SPARC64
1279 new_psr = xcc_table[CC_OP].compute_all();
1280 env->xcc = new_psr;
1281#endif
1282 CC_OP = CC_OP_FLAGS;
1283}
1284
1285uint32_t helper_compute_C_icc(void)
1286{
1287 uint32_t ret;
1288
1289 ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
1290 return ret;
1291}
1292
5a834bb4
BS
1293static inline void memcpy32(target_ulong *dst, const target_ulong *src)
1294{
1295 dst[0] = src[0];
1296 dst[1] = src[1];
1297 dst[2] = src[2];
1298 dst[3] = src[3];
1299 dst[4] = src[4];
1300 dst[5] = src[5];
1301 dst[6] = src[6];
1302 dst[7] = src[7];
1303}
1304
1305static void set_cwp(int new_cwp)
1306{
1307 /* put the modified wrap registers at their proper location */
1308 if (env->cwp == env->nwindows - 1) {
1309 memcpy32(env->regbase, env->regbase + env->nwindows * 16);
1310 }
1311 env->cwp = new_cwp;
1312
1313 /* put the wrap registers at their temporary location */
1314 if (new_cwp == env->nwindows - 1) {
1315 memcpy32(env->regbase + env->nwindows * 16, env->regbase);
1316 }
1317 env->regwptr = env->regbase + (new_cwp * 16);
1318}
1319
1320void cpu_set_cwp(CPUState *env1, int new_cwp)
1321{
1322 CPUState *saved_env;
1323
1324 saved_env = env;
1325 env = env1;
1326 set_cwp(new_cwp);
1327 env = saved_env;
1328}
1329
1330static target_ulong get_psr(void)
1331{
1332 helper_compute_psr();
1333
1334#if !defined (TARGET_SPARC64)
1335 return env->version | (env->psr & PSR_ICC) |
1336 (env->psref? PSR_EF : 0) |
1337 (env->psrpil << 8) |
1338 (env->psrs? PSR_S : 0) |
1339 (env->psrps? PSR_PS : 0) |
1340 (env->psret? PSR_ET : 0) | env->cwp;
1341#else
1342 return env->version | (env->psr & PSR_ICC) |
1343 (env->psref? PSR_EF : 0) |
1344 (env->psrpil << 8) |
1345 (env->psrs? PSR_S : 0) |
1346 (env->psrps? PSR_PS : 0) | env->cwp;
1347#endif
1348}
1349
1350target_ulong cpu_get_psr(CPUState *env1)
1351{
1352 CPUState *saved_env;
1353 target_ulong ret;
1354
1355 saved_env = env;
1356 env = env1;
1357 ret = get_psr();
1358 env = saved_env;
1359 return ret;
1360}
1361
1362static void put_psr(target_ulong val)
1363{
1364 env->psr = val & PSR_ICC;
1365 env->psref = (val & PSR_EF)? 1 : 0;
1366 env->psrpil = (val & PSR_PIL) >> 8;
1367#if ((!defined (TARGET_SPARC64)) && !defined(CONFIG_USER_ONLY))
1368 cpu_check_irqs(env);
1369#endif
1370 env->psrs = (val & PSR_S)? 1 : 0;
1371 env->psrps = (val & PSR_PS)? 1 : 0;
1372#if !defined (TARGET_SPARC64)
1373 env->psret = (val & PSR_ET)? 1 : 0;
1374#endif
1375 set_cwp(val & PSR_CWP);
1376 env->cc_op = CC_OP_FLAGS;
1377}
1378
1379void cpu_put_psr(CPUState *env1, target_ulong val)
1380{
1381 CPUState *saved_env;
1382
1383 saved_env = env;
1384 env = env1;
1385 put_psr(val);
1386 env = saved_env;
1387}
1388
1389static int cwp_inc(int cwp)
1390{
1391 if (unlikely(cwp >= env->nwindows)) {
1392 cwp -= env->nwindows;
1393 }
1394 return cwp;
1395}
1396
1397int cpu_cwp_inc(CPUState *env1, int cwp)
1398{
1399 CPUState *saved_env;
1400 target_ulong ret;
1401
1402 saved_env = env;
1403 env = env1;
1404 ret = cwp_inc(cwp);
1405 env = saved_env;
1406 return ret;
1407}
1408
1409static int cwp_dec(int cwp)
1410{
1411 if (unlikely(cwp < 0)) {
1412 cwp += env->nwindows;
1413 }
1414 return cwp;
1415}
1416
1417int cpu_cwp_dec(CPUState *env1, int cwp)
1418{
1419 CPUState *saved_env;
1420 target_ulong ret;
1421
1422 saved_env = env;
1423 env = env1;
1424 ret = cwp_dec(cwp);
1425 env = saved_env;
1426 return ret;
1427}
1428
3475187d 1429#ifdef TARGET_SPARC64
714547bb 1430GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
417454b0 1431GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
64a88d5d 1432GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
417454b0 1433
714547bb 1434GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
417454b0 1435GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
64a88d5d 1436GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
417454b0 1437
714547bb 1438GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
417454b0 1439GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
64a88d5d 1440GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
417454b0 1441
714547bb 1442GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
417454b0 1443GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
64a88d5d 1444GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
3475187d 1445
714547bb 1446GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
417454b0 1447GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
64a88d5d 1448GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
3475187d 1449
714547bb 1450GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
417454b0 1451GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
4e14008f
BS
1452GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
1453#endif
714547bb 1454#undef GEN_FCMPS
3475187d 1455
77f193da
BS
1456#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
1457 defined(DEBUG_MXCC)
952a328f
BS
1458static void dump_mxcc(CPUState *env)
1459{
0bf9e31a
BS
1460 printf("mxccdata: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1461 "\n",
77f193da
BS
1462 env->mxccdata[0], env->mxccdata[1],
1463 env->mxccdata[2], env->mxccdata[3]);
0bf9e31a
BS
1464 printf("mxccregs: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1465 "\n"
1466 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1467 "\n",
77f193da
BS
1468 env->mxccregs[0], env->mxccregs[1],
1469 env->mxccregs[2], env->mxccregs[3],
1470 env->mxccregs[4], env->mxccregs[5],
1471 env->mxccregs[6], env->mxccregs[7]);
952a328f
BS
1472}
1473#endif
1474
1a2fb1c0
BS
1475#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
1476 && defined(DEBUG_ASI)
1477static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
1478 uint64_t r1)
8543e2cf
BS
1479{
1480 switch (size)
1481 {
1482 case 1:
1a2fb1c0
BS
1483 DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
1484 addr, asi, r1 & 0xff);
8543e2cf
BS
1485 break;
1486 case 2:
1a2fb1c0
BS
1487 DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
1488 addr, asi, r1 & 0xffff);
8543e2cf
BS
1489 break;
1490 case 4:
1a2fb1c0
BS
1491 DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
1492 addr, asi, r1 & 0xffffffff);
8543e2cf
BS
1493 break;
1494 case 8:
1a2fb1c0
BS
1495 DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
1496 addr, asi, r1);
8543e2cf
BS
1497 break;
1498 }
1499}
1500#endif
1501
1a2fb1c0
BS
1502#ifndef TARGET_SPARC64
1503#ifndef CONFIG_USER_ONLY
1504uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
e8af50a3 1505{
1a2fb1c0 1506 uint64_t ret = 0;
8543e2cf 1507#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
1a2fb1c0 1508 uint32_t last_addr = addr;
952a328f 1509#endif
e80cfcfc 1510
c2bc0e38 1511 helper_check_align(addr, size - 1);
e80cfcfc 1512 switch (asi) {
6c36d3fa 1513 case 2: /* SuperSparc MXCC registers */
1a2fb1c0 1514 switch (addr) {
952a328f 1515 case 0x01c00a00: /* MXCC control register */
1a2fb1c0
BS
1516 if (size == 8)
1517 ret = env->mxccregs[3];
1518 else
77f193da
BS
1519 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1520 size);
952a328f
BS
1521 break;
1522 case 0x01c00a04: /* MXCC control register */
1523 if (size == 4)
1524 ret = env->mxccregs[3];
1525 else
77f193da
BS
1526 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1527 size);
952a328f 1528 break;
295db113
BS
1529 case 0x01c00c00: /* Module reset register */
1530 if (size == 8) {
1a2fb1c0 1531 ret = env->mxccregs[5];
295db113
BS
1532 // should we do something here?
1533 } else
77f193da
BS
1534 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1535 size);
295db113 1536 break;
952a328f 1537 case 0x01c00f00: /* MBus port address register */
1a2fb1c0
BS
1538 if (size == 8)
1539 ret = env->mxccregs[7];
1540 else
77f193da
BS
1541 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1542 size);
952a328f
BS
1543 break;
1544 default:
77f193da
BS
1545 DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1546 size);
952a328f
BS
1547 break;
1548 }
77f193da 1549 DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
9827e450 1550 "addr = %08x -> ret = %" PRIx64 ","
1a2fb1c0 1551 "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
952a328f
BS
1552#ifdef DEBUG_MXCC
1553 dump_mxcc(env);
1554#endif
6c36d3fa 1555 break;
e8af50a3 1556 case 3: /* MMU probe */
0f8a249a
BS
1557 {
1558 int mmulev;
1559
1a2fb1c0 1560 mmulev = (addr >> 8) & 15;
0f8a249a
BS
1561 if (mmulev > 4)
1562 ret = 0;
1a2fb1c0
BS
1563 else
1564 ret = mmu_probe(env, addr, mmulev);
1565 DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
1566 addr, mmulev, ret);
0f8a249a
BS
1567 }
1568 break;
e8af50a3 1569 case 4: /* read MMU regs */
0f8a249a 1570 {
1a2fb1c0 1571 int reg = (addr >> 8) & 0x1f;
3b46e624 1572
0f8a249a
BS
1573 ret = env->mmuregs[reg];
1574 if (reg == 3) /* Fault status cleared on read */
3dd9a152
BS
1575 env->mmuregs[3] = 0;
1576 else if (reg == 0x13) /* Fault status read */
1577 ret = env->mmuregs[3];
1578 else if (reg == 0x14) /* Fault address read */
1579 ret = env->mmuregs[4];
1a2fb1c0 1580 DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
0f8a249a
BS
1581 }
1582 break;
045380be
BS
1583 case 5: // Turbosparc ITLB Diagnostic
1584 case 6: // Turbosparc DTLB Diagnostic
1585 case 7: // Turbosparc IOTLB Diagnostic
1586 break;
6c36d3fa
BS
1587 case 9: /* Supervisor code access */
1588 switch(size) {
1589 case 1:
1a2fb1c0 1590 ret = ldub_code(addr);
6c36d3fa
BS
1591 break;
1592 case 2:
a4e7dd52 1593 ret = lduw_code(addr);
6c36d3fa
BS
1594 break;
1595 default:
1596 case 4:
a4e7dd52 1597 ret = ldl_code(addr);
6c36d3fa
BS
1598 break;
1599 case 8:
a4e7dd52 1600 ret = ldq_code(addr);
6c36d3fa
BS
1601 break;
1602 }
1603 break;
81ad8ba2
BS
1604 case 0xa: /* User data access */
1605 switch(size) {
1606 case 1:
1a2fb1c0 1607 ret = ldub_user(addr);
81ad8ba2
BS
1608 break;
1609 case 2:
a4e7dd52 1610 ret = lduw_user(addr);
81ad8ba2
BS
1611 break;
1612 default:
1613 case 4:
a4e7dd52 1614 ret = ldl_user(addr);
81ad8ba2
BS
1615 break;
1616 case 8:
a4e7dd52 1617 ret = ldq_user(addr);
81ad8ba2
BS
1618 break;
1619 }
1620 break;
1621 case 0xb: /* Supervisor data access */
1622 switch(size) {
1623 case 1:
1a2fb1c0 1624 ret = ldub_kernel(addr);
81ad8ba2
BS
1625 break;
1626 case 2:
a4e7dd52 1627 ret = lduw_kernel(addr);
81ad8ba2
BS
1628 break;
1629 default:
1630 case 4:
a4e7dd52 1631 ret = ldl_kernel(addr);
81ad8ba2
BS
1632 break;
1633 case 8:
a4e7dd52 1634 ret = ldq_kernel(addr);
81ad8ba2
BS
1635 break;
1636 }
1637 break;
6c36d3fa
BS
1638 case 0xc: /* I-cache tag */
1639 case 0xd: /* I-cache data */
1640 case 0xe: /* D-cache tag */
1641 case 0xf: /* D-cache data */
1642 break;
1643 case 0x20: /* MMU passthrough */
02aab46a
FB
1644 switch(size) {
1645 case 1:
1a2fb1c0 1646 ret = ldub_phys(addr);
02aab46a
FB
1647 break;
1648 case 2:
a4e7dd52 1649 ret = lduw_phys(addr);
02aab46a
FB
1650 break;
1651 default:
1652 case 4:
a4e7dd52 1653 ret = ldl_phys(addr);
02aab46a 1654 break;
9e61bde5 1655 case 8:
a4e7dd52 1656 ret = ldq_phys(addr);
0f8a249a 1657 break;
02aab46a 1658 }
0f8a249a 1659 break;
7d85892b 1660 case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
5dcb6b91
BS
1661 switch(size) {
1662 case 1:
c227f099
AL
1663 ret = ldub_phys((target_phys_addr_t)addr
1664 | ((target_phys_addr_t)(asi & 0xf) << 32));
5dcb6b91
BS
1665 break;
1666 case 2:
c227f099
AL
1667 ret = lduw_phys((target_phys_addr_t)addr
1668 | ((target_phys_addr_t)(asi & 0xf) << 32));
5dcb6b91
BS
1669 break;
1670 default:
1671 case 4:
c227f099
AL
1672 ret = ldl_phys((target_phys_addr_t)addr
1673 | ((target_phys_addr_t)(asi & 0xf) << 32));
5dcb6b91
BS
1674 break;
1675 case 8:
c227f099
AL
1676 ret = ldq_phys((target_phys_addr_t)addr
1677 | ((target_phys_addr_t)(asi & 0xf) << 32));
0f8a249a 1678 break;
5dcb6b91 1679 }
0f8a249a 1680 break;
045380be
BS
1681 case 0x30: // Turbosparc secondary cache diagnostic
1682 case 0x31: // Turbosparc RAM snoop
1683 case 0x32: // Turbosparc page table descriptor diagnostic
666c87aa
BS
1684 case 0x39: /* data cache diagnostic register */
1685 ret = 0;
1686 break;
4017190e
BS
1687 case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
1688 {
1689 int reg = (addr >> 8) & 3;
1690
1691 switch(reg) {
1692 case 0: /* Breakpoint Value (Addr) */
1693 ret = env->mmubpregs[reg];
1694 break;
1695 case 1: /* Breakpoint Mask */
1696 ret = env->mmubpregs[reg];
1697 break;
1698 case 2: /* Breakpoint Control */
1699 ret = env->mmubpregs[reg];
1700 break;
1701 case 3: /* Breakpoint Status */
1702 ret = env->mmubpregs[reg];
1703 env->mmubpregs[reg] = 0ULL;
1704 break;
1705 }
0bf9e31a
BS
1706 DPRINTF_MMU("read breakpoint reg[%d] 0x%016" PRIx64 "\n", reg,
1707 ret);
4017190e
BS
1708 }
1709 break;
045380be 1710 case 8: /* User code access, XXX */
e8af50a3 1711 default:
e18231a3 1712 do_unassigned_access(addr, 0, 0, asi, size);
0f8a249a
BS
1713 ret = 0;
1714 break;
e8af50a3 1715 }
81ad8ba2
BS
1716 if (sign) {
1717 switch(size) {
1718 case 1:
1a2fb1c0 1719 ret = (int8_t) ret;
e32664fb 1720 break;
81ad8ba2 1721 case 2:
1a2fb1c0
BS
1722 ret = (int16_t) ret;
1723 break;
1724 case 4:
1725 ret = (int32_t) ret;
e32664fb 1726 break;
81ad8ba2 1727 default:
81ad8ba2
BS
1728 break;
1729 }
1730 }
8543e2cf 1731#ifdef DEBUG_ASI
1a2fb1c0 1732 dump_asi("read ", last_addr, asi, size, ret);
8543e2cf 1733#endif
1a2fb1c0 1734 return ret;
e8af50a3
FB
1735}
1736
1a2fb1c0 1737void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
e8af50a3 1738{
c2bc0e38 1739 helper_check_align(addr, size - 1);
e8af50a3 1740 switch(asi) {
6c36d3fa 1741 case 2: /* SuperSparc MXCC registers */
1a2fb1c0 1742 switch (addr) {
952a328f
BS
1743 case 0x01c00000: /* MXCC stream data register 0 */
1744 if (size == 8)
1a2fb1c0 1745 env->mxccdata[0] = val;
952a328f 1746 else
77f193da
BS
1747 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1748 size);
952a328f
BS
1749 break;
1750 case 0x01c00008: /* MXCC stream data register 1 */
1751 if (size == 8)
1a2fb1c0 1752 env->mxccdata[1] = val;
952a328f 1753 else
77f193da
BS
1754 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1755 size);
952a328f
BS
1756 break;
1757 case 0x01c00010: /* MXCC stream data register 2 */
1758 if (size == 8)
1a2fb1c0 1759 env->mxccdata[2] = val;
952a328f 1760 else
77f193da
BS
1761 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1762 size);
952a328f
BS
1763 break;
1764 case 0x01c00018: /* MXCC stream data register 3 */
1765 if (size == 8)
1a2fb1c0 1766 env->mxccdata[3] = val;
952a328f 1767 else
77f193da
BS
1768 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1769 size);
952a328f
BS
1770 break;
1771 case 0x01c00100: /* MXCC stream source */
1772 if (size == 8)
1a2fb1c0 1773 env->mxccregs[0] = val;
952a328f 1774 else
77f193da
BS
1775 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1776 size);
1777 env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1778 0);
1779 env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1780 8);
1781 env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1782 16);
1783 env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1784 24);
952a328f
BS
1785 break;
1786 case 0x01c00200: /* MXCC stream destination */
1787 if (size == 8)
1a2fb1c0 1788 env->mxccregs[1] = val;
952a328f 1789 else
77f193da
BS
1790 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1791 size);
1792 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0,
1793 env->mxccdata[0]);
1794 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8,
1795 env->mxccdata[1]);
1796 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
1797 env->mxccdata[2]);
1798 stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
1799 env->mxccdata[3]);
952a328f
BS
1800 break;
1801 case 0x01c00a00: /* MXCC control register */
1802 if (size == 8)
1a2fb1c0 1803 env->mxccregs[3] = val;
952a328f 1804 else
77f193da
BS
1805 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1806 size);
952a328f
BS
1807 break;
1808 case 0x01c00a04: /* MXCC control register */
1809 if (size == 4)
9f4576f0 1810 env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
77f193da 1811 | val;
952a328f 1812 else
77f193da
BS
1813 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1814 size);
952a328f
BS
1815 break;
1816 case 0x01c00e00: /* MXCC error register */
bbf7d96b 1817 // writing a 1 bit clears the error
952a328f 1818 if (size == 8)
1a2fb1c0 1819 env->mxccregs[6] &= ~val;
952a328f 1820 else
77f193da
BS
1821 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1822 size);
952a328f
BS
1823 break;
1824 case 0x01c00f00: /* MBus port address register */
1825 if (size == 8)
1a2fb1c0 1826 env->mxccregs[7] = val;
952a328f 1827 else
77f193da
BS
1828 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1829 size);
952a328f
BS
1830 break;
1831 default:
77f193da
BS
1832 DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1833 size);
952a328f
BS
1834 break;
1835 }
9827e450
BS
1836 DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
1837 asi, size, addr, val);
952a328f
BS
1838#ifdef DEBUG_MXCC
1839 dump_mxcc(env);
1840#endif
6c36d3fa 1841 break;
e8af50a3 1842 case 3: /* MMU flush */
0f8a249a
BS
1843 {
1844 int mmulev;
e80cfcfc 1845
1a2fb1c0 1846 mmulev = (addr >> 8) & 15;
952a328f 1847 DPRINTF_MMU("mmu flush level %d\n", mmulev);
0f8a249a
BS
1848 switch (mmulev) {
1849 case 0: // flush page
1a2fb1c0 1850 tlb_flush_page(env, addr & 0xfffff000);
0f8a249a
BS
1851 break;
1852 case 1: // flush segment (256k)
1853 case 2: // flush region (16M)
1854 case 3: // flush context (4G)
1855 case 4: // flush entire
1856 tlb_flush(env, 1);
1857 break;
1858 default:
1859 break;
1860 }
55754d9e 1861#ifdef DEBUG_MMU
0f8a249a 1862 dump_mmu(env);
55754d9e 1863#endif
0f8a249a 1864 }
8543e2cf 1865 break;
e8af50a3 1866 case 4: /* write MMU regs */
0f8a249a 1867 {
1a2fb1c0 1868 int reg = (addr >> 8) & 0x1f;
0f8a249a 1869 uint32_t oldreg;
3b46e624 1870
0f8a249a 1871 oldreg = env->mmuregs[reg];
55754d9e 1872 switch(reg) {
3deaeab7 1873 case 0: // Control Register
3dd9a152 1874 env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
1a2fb1c0 1875 (val & 0x00ffffff);
0f8a249a
BS
1876 // Mappings generated during no-fault mode or MMU
1877 // disabled mode are invalid in normal mode
5578ceab
BS
1878 if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
1879 (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
55754d9e
FB
1880 tlb_flush(env, 1);
1881 break;
3deaeab7 1882 case 1: // Context Table Pointer Register
5578ceab 1883 env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
3deaeab7
BS
1884 break;
1885 case 2: // Context Register
5578ceab 1886 env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
55754d9e
FB
1887 if (oldreg != env->mmuregs[reg]) {
1888 /* we flush when the MMU context changes because
1889 QEMU has no MMU context support */
1890 tlb_flush(env, 1);
1891 }
1892 break;
3deaeab7
BS
1893 case 3: // Synchronous Fault Status Register with Clear
1894 case 4: // Synchronous Fault Address Register
1895 break;
1896 case 0x10: // TLB Replacement Control Register
5578ceab 1897 env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
55754d9e 1898 break;
3deaeab7 1899 case 0x13: // Synchronous Fault Status Register with Read and Clear
5578ceab 1900 env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
3dd9a152 1901 break;
3deaeab7 1902 case 0x14: // Synchronous Fault Address Register
1a2fb1c0 1903 env->mmuregs[4] = val;
3dd9a152 1904 break;
55754d9e 1905 default:
1a2fb1c0 1906 env->mmuregs[reg] = val;
55754d9e
FB
1907 break;
1908 }
55754d9e 1909 if (oldreg != env->mmuregs[reg]) {
77f193da
BS
1910 DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
1911 reg, oldreg, env->mmuregs[reg]);
55754d9e 1912 }
952a328f 1913#ifdef DEBUG_MMU
0f8a249a 1914 dump_mmu(env);
55754d9e 1915#endif
0f8a249a 1916 }
8543e2cf 1917 break;
045380be
BS
1918 case 5: // Turbosparc ITLB Diagnostic
1919 case 6: // Turbosparc DTLB Diagnostic
1920 case 7: // Turbosparc IOTLB Diagnostic
1921 break;
81ad8ba2
BS
1922 case 0xa: /* User data access */
1923 switch(size) {
1924 case 1:
1a2fb1c0 1925 stb_user(addr, val);
81ad8ba2
BS
1926 break;
1927 case 2:
a4e7dd52 1928 stw_user(addr, val);
81ad8ba2
BS
1929 break;
1930 default:
1931 case 4:
a4e7dd52 1932 stl_user(addr, val);
81ad8ba2
BS
1933 break;
1934 case 8:
a4e7dd52 1935 stq_user(addr, val);
81ad8ba2
BS
1936 break;
1937 }
1938 break;
1939 case 0xb: /* Supervisor data access */
1940 switch(size) {
1941 case 1:
1a2fb1c0 1942 stb_kernel(addr, val);
81ad8ba2
BS
1943 break;
1944 case 2:
a4e7dd52 1945 stw_kernel(addr, val);
81ad8ba2
BS
1946 break;
1947 default:
1948 case 4:
a4e7dd52 1949 stl_kernel(addr, val);
81ad8ba2
BS
1950 break;
1951 case 8:
a4e7dd52 1952 stq_kernel(addr, val);
81ad8ba2
BS
1953 break;
1954 }
1955 break;
6c36d3fa
BS
1956 case 0xc: /* I-cache tag */
1957 case 0xd: /* I-cache data */
1958 case 0xe: /* D-cache tag */
1959 case 0xf: /* D-cache data */
1960 case 0x10: /* I/D-cache flush page */
1961 case 0x11: /* I/D-cache flush segment */
1962 case 0x12: /* I/D-cache flush region */
1963 case 0x13: /* I/D-cache flush context */
1964 case 0x14: /* I/D-cache flush user */
1965 break;
e80cfcfc 1966 case 0x17: /* Block copy, sta access */
0f8a249a 1967 {
1a2fb1c0
BS
1968 // val = src
1969 // addr = dst
0f8a249a 1970 // copy 32 bytes
6c36d3fa 1971 unsigned int i;
1a2fb1c0 1972 uint32_t src = val & ~3, dst = addr & ~3, temp;
3b46e624 1973
6c36d3fa
BS
1974 for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1975 temp = ldl_kernel(src);
1976 stl_kernel(dst, temp);
1977 }
0f8a249a 1978 }
8543e2cf 1979 break;
e80cfcfc 1980 case 0x1f: /* Block fill, stda access */
0f8a249a 1981 {
1a2fb1c0
BS
1982 // addr = dst
1983 // fill 32 bytes with val
6c36d3fa 1984 unsigned int i;
1a2fb1c0 1985 uint32_t dst = addr & 7;
6c36d3fa
BS
1986
1987 for (i = 0; i < 32; i += 8, dst += 8)
1988 stq_kernel(dst, val);
0f8a249a 1989 }
8543e2cf 1990 break;
6c36d3fa 1991 case 0x20: /* MMU passthrough */
0f8a249a 1992 {
02aab46a
FB
1993 switch(size) {
1994 case 1:
1a2fb1c0 1995 stb_phys(addr, val);
02aab46a
FB
1996 break;
1997 case 2:
a4e7dd52 1998 stw_phys(addr, val);
02aab46a
FB
1999 break;
2000 case 4:
2001 default:
a4e7dd52 2002 stl_phys(addr, val);
02aab46a 2003 break;
9e61bde5 2004 case 8:
a4e7dd52 2005 stq_phys(addr, val);
9e61bde5 2006 break;
02aab46a 2007 }
0f8a249a 2008 }
8543e2cf 2009 break;
045380be 2010 case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
0f8a249a 2011 {
5dcb6b91
BS
2012 switch(size) {
2013 case 1:
c227f099
AL
2014 stb_phys((target_phys_addr_t)addr
2015 | ((target_phys_addr_t)(asi & 0xf) << 32), val);
5dcb6b91
BS
2016 break;
2017 case 2:
c227f099
AL
2018 stw_phys((target_phys_addr_t)addr
2019 | ((target_phys_addr_t)(asi & 0xf) << 32), val);
5dcb6b91
BS
2020 break;
2021 case 4:
2022 default:
c227f099
AL
2023 stl_phys((target_phys_addr_t)addr
2024 | ((target_phys_addr_t)(asi & 0xf) << 32), val);
5dcb6b91
BS
2025 break;
2026 case 8:
c227f099
AL
2027 stq_phys((target_phys_addr_t)addr
2028 | ((target_phys_addr_t)(asi & 0xf) << 32), val);
5dcb6b91
BS
2029 break;
2030 }
0f8a249a 2031 }
8543e2cf 2032 break;
045380be
BS
2033 case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
2034 case 0x31: // store buffer data, Ross RT620 I-cache flush or
2035 // Turbosparc snoop RAM
77f193da
BS
2036 case 0x32: // store buffer control or Turbosparc page table
2037 // descriptor diagnostic
6c36d3fa
BS
2038 case 0x36: /* I-cache flash clear */
2039 case 0x37: /* D-cache flash clear */
666c87aa 2040 case 0x4c: /* breakpoint action */
6c36d3fa 2041 break;
4017190e
BS
2042 case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
2043 {
2044 int reg = (addr >> 8) & 3;
2045
2046 switch(reg) {
2047 case 0: /* Breakpoint Value (Addr) */
2048 env->mmubpregs[reg] = (val & 0xfffffffffULL);
2049 break;
2050 case 1: /* Breakpoint Mask */
2051 env->mmubpregs[reg] = (val & 0xfffffffffULL);
2052 break;
2053 case 2: /* Breakpoint Control */
2054 env->mmubpregs[reg] = (val & 0x7fULL);
2055 break;
2056 case 3: /* Breakpoint Status */
2057 env->mmubpregs[reg] = (val & 0xfULL);
2058 break;
2059 }
0bf9e31a 2060 DPRINTF_MMU("write breakpoint reg[%d] 0x%016x\n", reg,
4017190e
BS
2061 env->mmuregs[reg]);
2062 }
2063 break;
045380be 2064 case 8: /* User code access, XXX */
6c36d3fa 2065 case 9: /* Supervisor code access, XXX */
e8af50a3 2066 default:
e18231a3 2067 do_unassigned_access(addr, 1, 0, asi, size);
8543e2cf 2068 break;
e8af50a3 2069 }
8543e2cf 2070#ifdef DEBUG_ASI
1a2fb1c0 2071 dump_asi("write", addr, asi, size, val);
8543e2cf 2072#endif
e8af50a3
FB
2073}
2074
81ad8ba2
BS
2075#endif /* CONFIG_USER_ONLY */
2076#else /* TARGET_SPARC64 */
2077
2078#ifdef CONFIG_USER_ONLY
1a2fb1c0 2079uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
81ad8ba2
BS
2080{
2081 uint64_t ret = 0;
1a2fb1c0
BS
2082#if defined(DEBUG_ASI)
2083 target_ulong last_addr = addr;
2084#endif
81ad8ba2
BS
2085
2086 if (asi < 0x80)
2087 raise_exception(TT_PRIV_ACT);
2088
c2bc0e38 2089 helper_check_align(addr, size - 1);
41db525e 2090 addr = address_mask(env, addr);
c2bc0e38 2091
81ad8ba2 2092 switch (asi) {
81ad8ba2 2093 case 0x82: // Primary no-fault
81ad8ba2 2094 case 0x8a: // Primary no-fault LE
e83ce550
BS
2095 if (page_check_range(addr, size, PAGE_READ) == -1) {
2096#ifdef DEBUG_ASI
2097 dump_asi("read ", last_addr, asi, size, ret);
2098#endif
2099 return 0;
2100 }
2101 // Fall through
2102 case 0x80: // Primary
2103 case 0x88: // Primary LE
81ad8ba2
BS
2104 {
2105 switch(size) {
2106 case 1:
1a2fb1c0 2107 ret = ldub_raw(addr);
81ad8ba2
BS
2108 break;
2109 case 2:
a4e7dd52 2110 ret = lduw_raw(addr);
81ad8ba2
BS
2111 break;
2112 case 4:
a4e7dd52 2113 ret = ldl_raw(addr);
81ad8ba2
BS
2114 break;
2115 default:
2116 case 8:
a4e7dd52 2117 ret = ldq_raw(addr);
81ad8ba2
BS
2118 break;
2119 }
2120 }
2121 break;
81ad8ba2 2122 case 0x83: // Secondary no-fault
81ad8ba2 2123 case 0x8b: // Secondary no-fault LE
e83ce550
BS
2124 if (page_check_range(addr, size, PAGE_READ) == -1) {
2125#ifdef DEBUG_ASI
2126 dump_asi("read ", last_addr, asi, size, ret);
2127#endif
2128 return 0;
2129 }
2130 // Fall through
2131 case 0x81: // Secondary
2132 case 0x89: // Secondary LE
81ad8ba2
BS
2133 // XXX
2134 break;
2135 default:
2136 break;
2137 }
2138
2139 /* Convert from little endian */
2140 switch (asi) {
2141 case 0x88: // Primary LE
2142 case 0x89: // Secondary LE
2143 case 0x8a: // Primary no-fault LE
2144 case 0x8b: // Secondary no-fault LE
2145 switch(size) {
2146 case 2:
2147 ret = bswap16(ret);
e32664fb 2148 break;
81ad8ba2
BS
2149 case 4:
2150 ret = bswap32(ret);
e32664fb 2151 break;
81ad8ba2
BS
2152 case 8:
2153 ret = bswap64(ret);
e32664fb 2154 break;
81ad8ba2
BS
2155 default:
2156 break;
2157 }
2158 default:
2159 break;
2160 }
2161
2162 /* Convert to signed number */
2163 if (sign) {
2164 switch(size) {
2165 case 1:
2166 ret = (int8_t) ret;
e32664fb 2167 break;
81ad8ba2
BS
2168 case 2:
2169 ret = (int16_t) ret;
e32664fb 2170 break;
81ad8ba2
BS
2171 case 4:
2172 ret = (int32_t) ret;
e32664fb 2173 break;
81ad8ba2
BS
2174 default:
2175 break;
2176 }
2177 }
1a2fb1c0
BS
2178#ifdef DEBUG_ASI
2179 dump_asi("read ", last_addr, asi, size, ret);
2180#endif
2181 return ret;
81ad8ba2
BS
2182}
2183
1a2fb1c0 2184void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
81ad8ba2 2185{
1a2fb1c0
BS
2186#ifdef DEBUG_ASI
2187 dump_asi("write", addr, asi, size, val);
2188#endif
81ad8ba2
BS
2189 if (asi < 0x80)
2190 raise_exception(TT_PRIV_ACT);
2191
c2bc0e38 2192 helper_check_align(addr, size - 1);
41db525e 2193 addr = address_mask(env, addr);
c2bc0e38 2194
81ad8ba2
BS
2195 /* Convert to little endian */
2196 switch (asi) {
2197 case 0x88: // Primary LE
2198 case 0x89: // Secondary LE
2199 switch(size) {
2200 case 2:
5b0f0bec 2201 val = bswap16(val);
e32664fb 2202 break;
81ad8ba2 2203 case 4:
5b0f0bec 2204 val = bswap32(val);
e32664fb 2205 break;
81ad8ba2 2206 case 8:
5b0f0bec 2207 val = bswap64(val);
e32664fb 2208 break;
81ad8ba2
BS
2209 default:
2210 break;
2211 }
2212 default:
2213 break;
2214 }
2215
2216 switch(asi) {
2217 case 0x80: // Primary
2218 case 0x88: // Primary LE
2219 {
2220 switch(size) {
2221 case 1:
1a2fb1c0 2222 stb_raw(addr, val);
81ad8ba2
BS
2223 break;
2224 case 2:
a4e7dd52 2225 stw_raw(addr, val);
81ad8ba2
BS
2226 break;
2227 case 4:
a4e7dd52 2228 stl_raw(addr, val);
81ad8ba2
BS
2229 break;
2230 case 8:
2231 default:
a4e7dd52 2232 stq_raw(addr, val);
81ad8ba2
BS
2233 break;
2234 }
2235 }
2236 break;
2237 case 0x81: // Secondary
2238 case 0x89: // Secondary LE
2239 // XXX
2240 return;
2241
2242 case 0x82: // Primary no-fault, RO
2243 case 0x83: // Secondary no-fault, RO
2244 case 0x8a: // Primary no-fault LE, RO
2245 case 0x8b: // Secondary no-fault LE, RO
2246 default:
e18231a3 2247 do_unassigned_access(addr, 1, 0, 1, size);
81ad8ba2
BS
2248 return;
2249 }
2250}
2251
2252#else /* CONFIG_USER_ONLY */
3475187d 2253
1a2fb1c0 2254uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
3475187d 2255{
83469015 2256 uint64_t ret = 0;
1a2fb1c0
BS
2257#if defined(DEBUG_ASI)
2258 target_ulong last_addr = addr;
2259#endif
3475187d 2260
01b5d4e5
IK
2261 asi &= 0xff;
2262
6f27aba6 2263 if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
5578ceab
BS
2264 || ((env->def->features & CPU_FEATURE_HYPV)
2265 && asi >= 0x30 && asi < 0x80
fb79ceb9 2266 && !(env->hpstate & HS_PRIV)))
0f8a249a 2267 raise_exception(TT_PRIV_ACT);
3475187d 2268
c2bc0e38 2269 helper_check_align(addr, size - 1);
3475187d 2270 switch (asi) {
e83ce550
BS
2271 case 0x82: // Primary no-fault
2272 case 0x8a: // Primary no-fault LE
2065061e
IK
2273 case 0x83: // Secondary no-fault
2274 case 0x8b: // Secondary no-fault LE
2275 {
2276 /* secondary space access has lowest asi bit equal to 1 */
2277 int access_mmu_idx = ( asi & 1 ) ? MMU_KERNEL_IDX
2278 : MMU_KERNEL_SECONDARY_IDX;
2279
2280 if (cpu_get_phys_page_nofault(env, addr, access_mmu_idx) == -1ULL) {
e83ce550 2281#ifdef DEBUG_ASI
2065061e 2282 dump_asi("read ", last_addr, asi, size, ret);
e83ce550 2283#endif
2065061e
IK
2284 return 0;
2285 }
e83ce550
BS
2286 }
2287 // Fall through
81ad8ba2 2288 case 0x10: // As if user primary
2065061e 2289 case 0x11: // As if user secondary
81ad8ba2 2290 case 0x18: // As if user primary LE
2065061e 2291 case 0x19: // As if user secondary LE
81ad8ba2 2292 case 0x80: // Primary
2065061e 2293 case 0x81: // Secondary
81ad8ba2 2294 case 0x88: // Primary LE
2065061e 2295 case 0x89: // Secondary LE
c99657d3
BS
2296 case 0xe2: // UA2007 Primary block init
2297 case 0xe3: // UA2007 Secondary block init
81ad8ba2 2298 if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
5578ceab
BS
2299 if ((env->def->features & CPU_FEATURE_HYPV)
2300 && env->hpstate & HS_PRIV) {
6f27aba6
BS
2301 switch(size) {
2302 case 1:
1a2fb1c0 2303 ret = ldub_hypv(addr);
6f27aba6
BS
2304 break;
2305 case 2:
a4e7dd52 2306 ret = lduw_hypv(addr);
6f27aba6
BS
2307 break;
2308 case 4:
a4e7dd52 2309 ret = ldl_hypv(addr);
6f27aba6
BS
2310 break;
2311 default:
2312 case 8:
a4e7dd52 2313 ret = ldq_hypv(addr);
6f27aba6
BS
2314 break;
2315 }
2316 } else {
2065061e
IK
2317 /* secondary space access has lowest asi bit equal to 1 */
2318 if (asi & 1) {
2319 switch(size) {
2320 case 1:
2321 ret = ldub_kernel_secondary(addr);
2322 break;
2323 case 2:
2324 ret = lduw_kernel_secondary(addr);
2325 break;
2326 case 4:
2327 ret = ldl_kernel_secondary(addr);
2328 break;
2329 default:
2330 case 8:
2331 ret = ldq_kernel_secondary(addr);
2332 break;
2333 }
2334 } else {
2335 switch(size) {
2336 case 1:
2337 ret = ldub_kernel(addr);
2338 break;
2339 case 2:
2340 ret = lduw_kernel(addr);
2341 break;
2342 case 4:
2343 ret = ldl_kernel(addr);
2344 break;
2345 default:
2346 case 8:
2347 ret = ldq_kernel(addr);
2348 break;
2349 }
2350 }
2351 }
2352 } else {
2353 /* secondary space access has lowest asi bit equal to 1 */
2354 if (asi & 1) {
6f27aba6
BS
2355 switch(size) {
2356 case 1:
2065061e 2357 ret = ldub_user_secondary(addr);
6f27aba6
BS
2358 break;
2359 case 2:
2065061e 2360 ret = lduw_user_secondary(addr);
6f27aba6
BS
2361 break;
2362 case 4:
2065061e 2363 ret = ldl_user_secondary(addr);
6f27aba6
BS
2364 break;
2365 default:
2366 case 8:
2065061e
IK
2367 ret = ldq_user_secondary(addr);
2368 break;
2369 }
2370 } else {
2371 switch(size) {
2372 case 1:
2373 ret = ldub_user(addr);
2374 break;
2375 case 2:
2376 ret = lduw_user(addr);
2377 break;
2378 case 4:
2379 ret = ldl_user(addr);
2380 break;
2381 default:
2382 case 8:
2383 ret = ldq_user(addr);
6f27aba6
BS
2384 break;
2385 }
81ad8ba2
BS
2386 }
2387 }
2388 break;
3475187d
FB
2389 case 0x14: // Bypass
2390 case 0x15: // Bypass, non-cacheable
81ad8ba2
BS
2391 case 0x1c: // Bypass LE
2392 case 0x1d: // Bypass, non-cacheable LE
0f8a249a 2393 {
02aab46a
FB
2394 switch(size) {
2395 case 1:
1a2fb1c0 2396 ret = ldub_phys(addr);
02aab46a
FB
2397 break;
2398 case 2:
a4e7dd52 2399 ret = lduw_phys(addr);
02aab46a
FB
2400 break;
2401 case 4:
a4e7dd52 2402 ret = ldl_phys(addr);
02aab46a
FB
2403 break;
2404 default:
2405 case 8:
a4e7dd52 2406 ret = ldq_phys(addr);
02aab46a
FB
2407 break;
2408 }
0f8a249a
BS
2409 break;
2410 }
db166940
BS
2411 case 0x24: // Nucleus quad LDD 128 bit atomic
2412 case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2413 // Only ldda allowed
2414 raise_exception(TT_ILL_INSN);
2415 return 0;
83469015
FB
2416 case 0x04: // Nucleus
2417 case 0x0c: // Nucleus Little Endian (LE)
2065061e
IK
2418 {
2419 switch(size) {
2420 case 1:
2421 ret = ldub_nucleus(addr);
2422 break;
2423 case 2:
2424 ret = lduw_nucleus(addr);
2425 break;
2426 case 4:
2427 ret = ldl_nucleus(addr);
2428 break;
2429 default:
2430 case 8:
2431 ret = ldq_nucleus(addr);
2432 break;
2433 }
2434 break;
2435 }
83469015 2436 case 0x4a: // UPA config
0f8a249a
BS
2437 // XXX
2438 break;
3475187d 2439 case 0x45: // LSU
0f8a249a
BS
2440 ret = env->lsu;
2441 break;
3475187d 2442 case 0x50: // I-MMU regs
0f8a249a 2443 {
1a2fb1c0 2444 int reg = (addr >> 3) & 0xf;
3475187d 2445
697a77e6
IK
2446 if (reg == 0) {
2447 // I-TSB Tag Target register
6e8e7d4c 2448 ret = ultrasparc_tag_target(env->immu.tag_access);
697a77e6
IK
2449 } else {
2450 ret = env->immuregs[reg];
2451 }
2452
0f8a249a
BS
2453 break;
2454 }
3475187d 2455 case 0x51: // I-MMU 8k TSB pointer
697a77e6
IK
2456 {
2457 // env->immuregs[5] holds I-MMU TSB register value
2458 // env->immuregs[6] holds I-MMU Tag Access register value
6e8e7d4c 2459 ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
697a77e6
IK
2460 8*1024);
2461 break;
2462 }
3475187d 2463 case 0x52: // I-MMU 64k TSB pointer
697a77e6
IK
2464 {
2465 // env->immuregs[5] holds I-MMU TSB register value
2466 // env->immuregs[6] holds I-MMU Tag Access register value
6e8e7d4c 2467 ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
697a77e6
IK
2468 64*1024);
2469 break;
2470 }
a5a52cf2
BS
2471 case 0x55: // I-MMU data access
2472 {
2473 int reg = (addr >> 3) & 0x3f;
2474
6e8e7d4c 2475 ret = env->itlb[reg].tte;
a5a52cf2
BS
2476 break;
2477 }
83469015 2478 case 0x56: // I-MMU tag read
0f8a249a 2479 {
43e9e742 2480 int reg = (addr >> 3) & 0x3f;
0f8a249a 2481
6e8e7d4c 2482 ret = env->itlb[reg].tag;
0f8a249a
BS
2483 break;
2484 }
3475187d 2485 case 0x58: // D-MMU regs
0f8a249a 2486 {
1a2fb1c0 2487 int reg = (addr >> 3) & 0xf;
3475187d 2488
697a77e6
IK
2489 if (reg == 0) {
2490 // D-TSB Tag Target register
6e8e7d4c 2491 ret = ultrasparc_tag_target(env->dmmu.tag_access);
697a77e6
IK
2492 } else {
2493 ret = env->dmmuregs[reg];
2494 }
2495 break;
2496 }
2497 case 0x59: // D-MMU 8k TSB pointer
2498 {
2499 // env->dmmuregs[5] holds D-MMU TSB register value
2500 // env->dmmuregs[6] holds D-MMU Tag Access register value
6e8e7d4c 2501 ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
697a77e6
IK
2502 8*1024);
2503 break;
2504 }
2505 case 0x5a: // D-MMU 64k TSB pointer
2506 {
2507 // env->dmmuregs[5] holds D-MMU TSB register value
2508 // env->dmmuregs[6] holds D-MMU Tag Access register value
6e8e7d4c 2509 ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
697a77e6 2510 64*1024);
0f8a249a
BS
2511 break;
2512 }
a5a52cf2
BS
2513 case 0x5d: // D-MMU data access
2514 {
2515 int reg = (addr >> 3) & 0x3f;
2516
6e8e7d4c 2517 ret = env->dtlb[reg].tte;
a5a52cf2
BS
2518 break;
2519 }
83469015 2520 case 0x5e: // D-MMU tag read
0f8a249a 2521 {
43e9e742 2522 int reg = (addr >> 3) & 0x3f;
0f8a249a 2523
6e8e7d4c 2524 ret = env->dtlb[reg].tag;
0f8a249a
BS
2525 break;
2526 }
f7350b47
BS
2527 case 0x46: // D-cache data
2528 case 0x47: // D-cache tag access
a5a52cf2
BS
2529 case 0x4b: // E-cache error enable
2530 case 0x4c: // E-cache asynchronous fault status
2531 case 0x4d: // E-cache asynchronous fault address
f7350b47
BS
2532 case 0x4e: // E-cache tag data
2533 case 0x66: // I-cache instruction access
2534 case 0x67: // I-cache tag access
2535 case 0x6e: // I-cache predecode
2536 case 0x6f: // I-cache LRU etc.
2537 case 0x76: // E-cache tag
2538 case 0x7e: // E-cache tag
2539 break;
3475187d 2540 case 0x5b: // D-MMU data pointer
83469015
FB
2541 case 0x48: // Interrupt dispatch, RO
2542 case 0x49: // Interrupt data receive
2543 case 0x7f: // Incoming interrupt vector, RO
0f8a249a
BS
2544 // XXX
2545 break;
3475187d
FB
2546 case 0x54: // I-MMU data in, WO
2547 case 0x57: // I-MMU demap, WO
2548 case 0x5c: // D-MMU data in, WO
2549 case 0x5f: // D-MMU demap, WO
83469015 2550 case 0x77: // Interrupt vector, WO
3475187d 2551 default:
e18231a3 2552 do_unassigned_access(addr, 0, 0, 1, size);
0f8a249a
BS
2553 ret = 0;
2554 break;
3475187d 2555 }
81ad8ba2
BS
2556
2557 /* Convert from little endian */
2558 switch (asi) {
2559 case 0x0c: // Nucleus Little Endian (LE)
2560 case 0x18: // As if user primary LE
2561 case 0x19: // As if user secondary LE
2562 case 0x1c: // Bypass LE
2563 case 0x1d: // Bypass, non-cacheable LE
2564 case 0x88: // Primary LE
2565 case 0x89: // Secondary LE
2566 case 0x8a: // Primary no-fault LE
2567 case 0x8b: // Secondary no-fault LE
2568 switch(size) {
2569 case 2:
2570 ret = bswap16(ret);
e32664fb 2571 break;
81ad8ba2
BS
2572 case 4:
2573 ret = bswap32(ret);
e32664fb 2574 break;
81ad8ba2
BS
2575 case 8:
2576 ret = bswap64(ret);
e32664fb 2577 break;
81ad8ba2
BS
2578 default:
2579 break;
2580 }
2581 default:
2582 break;
2583 }
2584
2585 /* Convert to signed number */
2586 if (sign) {
2587 switch(size) {
2588 case 1:
2589 ret = (int8_t) ret;
e32664fb 2590 break;
81ad8ba2
BS
2591 case 2:
2592 ret = (int16_t) ret;
e32664fb 2593 break;
81ad8ba2
BS
2594 case 4:
2595 ret = (int32_t) ret;
e32664fb 2596 break;
81ad8ba2
BS
2597 default:
2598 break;
2599 }
2600 }
1a2fb1c0
BS
2601#ifdef DEBUG_ASI
2602 dump_asi("read ", last_addr, asi, size, ret);
2603#endif
2604 return ret;
3475187d
FB
2605}
2606
1a2fb1c0 2607void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
3475187d 2608{
1a2fb1c0
BS
2609#ifdef DEBUG_ASI
2610 dump_asi("write", addr, asi, size, val);
2611#endif
01b5d4e5
IK
2612
2613 asi &= 0xff;
2614
6f27aba6 2615 if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
5578ceab
BS
2616 || ((env->def->features & CPU_FEATURE_HYPV)
2617 && asi >= 0x30 && asi < 0x80
fb79ceb9 2618 && !(env->hpstate & HS_PRIV)))
0f8a249a 2619 raise_exception(TT_PRIV_ACT);
3475187d 2620
c2bc0e38 2621 helper_check_align(addr, size - 1);
81ad8ba2
BS
2622 /* Convert to little endian */
2623 switch (asi) {
2624 case 0x0c: // Nucleus Little Endian (LE)
2625 case 0x18: // As if user primary LE
2626 case 0x19: // As if user secondary LE
2627 case 0x1c: // Bypass LE
2628 case 0x1d: // Bypass, non-cacheable LE
81ad8ba2
BS
2629 case 0x88: // Primary LE
2630 case 0x89: // Secondary LE
2631 switch(size) {
2632 case 2:
5b0f0bec 2633 val = bswap16(val);
e32664fb 2634 break;
81ad8ba2 2635 case 4:
5b0f0bec 2636 val = bswap32(val);
e32664fb 2637 break;
81ad8ba2 2638 case 8:
5b0f0bec 2639 val = bswap64(val);
e32664fb 2640 break;
81ad8ba2
BS
2641 default:
2642 break;
2643 }
2644 default:
2645 break;
2646 }
2647
3475187d 2648 switch(asi) {
81ad8ba2 2649 case 0x10: // As if user primary
2065061e 2650 case 0x11: // As if user secondary
81ad8ba2 2651 case 0x18: // As if user primary LE
2065061e 2652 case 0x19: // As if user secondary LE
81ad8ba2 2653 case 0x80: // Primary
2065061e 2654 case 0x81: // Secondary
81ad8ba2 2655 case 0x88: // Primary LE
2065061e 2656 case 0x89: // Secondary LE
c99657d3
BS
2657 case 0xe2: // UA2007 Primary block init
2658 case 0xe3: // UA2007 Secondary block init
81ad8ba2 2659 if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
5578ceab
BS
2660 if ((env->def->features & CPU_FEATURE_HYPV)
2661 && env->hpstate & HS_PRIV) {
6f27aba6
BS
2662 switch(size) {
2663 case 1:
1a2fb1c0 2664 stb_hypv(addr, val);
6f27aba6
BS
2665 break;
2666 case 2:
a4e7dd52 2667 stw_hypv(addr, val);
6f27aba6
BS
2668 break;
2669 case 4:
a4e7dd52 2670 stl_hypv(addr, val);
6f27aba6
BS
2671 break;
2672 case 8:
2673 default:
a4e7dd52 2674 stq_hypv(addr, val);
6f27aba6
BS
2675 break;
2676 }
2677 } else {
2065061e
IK
2678 /* secondary space access has lowest asi bit equal to 1 */
2679 if (asi & 1) {
2680 switch(size) {
2681 case 1:
2682 stb_kernel_secondary(addr, val);
2683 break;
2684 case 2:
2685 stw_kernel_secondary(addr, val);
2686 break;
2687 case 4:
2688 stl_kernel_secondary(addr, val);
2689 break;
2690 case 8:
2691 default:
2692 stq_kernel_secondary(addr, val);
2693 break;
2694 }
2695 } else {
2696 switch(size) {
2697 case 1:
2698 stb_kernel(addr, val);
2699 break;
2700 case 2:
2701 stw_kernel(addr, val);
2702 break;
2703 case 4:
2704 stl_kernel(addr, val);
2705 break;
2706 case 8:
2707 default:
2708 stq_kernel(addr, val);
2709 break;
2710 }
2711 }
2712 }
2713 } else {
2714 /* secondary space access has lowest asi bit equal to 1 */
2715 if (asi & 1) {
6f27aba6
BS
2716 switch(size) {
2717 case 1:
2065061e 2718 stb_user_secondary(addr, val);
6f27aba6
BS
2719 break;
2720 case 2:
2065061e 2721 stw_user_secondary(addr, val);
6f27aba6
BS
2722 break;
2723 case 4:
2065061e 2724 stl_user_secondary(addr, val);
6f27aba6
BS
2725 break;
2726 case 8:
2727 default:
2065061e
IK
2728 stq_user_secondary(addr, val);
2729 break;
2730 }
2731 } else {
2732 switch(size) {
2733 case 1:
2734 stb_user(addr, val);
2735 break;
2736 case 2:
2737 stw_user(addr, val);
2738 break;
2739 case 4:
2740 stl_user(addr, val);
2741 break;
2742 case 8:
2743 default:
2744 stq_user(addr, val);
6f27aba6
BS
2745 break;
2746 }
81ad8ba2
BS
2747 }
2748 }
2749 break;
3475187d
FB
2750 case 0x14: // Bypass
2751 case 0x15: // Bypass, non-cacheable
81ad8ba2
BS
2752 case 0x1c: // Bypass LE
2753 case 0x1d: // Bypass, non-cacheable LE
0f8a249a 2754 {
02aab46a
FB
2755 switch(size) {
2756 case 1:
1a2fb1c0 2757 stb_phys(addr, val);
02aab46a
FB
2758 break;
2759 case 2:
a4e7dd52 2760 stw_phys(addr, val);
02aab46a
FB
2761 break;
2762 case 4:
a4e7dd52 2763 stl_phys(addr, val);
02aab46a
FB
2764 break;
2765 case 8:
2766 default:
a4e7dd52 2767 stq_phys(addr, val);
02aab46a
FB
2768 break;
2769 }
0f8a249a
BS
2770 }
2771 return;
db166940
BS
2772 case 0x24: // Nucleus quad LDD 128 bit atomic
2773 case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2774 // Only ldda allowed
2775 raise_exception(TT_ILL_INSN);
2776 return;
83469015
FB
2777 case 0x04: // Nucleus
2778 case 0x0c: // Nucleus Little Endian (LE)
2065061e
IK
2779 {
2780 switch(size) {
2781 case 1:
2782 stb_nucleus(addr, val);
2783 break;
2784 case 2:
2785 stw_nucleus(addr, val);
2786 break;
2787 case 4:
2788 stl_nucleus(addr, val);
2789 break;
2790 default:
2791 case 8:
2792 stq_nucleus(addr, val);
2793 break;
2794 }
2795 break;
2796 }
2797
83469015 2798 case 0x4a: // UPA config
0f8a249a
BS
2799 // XXX
2800 return;
3475187d 2801 case 0x45: // LSU
0f8a249a
BS
2802 {
2803 uint64_t oldreg;
2804
2805 oldreg = env->lsu;
1a2fb1c0 2806 env->lsu = val & (DMMU_E | IMMU_E);
0f8a249a
BS
2807 // Mappings generated during D/I MMU disabled mode are
2808 // invalid in normal mode
2809 if (oldreg != env->lsu) {
77f193da
BS
2810 DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
2811 oldreg, env->lsu);
83469015 2812#ifdef DEBUG_MMU
0f8a249a 2813 dump_mmu(env);
83469015 2814#endif
0f8a249a
BS
2815 tlb_flush(env, 1);
2816 }
2817 return;
2818 }
3475187d 2819 case 0x50: // I-MMU regs
0f8a249a 2820 {
1a2fb1c0 2821 int reg = (addr >> 3) & 0xf;
0f8a249a 2822 uint64_t oldreg;
3b46e624 2823
0f8a249a 2824 oldreg = env->immuregs[reg];
3475187d
FB
2825 switch(reg) {
2826 case 0: // RO
3475187d
FB
2827 return;
2828 case 1: // Not in I-MMU
2829 case 2:
3475187d
FB
2830 return;
2831 case 3: // SFSR
1a2fb1c0
BS
2832 if ((val & 1) == 0)
2833 val = 0; // Clear SFSR
6e8e7d4c 2834 env->immu.sfsr = val;
3475187d 2835 break;
6e8e7d4c
IK
2836 case 4: // RO
2837 return;
3475187d 2838 case 5: // TSB access
6e8e7d4c
IK
2839 DPRINTF_MMU("immu TSB write: 0x%016" PRIx64 " -> 0x%016"
2840 PRIx64 "\n", env->immu.tsb, val);
2841 env->immu.tsb = val;
2842 break;
3475187d 2843 case 6: // Tag access
6e8e7d4c
IK
2844 env->immu.tag_access = val;
2845 break;
2846 case 7:
2847 case 8:
2848 return;
3475187d
FB
2849 default:
2850 break;
2851 }
6e8e7d4c 2852
3475187d 2853 if (oldreg != env->immuregs[reg]) {
6e8e7d4c 2854 DPRINTF_MMU("immu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
77f193da 2855 PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
3475187d 2856 }
952a328f 2857#ifdef DEBUG_MMU
0f8a249a 2858 dump_mmu(env);
3475187d 2859#endif
0f8a249a
BS
2860 return;
2861 }
3475187d 2862 case 0x54: // I-MMU data in
f707726e
IK
2863 replace_tlb_1bit_lru(env->itlb, env->immu.tag_access, val, "immu", env);
2864 return;
3475187d 2865 case 0x55: // I-MMU data access
0f8a249a 2866 {
cc6747f4
BS
2867 // TODO: auto demap
2868
1a2fb1c0 2869 unsigned int i = (addr >> 3) & 0x3f;
3475187d 2870
f707726e 2871 replace_tlb_entry(&env->itlb[i], env->immu.tag_access, val, env);
6e8e7d4c
IK
2872
2873#ifdef DEBUG_MMU
f707726e 2874 DPRINTF_MMU("immu data access replaced entry [%i]\n", i);
6e8e7d4c
IK
2875 dump_mmu(env);
2876#endif
0f8a249a
BS
2877 return;
2878 }
3475187d 2879 case 0x57: // I-MMU demap
170f4c55 2880 demap_tlb(env->itlb, addr, "immu", env);
0f8a249a 2881 return;
3475187d 2882 case 0x58: // D-MMU regs
0f8a249a 2883 {
1a2fb1c0 2884 int reg = (addr >> 3) & 0xf;
0f8a249a 2885 uint64_t oldreg;
3b46e624 2886
0f8a249a 2887 oldreg = env->dmmuregs[reg];
3475187d
FB
2888 switch(reg) {
2889 case 0: // RO
2890 case 4:
2891 return;
2892 case 3: // SFSR
1a2fb1c0
BS
2893 if ((val & 1) == 0) {
2894 val = 0; // Clear SFSR, Fault address
6e8e7d4c 2895 env->dmmu.sfar = 0;
0f8a249a 2896 }
6e8e7d4c 2897 env->dmmu.sfsr = val;
3475187d
FB
2898 break;
2899 case 1: // Primary context
6e8e7d4c
IK
2900 env->dmmu.mmu_primary_context = val;
2901 break;
3475187d 2902 case 2: // Secondary context
6e8e7d4c
IK
2903 env->dmmu.mmu_secondary_context = val;
2904 break;
3475187d 2905 case 5: // TSB access
6e8e7d4c
IK
2906 DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64 " -> 0x%016"
2907 PRIx64 "\n", env->dmmu.tsb, val);
2908 env->dmmu.tsb = val;
2909 break;
3475187d 2910 case 6: // Tag access
6e8e7d4c
IK
2911 env->dmmu.tag_access = val;
2912 break;
3475187d
FB
2913 case 7: // Virtual Watchpoint
2914 case 8: // Physical Watchpoint
2915 default:
6e8e7d4c 2916 env->dmmuregs[reg] = val;
3475187d
FB
2917 break;
2918 }
6e8e7d4c 2919
3475187d 2920 if (oldreg != env->dmmuregs[reg]) {
6e8e7d4c 2921 DPRINTF_MMU("dmmu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
77f193da 2922 PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
3475187d 2923 }
952a328f 2924#ifdef DEBUG_MMU
0f8a249a 2925 dump_mmu(env);
3475187d 2926#endif
0f8a249a
BS
2927 return;
2928 }
3475187d 2929 case 0x5c: // D-MMU data in
f707726e
IK
2930 replace_tlb_1bit_lru(env->dtlb, env->dmmu.tag_access, val, "dmmu", env);
2931 return;
3475187d 2932 case 0x5d: // D-MMU data access
0f8a249a 2933 {
1a2fb1c0 2934 unsigned int i = (addr >> 3) & 0x3f;
3475187d 2935
f707726e
IK
2936 replace_tlb_entry(&env->dtlb[i], env->dmmu.tag_access, val, env);
2937
6e8e7d4c 2938#ifdef DEBUG_MMU
f707726e 2939 DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i);
6e8e7d4c
IK
2940 dump_mmu(env);
2941#endif
0f8a249a
BS
2942 return;
2943 }
3475187d 2944 case 0x5f: // D-MMU demap
170f4c55 2945 demap_tlb(env->dtlb, addr, "dmmu", env);
cc6747f4 2946 return;
83469015 2947 case 0x49: // Interrupt data receive
0f8a249a
BS
2948 // XXX
2949 return;
f7350b47
BS
2950 case 0x46: // D-cache data
2951 case 0x47: // D-cache tag access
a5a52cf2
BS
2952 case 0x4b: // E-cache error enable
2953 case 0x4c: // E-cache asynchronous fault status
2954 case 0x4d: // E-cache asynchronous fault address
f7350b47
BS
2955 case 0x4e: // E-cache tag data
2956 case 0x66: // I-cache instruction access
2957 case 0x67: // I-cache tag access
2958 case 0x6e: // I-cache predecode
2959 case 0x6f: // I-cache LRU etc.
2960 case 0x76: // E-cache tag
2961 case 0x7e: // E-cache tag
2962 return;
3475187d
FB
2963 case 0x51: // I-MMU 8k TSB pointer, RO
2964 case 0x52: // I-MMU 64k TSB pointer, RO
2965 case 0x56: // I-MMU tag read, RO
2966 case 0x59: // D-MMU 8k TSB pointer, RO
2967 case 0x5a: // D-MMU 64k TSB pointer, RO
2968 case 0x5b: // D-MMU data pointer, RO
2969 case 0x5e: // D-MMU tag read, RO
83469015
FB
2970 case 0x48: // Interrupt dispatch, RO
2971 case 0x7f: // Incoming interrupt vector, RO
2972 case 0x82: // Primary no-fault, RO
2973 case 0x83: // Secondary no-fault, RO
2974 case 0x8a: // Primary no-fault LE, RO
2975 case 0x8b: // Secondary no-fault LE, RO
3475187d 2976 default:
e18231a3 2977 do_unassigned_access(addr, 1, 0, 1, size);
0f8a249a 2978 return;
3475187d
FB
2979 }
2980}
81ad8ba2 2981#endif /* CONFIG_USER_ONLY */
3391c818 2982
db166940
BS
2983void helper_ldda_asi(target_ulong addr, int asi, int rd)
2984{
db166940 2985 if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
5578ceab
BS
2986 || ((env->def->features & CPU_FEATURE_HYPV)
2987 && asi >= 0x30 && asi < 0x80
fb79ceb9 2988 && !(env->hpstate & HS_PRIV)))
db166940
BS
2989 raise_exception(TT_PRIV_ACT);
2990
2991 switch (asi) {
2992 case 0x24: // Nucleus quad LDD 128 bit atomic
2993 case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2994 helper_check_align(addr, 0xf);
2995 if (rd == 0) {
2996 env->gregs[1] = ldq_kernel(addr + 8);
2997 if (asi == 0x2c)
2998 bswap64s(&env->gregs[1]);
2999 } else if (rd < 8) {
3000 env->gregs[rd] = ldq_kernel(addr);
3001 env->gregs[rd + 1] = ldq_kernel(addr + 8);
3002 if (asi == 0x2c) {
3003 bswap64s(&env->gregs[rd]);
3004 bswap64s(&env->gregs[rd + 1]);
3005 }
3006 } else {
3007 env->regwptr[rd] = ldq_kernel(addr);
3008 env->regwptr[rd + 1] = ldq_kernel(addr + 8);
3009 if (asi == 0x2c) {
3010 bswap64s(&env->regwptr[rd]);
3011 bswap64s(&env->regwptr[rd + 1]);
3012 }
3013 }
3014 break;
3015 default:
3016 helper_check_align(addr, 0x3);
3017 if (rd == 0)
3018 env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
3019 else if (rd < 8) {
3020 env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
3021 env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
3022 } else {
3023 env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
3024 env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
3025 }
3026 break;
3027 }
3028}
3029
1a2fb1c0 3030void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
3391c818 3031{
3391c818 3032 unsigned int i;
1a2fb1c0 3033 target_ulong val;
3391c818 3034
c2bc0e38 3035 helper_check_align(addr, 3);
3391c818
BS
3036 switch (asi) {
3037 case 0xf0: // Block load primary
3038 case 0xf1: // Block load secondary
3039 case 0xf8: // Block load primary LE
3040 case 0xf9: // Block load secondary LE
51996525
BS
3041 if (rd & 7) {
3042 raise_exception(TT_ILL_INSN);
3043 return;
3044 }
c2bc0e38 3045 helper_check_align(addr, 0x3f);
51996525 3046 for (i = 0; i < 16; i++) {
77f193da
BS
3047 *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
3048 0);
1a2fb1c0 3049 addr += 4;
3391c818 3050 }
3391c818
BS
3051
3052 return;
3053 default:
3054 break;
3055 }
3056
1a2fb1c0 3057 val = helper_ld_asi(addr, asi, size, 0);
3391c818
BS
3058 switch(size) {
3059 default:
3060 case 4:
714547bb 3061 *((uint32_t *)&env->fpr[rd]) = val;
3391c818
BS
3062 break;
3063 case 8:
1a2fb1c0 3064 *((int64_t *)&DT0) = val;
3391c818 3065 break;
1f587329
BS
3066 case 16:
3067 // XXX
3068 break;
3391c818 3069 }
3391c818
BS
3070}
3071
1a2fb1c0 3072void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
3391c818 3073{
3391c818 3074 unsigned int i;
1a2fb1c0 3075 target_ulong val = 0;
3391c818 3076
c2bc0e38 3077 helper_check_align(addr, 3);
3391c818 3078 switch (asi) {
c99657d3
BS
3079 case 0xe0: // UA2007 Block commit store primary (cache flush)
3080 case 0xe1: // UA2007 Block commit store secondary (cache flush)
3391c818
BS
3081 case 0xf0: // Block store primary
3082 case 0xf1: // Block store secondary
3083 case 0xf8: // Block store primary LE
3084 case 0xf9: // Block store secondary LE
51996525
BS
3085 if (rd & 7) {
3086 raise_exception(TT_ILL_INSN);
3087 return;
3088 }
c2bc0e38 3089 helper_check_align(addr, 0x3f);
51996525 3090 for (i = 0; i < 16; i++) {
1a2fb1c0
BS
3091 val = *(uint32_t *)&env->fpr[rd++];
3092 helper_st_asi(addr, val, asi & 0x8f, 4);
3093 addr += 4;
3391c818 3094 }
3391c818
BS
3095
3096 return;
3097 default:
3098 break;
3099 }
3100
3101 switch(size) {
3102 default:
3103 case 4:
714547bb 3104 val = *((uint32_t *)&env->fpr[rd]);
3391c818
BS
3105 break;
3106 case 8:
1a2fb1c0 3107 val = *((int64_t *)&DT0);
3391c818 3108 break;
1f587329
BS
3109 case 16:
3110 // XXX
3111 break;
3391c818 3112 }
1a2fb1c0
BS
3113 helper_st_asi(addr, val, asi, size);
3114}
3115
3116target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
3117 target_ulong val2, uint32_t asi)
3118{
3119 target_ulong ret;
3120
1121f879 3121 val2 &= 0xffffffffUL;
1a2fb1c0
BS
3122 ret = helper_ld_asi(addr, asi, 4, 0);
3123 ret &= 0xffffffffUL;
1121f879
BS
3124 if (val2 == ret)
3125 helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
1a2fb1c0 3126 return ret;
3391c818
BS
3127}
3128
1a2fb1c0
BS
3129target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
3130 target_ulong val2, uint32_t asi)
3131{
3132 target_ulong ret;
3133
3134 ret = helper_ld_asi(addr, asi, 8, 0);
1121f879
BS
3135 if (val2 == ret)
3136 helper_st_asi(addr, val1, asi, 8);
1a2fb1c0
BS
3137 return ret;
3138}
81ad8ba2 3139#endif /* TARGET_SPARC64 */
3475187d
FB
3140
3141#ifndef TARGET_SPARC64
1a2fb1c0 3142void helper_rett(void)
e8af50a3 3143{
af7bf89b
FB
3144 unsigned int cwp;
3145
d4218d99
BS
3146 if (env->psret == 1)
3147 raise_exception(TT_ILL_INSN);
3148
e8af50a3 3149 env->psret = 1;
5a834bb4 3150 cwp = cwp_inc(env->cwp + 1) ;
e8af50a3
FB
3151 if (env->wim & (1 << cwp)) {
3152 raise_exception(TT_WIN_UNF);
3153 }
3154 set_cwp(cwp);
3155 env->psrs = env->psrps;
3156}
3475187d 3157#endif
e8af50a3 3158
3b89f26c
BS
3159target_ulong helper_udiv(target_ulong a, target_ulong b)
3160{
3161 uint64_t x0;
3162 uint32_t x1;
3163
7621a90d 3164 x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
3b89f26c
BS
3165 x1 = b;
3166
3167 if (x1 == 0) {
3168 raise_exception(TT_DIV_ZERO);
3169 }
3170
3171 x0 = x0 / x1;
3172 if (x0 > 0xffffffff) {
3173 env->cc_src2 = 1;
3174 return 0xffffffff;
3175 } else {
3176 env->cc_src2 = 0;
3177 return x0;
3178 }
3179}
3180
3181target_ulong helper_sdiv(target_ulong a, target_ulong b)
3182{
3183 int64_t x0;
3184 int32_t x1;
3185
7621a90d 3186 x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
3b89f26c
BS
3187 x1 = b;
3188
3189 if (x1 == 0) {
3190 raise_exception(TT_DIV_ZERO);
3191 }
3192
3193 x0 = x0 / x1;
3194 if ((int32_t) x0 != x0) {
3195 env->cc_src2 = 1;
3196 return x0 < 0? 0x80000000: 0x7fffffff;
3197 } else {
3198 env->cc_src2 = 0;
3199 return x0;
3200 }
3201}
3202
7fa76c0b
BS
3203void helper_stdf(target_ulong addr, int mem_idx)
3204{
c2bc0e38 3205 helper_check_align(addr, 7);
7fa76c0b
BS
3206#if !defined(CONFIG_USER_ONLY)
3207 switch (mem_idx) {
3208 case 0:
c2bc0e38 3209 stfq_user(addr, DT0);
7fa76c0b
BS
3210 break;
3211 case 1:
c2bc0e38 3212 stfq_kernel(addr, DT0);
7fa76c0b
BS
3213 break;
3214#ifdef TARGET_SPARC64
3215 case 2:
c2bc0e38 3216 stfq_hypv(addr, DT0);
7fa76c0b
BS
3217 break;
3218#endif
3219 default:
3220 break;
3221 }
3222#else
41db525e 3223 stfq_raw(address_mask(env, addr), DT0);
7fa76c0b
BS
3224#endif
3225}
3226
3227void helper_lddf(target_ulong addr, int mem_idx)
3228{
c2bc0e38 3229 helper_check_align(addr, 7);
7fa76c0b
BS
3230#if !defined(CONFIG_USER_ONLY)
3231 switch (mem_idx) {
3232 case 0:
c2bc0e38 3233 DT0 = ldfq_user(addr);
7fa76c0b
BS
3234 break;
3235 case 1:
c2bc0e38 3236 DT0 = ldfq_kernel(addr);
7fa76c0b
BS
3237 break;
3238#ifdef TARGET_SPARC64
3239 case 2:
c2bc0e38 3240 DT0 = ldfq_hypv(addr);
7fa76c0b
BS
3241 break;
3242#endif
3243 default:
3244 break;
3245 }
3246#else
41db525e 3247 DT0 = ldfq_raw(address_mask(env, addr));
7fa76c0b
BS
3248#endif
3249}
3250
64a88d5d 3251void helper_ldqf(target_ulong addr, int mem_idx)
7fa76c0b
BS
3252{
3253 // XXX add 128 bit load
3254 CPU_QuadU u;
3255
c2bc0e38 3256 helper_check_align(addr, 7);
64a88d5d
BS
3257#if !defined(CONFIG_USER_ONLY)
3258 switch (mem_idx) {
3259 case 0:
c2bc0e38
BS
3260 u.ll.upper = ldq_user(addr);
3261 u.ll.lower = ldq_user(addr + 8);
64a88d5d
BS
3262 QT0 = u.q;
3263 break;
3264 case 1:
c2bc0e38
BS
3265 u.ll.upper = ldq_kernel(addr);
3266 u.ll.lower = ldq_kernel(addr + 8);
64a88d5d
BS
3267 QT0 = u.q;
3268 break;
3269#ifdef TARGET_SPARC64
3270 case 2:
c2bc0e38
BS
3271 u.ll.upper = ldq_hypv(addr);
3272 u.ll.lower = ldq_hypv(addr + 8);
64a88d5d
BS
3273 QT0 = u.q;
3274 break;
3275#endif
3276 default:
3277 break;
3278 }
3279#else
41db525e
RH
3280 u.ll.upper = ldq_raw(address_mask(env, addr));
3281 u.ll.lower = ldq_raw(address_mask(env, addr + 8));
7fa76c0b 3282 QT0 = u.q;
64a88d5d 3283#endif
7fa76c0b
BS
3284}
3285
64a88d5d 3286void helper_stqf(target_ulong addr, int mem_idx)
7fa76c0b
BS
3287{
3288 // XXX add 128 bit store
3289 CPU_QuadU u;
3290
c2bc0e38 3291 helper_check_align(addr, 7);
64a88d5d
BS
3292#if !defined(CONFIG_USER_ONLY)
3293 switch (mem_idx) {
3294 case 0:
3295 u.q = QT0;
c2bc0e38
BS
3296 stq_user(addr, u.ll.upper);
3297 stq_user(addr + 8, u.ll.lower);
64a88d5d
BS
3298 break;
3299 case 1:
3300 u.q = QT0;
c2bc0e38
BS
3301 stq_kernel(addr, u.ll.upper);
3302 stq_kernel(addr + 8, u.ll.lower);
64a88d5d
BS
3303 break;
3304#ifdef TARGET_SPARC64
3305 case 2:
3306 u.q = QT0;
c2bc0e38
BS
3307 stq_hypv(addr, u.ll.upper);
3308 stq_hypv(addr + 8, u.ll.lower);
64a88d5d
BS
3309 break;
3310#endif
3311 default:
3312 break;
3313 }
3314#else
7fa76c0b 3315 u.q = QT0;
41db525e
RH
3316 stq_raw(address_mask(env, addr), u.ll.upper);
3317 stq_raw(address_mask(env, addr + 8), u.ll.lower);
7fa76c0b 3318#endif
64a88d5d 3319}
7fa76c0b 3320
3a3b925d 3321static inline void set_fsr(void)
e8af50a3 3322{
7a0e1f41 3323 int rnd_mode;
bb5529bb 3324
e8af50a3
FB
3325 switch (env->fsr & FSR_RD_MASK) {
3326 case FSR_RD_NEAREST:
7a0e1f41 3327 rnd_mode = float_round_nearest_even;
0f8a249a 3328 break;
ed910241 3329 default:
e8af50a3 3330 case FSR_RD_ZERO:
7a0e1f41 3331 rnd_mode = float_round_to_zero;
0f8a249a 3332 break;
e8af50a3 3333 case FSR_RD_POS:
7a0e1f41 3334 rnd_mode = float_round_up;
0f8a249a 3335 break;
e8af50a3 3336 case FSR_RD_NEG:
7a0e1f41 3337 rnd_mode = float_round_down;
0f8a249a 3338 break;
e8af50a3 3339 }
7a0e1f41 3340 set_float_rounding_mode(rnd_mode, &env->fp_status);
e8af50a3 3341}
e80cfcfc 3342
3a3b925d 3343void helper_ldfsr(uint32_t new_fsr)
bb5529bb 3344{
3a3b925d
BS
3345 env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
3346 set_fsr();
bb5529bb
BS
3347}
3348
3a3b925d
BS
3349#ifdef TARGET_SPARC64
3350void helper_ldxfsr(uint64_t new_fsr)
3351{
3352 env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
3353 set_fsr();
3354}
3355#endif
3356
bb5529bb 3357void helper_debug(void)
e80cfcfc
FB
3358{
3359 env->exception_index = EXCP_DEBUG;
3360 cpu_loop_exit();
3361}
af7bf89b 3362
3475187d 3363#ifndef TARGET_SPARC64
72a9747b
BS
3364/* XXX: use another pointer for %iN registers to avoid slow wrapping
3365 handling ? */
3366void helper_save(void)
3367{
3368 uint32_t cwp;
3369
5a834bb4 3370 cwp = cwp_dec(env->cwp - 1);
72a9747b
BS
3371 if (env->wim & (1 << cwp)) {
3372 raise_exception(TT_WIN_OVF);
3373 }
3374 set_cwp(cwp);
3375}
3376
3377void helper_restore(void)
3378{
3379 uint32_t cwp;
3380
5a834bb4 3381 cwp = cwp_inc(env->cwp + 1);
72a9747b
BS
3382 if (env->wim & (1 << cwp)) {
3383 raise_exception(TT_WIN_UNF);
3384 }
3385 set_cwp(cwp);
3386}
3387
1a2fb1c0 3388void helper_wrpsr(target_ulong new_psr)
af7bf89b 3389{
5a834bb4 3390 if ((new_psr & PSR_CWP) >= env->nwindows) {
d4218d99 3391 raise_exception(TT_ILL_INSN);
5a834bb4
BS
3392 } else {
3393 cpu_put_psr(env, new_psr);
3394 }
af7bf89b
FB
3395}
3396
1a2fb1c0 3397target_ulong helper_rdpsr(void)
af7bf89b 3398{
5a834bb4 3399 return get_psr();
af7bf89b 3400}
3475187d
FB
3401
3402#else
72a9747b
BS
3403/* XXX: use another pointer for %iN registers to avoid slow wrapping
3404 handling ? */
3405void helper_save(void)
3406{
3407 uint32_t cwp;
3408
5a834bb4 3409 cwp = cwp_dec(env->cwp - 1);
72a9747b
BS
3410 if (env->cansave == 0) {
3411 raise_exception(TT_SPILL | (env->otherwin != 0 ?
3412 (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3413 ((env->wstate & 0x7) << 2)));
3414 } else {
3415 if (env->cleanwin - env->canrestore == 0) {
3416 // XXX Clean windows without trap
3417 raise_exception(TT_CLRWIN);
3418 } else {
3419 env->cansave--;
3420 env->canrestore++;
3421 set_cwp(cwp);
3422 }
3423 }
3424}
3425
3426void helper_restore(void)
3427{
3428 uint32_t cwp;
3429
5a834bb4 3430 cwp = cwp_inc(env->cwp + 1);
72a9747b
BS
3431 if (env->canrestore == 0) {
3432 raise_exception(TT_FILL | (env->otherwin != 0 ?
3433 (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3434 ((env->wstate & 0x7) << 2)));
3435 } else {
3436 env->cansave++;
3437 env->canrestore--;
3438 set_cwp(cwp);
3439 }
3440}
3441
3442void helper_flushw(void)
3443{
1a14026e 3444 if (env->cansave != env->nwindows - 2) {
72a9747b
BS
3445 raise_exception(TT_SPILL | (env->otherwin != 0 ?
3446 (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3447 ((env->wstate & 0x7) << 2)));
3448 }
3449}
3450
3451void helper_saved(void)
3452{
3453 env->cansave++;
3454 if (env->otherwin == 0)
3455 env->canrestore--;
3456 else
3457 env->otherwin--;
3458}
3459
3460void helper_restored(void)
3461{
3462 env->canrestore++;
1a14026e 3463 if (env->cleanwin < env->nwindows - 1)
72a9747b
BS
3464 env->cleanwin++;
3465 if (env->otherwin == 0)
3466 env->cansave--;
3467 else
3468 env->otherwin--;
3469}
3470
5a834bb4
BS
3471static target_ulong get_ccr(void)
3472{
3473 target_ulong psr;
3474
3475 psr = get_psr();
3476
3477 return ((env->xcc >> 20) << 4) | ((psr & PSR_ICC) >> 20);
3478}
3479
3480target_ulong cpu_get_ccr(CPUState *env1)
3481{
3482 CPUState *saved_env;
3483 target_ulong ret;
3484
3485 saved_env = env;
3486 env = env1;
3487 ret = get_ccr();
3488 env = saved_env;
3489 return ret;
3490}
3491
3492static void put_ccr(target_ulong val)
3493{
3494 target_ulong tmp = val;
3495
3496 env->xcc = (tmp >> 4) << 20;
3497 env->psr = (tmp & 0xf) << 20;
3498 CC_OP = CC_OP_FLAGS;
3499}
3500
3501void cpu_put_ccr(CPUState *env1, target_ulong val)
3502{
3503 CPUState *saved_env;
3504
3505 saved_env = env;
3506 env = env1;
3507 put_ccr(val);
3508 env = saved_env;
3509}
3510
3511static target_ulong get_cwp64(void)
3512{
3513 return env->nwindows - 1 - env->cwp;
3514}
3515
3516target_ulong cpu_get_cwp64(CPUState *env1)
3517{
3518 CPUState *saved_env;
3519 target_ulong ret;
3520
3521 saved_env = env;
3522 env = env1;
3523 ret = get_cwp64();
3524 env = saved_env;
3525 return ret;
3526}
3527
3528static void put_cwp64(int cwp)
3529{
3530 if (unlikely(cwp >= env->nwindows || cwp < 0)) {
3531 cwp %= env->nwindows;
3532 }
3533 set_cwp(env->nwindows - 1 - cwp);
3534}
3535
3536void cpu_put_cwp64(CPUState *env1, int cwp)
3537{
3538 CPUState *saved_env;
3539
3540 saved_env = env;
3541 env = env1;
3542 put_cwp64(cwp);
3543 env = saved_env;
3544}
3545
d35527d9
BS
3546target_ulong helper_rdccr(void)
3547{
5a834bb4 3548 return get_ccr();
d35527d9
BS
3549}
3550
3551void helper_wrccr(target_ulong new_ccr)
3552{
5a834bb4 3553 put_ccr(new_ccr);
d35527d9
BS
3554}
3555
3556// CWP handling is reversed in V9, but we still use the V8 register
3557// order.
3558target_ulong helper_rdcwp(void)
3559{
5a834bb4 3560 return get_cwp64();
d35527d9
BS
3561}
3562
3563void helper_wrcwp(target_ulong new_cwp)
3564{
5a834bb4 3565 put_cwp64(new_cwp);
d35527d9 3566}
3475187d 3567
1f5063fb
BS
3568// This function uses non-native bit order
3569#define GET_FIELD(X, FROM, TO) \
3570 ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
3571
3572// This function uses the order in the manuals, i.e. bit 0 is 2^0
3573#define GET_FIELD_SP(X, FROM, TO) \
3574 GET_FIELD(X, 63 - (TO), 63 - (FROM))
3575
3576target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
3577{
3578 return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
3579 (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
3580 (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
3581 (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
3582 (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
3583 (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
3584 (((pixel_addr >> 55) & 1) << 4) |
3585 (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
3586 GET_FIELD_SP(pixel_addr, 11, 12);
3587}
3588
3589target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
3590{
3591 uint64_t tmp;
3592
3593 tmp = addr + offset;
3594 env->gsr &= ~7ULL;
3595 env->gsr |= tmp & 7ULL;
3596 return tmp & ~7ULL;
3597}
3598
1a2fb1c0 3599target_ulong helper_popc(target_ulong val)
3475187d 3600{
1a2fb1c0 3601 return ctpop64(val);
3475187d 3602}
83469015 3603
d780a466 3604static inline uint64_t *get_gregset(uint32_t pstate)
83469015
FB
3605{
3606 switch (pstate) {
3607 default:
7e8695ed
IK
3608 DPRINTF_PSTATE("ERROR in get_gregset: active pstate bits=%x%s%s%s\n",
3609 pstate,
3610 (pstate & PS_IG) ? " IG" : "",
3611 (pstate & PS_MG) ? " MG" : "",
3612 (pstate & PS_AG) ? " AG" : "");
3613 /* pass through to normal set of global registers */
83469015 3614 case 0:
0f8a249a 3615 return env->bgregs;
83469015 3616 case PS_AG:
0f8a249a 3617 return env->agregs;
83469015 3618 case PS_MG:
0f8a249a 3619 return env->mgregs;
83469015 3620 case PS_IG:
0f8a249a 3621 return env->igregs;
83469015
FB
3622 }
3623}
3624
d780a466 3625static inline void change_pstate(uint32_t new_pstate)
83469015 3626{
d780a466 3627 uint32_t pstate_regs, new_pstate_regs;
83469015
FB
3628 uint64_t *src, *dst;
3629
5210977a
IK
3630 if (env->def->features & CPU_FEATURE_GL) {
3631 // PS_AG is not implemented in this case
3632 new_pstate &= ~PS_AG;
3633 }
3634
83469015
FB
3635 pstate_regs = env->pstate & 0xc01;
3636 new_pstate_regs = new_pstate & 0xc01;
5210977a 3637
83469015 3638 if (new_pstate_regs != pstate_regs) {
7e8695ed
IK
3639 DPRINTF_PSTATE("change_pstate: switching regs old=%x new=%x\n",
3640 pstate_regs, new_pstate_regs);
0f8a249a
BS
3641 // Switch global register bank
3642 src = get_gregset(new_pstate_regs);
3643 dst = get_gregset(pstate_regs);
3644 memcpy32(dst, env->gregs);
3645 memcpy32(env->gregs, src);
83469015 3646 }
7e8695ed
IK
3647 else {
3648 DPRINTF_PSTATE("change_pstate: regs new=%x (unchanged)\n",
3649 new_pstate_regs);
3650 }
83469015
FB
3651 env->pstate = new_pstate;
3652}
3653
1a2fb1c0 3654void helper_wrpstate(target_ulong new_state)
8f1f22f6 3655{
5210977a 3656 change_pstate(new_state & 0xf3f);
4dc28134
IK
3657
3658#if !defined(CONFIG_USER_ONLY)
3659 if (cpu_interrupts_enabled(env)) {
3660 cpu_check_irqs(env);
3661 }
3662#endif
8f1f22f6
BS
3663}
3664
1fae7b70
IK
3665void helper_wrpil(target_ulong new_pil)
3666{
3667#if !defined(CONFIG_USER_ONLY)
3668 DPRINTF_PSTATE("helper_wrpil old=%x new=%x\n",
3669 env->psrpil, (uint32_t)new_pil);
3670
3671 env->psrpil = new_pil;
3672
3673 if (cpu_interrupts_enabled(env)) {
3674 cpu_check_irqs(env);
3675 }
3676#endif
3677}
3678
1a2fb1c0 3679void helper_done(void)
83469015 3680{
8194f35a
IK
3681 trap_state* tsptr = cpu_tsptr(env);
3682
3723cd09 3683 env->pc = tsptr->tnpc;
8194f35a 3684 env->npc = tsptr->tnpc + 4;
5a834bb4 3685 put_ccr(tsptr->tstate >> 32);
8194f35a
IK
3686 env->asi = (tsptr->tstate >> 24) & 0xff;
3687 change_pstate((tsptr->tstate >> 8) & 0xf3f);
5a834bb4 3688 put_cwp64(tsptr->tstate & 0xff);
e6bf7d70 3689 env->tl--;
4dc28134
IK
3690
3691 DPRINTF_PSTATE("... helper_done tl=%d\n", env->tl);
3692
3693#if !defined(CONFIG_USER_ONLY)
3694 if (cpu_interrupts_enabled(env)) {
3695 cpu_check_irqs(env);
3696 }
3697#endif
83469015
FB
3698}
3699
1a2fb1c0 3700void helper_retry(void)
83469015 3701{
8194f35a
IK
3702 trap_state* tsptr = cpu_tsptr(env);
3703
3704 env->pc = tsptr->tpc;
3705 env->npc = tsptr->tnpc;
5a834bb4 3706 put_ccr(tsptr->tstate >> 32);
8194f35a
IK
3707 env->asi = (tsptr->tstate >> 24) & 0xff;
3708 change_pstate((tsptr->tstate >> 8) & 0xf3f);
5a834bb4 3709 put_cwp64(tsptr->tstate & 0xff);
e6bf7d70 3710 env->tl--;
4dc28134
IK
3711
3712 DPRINTF_PSTATE("... helper_retry tl=%d\n", env->tl);
3713
3714#if !defined(CONFIG_USER_ONLY)
3715 if (cpu_interrupts_enabled(env)) {
3716 cpu_check_irqs(env);
3717 }
3718#endif
3719}
3720
3721static void do_modify_softint(const char* operation, uint32_t value)
3722{
3723 if (env->softint != value) {
3724 env->softint = value;
3725 DPRINTF_PSTATE(": %s new %08x\n", operation, env->softint);
3726#if !defined(CONFIG_USER_ONLY)
3727 if (cpu_interrupts_enabled(env)) {
3728 cpu_check_irqs(env);
3729 }
3730#endif
3731 }
83469015 3732}
9d926598
BS
3733
3734void helper_set_softint(uint64_t value)
3735{
4dc28134 3736 do_modify_softint("helper_set_softint", env->softint | (uint32_t)value);
9d926598
BS
3737}
3738
3739void helper_clear_softint(uint64_t value)
3740{
4dc28134 3741 do_modify_softint("helper_clear_softint", env->softint & (uint32_t)~value);
9d926598
BS
3742}
3743
3744void helper_write_softint(uint64_t value)
3745{
4dc28134 3746 do_modify_softint("helper_write_softint", (uint32_t)value);
9d926598 3747}
3475187d 3748#endif
ee5bbe38 3749
91736d37 3750void helper_flush(target_ulong addr)
ee5bbe38 3751{
91736d37
BS
3752 addr &= ~7;
3753 tb_invalidate_page_range(addr, addr + 8);
ee5bbe38
FB
3754}
3755
91736d37
BS
3756#ifdef TARGET_SPARC64
3757#ifdef DEBUG_PCALL
3758static const char * const excp_names[0x80] = {
3759 [TT_TFAULT] = "Instruction Access Fault",
3760 [TT_TMISS] = "Instruction Access MMU Miss",
3761 [TT_CODE_ACCESS] = "Instruction Access Error",
3762 [TT_ILL_INSN] = "Illegal Instruction",
3763 [TT_PRIV_INSN] = "Privileged Instruction",
3764 [TT_NFPU_INSN] = "FPU Disabled",
3765 [TT_FP_EXCP] = "FPU Exception",
3766 [TT_TOVF] = "Tag Overflow",
3767 [TT_CLRWIN] = "Clean Windows",
3768 [TT_DIV_ZERO] = "Division By Zero",
3769 [TT_DFAULT] = "Data Access Fault",
3770 [TT_DMISS] = "Data Access MMU Miss",
3771 [TT_DATA_ACCESS] = "Data Access Error",
3772 [TT_DPROT] = "Data Protection Error",
3773 [TT_UNALIGNED] = "Unaligned Memory Access",
3774 [TT_PRIV_ACT] = "Privileged Action",
3775 [TT_EXTINT | 0x1] = "External Interrupt 1",
3776 [TT_EXTINT | 0x2] = "External Interrupt 2",
3777 [TT_EXTINT | 0x3] = "External Interrupt 3",
3778 [TT_EXTINT | 0x4] = "External Interrupt 4",
3779 [TT_EXTINT | 0x5] = "External Interrupt 5",
3780 [TT_EXTINT | 0x6] = "External Interrupt 6",
3781 [TT_EXTINT | 0x7] = "External Interrupt 7",
3782 [TT_EXTINT | 0x8] = "External Interrupt 8",
3783 [TT_EXTINT | 0x9] = "External Interrupt 9",
3784 [TT_EXTINT | 0xa] = "External Interrupt 10",
3785 [TT_EXTINT | 0xb] = "External Interrupt 11",
3786 [TT_EXTINT | 0xc] = "External Interrupt 12",
3787 [TT_EXTINT | 0xd] = "External Interrupt 13",
3788 [TT_EXTINT | 0xe] = "External Interrupt 14",
3789 [TT_EXTINT | 0xf] = "External Interrupt 15",
3790};
3791#endif
3792
8194f35a
IK
3793trap_state* cpu_tsptr(CPUState* env)
3794{
3795 return &env->ts[env->tl & MAXTL_MASK];
3796}
3797
91736d37
BS
3798void do_interrupt(CPUState *env)
3799{
3800 int intno = env->exception_index;
8194f35a 3801 trap_state* tsptr;
91736d37
BS
3802
3803#ifdef DEBUG_PCALL
8fec2b8c 3804 if (qemu_loglevel_mask(CPU_LOG_INT)) {
91736d37
BS
3805 static int count;
3806 const char *name;
3807
3808 if (intno < 0 || intno >= 0x180)
3809 name = "Unknown";
3810 else if (intno >= 0x100)
3811 name = "Trap Instruction";
3812 else if (intno >= 0xc0)
3813 name = "Window Fill";
3814 else if (intno >= 0x80)
3815 name = "Window Spill";
3816 else {
3817 name = excp_names[intno];
3818 if (!name)
3819 name = "Unknown";
3820 }
3821
93fcfe39 3822 qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
91736d37
BS
3823 " SP=%016" PRIx64 "\n",
3824 count, name, intno,
3825 env->pc,
3826 env->npc, env->regwptr[6]);
93fcfe39 3827 log_cpu_state(env, 0);
91736d37
BS
3828#if 0
3829 {
3830 int i;
3831 uint8_t *ptr;
3832
93fcfe39 3833 qemu_log(" code=");
91736d37
BS
3834 ptr = (uint8_t *)env->pc;
3835 for(i = 0; i < 16; i++) {
93fcfe39 3836 qemu_log(" %02x", ldub(ptr + i));
91736d37 3837 }
93fcfe39 3838 qemu_log("\n");
91736d37
BS
3839 }
3840#endif
3841 count++;
3842 }
3843#endif
3844#if !defined(CONFIG_USER_ONLY)
3845 if (env->tl >= env->maxtl) {
3846 cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
3847 " Error state", env->exception_index, env->tl, env->maxtl);
3848 return;
3849 }
3850#endif
3851 if (env->tl < env->maxtl - 1) {
3852 env->tl++;
3853 } else {
3854 env->pstate |= PS_RED;
3855 if (env->tl < env->maxtl)
3856 env->tl++;
3857 }
8194f35a
IK
3858 tsptr = cpu_tsptr(env);
3859
5a834bb4 3860 tsptr->tstate = (get_ccr() << 32) |
91736d37 3861 ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
5a834bb4 3862 get_cwp64();
8194f35a
IK
3863 tsptr->tpc = env->pc;
3864 tsptr->tnpc = env->npc;
3865 tsptr->tt = intno;
5210977a
IK
3866
3867 switch (intno) {
3868 case TT_IVEC:
3869 change_pstate(PS_PEF | PS_PRIV | PS_IG);
3870 break;
3871 case TT_TFAULT:
5210977a 3872 case TT_DFAULT:
87f6d3f6
IK
3873 case TT_TMISS ... TT_TMISS + 3:
3874 case TT_DMISS ... TT_DMISS + 3:
3875 case TT_DPROT ... TT_DPROT + 3:
5210977a
IK
3876 change_pstate(PS_PEF | PS_PRIV | PS_MG);
3877 break;
3878 default:
3879 change_pstate(PS_PEF | PS_PRIV | PS_AG);
3880 break;
91736d37 3881 }
5210977a 3882
5a834bb4
BS
3883 if (intno == TT_CLRWIN) {
3884 set_cwp(cwp_dec(env->cwp - 1));
3885 } else if ((intno & 0x1c0) == TT_SPILL) {
3886 set_cwp(cwp_dec(env->cwp - env->cansave - 2));
3887 } else if ((intno & 0x1c0) == TT_FILL) {
3888 set_cwp(cwp_inc(env->cwp + 1));
3889 }
91736d37
BS
3890 env->tbr &= ~0x7fffULL;
3891 env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
3892 env->pc = env->tbr;
3893 env->npc = env->pc + 4;
821b19fe 3894 env->exception_index = -1;
ee5bbe38 3895}
91736d37
BS
3896#else
3897#ifdef DEBUG_PCALL
3898static const char * const excp_names[0x80] = {
3899 [TT_TFAULT] = "Instruction Access Fault",
3900 [TT_ILL_INSN] = "Illegal Instruction",
3901 [TT_PRIV_INSN] = "Privileged Instruction",
3902 [TT_NFPU_INSN] = "FPU Disabled",
3903 [TT_WIN_OVF] = "Window Overflow",
3904 [TT_WIN_UNF] = "Window Underflow",
3905 [TT_UNALIGNED] = "Unaligned Memory Access",
3906 [TT_FP_EXCP] = "FPU Exception",
3907 [TT_DFAULT] = "Data Access Fault",
3908 [TT_TOVF] = "Tag Overflow",
3909 [TT_EXTINT | 0x1] = "External Interrupt 1",
3910 [TT_EXTINT | 0x2] = "External Interrupt 2",
3911 [TT_EXTINT | 0x3] = "External Interrupt 3",
3912 [TT_EXTINT | 0x4] = "External Interrupt 4",
3913 [TT_EXTINT | 0x5] = "External Interrupt 5",
3914 [TT_EXTINT | 0x6] = "External Interrupt 6",
3915 [TT_EXTINT | 0x7] = "External Interrupt 7",
3916 [TT_EXTINT | 0x8] = "External Interrupt 8",
3917 [TT_EXTINT | 0x9] = "External Interrupt 9",
3918 [TT_EXTINT | 0xa] = "External Interrupt 10",
3919 [TT_EXTINT | 0xb] = "External Interrupt 11",
3920 [TT_EXTINT | 0xc] = "External Interrupt 12",
3921 [TT_EXTINT | 0xd] = "External Interrupt 13",
3922 [TT_EXTINT | 0xe] = "External Interrupt 14",
3923 [TT_EXTINT | 0xf] = "External Interrupt 15",
3924 [TT_TOVF] = "Tag Overflow",
3925 [TT_CODE_ACCESS] = "Instruction Access Error",
3926 [TT_DATA_ACCESS] = "Data Access Error",
3927 [TT_DIV_ZERO] = "Division By Zero",
3928 [TT_NCP_INSN] = "Coprocessor Disabled",
3929};
3930#endif
ee5bbe38 3931
91736d37 3932void do_interrupt(CPUState *env)
ee5bbe38 3933{
91736d37
BS
3934 int cwp, intno = env->exception_index;
3935
3936#ifdef DEBUG_PCALL
8fec2b8c 3937 if (qemu_loglevel_mask(CPU_LOG_INT)) {
91736d37
BS
3938 static int count;
3939 const char *name;
3940
3941 if (intno < 0 || intno >= 0x100)
3942 name = "Unknown";
3943 else if (intno >= 0x80)
3944 name = "Trap Instruction";
3945 else {
3946 name = excp_names[intno];
3947 if (!name)
3948 name = "Unknown";
3949 }
3950
93fcfe39 3951 qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
91736d37
BS
3952 count, name, intno,
3953 env->pc,
3954 env->npc, env->regwptr[6]);
93fcfe39 3955 log_cpu_state(env, 0);
91736d37
BS
3956#if 0
3957 {
3958 int i;
3959 uint8_t *ptr;
3960
93fcfe39 3961 qemu_log(" code=");
91736d37
BS
3962 ptr = (uint8_t *)env->pc;
3963 for(i = 0; i < 16; i++) {
93fcfe39 3964 qemu_log(" %02x", ldub(ptr + i));
91736d37 3965 }
93fcfe39 3966 qemu_log("\n");
91736d37
BS
3967 }
3968#endif
3969 count++;
3970 }
3971#endif
3972#if !defined(CONFIG_USER_ONLY)
3973 if (env->psret == 0) {
3974 cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
3975 env->exception_index);
3976 return;
3977 }
3978#endif
3979 env->psret = 0;
5a834bb4
BS
3980 cwp = cwp_dec(env->cwp - 1);
3981 set_cwp(cwp);
91736d37
BS
3982 env->regwptr[9] = env->pc;
3983 env->regwptr[10] = env->npc;
3984 env->psrps = env->psrs;
3985 env->psrs = 1;
3986 env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
3987 env->pc = env->tbr;
3988 env->npc = env->pc + 4;
95372a39 3989 env->exception_index = -1;
ee5bbe38 3990}
91736d37 3991#endif
ee5bbe38 3992
5fafdf24 3993#if !defined(CONFIG_USER_ONLY)
ee5bbe38 3994
d2889a3e
BS
3995static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3996 void *retaddr);
3997
ee5bbe38 3998#define MMUSUFFIX _mmu
d2889a3e 3999#define ALIGNED_ONLY
ee5bbe38
FB
4000
4001#define SHIFT 0
4002#include "softmmu_template.h"
4003
4004#define SHIFT 1
4005#include "softmmu_template.h"
4006
4007#define SHIFT 2
4008#include "softmmu_template.h"
4009
4010#define SHIFT 3
4011#include "softmmu_template.h"
4012
c2bc0e38
BS
4013/* XXX: make it generic ? */
4014static void cpu_restore_state2(void *retaddr)
4015{
4016 TranslationBlock *tb;
4017 unsigned long pc;
4018
4019 if (retaddr) {
4020 /* now we have a real cpu fault */
4021 pc = (unsigned long)retaddr;
4022 tb = tb_find_pc(pc);
4023 if (tb) {
4024 /* the PC is inside the translated code. It means that we have
4025 a virtual CPU fault */
4026 cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
4027 }
4028 }
4029}
4030
d2889a3e
BS
4031static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
4032 void *retaddr)
4033{
94554550 4034#ifdef DEBUG_UNALIGNED
c2bc0e38
BS
4035 printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
4036 "\n", addr, env->pc);
94554550 4037#endif
c2bc0e38 4038 cpu_restore_state2(retaddr);
94554550 4039 raise_exception(TT_UNALIGNED);
d2889a3e 4040}
ee5bbe38
FB
4041
4042/* try to fill the TLB and return an exception if error. If retaddr is
4043 NULL, it means that the function was called in C code (i.e. not
4044 from generated code or from helper.c) */
4045/* XXX: fix it to restore all registers */
6ebbf390 4046void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
ee5bbe38 4047{
ee5bbe38 4048 int ret;
ee5bbe38
FB
4049 CPUState *saved_env;
4050
4051 /* XXX: hack to restore env in all cases, even if not called from
4052 generated code */
4053 saved_env = env;
4054 env = cpu_single_env;
4055
6ebbf390 4056 ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
ee5bbe38 4057 if (ret) {
c2bc0e38 4058 cpu_restore_state2(retaddr);
ee5bbe38
FB
4059 cpu_loop_exit();
4060 }
4061 env = saved_env;
4062}
4063
3c7b48b7 4064#endif /* !CONFIG_USER_ONLY */
6c36d3fa
BS
4065
4066#ifndef TARGET_SPARC64
3c7b48b7 4067#if !defined(CONFIG_USER_ONLY)
c227f099 4068void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
e18231a3 4069 int is_asi, int size)
6c36d3fa
BS
4070{
4071 CPUState *saved_env;
576c2cdc 4072 int fault_type;
6c36d3fa
BS
4073
4074 /* XXX: hack to restore env in all cases, even if not called from
4075 generated code */
4076 saved_env = env;
4077 env = cpu_single_env;
8543e2cf
BS
4078#ifdef DEBUG_UNASSIGNED
4079 if (is_asi)
e18231a3 4080 printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
77f193da 4081 " asi 0x%02x from " TARGET_FMT_lx "\n",
e18231a3
BS
4082 is_exec ? "exec" : is_write ? "write" : "read", size,
4083 size == 1 ? "" : "s", addr, is_asi, env->pc);
8543e2cf 4084 else
e18231a3
BS
4085 printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
4086 " from " TARGET_FMT_lx "\n",
4087 is_exec ? "exec" : is_write ? "write" : "read", size,
4088 size == 1 ? "" : "s", addr, env->pc);
8543e2cf 4089#endif
576c2cdc
AT
4090 /* Don't overwrite translation and access faults */
4091 fault_type = (env->mmuregs[3] & 0x1c) >> 2;
4092 if ((fault_type > 4) || (fault_type == 0)) {
4093 env->mmuregs[3] = 0; /* Fault status register */
4094 if (is_asi)
4095 env->mmuregs[3] |= 1 << 16;
4096 if (env->psrs)
4097 env->mmuregs[3] |= 1 << 5;
4098 if (is_exec)
4099 env->mmuregs[3] |= 1 << 6;
4100 if (is_write)
4101 env->mmuregs[3] |= 1 << 7;
4102 env->mmuregs[3] |= (5 << 2) | 2;
4103 /* SuperSPARC will never place instruction fault addresses in the FAR */
4104 if (!is_exec) {
4105 env->mmuregs[4] = addr; /* Fault address register */
4106 }
4107 }
4108 /* overflow (same type fault was not read before another fault) */
4109 if (fault_type == ((env->mmuregs[3] & 0x1c)) >> 2) {
4110 env->mmuregs[3] |= 1;
4111 }
4112
6c36d3fa 4113 if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
1b2e93c1
BS
4114 if (is_exec)
4115 raise_exception(TT_CODE_ACCESS);
4116 else
4117 raise_exception(TT_DATA_ACCESS);
6c36d3fa 4118 }
576c2cdc
AT
4119
4120 /* flush neverland mappings created during no-fault mode,
4121 so the sequential MMU faults report proper fault types */
4122 if (env->mmuregs[0] & MMU_NF) {
4123 tlb_flush(env, 1);
4124 }
15e7c451
AT
4125
4126 env = saved_env;
6c36d3fa 4127}
3c7b48b7
PB
4128#endif
4129#else
4130#if defined(CONFIG_USER_ONLY)
4131static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
4132 int is_asi, int size)
6c36d3fa 4133#else
c227f099 4134void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
e18231a3 4135 int is_asi, int size)
3c7b48b7 4136#endif
6c36d3fa 4137{
6c36d3fa
BS
4138 CPUState *saved_env;
4139
4140 /* XXX: hack to restore env in all cases, even if not called from
4141 generated code */
4142 saved_env = env;
4143 env = cpu_single_env;
dffbe217
IK
4144
4145#ifdef DEBUG_UNASSIGNED
77f193da
BS
4146 printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
4147 "\n", addr, env->pc);
6c36d3fa 4148#endif
dffbe217 4149
1b2e93c1
BS
4150 if (is_exec)
4151 raise_exception(TT_CODE_ACCESS);
4152 else
4153 raise_exception(TT_DATA_ACCESS);
dffbe217
IK
4154
4155 env = saved_env;
6c36d3fa
BS
4156}
4157#endif
20c9f095 4158
3c7b48b7 4159
f4b1a842
BS
4160#ifdef TARGET_SPARC64
4161void helper_tick_set_count(void *opaque, uint64_t count)
4162{
4163#if !defined(CONFIG_USER_ONLY)
4164 cpu_tick_set_count(opaque, count);
4165#endif
4166}
4167
4168uint64_t helper_tick_get_count(void *opaque)
4169{
4170#if !defined(CONFIG_USER_ONLY)
4171 return cpu_tick_get_count(opaque);
4172#else
4173 return 0;
4174#endif
4175}
4176
4177void helper_tick_set_limit(void *opaque, uint64_t limit)
4178{
4179#if !defined(CONFIG_USER_ONLY)
4180 cpu_tick_set_limit(opaque, limit);
4181#endif
4182}
4183#endif