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