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