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); |