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 | 181 | |
| 182 | 182 | @itemize |
| 183 | 183 | |
| 184 | -@item Tagged add/subtract instructions are not supported, but they are | |
| 185 | -probably not used. | |
| 186 | - | |
| 187 | 184 | @item IPC syscalls are missing. |
| 188 | 185 | |
| 189 | 186 | @item 128-bit floating point operations are not supported, though none of the | ... | ... |
target-sparc/cpu.h
| ... | ... | @@ -37,6 +37,7 @@ |
| 37 | 37 | #define TT_WIN_UNF 0x06 |
| 38 | 38 | #define TT_FP_EXCP 0x08 |
| 39 | 39 | #define TT_DFAULT 0x09 |
| 40 | +#define TT_TOVF 0x0a | |
| 40 | 41 | #define TT_EXTINT 0x10 |
| 41 | 42 | #define TT_DIV_ZERO 0x2a |
| 42 | 43 | #define TT_TRAP 0x80 |
| ... | ... | @@ -47,6 +48,7 @@ |
| 47 | 48 | #define TT_PRIV_INSN 0x11 |
| 48 | 49 | #define TT_NFPU_INSN 0x20 |
| 49 | 50 | #define TT_FP_EXCP 0x21 |
| 51 | +#define TT_TOVF 0x23 | |
| 50 | 52 | #define TT_CLRWIN 0x24 |
| 51 | 53 | #define TT_DIV_ZERO 0x28 |
| 52 | 54 | #define TT_DFAULT 0x30 | ... | ... |
target-sparc/op.c
| ... | ... | @@ -472,6 +472,96 @@ void OPPROTO op_addx_T1_T0_cc(void) |
| 472 | 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 | 565 | void OPPROTO op_sub_T1_T0(void) |
| 476 | 566 | { |
| 477 | 567 | T0 -= T1; |
| ... | ... | @@ -582,6 +672,96 @@ void OPPROTO op_subx_T1_T0_cc(void) |
| 582 | 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 | 765 | void OPPROTO op_and_T1_T0(void) |
| 586 | 766 | { |
| 587 | 767 | T0 &= T1; | ... | ... |
target-sparc/translate.c
| ... | ... | @@ -27,7 +27,6 @@ |
| 27 | 27 | Optimize synthetic instructions |
| 28 | 28 | Optional alignment check |
| 29 | 29 | 128-bit float |
| 30 | - Tagged add/sub | |
| 31 | 30 | */ |
| 32 | 31 | |
| 33 | 32 | #include <stdarg.h> |
| ... | ... | @@ -1833,10 +1832,21 @@ static void disas_sparc_insn(DisasContext * dc) |
| 1833 | 1832 | } else { |
| 1834 | 1833 | switch (xop) { |
| 1835 | 1834 | case 0x20: /* taddcc */ |
| 1835 | + gen_op_tadd_T1_T0_cc(); | |
| 1836 | + gen_movl_T0_reg(rd); | |
| 1837 | + break; | |
| 1836 | 1838 | case 0x21: /* tsubcc */ |
| 1839 | + gen_op_tsub_T1_T0_cc(); | |
| 1840 | + gen_movl_T0_reg(rd); | |
| 1841 | + break; | |
| 1837 | 1842 | case 0x22: /* taddcctv */ |
| 1843 | + gen_op_tadd_T1_T0_ccTV(); | |
| 1844 | + gen_movl_T0_reg(rd); | |
| 1845 | + break; | |
| 1838 | 1846 | case 0x23: /* tsubcctv */ |
| 1839 | - goto illegal_insn; | |
| 1847 | + gen_op_tsub_T1_T0_ccTV(); | |
| 1848 | + gen_movl_T0_reg(rd); | |
| 1849 | + break; | |
| 1840 | 1850 | case 0x24: /* mulscc */ |
| 1841 | 1851 | gen_op_mulscc_T1_T0(); |
| 1842 | 1852 | gen_movl_T0_reg(rd); | ... | ... |