Commit e32f879d1b5cbde3c996d6db5e15e487ae3064a5
1 parent
426613db
Sparc tagged operations (Aurelien Jarno)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2531 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
194 additions
and
5 deletions
qemu-tech.texi
@@ -181,9 +181,6 @@ Current QEMU limitations: | @@ -181,9 +181,6 @@ Current QEMU limitations: | ||
181 | 181 | ||
182 | @itemize | 182 | @itemize |
183 | 183 | ||
184 | -@item Tagged add/subtract instructions are not supported, but they are | ||
185 | -probably not used. | ||
186 | - | ||
187 | @item IPC syscalls are missing. | 184 | @item IPC syscalls are missing. |
188 | 185 | ||
189 | @item 128-bit floating point operations are not supported, though none of the | 186 | @item 128-bit floating point operations are not supported, though none of the |
target-sparc/cpu.h
@@ -37,6 +37,7 @@ | @@ -37,6 +37,7 @@ | ||
37 | #define TT_WIN_UNF 0x06 | 37 | #define TT_WIN_UNF 0x06 |
38 | #define TT_FP_EXCP 0x08 | 38 | #define TT_FP_EXCP 0x08 |
39 | #define TT_DFAULT 0x09 | 39 | #define TT_DFAULT 0x09 |
40 | +#define TT_TOVF 0x0a | ||
40 | #define TT_EXTINT 0x10 | 41 | #define TT_EXTINT 0x10 |
41 | #define TT_DIV_ZERO 0x2a | 42 | #define TT_DIV_ZERO 0x2a |
42 | #define TT_TRAP 0x80 | 43 | #define TT_TRAP 0x80 |
@@ -47,6 +48,7 @@ | @@ -47,6 +48,7 @@ | ||
47 | #define TT_PRIV_INSN 0x11 | 48 | #define TT_PRIV_INSN 0x11 |
48 | #define TT_NFPU_INSN 0x20 | 49 | #define TT_NFPU_INSN 0x20 |
49 | #define TT_FP_EXCP 0x21 | 50 | #define TT_FP_EXCP 0x21 |
51 | +#define TT_TOVF 0x23 | ||
50 | #define TT_CLRWIN 0x24 | 52 | #define TT_CLRWIN 0x24 |
51 | #define TT_DIV_ZERO 0x28 | 53 | #define TT_DIV_ZERO 0x28 |
52 | #define TT_DFAULT 0x30 | 54 | #define TT_DFAULT 0x30 |
target-sparc/op.c
@@ -472,6 +472,96 @@ void OPPROTO op_addx_T1_T0_cc(void) | @@ -472,6 +472,96 @@ void OPPROTO op_addx_T1_T0_cc(void) | ||
472 | FORCE_RET(); | 472 | FORCE_RET(); |
473 | } | 473 | } |
474 | 474 | ||
475 | +void OPPROTO op_tadd_T1_T0_cc(void) | ||
476 | +{ | ||
477 | + target_ulong src1; | ||
478 | + | ||
479 | + src1 = T0; | ||
480 | + T0 += T1; | ||
481 | + env->psr = 0; | ||
482 | +#ifdef TARGET_SPARC64 | ||
483 | + if (!(T0 & 0xffffffff)) | ||
484 | + env->psr |= PSR_ZERO; | ||
485 | + if ((int32_t) T0 < 0) | ||
486 | + env->psr |= PSR_NEG; | ||
487 | + if ((T0 & 0xffffffff) < (src1 & 0xffffffff)) | ||
488 | + env->psr |= PSR_CARRY; | ||
489 | + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) & | ||
490 | + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) | ||
491 | + env->psr |= PSR_OVF; | ||
492 | + if ((src1 & 0x03) || (T1 & 0x03)) | ||
493 | + env->psr |= PSR_OVF; | ||
494 | + | ||
495 | + env->xcc = 0; | ||
496 | + if (!T0) | ||
497 | + env->xcc |= PSR_ZERO; | ||
498 | + if ((int64_t) T0 < 0) | ||
499 | + env->xcc |= PSR_NEG; | ||
500 | + if (T0 < src1) | ||
501 | + env->xcc |= PSR_CARRY; | ||
502 | + if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1ULL << 63)) | ||
503 | + env->xcc |= PSR_OVF; | ||
504 | +#else | ||
505 | + if (!T0) | ||
506 | + env->psr |= PSR_ZERO; | ||
507 | + if ((int32_t) T0 < 0) | ||
508 | + env->psr |= PSR_NEG; | ||
509 | + if (T0 < src1) | ||
510 | + env->psr |= PSR_CARRY; | ||
511 | + if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31)) | ||
512 | + env->psr |= PSR_OVF; | ||
513 | + if ((src1 & 0x03) || (T1 & 0x03)) | ||
514 | + env->psr |= PSR_OVF; | ||
515 | +#endif | ||
516 | + FORCE_RET(); | ||
517 | +} | ||
518 | + | ||
519 | +void OPPROTO op_tadd_T1_T0_ccTV(void) | ||
520 | +{ | ||
521 | + target_ulong src1; | ||
522 | + | ||
523 | + if ((T0 & 0x03) || (T1 & 0x03)) | ||
524 | + raise_exception(TT_TOVF); | ||
525 | + | ||
526 | + src1 = T0; | ||
527 | + T0 += T1; | ||
528 | + | ||
529 | +#ifdef TARGET_SPARC64 | ||
530 | + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) & | ||
531 | + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) | ||
532 | + raise_exception(TT_TOVF); | ||
533 | +#else | ||
534 | + if ((src1 & 0x03) || (T1 & 0x03)) | ||
535 | + raise_exception(TT_TOVF); | ||
536 | +#endif | ||
537 | + | ||
538 | + env->psr = 0; | ||
539 | +#ifdef TARGET_SPARC64 | ||
540 | + if (!(T0 & 0xffffffff)) | ||
541 | + env->psr |= PSR_ZERO; | ||
542 | + if ((int32_t) T0 < 0) | ||
543 | + env->psr |= PSR_NEG; | ||
544 | + if ((T0 & 0xffffffff) < (src1 & 0xffffffff)) | ||
545 | + env->psr |= PSR_CARRY; | ||
546 | + | ||
547 | + env->xcc = 0; | ||
548 | + if (!T0) | ||
549 | + env->xcc |= PSR_ZERO; | ||
550 | + if ((int64_t) T0 < 0) | ||
551 | + env->xcc |= PSR_NEG; | ||
552 | + if (T0 < src1) | ||
553 | + env->xcc |= PSR_CARRY; | ||
554 | +#else | ||
555 | + if (!T0) | ||
556 | + env->psr |= PSR_ZERO; | ||
557 | + if ((int32_t) T0 < 0) | ||
558 | + env->psr |= PSR_NEG; | ||
559 | + if (T0 < src1) | ||
560 | + env->psr |= PSR_CARRY; | ||
561 | +#endif | ||
562 | + FORCE_RET(); | ||
563 | +} | ||
564 | + | ||
475 | void OPPROTO op_sub_T1_T0(void) | 565 | void OPPROTO op_sub_T1_T0(void) |
476 | { | 566 | { |
477 | T0 -= T1; | 567 | T0 -= T1; |
@@ -582,6 +672,96 @@ void OPPROTO op_subx_T1_T0_cc(void) | @@ -582,6 +672,96 @@ void OPPROTO op_subx_T1_T0_cc(void) | ||
582 | FORCE_RET(); | 672 | FORCE_RET(); |
583 | } | 673 | } |
584 | 674 | ||
675 | +void OPPROTO op_tsub_T1_T0_cc(void) | ||
676 | +{ | ||
677 | + target_ulong src1; | ||
678 | + | ||
679 | + src1 = T0; | ||
680 | + T0 -= T1; | ||
681 | + env->psr = 0; | ||
682 | +#ifdef TARGET_SPARC64 | ||
683 | + if (!(T0 & 0xffffffff)) | ||
684 | + env->psr |= PSR_ZERO; | ||
685 | + if ((int32_t) T0 < 0) | ||
686 | + env->psr |= PSR_NEG; | ||
687 | + if ((src1 & 0xffffffff) < (T1 & 0xffffffff)) | ||
688 | + env->psr |= PSR_CARRY; | ||
689 | + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) & | ||
690 | + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) | ||
691 | + env->psr |= PSR_OVF; | ||
692 | + if ((src1 & 0x03) || (T1 & 0x03)) | ||
693 | + env->psr |= PSR_OVF; | ||
694 | + | ||
695 | + env->xcc = 0; | ||
696 | + if (!T0) | ||
697 | + env->xcc |= PSR_ZERO; | ||
698 | + if ((int64_t) T0 < 0) | ||
699 | + env->xcc |= PSR_NEG; | ||
700 | + if (src1 < T1) | ||
701 | + env->xcc |= PSR_CARRY; | ||
702 | + if (((src1 ^ T1) & (src1 ^ T0)) & (1ULL << 63)) | ||
703 | + env->xcc |= PSR_OVF; | ||
704 | +#else | ||
705 | + if (!T0) | ||
706 | + env->psr |= PSR_ZERO; | ||
707 | + if ((int32_t) T0 < 0) | ||
708 | + env->psr |= PSR_NEG; | ||
709 | + if (src1 < T1) | ||
710 | + env->psr |= PSR_CARRY; | ||
711 | + if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31)) | ||
712 | + env->psr |= PSR_OVF; | ||
713 | + if ((src1 & 0x03) || (T1 & 0x03)) | ||
714 | + env->psr |= PSR_OVF; | ||
715 | +#endif | ||
716 | + FORCE_RET(); | ||
717 | +} | ||
718 | + | ||
719 | +void OPPROTO op_tsub_T1_T0_ccTV(void) | ||
720 | +{ | ||
721 | + target_ulong src1; | ||
722 | + | ||
723 | + if ((T0 & 0x03) || (T1 & 0x03)) | ||
724 | + raise_exception(TT_TOVF); | ||
725 | + | ||
726 | + src1 = T0; | ||
727 | + T0 -= T1; | ||
728 | + | ||
729 | +#ifdef TARGET_SPARC64 | ||
730 | + if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) & | ||
731 | + ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) | ||
732 | + raise_exception(TT_TOVF); | ||
733 | +#else | ||
734 | + if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31)) | ||
735 | + raise_exception(TT_TOVF); | ||
736 | +#endif | ||
737 | + | ||
738 | + env->psr = 0; | ||
739 | +#ifdef TARGET_SPARC64 | ||
740 | + if (!(T0 & 0xffffffff)) | ||
741 | + env->psr |= PSR_ZERO; | ||
742 | + if ((int32_t) T0 < 0) | ||
743 | + env->psr |= PSR_NEG; | ||
744 | + if ((src1 & 0xffffffff) < (T1 & 0xffffffff)) | ||
745 | + env->psr |= PSR_CARRY; | ||
746 | + | ||
747 | + env->xcc = 0; | ||
748 | + if (!T0) | ||
749 | + env->xcc |= PSR_ZERO; | ||
750 | + if ((int64_t) T0 < 0) | ||
751 | + env->xcc |= PSR_NEG; | ||
752 | + if (src1 < T1) | ||
753 | + env->xcc |= PSR_CARRY; | ||
754 | +#else | ||
755 | + if (!T0) | ||
756 | + env->psr |= PSR_ZERO; | ||
757 | + if ((int32_t) T0 < 0) | ||
758 | + env->psr |= PSR_NEG; | ||
759 | + if (src1 < T1) | ||
760 | + env->psr |= PSR_CARRY; | ||
761 | +#endif | ||
762 | + FORCE_RET(); | ||
763 | +} | ||
764 | + | ||
585 | void OPPROTO op_and_T1_T0(void) | 765 | void OPPROTO op_and_T1_T0(void) |
586 | { | 766 | { |
587 | T0 &= T1; | 767 | T0 &= T1; |
target-sparc/translate.c
@@ -27,7 +27,6 @@ | @@ -27,7 +27,6 @@ | ||
27 | Optimize synthetic instructions | 27 | Optimize synthetic instructions |
28 | Optional alignment check | 28 | Optional alignment check |
29 | 128-bit float | 29 | 128-bit float |
30 | - Tagged add/sub | ||
31 | */ | 30 | */ |
32 | 31 | ||
33 | #include <stdarg.h> | 32 | #include <stdarg.h> |
@@ -1833,10 +1832,21 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -1833,10 +1832,21 @@ static void disas_sparc_insn(DisasContext * dc) | ||
1833 | } else { | 1832 | } else { |
1834 | switch (xop) { | 1833 | switch (xop) { |
1835 | case 0x20: /* taddcc */ | 1834 | case 0x20: /* taddcc */ |
1835 | + gen_op_tadd_T1_T0_cc(); | ||
1836 | + gen_movl_T0_reg(rd); | ||
1837 | + break; | ||
1836 | case 0x21: /* tsubcc */ | 1838 | case 0x21: /* tsubcc */ |
1839 | + gen_op_tsub_T1_T0_cc(); | ||
1840 | + gen_movl_T0_reg(rd); | ||
1841 | + break; | ||
1837 | case 0x22: /* taddcctv */ | 1842 | case 0x22: /* taddcctv */ |
1843 | + gen_op_tadd_T1_T0_ccTV(); | ||
1844 | + gen_movl_T0_reg(rd); | ||
1845 | + break; | ||
1838 | case 0x23: /* tsubcctv */ | 1846 | case 0x23: /* tsubcctv */ |
1839 | - goto illegal_insn; | 1847 | + gen_op_tsub_T1_T0_ccTV(); |
1848 | + gen_movl_T0_reg(rd); | ||
1849 | + break; | ||
1840 | case 0x24: /* mulscc */ | 1850 | case 0x24: /* mulscc */ |
1841 | gen_op_mulscc_T1_T0(); | 1851 | gen_op_mulscc_T1_T0(); |
1842 | gen_movl_T0_reg(rd); | 1852 | gen_movl_T0_reg(rd); |