]> git.proxmox.com Git - qemu.git/blame - target-sparc/op_helper.c
Only build qemu-img with softmmu targets.
[qemu.git] / target-sparc / op_helper.c
CommitLineData
e8af50a3
FB
1#include "exec.h"
2
83469015 3//#define DEBUG_PCALL
e80cfcfc 4//#define DEBUG_MMU
94554550 5//#define DEBUG_UNALIGNED
6c36d3fa 6//#define DEBUG_UNASSIGNED
e80cfcfc 7
9d893301
FB
8void raise_exception(int tt)
9{
10 env->exception_index = tt;
11 cpu_loop_exit();
3b46e624 12}
9d893301 13
417454b0
BS
14void check_ieee_exceptions()
15{
16 T0 = get_float_exception_flags(&env->fp_status);
17 if (T0)
18 {
0f8a249a
BS
19 /* Copy IEEE 754 flags into FSR */
20 if (T0 & float_flag_invalid)
21 env->fsr |= FSR_NVC;
22 if (T0 & float_flag_overflow)
23 env->fsr |= FSR_OFC;
24 if (T0 & float_flag_underflow)
25 env->fsr |= FSR_UFC;
26 if (T0 & float_flag_divbyzero)
27 env->fsr |= FSR_DZC;
28 if (T0 & float_flag_inexact)
29 env->fsr |= FSR_NXC;
30
31 if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23))
32 {
33 /* Unmasked exception, generate a trap */
34 env->fsr |= FSR_FTT_IEEE_EXCP;
35 raise_exception(TT_FP_EXCP);
36 }
37 else
38 {
39 /* Accumulate exceptions */
40 env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
41 }
417454b0
BS
42 }
43}
44
a0c4cb4a
FB
45#ifdef USE_INT_TO_FLOAT_HELPERS
46void do_fitos(void)
47{
417454b0 48 set_float_exception_flags(0, &env->fp_status);
ec230928 49 FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
417454b0 50 check_ieee_exceptions();
a0c4cb4a
FB
51}
52
53void do_fitod(void)
54{
ec230928 55 DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
a0c4cb4a
FB
56}
57#endif
58
59void do_fabss(void)
e8af50a3 60{
7a0e1f41 61 FT0 = float32_abs(FT1);
e8af50a3
FB
62}
63
3475187d
FB
64#ifdef TARGET_SPARC64
65void do_fabsd(void)
66{
67 DT0 = float64_abs(DT1);
68}
69#endif
70
a0c4cb4a 71void do_fsqrts(void)
e8af50a3 72{
417454b0 73 set_float_exception_flags(0, &env->fp_status);
7a0e1f41 74 FT0 = float32_sqrt(FT1, &env->fp_status);
417454b0 75 check_ieee_exceptions();
e8af50a3
FB
76}
77
a0c4cb4a 78void do_fsqrtd(void)
e8af50a3 79{
417454b0 80 set_float_exception_flags(0, &env->fp_status);
7a0e1f41 81 DT0 = float64_sqrt(DT1, &env->fp_status);
417454b0 82 check_ieee_exceptions();
e8af50a3
FB
83}
84
417454b0 85#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
65ce8c2f
FB
86 void glue(do_, name) (void) \
87 { \
88 env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
89 switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
90 case float_relation_unordered: \
91 T0 = (FSR_FCC1 | FSR_FCC0) << FS; \
417454b0 92 if ((env->fsr & FSR_NVM) || TRAP) { \
65ce8c2f 93 env->fsr |= T0; \
417454b0
BS
94 env->fsr |= FSR_NVC; \
95 env->fsr |= FSR_FTT_IEEE_EXCP; \
65ce8c2f
FB
96 raise_exception(TT_FP_EXCP); \
97 } else { \
98 env->fsr |= FSR_NVA; \
99 } \
100 break; \
101 case float_relation_less: \
102 T0 = FSR_FCC0 << FS; \
103 break; \
104 case float_relation_greater: \
105 T0 = FSR_FCC1 << FS; \
106 break; \
107 default: \
108 T0 = 0; \
109 break; \
110 } \
111 env->fsr |= T0; \
e8af50a3 112 }
e8af50a3 113
417454b0
BS
114GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
115GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
116
117GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
118GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
3475187d
FB
119
120#ifdef TARGET_SPARC64
417454b0
BS
121GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
122GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
123
124GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
125GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
126
127GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
128GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
129
130GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
131GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
3475187d 132
417454b0
BS
133GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
134GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
3475187d 135
417454b0
BS
136GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
137GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
3475187d
FB
138#endif
139
140#ifndef TARGET_SPARC64
81ad8ba2 141#ifndef CONFIG_USER_ONLY
a0c4cb4a 142void helper_ld_asi(int asi, int size, int sign)
e8af50a3 143{
83469015 144 uint32_t ret = 0;
e80cfcfc
FB
145
146 switch (asi) {
6c36d3fa
BS
147 case 2: /* SuperSparc MXCC registers */
148 break;
e8af50a3 149 case 3: /* MMU probe */
0f8a249a
BS
150 {
151 int mmulev;
152
153 mmulev = (T0 >> 8) & 15;
154 if (mmulev > 4)
155 ret = 0;
156 else {
157 ret = mmu_probe(env, T0, mmulev);
158 //bswap32s(&ret);
159 }
e80cfcfc 160#ifdef DEBUG_MMU
0f8a249a 161 printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
e80cfcfc 162#endif
0f8a249a
BS
163 }
164 break;
e8af50a3 165 case 4: /* read MMU regs */
0f8a249a
BS
166 {
167 int reg = (T0 >> 8) & 0xf;
3b46e624 168
0f8a249a
BS
169 ret = env->mmuregs[reg];
170 if (reg == 3) /* Fault status cleared on read */
171 env->mmuregs[reg] = 0;
55754d9e 172#ifdef DEBUG_MMU
0f8a249a 173 printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
55754d9e 174#endif
0f8a249a
BS
175 }
176 break;
6c36d3fa
BS
177 case 9: /* Supervisor code access */
178 switch(size) {
179 case 1:
180 ret = ldub_code(T0);
181 break;
182 case 2:
183 ret = lduw_code(T0 & ~1);
184 break;
185 default:
186 case 4:
187 ret = ldl_code(T0 & ~3);
188 break;
189 case 8:
190 ret = ldl_code(T0 & ~3);
191 T0 = ldl_code((T0 + 4) & ~3);
192 break;
193 }
194 break;
81ad8ba2
BS
195 case 0xa: /* User data access */
196 switch(size) {
197 case 1:
198 ret = ldub_user(T0);
199 break;
200 case 2:
201 ret = lduw_user(T0 & ~1);
202 break;
203 default:
204 case 4:
205 ret = ldl_user(T0 & ~3);
206 break;
207 case 8:
208 ret = ldl_user(T0 & ~3);
209 T0 = ldl_user((T0 + 4) & ~3);
210 break;
211 }
212 break;
213 case 0xb: /* Supervisor data access */
214 switch(size) {
215 case 1:
216 ret = ldub_kernel(T0);
217 break;
218 case 2:
219 ret = lduw_kernel(T0 & ~1);
220 break;
221 default:
222 case 4:
223 ret = ldl_kernel(T0 & ~3);
224 break;
225 case 8:
226 ret = ldl_kernel(T0 & ~3);
227 T0 = ldl_kernel((T0 + 4) & ~3);
228 break;
229 }
230 break;
6c36d3fa
BS
231 case 0xc: /* I-cache tag */
232 case 0xd: /* I-cache data */
233 case 0xe: /* D-cache tag */
234 case 0xf: /* D-cache data */
235 break;
236 case 0x20: /* MMU passthrough */
02aab46a
FB
237 switch(size) {
238 case 1:
239 ret = ldub_phys(T0);
240 break;
241 case 2:
242 ret = lduw_phys(T0 & ~1);
243 break;
244 default:
245 case 4:
246 ret = ldl_phys(T0 & ~3);
247 break;
9e61bde5 248 case 8:
0f8a249a
BS
249 ret = ldl_phys(T0 & ~3);
250 T0 = ldl_phys((T0 + 4) & ~3);
251 break;
02aab46a 252 }
0f8a249a 253 break;
5dcb6b91
BS
254 case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
255 case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
256 switch(size) {
257 case 1:
258 ret = ldub_phys((target_phys_addr_t)T0
259 | ((target_phys_addr_t)(asi & 0xf) << 32));
260 break;
261 case 2:
262 ret = lduw_phys((target_phys_addr_t)(T0 & ~1)
263 | ((target_phys_addr_t)(asi & 0xf) << 32));
264 break;
265 default:
266 case 4:
267 ret = ldl_phys((target_phys_addr_t)(T0 & ~3)
268 | ((target_phys_addr_t)(asi & 0xf) << 32));
269 break;
270 case 8:
271 ret = ldl_phys((target_phys_addr_t)(T0 & ~3)
272 | ((target_phys_addr_t)(asi & 0xf) << 32));
273 T0 = ldl_phys((target_phys_addr_t)((T0 + 4) & ~3)
274 | ((target_phys_addr_t)(asi & 0xf) << 32));
0f8a249a 275 break;
5dcb6b91 276 }
0f8a249a 277 break;
5dcb6b91 278 case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
e8af50a3 279 default:
6c36d3fa 280 do_unassigned_access(T0, 0, 0, 1);
0f8a249a
BS
281 ret = 0;
282 break;
e8af50a3 283 }
81ad8ba2
BS
284 if (sign) {
285 switch(size) {
286 case 1:
287 T1 = (int8_t) ret;
288 case 2:
289 T1 = (int16_t) ret;
290 default:
291 T1 = ret;
292 break;
293 }
294 }
295 else
296 T1 = ret;
e8af50a3
FB
297}
298
81ad8ba2 299void helper_st_asi(int asi, int size)
e8af50a3
FB
300{
301 switch(asi) {
6c36d3fa
BS
302 case 2: /* SuperSparc MXCC registers */
303 break;
e8af50a3 304 case 3: /* MMU flush */
0f8a249a
BS
305 {
306 int mmulev;
e80cfcfc 307
0f8a249a 308 mmulev = (T0 >> 8) & 15;
55754d9e 309#ifdef DEBUG_MMU
0f8a249a 310 printf("mmu flush level %d\n", mmulev);
55754d9e 311#endif
0f8a249a
BS
312 switch (mmulev) {
313 case 0: // flush page
314 tlb_flush_page(env, T0 & 0xfffff000);
315 break;
316 case 1: // flush segment (256k)
317 case 2: // flush region (16M)
318 case 3: // flush context (4G)
319 case 4: // flush entire
320 tlb_flush(env, 1);
321 break;
322 default:
323 break;
324 }
55754d9e 325#ifdef DEBUG_MMU
0f8a249a 326 dump_mmu(env);
55754d9e 327#endif
0f8a249a
BS
328 return;
329 }
e8af50a3 330 case 4: /* write MMU regs */
0f8a249a
BS
331 {
332 int reg = (T0 >> 8) & 0xf;
333 uint32_t oldreg;
3b46e624 334
0f8a249a 335 oldreg = env->mmuregs[reg];
55754d9e
FB
336 switch(reg) {
337 case 0:
0f8a249a
BS
338 env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
339 env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
340 // Mappings generated during no-fault mode or MMU
341 // disabled mode are invalid in normal mode
6f7e9aec 342 if (oldreg != env->mmuregs[reg])
55754d9e
FB
343 tlb_flush(env, 1);
344 break;
345 case 2:
0f8a249a 346 env->mmuregs[reg] = T1;
55754d9e
FB
347 if (oldreg != env->mmuregs[reg]) {
348 /* we flush when the MMU context changes because
349 QEMU has no MMU context support */
350 tlb_flush(env, 1);
351 }
352 break;
353 case 3:
354 case 4:
355 break;
356 default:
0f8a249a 357 env->mmuregs[reg] = T1;
55754d9e
FB
358 break;
359 }
360#ifdef DEBUG_MMU
361 if (oldreg != env->mmuregs[reg]) {
362 printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
363 }
0f8a249a 364 dump_mmu(env);
55754d9e 365#endif
0f8a249a
BS
366 return;
367 }
81ad8ba2
BS
368 case 0xa: /* User data access */
369 switch(size) {
370 case 1:
371 stb_user(T0, T1);
372 break;
373 case 2:
374 stw_user(T0 & ~1, T1);
375 break;
376 default:
377 case 4:
378 stl_user(T0 & ~3, T1);
379 break;
380 case 8:
381 stl_user(T0 & ~3, T1);
382 stl_user((T0 + 4) & ~3, T2);
383 break;
384 }
385 break;
386 case 0xb: /* Supervisor data access */
387 switch(size) {
388 case 1:
389 stb_kernel(T0, T1);
390 break;
391 case 2:
392 stw_kernel(T0 & ~1, T1);
393 break;
394 default:
395 case 4:
396 stl_kernel(T0 & ~3, T1);
397 break;
398 case 8:
399 stl_kernel(T0 & ~3, T1);
400 stl_kernel((T0 + 4) & ~3, T2);
401 break;
402 }
403 break;
6c36d3fa
BS
404 case 0xc: /* I-cache tag */
405 case 0xd: /* I-cache data */
406 case 0xe: /* D-cache tag */
407 case 0xf: /* D-cache data */
408 case 0x10: /* I/D-cache flush page */
409 case 0x11: /* I/D-cache flush segment */
410 case 0x12: /* I/D-cache flush region */
411 case 0x13: /* I/D-cache flush context */
412 case 0x14: /* I/D-cache flush user */
413 break;
e80cfcfc 414 case 0x17: /* Block copy, sta access */
0f8a249a
BS
415 {
416 // value (T1) = src
417 // address (T0) = dst
418 // copy 32 bytes
6c36d3fa
BS
419 unsigned int i;
420 uint32_t src = T1 & ~3, dst = T0 & ~3, temp;
3b46e624 421
6c36d3fa
BS
422 for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
423 temp = ldl_kernel(src);
424 stl_kernel(dst, temp);
425 }
0f8a249a
BS
426 }
427 return;
e80cfcfc 428 case 0x1f: /* Block fill, stda access */
0f8a249a
BS
429 {
430 // value (T1, T2)
431 // address (T0) = dst
432 // fill 32 bytes
6c36d3fa
BS
433 unsigned int i;
434 uint32_t dst = T0 & 7;
435 uint64_t val;
e80cfcfc 436
6c36d3fa
BS
437 val = (((uint64_t)T1) << 32) | T2;
438
439 for (i = 0; i < 32; i += 8, dst += 8)
440 stq_kernel(dst, val);
0f8a249a
BS
441 }
442 return;
6c36d3fa 443 case 0x20: /* MMU passthrough */
0f8a249a 444 {
02aab46a
FB
445 switch(size) {
446 case 1:
447 stb_phys(T0, T1);
448 break;
449 case 2:
450 stw_phys(T0 & ~1, T1);
451 break;
452 case 4:
453 default:
454 stl_phys(T0 & ~3, T1);
455 break;
9e61bde5
FB
456 case 8:
457 stl_phys(T0 & ~3, T1);
458 stl_phys((T0 + 4) & ~3, T2);
459 break;
02aab46a 460 }
0f8a249a
BS
461 }
462 return;
5dcb6b91
BS
463 case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
464 case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
0f8a249a 465 {
5dcb6b91
BS
466 switch(size) {
467 case 1:
468 stb_phys((target_phys_addr_t)T0
469 | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
470 break;
471 case 2:
472 stw_phys((target_phys_addr_t)(T0 & ~1)
473 | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
474 break;
475 case 4:
476 default:
477 stl_phys((target_phys_addr_t)(T0 & ~3)
478 | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
479 break;
480 case 8:
481 stl_phys((target_phys_addr_t)(T0 & ~3)
482 | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
483 stl_phys((target_phys_addr_t)((T0 + 4) & ~3)
484 | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
485 break;
486 }
0f8a249a
BS
487 }
488 return;
6c36d3fa
BS
489 case 0x31: /* Ross RT620 I-cache flush */
490 case 0x36: /* I-cache flash clear */
491 case 0x37: /* D-cache flash clear */
492 break;
493 case 9: /* Supervisor code access, XXX */
5dcb6b91 494 case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
e8af50a3 495 default:
6c36d3fa 496 do_unassigned_access(T0, 1, 0, 1);
0f8a249a 497 return;
e8af50a3
FB
498 }
499}
500
81ad8ba2
BS
501#endif /* CONFIG_USER_ONLY */
502#else /* TARGET_SPARC64 */
503
504#ifdef CONFIG_USER_ONLY
505void helper_ld_asi(int asi, int size, int sign)
506{
507 uint64_t ret = 0;
508
509 if (asi < 0x80)
510 raise_exception(TT_PRIV_ACT);
511
512 switch (asi) {
513 case 0x80: // Primary
514 case 0x82: // Primary no-fault
515 case 0x88: // Primary LE
516 case 0x8a: // Primary no-fault LE
517 {
518 switch(size) {
519 case 1:
520 ret = ldub_raw(T0);
521 break;
522 case 2:
523 ret = lduw_raw(T0 & ~1);
524 break;
525 case 4:
526 ret = ldl_raw(T0 & ~3);
527 break;
528 default:
529 case 8:
530 ret = ldq_raw(T0 & ~7);
531 break;
532 }
533 }
534 break;
535 case 0x81: // Secondary
536 case 0x83: // Secondary no-fault
537 case 0x89: // Secondary LE
538 case 0x8b: // Secondary no-fault LE
539 // XXX
540 break;
541 default:
542 break;
543 }
544
545 /* Convert from little endian */
546 switch (asi) {
547 case 0x88: // Primary LE
548 case 0x89: // Secondary LE
549 case 0x8a: // Primary no-fault LE
550 case 0x8b: // Secondary no-fault LE
551 switch(size) {
552 case 2:
553 ret = bswap16(ret);
554 case 4:
555 ret = bswap32(ret);
556 case 8:
557 ret = bswap64(ret);
558 default:
559 break;
560 }
561 default:
562 break;
563 }
564
565 /* Convert to signed number */
566 if (sign) {
567 switch(size) {
568 case 1:
569 ret = (int8_t) ret;
570 case 2:
571 ret = (int16_t) ret;
572 case 4:
573 ret = (int32_t) ret;
574 default:
575 break;
576 }
577 }
578 T1 = ret;
579}
580
581void helper_st_asi(int asi, int size)
582{
583 if (asi < 0x80)
584 raise_exception(TT_PRIV_ACT);
585
586 /* Convert to little endian */
587 switch (asi) {
588 case 0x88: // Primary LE
589 case 0x89: // Secondary LE
590 switch(size) {
591 case 2:
592 T0 = bswap16(T0);
593 case 4:
594 T0 = bswap32(T0);
595 case 8:
596 T0 = bswap64(T0);
597 default:
598 break;
599 }
600 default:
601 break;
602 }
603
604 switch(asi) {
605 case 0x80: // Primary
606 case 0x88: // Primary LE
607 {
608 switch(size) {
609 case 1:
610 stb_raw(T0, T1);
611 break;
612 case 2:
613 stw_raw(T0 & ~1, T1);
614 break;
615 case 4:
616 stl_raw(T0 & ~3, T1);
617 break;
618 case 8:
619 default:
620 stq_raw(T0 & ~7, T1);
621 break;
622 }
623 }
624 break;
625 case 0x81: // Secondary
626 case 0x89: // Secondary LE
627 // XXX
628 return;
629
630 case 0x82: // Primary no-fault, RO
631 case 0x83: // Secondary no-fault, RO
632 case 0x8a: // Primary no-fault LE, RO
633 case 0x8b: // Secondary no-fault LE, RO
634 default:
635 do_unassigned_access(T0, 1, 0, 1);
636 return;
637 }
638}
639
640#else /* CONFIG_USER_ONLY */
3475187d
FB
641
642void helper_ld_asi(int asi, int size, int sign)
643{
83469015 644 uint64_t ret = 0;
3475187d
FB
645
646 if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
0f8a249a 647 raise_exception(TT_PRIV_ACT);
3475187d
FB
648
649 switch (asi) {
81ad8ba2
BS
650 case 0x10: // As if user primary
651 case 0x18: // As if user primary LE
652 case 0x80: // Primary
653 case 0x82: // Primary no-fault
654 case 0x88: // Primary LE
655 case 0x8a: // Primary no-fault LE
656 if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
657 switch(size) {
658 case 1:
659 ret = ldub_kernel(T0);
660 break;
661 case 2:
662 ret = lduw_kernel(T0 & ~1);
663 break;
664 case 4:
665 ret = ldl_kernel(T0 & ~3);
666 break;
667 default:
668 case 8:
669 ret = ldq_kernel(T0 & ~7);
670 break;
671 }
672 } else {
673 switch(size) {
674 case 1:
675 ret = ldub_user(T0);
676 break;
677 case 2:
678 ret = lduw_user(T0 & ~1);
679 break;
680 case 4:
681 ret = ldl_user(T0 & ~3);
682 break;
683 default:
684 case 8:
685 ret = ldq_user(T0 & ~7);
686 break;
687 }
688 }
689 break;
3475187d
FB
690 case 0x14: // Bypass
691 case 0x15: // Bypass, non-cacheable
81ad8ba2
BS
692 case 0x1c: // Bypass LE
693 case 0x1d: // Bypass, non-cacheable LE
0f8a249a 694 {
02aab46a
FB
695 switch(size) {
696 case 1:
697 ret = ldub_phys(T0);
698 break;
699 case 2:
700 ret = lduw_phys(T0 & ~1);
701 break;
702 case 4:
703 ret = ldl_phys(T0 & ~3);
704 break;
705 default:
706 case 8:
707 ret = ldq_phys(T0 & ~7);
708 break;
709 }
0f8a249a
BS
710 break;
711 }
83469015
FB
712 case 0x04: // Nucleus
713 case 0x0c: // Nucleus Little Endian (LE)
83469015 714 case 0x11: // As if user secondary
83469015 715 case 0x19: // As if user secondary LE
83469015
FB
716 case 0x24: // Nucleus quad LDD 128 bit atomic
717 case 0x2c: // Nucleus quad LDD 128 bit atomic
718 case 0x4a: // UPA config
81ad8ba2 719 case 0x81: // Secondary
83469015 720 case 0x83: // Secondary no-fault
83469015 721 case 0x89: // Secondary LE
83469015 722 case 0x8b: // Secondary no-fault LE
0f8a249a
BS
723 // XXX
724 break;
3475187d 725 case 0x45: // LSU
0f8a249a
BS
726 ret = env->lsu;
727 break;
3475187d 728 case 0x50: // I-MMU regs
0f8a249a
BS
729 {
730 int reg = (T0 >> 3) & 0xf;
3475187d 731
0f8a249a
BS
732 ret = env->immuregs[reg];
733 break;
734 }
3475187d
FB
735 case 0x51: // I-MMU 8k TSB pointer
736 case 0x52: // I-MMU 64k TSB pointer
737 case 0x55: // I-MMU data access
0f8a249a
BS
738 // XXX
739 break;
83469015 740 case 0x56: // I-MMU tag read
0f8a249a
BS
741 {
742 unsigned int i;
743
744 for (i = 0; i < 64; i++) {
745 // Valid, ctx match, vaddr match
746 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
747 env->itlb_tag[i] == T0) {
748 ret = env->itlb_tag[i];
749 break;
750 }
751 }
752 break;
753 }
3475187d 754 case 0x58: // D-MMU regs
0f8a249a
BS
755 {
756 int reg = (T0 >> 3) & 0xf;
3475187d 757
0f8a249a
BS
758 ret = env->dmmuregs[reg];
759 break;
760 }
83469015 761 case 0x5e: // D-MMU tag read
0f8a249a
BS
762 {
763 unsigned int i;
764
765 for (i = 0; i < 64; i++) {
766 // Valid, ctx match, vaddr match
767 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
768 env->dtlb_tag[i] == T0) {
769 ret = env->dtlb_tag[i];
770 break;
771 }
772 }
773 break;
774 }
3475187d
FB
775 case 0x59: // D-MMU 8k TSB pointer
776 case 0x5a: // D-MMU 64k TSB pointer
777 case 0x5b: // D-MMU data pointer
778 case 0x5d: // D-MMU data access
83469015
FB
779 case 0x48: // Interrupt dispatch, RO
780 case 0x49: // Interrupt data receive
781 case 0x7f: // Incoming interrupt vector, RO
0f8a249a
BS
782 // XXX
783 break;
3475187d
FB
784 case 0x54: // I-MMU data in, WO
785 case 0x57: // I-MMU demap, WO
786 case 0x5c: // D-MMU data in, WO
787 case 0x5f: // D-MMU demap, WO
83469015 788 case 0x77: // Interrupt vector, WO
3475187d 789 default:
6c36d3fa 790 do_unassigned_access(T0, 0, 0, 1);
0f8a249a
BS
791 ret = 0;
792 break;
3475187d 793 }
81ad8ba2
BS
794
795 /* Convert from little endian */
796 switch (asi) {
797 case 0x0c: // Nucleus Little Endian (LE)
798 case 0x18: // As if user primary LE
799 case 0x19: // As if user secondary LE
800 case 0x1c: // Bypass LE
801 case 0x1d: // Bypass, non-cacheable LE
802 case 0x88: // Primary LE
803 case 0x89: // Secondary LE
804 case 0x8a: // Primary no-fault LE
805 case 0x8b: // Secondary no-fault LE
806 switch(size) {
807 case 2:
808 ret = bswap16(ret);
809 case 4:
810 ret = bswap32(ret);
811 case 8:
812 ret = bswap64(ret);
813 default:
814 break;
815 }
816 default:
817 break;
818 }
819
820 /* Convert to signed number */
821 if (sign) {
822 switch(size) {
823 case 1:
824 ret = (int8_t) ret;
825 case 2:
826 ret = (int16_t) ret;
827 case 4:
828 ret = (int32_t) ret;
829 default:
830 break;
831 }
832 }
3475187d
FB
833 T1 = ret;
834}
835
81ad8ba2 836void helper_st_asi(int asi, int size)
3475187d
FB
837{
838 if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
0f8a249a 839 raise_exception(TT_PRIV_ACT);
3475187d 840
81ad8ba2
BS
841 /* Convert to little endian */
842 switch (asi) {
843 case 0x0c: // Nucleus Little Endian (LE)
844 case 0x18: // As if user primary LE
845 case 0x19: // As if user secondary LE
846 case 0x1c: // Bypass LE
847 case 0x1d: // Bypass, non-cacheable LE
848 case 0x81: // Secondary
849 case 0x88: // Primary LE
850 case 0x89: // Secondary LE
851 switch(size) {
852 case 2:
853 T0 = bswap16(T0);
854 case 4:
855 T0 = bswap32(T0);
856 case 8:
857 T0 = bswap64(T0);
858 default:
859 break;
860 }
861 default:
862 break;
863 }
864
3475187d 865 switch(asi) {
81ad8ba2
BS
866 case 0x10: // As if user primary
867 case 0x18: // As if user primary LE
868 case 0x80: // Primary
869 case 0x88: // Primary LE
870 if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
871 switch(size) {
872 case 1:
873 stb_kernel(T0, T1);
874 break;
875 case 2:
876 stw_kernel(T0 & ~1, T1);
877 break;
878 case 4:
879 stl_kernel(T0 & ~3, T1);
880 break;
881 case 8:
882 default:
883 stq_kernel(T0 & ~7, T1);
884 break;
885 }
886 } else {
887 switch(size) {
888 case 1:
889 stb_user(T0, T1);
890 break;
891 case 2:
892 stw_user(T0 & ~1, T1);
893 break;
894 case 4:
895 stl_user(T0 & ~3, T1);
896 break;
897 case 8:
898 default:
899 stq_user(T0 & ~7, T1);
900 break;
901 }
902 }
903 break;
3475187d
FB
904 case 0x14: // Bypass
905 case 0x15: // Bypass, non-cacheable
81ad8ba2
BS
906 case 0x1c: // Bypass LE
907 case 0x1d: // Bypass, non-cacheable LE
0f8a249a 908 {
02aab46a
FB
909 switch(size) {
910 case 1:
911 stb_phys(T0, T1);
912 break;
913 case 2:
914 stw_phys(T0 & ~1, T1);
915 break;
916 case 4:
917 stl_phys(T0 & ~3, T1);
918 break;
919 case 8:
920 default:
921 stq_phys(T0 & ~7, T1);
922 break;
923 }
0f8a249a
BS
924 }
925 return;
83469015
FB
926 case 0x04: // Nucleus
927 case 0x0c: // Nucleus Little Endian (LE)
83469015 928 case 0x11: // As if user secondary
83469015 929 case 0x19: // As if user secondary LE
83469015
FB
930 case 0x24: // Nucleus quad LDD 128 bit atomic
931 case 0x2c: // Nucleus quad LDD 128 bit atomic
932 case 0x4a: // UPA config
83469015 933 case 0x89: // Secondary LE
0f8a249a
BS
934 // XXX
935 return;
3475187d 936 case 0x45: // LSU
0f8a249a
BS
937 {
938 uint64_t oldreg;
939
940 oldreg = env->lsu;
941 env->lsu = T1 & (DMMU_E | IMMU_E);
942 // Mappings generated during D/I MMU disabled mode are
943 // invalid in normal mode
944 if (oldreg != env->lsu) {
83469015 945#ifdef DEBUG_MMU
26a76461 946 printf("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
0f8a249a 947 dump_mmu(env);
83469015 948#endif
0f8a249a
BS
949 tlb_flush(env, 1);
950 }
951 return;
952 }
3475187d 953 case 0x50: // I-MMU regs
0f8a249a
BS
954 {
955 int reg = (T0 >> 3) & 0xf;
956 uint64_t oldreg;
3b46e624 957
0f8a249a 958 oldreg = env->immuregs[reg];
3475187d
FB
959 switch(reg) {
960 case 0: // RO
961 case 4:
962 return;
963 case 1: // Not in I-MMU
964 case 2:
965 case 7:
966 case 8:
967 return;
968 case 3: // SFSR
0f8a249a
BS
969 if ((T1 & 1) == 0)
970 T1 = 0; // Clear SFSR
3475187d
FB
971 break;
972 case 5: // TSB access
973 case 6: // Tag access
974 default:
975 break;
976 }
0f8a249a 977 env->immuregs[reg] = T1;
3475187d
FB
978#ifdef DEBUG_MMU
979 if (oldreg != env->immuregs[reg]) {
26a76461 980 printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
3475187d 981 }
0f8a249a 982 dump_mmu(env);
3475187d 983#endif
0f8a249a
BS
984 return;
985 }
3475187d 986 case 0x54: // I-MMU data in
0f8a249a
BS
987 {
988 unsigned int i;
989
990 // Try finding an invalid entry
991 for (i = 0; i < 64; i++) {
992 if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
993 env->itlb_tag[i] = env->immuregs[6];
994 env->itlb_tte[i] = T1;
995 return;
996 }
997 }
998 // Try finding an unlocked entry
999 for (i = 0; i < 64; i++) {
1000 if ((env->itlb_tte[i] & 0x40) == 0) {
1001 env->itlb_tag[i] = env->immuregs[6];
1002 env->itlb_tte[i] = T1;
1003 return;
1004 }
1005 }
1006 // error state?
1007 return;
1008 }
3475187d 1009 case 0x55: // I-MMU data access
0f8a249a
BS
1010 {
1011 unsigned int i = (T0 >> 3) & 0x3f;
3475187d 1012
0f8a249a
BS
1013 env->itlb_tag[i] = env->immuregs[6];
1014 env->itlb_tte[i] = T1;
1015 return;
1016 }
3475187d 1017 case 0x57: // I-MMU demap
0f8a249a
BS
1018 // XXX
1019 return;
3475187d 1020 case 0x58: // D-MMU regs
0f8a249a
BS
1021 {
1022 int reg = (T0 >> 3) & 0xf;
1023 uint64_t oldreg;
3b46e624 1024
0f8a249a 1025 oldreg = env->dmmuregs[reg];
3475187d
FB
1026 switch(reg) {
1027 case 0: // RO
1028 case 4:
1029 return;
1030 case 3: // SFSR
0f8a249a
BS
1031 if ((T1 & 1) == 0) {
1032 T1 = 0; // Clear SFSR, Fault address
1033 env->dmmuregs[4] = 0;
1034 }
1035 env->dmmuregs[reg] = T1;
3475187d
FB
1036 break;
1037 case 1: // Primary context
1038 case 2: // Secondary context
1039 case 5: // TSB access
1040 case 6: // Tag access
1041 case 7: // Virtual Watchpoint
1042 case 8: // Physical Watchpoint
1043 default:
1044 break;
1045 }
0f8a249a 1046 env->dmmuregs[reg] = T1;
3475187d
FB
1047#ifdef DEBUG_MMU
1048 if (oldreg != env->dmmuregs[reg]) {
26a76461 1049 printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
3475187d 1050 }
0f8a249a 1051 dump_mmu(env);
3475187d 1052#endif
0f8a249a
BS
1053 return;
1054 }
3475187d 1055 case 0x5c: // D-MMU data in
0f8a249a
BS
1056 {
1057 unsigned int i;
1058
1059 // Try finding an invalid entry
1060 for (i = 0; i < 64; i++) {
1061 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
1062 env->dtlb_tag[i] = env->dmmuregs[6];
1063 env->dtlb_tte[i] = T1;
1064 return;
1065 }
1066 }
1067 // Try finding an unlocked entry
1068 for (i = 0; i < 64; i++) {
1069 if ((env->dtlb_tte[i] & 0x40) == 0) {
1070 env->dtlb_tag[i] = env->dmmuregs[6];
1071 env->dtlb_tte[i] = T1;
1072 return;
1073 }
1074 }
1075 // error state?
1076 return;
1077 }
3475187d 1078 case 0x5d: // D-MMU data access
0f8a249a
BS
1079 {
1080 unsigned int i = (T0 >> 3) & 0x3f;
3475187d 1081
0f8a249a
BS
1082 env->dtlb_tag[i] = env->dmmuregs[6];
1083 env->dtlb_tte[i] = T1;
1084 return;
1085 }
3475187d 1086 case 0x5f: // D-MMU demap
83469015 1087 case 0x49: // Interrupt data receive
0f8a249a
BS
1088 // XXX
1089 return;
3475187d
FB
1090 case 0x51: // I-MMU 8k TSB pointer, RO
1091 case 0x52: // I-MMU 64k TSB pointer, RO
1092 case 0x56: // I-MMU tag read, RO
1093 case 0x59: // D-MMU 8k TSB pointer, RO
1094 case 0x5a: // D-MMU 64k TSB pointer, RO
1095 case 0x5b: // D-MMU data pointer, RO
1096 case 0x5e: // D-MMU tag read, RO
83469015
FB
1097 case 0x48: // Interrupt dispatch, RO
1098 case 0x7f: // Incoming interrupt vector, RO
1099 case 0x82: // Primary no-fault, RO
1100 case 0x83: // Secondary no-fault, RO
1101 case 0x8a: // Primary no-fault LE, RO
1102 case 0x8b: // Secondary no-fault LE, RO
3475187d 1103 default:
6c36d3fa 1104 do_unassigned_access(T0, 1, 0, 1);
0f8a249a 1105 return;
3475187d
FB
1106 }
1107}
81ad8ba2
BS
1108#endif /* CONFIG_USER_ONLY */
1109#endif /* TARGET_SPARC64 */
3475187d
FB
1110
1111#ifndef TARGET_SPARC64
a0c4cb4a 1112void helper_rett()
e8af50a3 1113{
af7bf89b
FB
1114 unsigned int cwp;
1115
d4218d99
BS
1116 if (env->psret == 1)
1117 raise_exception(TT_ILL_INSN);
1118
e8af50a3 1119 env->psret = 1;
5fafdf24 1120 cwp = (env->cwp + 1) & (NWINDOWS - 1);
e8af50a3
FB
1121 if (env->wim & (1 << cwp)) {
1122 raise_exception(TT_WIN_UNF);
1123 }
1124 set_cwp(cwp);
1125 env->psrs = env->psrps;
1126}
3475187d 1127#endif
e8af50a3 1128
8d5f07fa 1129void helper_ldfsr(void)
e8af50a3 1130{
7a0e1f41 1131 int rnd_mode;
e8af50a3
FB
1132 switch (env->fsr & FSR_RD_MASK) {
1133 case FSR_RD_NEAREST:
7a0e1f41 1134 rnd_mode = float_round_nearest_even;
0f8a249a 1135 break;
ed910241 1136 default:
e8af50a3 1137 case FSR_RD_ZERO:
7a0e1f41 1138 rnd_mode = float_round_to_zero;
0f8a249a 1139 break;
e8af50a3 1140 case FSR_RD_POS:
7a0e1f41 1141 rnd_mode = float_round_up;
0f8a249a 1142 break;
e8af50a3 1143 case FSR_RD_NEG:
7a0e1f41 1144 rnd_mode = float_round_down;
0f8a249a 1145 break;
e8af50a3 1146 }
7a0e1f41 1147 set_float_rounding_mode(rnd_mode, &env->fp_status);
e8af50a3 1148}
e80cfcfc 1149
e80cfcfc
FB
1150void helper_debug()
1151{
1152 env->exception_index = EXCP_DEBUG;
1153 cpu_loop_exit();
1154}
af7bf89b 1155
3475187d 1156#ifndef TARGET_SPARC64
af7bf89b
FB
1157void do_wrpsr()
1158{
d4218d99
BS
1159 if ((T0 & PSR_CWP) >= NWINDOWS)
1160 raise_exception(TT_ILL_INSN);
1161 else
1162 PUT_PSR(env, T0);
af7bf89b
FB
1163}
1164
1165void do_rdpsr()
1166{
1167 T0 = GET_PSR(env);
1168}
3475187d
FB
1169
1170#else
1171
1172void do_popc()
1173{
1174 T0 = (T1 & 0x5555555555555555ULL) + ((T1 >> 1) & 0x5555555555555555ULL);
1175 T0 = (T0 & 0x3333333333333333ULL) + ((T0 >> 2) & 0x3333333333333333ULL);
1176 T0 = (T0 & 0x0f0f0f0f0f0f0f0fULL) + ((T0 >> 4) & 0x0f0f0f0f0f0f0f0fULL);
1177 T0 = (T0 & 0x00ff00ff00ff00ffULL) + ((T0 >> 8) & 0x00ff00ff00ff00ffULL);
1178 T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);
1179 T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);
1180}
83469015
FB
1181
1182static inline uint64_t *get_gregset(uint64_t pstate)
1183{
1184 switch (pstate) {
1185 default:
1186 case 0:
0f8a249a 1187 return env->bgregs;
83469015 1188 case PS_AG:
0f8a249a 1189 return env->agregs;
83469015 1190 case PS_MG:
0f8a249a 1191 return env->mgregs;
83469015 1192 case PS_IG:
0f8a249a 1193 return env->igregs;
83469015
FB
1194 }
1195}
1196
8f1f22f6 1197static inline void change_pstate(uint64_t new_pstate)
83469015 1198{
8f1f22f6 1199 uint64_t pstate_regs, new_pstate_regs;
83469015
FB
1200 uint64_t *src, *dst;
1201
83469015
FB
1202 pstate_regs = env->pstate & 0xc01;
1203 new_pstate_regs = new_pstate & 0xc01;
1204 if (new_pstate_regs != pstate_regs) {
0f8a249a
BS
1205 // Switch global register bank
1206 src = get_gregset(new_pstate_regs);
1207 dst = get_gregset(pstate_regs);
1208 memcpy32(dst, env->gregs);
1209 memcpy32(env->gregs, src);
83469015
FB
1210 }
1211 env->pstate = new_pstate;
1212}
1213
8f1f22f6
BS
1214void do_wrpstate(void)
1215{
1216 change_pstate(T0 & 0xf3f);
1217}
1218
83469015
FB
1219void do_done(void)
1220{
1221 env->tl--;
1222 env->pc = env->tnpc[env->tl];
1223 env->npc = env->tnpc[env->tl] + 4;
1224 PUT_CCR(env, env->tstate[env->tl] >> 32);
1225 env->asi = (env->tstate[env->tl] >> 24) & 0xff;
8f1f22f6 1226 change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
17d996e1 1227 PUT_CWP64(env, env->tstate[env->tl] & 0xff);
83469015
FB
1228}
1229
1230void do_retry(void)
1231{
1232 env->tl--;
1233 env->pc = env->tpc[env->tl];
1234 env->npc = env->tnpc[env->tl];
1235 PUT_CCR(env, env->tstate[env->tl] >> 32);
1236 env->asi = (env->tstate[env->tl] >> 24) & 0xff;
8f1f22f6 1237 change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
17d996e1 1238 PUT_CWP64(env, env->tstate[env->tl] & 0xff);
83469015 1239}
3475187d 1240#endif
ee5bbe38
FB
1241
1242void set_cwp(int new_cwp)
1243{
1244 /* put the modified wrap registers at their proper location */
1245 if (env->cwp == (NWINDOWS - 1))
1246 memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
1247 env->cwp = new_cwp;
1248 /* put the wrap registers at their temporary location */
1249 if (new_cwp == (NWINDOWS - 1))
1250 memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
1251 env->regwptr = env->regbase + (new_cwp * 16);
1252 REGWPTR = env->regwptr;
1253}
1254
1255void cpu_set_cwp(CPUState *env1, int new_cwp)
1256{
1257 CPUState *saved_env;
1258#ifdef reg_REGWPTR
1259 target_ulong *saved_regwptr;
1260#endif
1261
1262 saved_env = env;
1263#ifdef reg_REGWPTR
1264 saved_regwptr = REGWPTR;
1265#endif
1266 env = env1;
1267 set_cwp(new_cwp);
1268 env = saved_env;
1269#ifdef reg_REGWPTR
1270 REGWPTR = saved_regwptr;
1271#endif
1272}
1273
1274#ifdef TARGET_SPARC64
1275void do_interrupt(int intno)
1276{
1277#ifdef DEBUG_PCALL
1278 if (loglevel & CPU_LOG_INT) {
0f8a249a
BS
1279 static int count;
1280 fprintf(logfile, "%6d: v=%04x pc=%016" PRIx64 " npc=%016" PRIx64 " SP=%016" PRIx64 "\n",
ee5bbe38
FB
1281 count, intno,
1282 env->pc,
1283 env->npc, env->regwptr[6]);
0f8a249a 1284 cpu_dump_state(env, logfile, fprintf, 0);
ee5bbe38 1285#if 0
0f8a249a
BS
1286 {
1287 int i;
1288 uint8_t *ptr;
1289
1290 fprintf(logfile, " code=");
1291 ptr = (uint8_t *)env->pc;
1292 for(i = 0; i < 16; i++) {
1293 fprintf(logfile, " %02x", ldub(ptr + i));
1294 }
1295 fprintf(logfile, "\n");
1296 }
ee5bbe38 1297#endif
0f8a249a 1298 count++;
ee5bbe38
FB
1299 }
1300#endif
5fafdf24 1301#if !defined(CONFIG_USER_ONLY)
83469015 1302 if (env->tl == MAXTL) {
c68ea704 1303 cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
0f8a249a 1304 return;
ee5bbe38
FB
1305 }
1306#endif
1307 env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
0f8a249a 1308 ((env->pstate & 0xf3f) << 8) | GET_CWP64(env);
ee5bbe38
FB
1309 env->tpc[env->tl] = env->pc;
1310 env->tnpc[env->tl] = env->npc;
1311 env->tt[env->tl] = intno;
8f1f22f6
BS
1312 change_pstate(PS_PEF | PS_PRIV | PS_AG);
1313
1314 if (intno == TT_CLRWIN)
1315 set_cwp((env->cwp - 1) & (NWINDOWS - 1));
1316 else if ((intno & 0x1c0) == TT_SPILL)
1317 set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1));
1318 else if ((intno & 0x1c0) == TT_FILL)
1319 set_cwp((env->cwp + 1) & (NWINDOWS - 1));
83469015
FB
1320 env->tbr &= ~0x7fffULL;
1321 env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
1322 if (env->tl < MAXTL - 1) {
0f8a249a 1323 env->tl++;
83469015 1324 } else {
0f8a249a
BS
1325 env->pstate |= PS_RED;
1326 if (env->tl != MAXTL)
1327 env->tl++;
83469015 1328 }
ee5bbe38
FB
1329 env->pc = env->tbr;
1330 env->npc = env->pc + 4;
1331 env->exception_index = 0;
1332}
1333#else
1334void do_interrupt(int intno)
1335{
1336 int cwp;
1337
1338#ifdef DEBUG_PCALL
1339 if (loglevel & CPU_LOG_INT) {
0f8a249a
BS
1340 static int count;
1341 fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
ee5bbe38
FB
1342 count, intno,
1343 env->pc,
1344 env->npc, env->regwptr[6]);
0f8a249a 1345 cpu_dump_state(env, logfile, fprintf, 0);
ee5bbe38 1346#if 0
0f8a249a
BS
1347 {
1348 int i;
1349 uint8_t *ptr;
1350
1351 fprintf(logfile, " code=");
1352 ptr = (uint8_t *)env->pc;
1353 for(i = 0; i < 16; i++) {
1354 fprintf(logfile, " %02x", ldub(ptr + i));
1355 }
1356 fprintf(logfile, "\n");
1357 }
ee5bbe38 1358#endif
0f8a249a 1359 count++;
ee5bbe38
FB
1360 }
1361#endif
5fafdf24 1362#if !defined(CONFIG_USER_ONLY)
ee5bbe38 1363 if (env->psret == 0) {
c68ea704 1364 cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
0f8a249a 1365 return;
ee5bbe38
FB
1366 }
1367#endif
1368 env->psret = 0;
5fafdf24 1369 cwp = (env->cwp - 1) & (NWINDOWS - 1);
ee5bbe38
FB
1370 set_cwp(cwp);
1371 env->regwptr[9] = env->pc;
1372 env->regwptr[10] = env->npc;
1373 env->psrps = env->psrs;
1374 env->psrs = 1;
1375 env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
1376 env->pc = env->tbr;
1377 env->npc = env->pc + 4;
1378 env->exception_index = 0;
1379}
1380#endif
1381
5fafdf24 1382#if !defined(CONFIG_USER_ONLY)
ee5bbe38 1383
d2889a3e
BS
1384static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1385 void *retaddr);
1386
ee5bbe38 1387#define MMUSUFFIX _mmu
d2889a3e 1388#define ALIGNED_ONLY
ee5bbe38
FB
1389#define GETPC() (__builtin_return_address(0))
1390
1391#define SHIFT 0
1392#include "softmmu_template.h"
1393
1394#define SHIFT 1
1395#include "softmmu_template.h"
1396
1397#define SHIFT 2
1398#include "softmmu_template.h"
1399
1400#define SHIFT 3
1401#include "softmmu_template.h"
1402
d2889a3e
BS
1403static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1404 void *retaddr)
1405{
94554550
BS
1406#ifdef DEBUG_UNALIGNED
1407 printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
1408#endif
1409 raise_exception(TT_UNALIGNED);
d2889a3e 1410}
ee5bbe38
FB
1411
1412/* try to fill the TLB and return an exception if error. If retaddr is
1413 NULL, it means that the function was called in C code (i.e. not
1414 from generated code or from helper.c) */
1415/* XXX: fix it to restore all registers */
1416void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
1417{
1418 TranslationBlock *tb;
1419 int ret;
1420 unsigned long pc;
1421 CPUState *saved_env;
1422
1423 /* XXX: hack to restore env in all cases, even if not called from
1424 generated code */
1425 saved_env = env;
1426 env = cpu_single_env;
1427
1428 ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
1429 if (ret) {
1430 if (retaddr) {
1431 /* now we have a real cpu fault */
1432 pc = (unsigned long)retaddr;
1433 tb = tb_find_pc(pc);
1434 if (tb) {
1435 /* the PC is inside the translated code. It means that we have
1436 a virtual CPU fault */
1437 cpu_restore_state(tb, env, pc, (void *)T2);
1438 }
1439 }
1440 cpu_loop_exit();
1441 }
1442 env = saved_env;
1443}
1444
1445#endif
6c36d3fa
BS
1446
1447#ifndef TARGET_SPARC64
5dcb6b91 1448void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
6c36d3fa
BS
1449 int is_asi)
1450{
1451 CPUState *saved_env;
1452
1453 /* XXX: hack to restore env in all cases, even if not called from
1454 generated code */
1455 saved_env = env;
1456 env = cpu_single_env;
1457 if (env->mmuregs[3]) /* Fault status register */
0f8a249a 1458 env->mmuregs[3] = 1; /* overflow (not read before another fault) */
6c36d3fa
BS
1459 if (is_asi)
1460 env->mmuregs[3] |= 1 << 16;
1461 if (env->psrs)
1462 env->mmuregs[3] |= 1 << 5;
1463 if (is_exec)
1464 env->mmuregs[3] |= 1 << 6;
1465 if (is_write)
1466 env->mmuregs[3] |= 1 << 7;
1467 env->mmuregs[3] |= (5 << 2) | 2;
1468 env->mmuregs[4] = addr; /* Fault address register */
1469 if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
1470#ifdef DEBUG_UNASSIGNED
5dcb6b91 1471 printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
6c36d3fa
BS
1472 "\n", addr, env->pc);
1473#endif
1b2e93c1
BS
1474 if (is_exec)
1475 raise_exception(TT_CODE_ACCESS);
1476 else
1477 raise_exception(TT_DATA_ACCESS);
6c36d3fa
BS
1478 }
1479 env = saved_env;
1480}
1481#else
5dcb6b91 1482void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
6c36d3fa
BS
1483 int is_asi)
1484{
1485#ifdef DEBUG_UNASSIGNED
1486 CPUState *saved_env;
1487
1488 /* XXX: hack to restore env in all cases, even if not called from
1489 generated code */
1490 saved_env = env;
1491 env = cpu_single_env;
5dcb6b91 1492 printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n",
6c36d3fa
BS
1493 addr, env->pc);
1494 env = saved_env;
1495#endif
1b2e93c1
BS
1496 if (is_exec)
1497 raise_exception(TT_CODE_ACCESS);
1498 else
1499 raise_exception(TT_DATA_ACCESS);
6c36d3fa
BS
1500}
1501#endif
20c9f095
BS
1502
1503#ifdef TARGET_SPARC64
1504void do_tick_set_count(void *opaque, uint64_t count)
1505{
d8bdf5fa 1506#if !defined(CONFIG_USER_ONLY)
20c9f095 1507 ptimer_set_count(opaque, -count);
d8bdf5fa 1508#endif
20c9f095
BS
1509}
1510
1511uint64_t do_tick_get_count(void *opaque)
1512{
d8bdf5fa 1513#if !defined(CONFIG_USER_ONLY)
20c9f095 1514 return -ptimer_get_count(opaque);
d8bdf5fa
BS
1515#else
1516 return 0;
1517#endif
20c9f095
BS
1518}
1519
1520void do_tick_set_limit(void *opaque, uint64_t limit)
1521{
d8bdf5fa 1522#if !defined(CONFIG_USER_ONLY)
20c9f095 1523 ptimer_set_limit(opaque, -limit, 0);
d8bdf5fa 1524#endif
20c9f095
BS
1525}
1526#endif