Commit d014c98c8dce88c3b6cc19bd2e0e558900f5c1d0
1 parent
a98fd896
sparc support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@119 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
310 additions
and
3 deletions
cpu-i386.h
... | ... | @@ -180,6 +180,12 @@ typedef struct CPUX86State { |
180 | 180 | |
181 | 181 | /* emulator internal variables */ |
182 | 182 | CPU86_LDouble ft0; |
183 | + union { | |
184 | + float f; | |
185 | + double d; | |
186 | + int i32; | |
187 | + int64_t i64; | |
188 | + } fp_convert; | |
183 | 189 | |
184 | 190 | /* segments */ |
185 | 191 | uint32_t segs[6]; /* selector values */ | ... | ... |
dyngen.c
... | ... | @@ -65,6 +65,20 @@ |
65 | 65 | #define elf_check_arch(x) ((x) == EM_IA_64) |
66 | 66 | #define ELF_USES_RELOCA |
67 | 67 | |
68 | +#elif defined(HOST_SPARC) | |
69 | + | |
70 | +#define ELF_CLASS ELFCLASS32 | |
71 | +#define ELF_ARCH EM_SPARC | |
72 | +#define elf_check_arch(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS) | |
73 | +#define ELF_USES_RELOCA | |
74 | + | |
75 | +#elif defined(HOST_SPARC64) | |
76 | + | |
77 | +#define ELF_CLASS ELFCLASS64 | |
78 | +#define ELF_ARCH EM_SPARCV9 | |
79 | +#define elf_check_arch(x) ((x) == EM_SPARCV9) | |
80 | +#define ELF_USES_RELOCA | |
81 | + | |
68 | 82 | #else |
69 | 83 | #error unsupported CPU - please update the code |
70 | 84 | #endif |
... | ... | @@ -326,6 +340,47 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
326 | 340 | copy_size = p - p_start; |
327 | 341 | } |
328 | 342 | break; |
343 | + case EM_SPARC: | |
344 | + case EM_SPARC32PLUS: | |
345 | + { | |
346 | + uint8_t *p; | |
347 | + p = (void *)(p_end - 8); | |
348 | + if (p <= p_start) | |
349 | + error("empty code for %s", name); | |
350 | + if (get32((uint32_t *)(p_start + 0x0)) != 0x9de3bf98) | |
351 | + error("save %%sp,-104,%%sp expected at the start of %s " | |
352 | + "found [%08x]", | |
353 | + name, get32((uint32_t *)(p_start + 0x0))); | |
354 | + if (get32((uint32_t *)(p + 0x0)) != 0x81c7e008 || | |
355 | + get32((uint32_t *)(p + 0x4)) != 0x81e80000) | |
356 | + error("ret; restore; expected at the end of %s found [%08x:%08x]", | |
357 | + name, | |
358 | + get32((uint32_t *)(p + 0x0)), | |
359 | + get32((uint32_t *)(p + 0x4))); | |
360 | + | |
361 | + copy_size = p - p_start; | |
362 | + } | |
363 | + break; | |
364 | + case EM_SPARCV9: | |
365 | + { | |
366 | + uint8_t *p; | |
367 | + p = (void *)(p_end - 8); | |
368 | + if (p <= p_start) | |
369 | + error("empty code for %s", name); | |
370 | + if (get32((uint32_t *)(p_start + 0x0)) != 0x9de3bf40) | |
371 | + error("save %%sp,-192,%%sp expected at the start of %s " | |
372 | + "found [%08x]", | |
373 | + name, get32((uint32_t *)(p_start + 0x0))); | |
374 | + if (get32((uint32_t *)(p + 0x0)) != 0x81cfe008 || | |
375 | + get32((uint32_t *)(p + 0x4)) != 0x01000000) | |
376 | + error("rett %%i7+8; nop; expected at the end of %s " | |
377 | + "found [%08x:%08x]", | |
378 | + name, | |
379 | + get32((uint32_t *)(p + 0x0)), | |
380 | + get32((uint32_t *)(p + 0x4))); | |
381 | + copy_size = p - p_start; | |
382 | + } | |
383 | + break; | |
329 | 384 | default: |
330 | 385 | error("unknown ELF architecture"); |
331 | 386 | } |
... | ... | @@ -375,6 +430,14 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
375 | 430 | if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { |
376 | 431 | sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; |
377 | 432 | if (!strstart(sym_name, "__op_param", &p)) { |
433 | +#if defined(HOST_SPARC) | |
434 | + if (sym_name[0] == '.') { | |
435 | + fprintf(outfile, | |
436 | + "extern char __dot_%s __asm__(\"%s\");\n", | |
437 | + sym_name+1, sym_name); | |
438 | + continue; | |
439 | + } | |
440 | +#endif | |
378 | 441 | fprintf(outfile, "extern char %s;\n", sym_name); |
379 | 442 | } |
380 | 443 | } |
... | ... | @@ -554,6 +617,126 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
554 | 617 | } |
555 | 618 | } |
556 | 619 | } |
620 | +#elif defined(HOST_SPARC) | |
621 | + { | |
622 | + char name[256]; | |
623 | + int type; | |
624 | + int addend; | |
625 | + for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | |
626 | + if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | |
627 | + sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; | |
628 | + if (strstart(sym_name, "__op_param", &p)) { | |
629 | + snprintf(name, sizeof(name), "param%s", p); | |
630 | + } else { | |
631 | + if (sym_name[0] == '.') | |
632 | + snprintf(name, sizeof(name), | |
633 | + "(long)(&__dot_%s)", | |
634 | + sym_name + 1); | |
635 | + else | |
636 | + snprintf(name, sizeof(name), | |
637 | + "(long)(&%s)", sym_name); | |
638 | + } | |
639 | + type = ELF32_R_TYPE(rel->r_info); | |
640 | + addend = rel->r_addend; | |
641 | + switch(type) { | |
642 | + case R_SPARC_32: | |
643 | + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", | |
644 | + rel->r_offset - offset, name, addend); | |
645 | + break; | |
646 | + case R_SPARC_HI22: | |
647 | + fprintf(outfile, | |
648 | + " *(uint32_t *)(gen_code_ptr + %d) = " | |
649 | + "((*(uint32_t *)(gen_code_ptr + %d)) " | |
650 | + " & ~0x3fffff) " | |
651 | + " | ((%s + %d) & 0x3fffff);\n", | |
652 | + rel->r_offset - offset, | |
653 | + rel->r_offset - offset, | |
654 | + name, addend); | |
655 | + break; | |
656 | + case R_SPARC_LO10: | |
657 | + fprintf(outfile, | |
658 | + " *(uint32_t *)(gen_code_ptr + %d) = " | |
659 | + "((*(uint32_t *)(gen_code_ptr + %d)) " | |
660 | + " & ~0x3ff) " | |
661 | + " | ((%s + %d) & 0x3ff);\n", | |
662 | + rel->r_offset - offset, | |
663 | + rel->r_offset - offset, | |
664 | + name, addend); | |
665 | + break; | |
666 | + case R_SPARC_WDISP30: | |
667 | + fprintf(outfile, | |
668 | + " *(uint32_t *)(gen_code_ptr + %d) = " | |
669 | + "((*(uint32_t *)(gen_code_ptr + %d)) " | |
670 | + " & ~0x3fffffff) " | |
671 | + " | ((((%s + %d) - (long)gen_code_ptr)>>2) " | |
672 | + " & 0x3fffffff);\n", | |
673 | + rel->r_offset - offset, | |
674 | + rel->r_offset - offset, | |
675 | + name, addend); | |
676 | + break; | |
677 | + default: | |
678 | + error("unsupported sparc relocation (%d)", type); | |
679 | + } | |
680 | + } | |
681 | + } | |
682 | + } | |
683 | +#elif defined(HOST_SPARC64) | |
684 | + { | |
685 | + char name[256]; | |
686 | + int type; | |
687 | + int addend; | |
688 | + for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { | |
689 | + if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { | |
690 | + sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; | |
691 | + if (strstart(sym_name, "__op_param", &p)) { | |
692 | + snprintf(name, sizeof(name), "param%s", p); | |
693 | + } else { | |
694 | + snprintf(name, sizeof(name), "(long)(&%s)", sym_name); | |
695 | + } | |
696 | + type = ELF64_R_TYPE(rel->r_info); | |
697 | + addend = rel->r_addend; | |
698 | + switch(type) { | |
699 | + case R_SPARC_32: | |
700 | + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", | |
701 | + rel->r_offset - offset, name, addend); | |
702 | + break; | |
703 | + case R_SPARC_HI22: | |
704 | + fprintf(outfile, | |
705 | + " *(uint32_t *)(gen_code_ptr + %d) = " | |
706 | + "((*(uint32_t *)(gen_code_ptr + %d)) " | |
707 | + " & ~0x3fffff) " | |
708 | + " | ((%s + %d) & 0x3fffff);\n", | |
709 | + rel->r_offset - offset, | |
710 | + rel->r_offset - offset, | |
711 | + name, addend); | |
712 | + break; | |
713 | + case R_SPARC_LO10: | |
714 | + fprintf(outfile, | |
715 | + " *(uint32_t *)(gen_code_ptr + %d) = " | |
716 | + "((*(uint32_t *)(gen_code_ptr + %d)) " | |
717 | + " & ~0x3ff) " | |
718 | + " | ((%s + %d) & 0x3ff);\n", | |
719 | + rel->r_offset - offset, | |
720 | + rel->r_offset - offset, | |
721 | + name, addend); | |
722 | + break; | |
723 | + case R_SPARC_WDISP30: | |
724 | + fprintf(outfile, | |
725 | + " *(uint32_t *)(gen_code_ptr + %d) = " | |
726 | + "((*(uint32_t *)(gen_code_ptr + %d)) " | |
727 | + " & ~0x3fffffff) " | |
728 | + " | ((((%s + %d) - (long)gen_code_ptr)>>2) " | |
729 | + " & 0x3fffffff);\n", | |
730 | + rel->r_offset - offset, | |
731 | + rel->r_offset - offset, | |
732 | + name, addend); | |
733 | + break; | |
734 | + default: | |
735 | + error("unsupported sparc64 relocation (%d)", type); | |
736 | + } | |
737 | + } | |
738 | + } | |
739 | + } | |
557 | 740 | #else |
558 | 741 | #error unsupported CPU |
559 | 742 | #endif |
... | ... | @@ -759,6 +942,14 @@ fprintf(outfile, |
759 | 942 | case EM_IA_64: |
760 | 943 | fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x00840008; /* br.ret.sptk.many b0;; */\n"); |
761 | 944 | break; |
945 | + case EM_SPARC: | |
946 | + case EM_SPARC32PLUS: | |
947 | + case EM_SPARCV9: | |
948 | + /* Fill the delay slot. */ | |
949 | + fprintf(outfile, "*((uint32_t *)gen_code_ptr) = *((uint32_t *)gen_code_ptr - 1); /* delay slot */\n"); | |
950 | + fprintf(outfile, "*((uint32_t *)gen_code_ptr - 1) = 0x81c3e008; /* retl */\n"); | |
951 | + fprintf(outfile, "gen_code_ptr++;\n"); | |
952 | + break; | |
762 | 953 | default: |
763 | 954 | error("unknown ELF architecture"); |
764 | 955 | } | ... | ... |
exec-i386.c
... | ... | @@ -121,6 +121,20 @@ int testandset (int *p) |
121 | 121 | } |
122 | 122 | #endif |
123 | 123 | |
124 | +#ifdef __sparc__ | |
125 | +static inline int testandset (int *p) | |
126 | +{ | |
127 | + int ret; | |
128 | + | |
129 | + __asm__ __volatile__("ldstub [%1], %0" | |
130 | + : "=r" (ret) | |
131 | + : "r" (p) | |
132 | + : "memory"); | |
133 | + | |
134 | + return (ret ? 1 : 0); | |
135 | +} | |
136 | +#endif | |
137 | + | |
124 | 138 | int global_cpu_lock = 0; |
125 | 139 | |
126 | 140 | void cpu_lock(void) | ... | ... |
exec-i386.h
... | ... | @@ -93,6 +93,7 @@ register unsigned int T0 asm("l0"); |
93 | 93 | register unsigned int T1 asm("l1"); |
94 | 94 | register unsigned int A0 asm("l2"); |
95 | 95 | register struct CPUX86State *env asm("l3"); |
96 | +#define USE_FP_CONVERT | |
96 | 97 | #endif |
97 | 98 | #ifdef __s390__ |
98 | 99 | register unsigned int T0 asm("r7"); |
... | ... | @@ -160,6 +161,10 @@ register struct CPUX86State *env asm("r27"); |
160 | 161 | #define ST(n) (env->fpregs[(env->fpstt + (n)) & 7]) |
161 | 162 | #define ST1 ST(1) |
162 | 163 | |
164 | +#ifdef USE_FP_CONVERT | |
165 | +#define FP_CONVERT (env->fp_convert) | |
166 | +#endif | |
167 | + | |
163 | 168 | extern int __op_param1, __op_param2, __op_param3; |
164 | 169 | #define PARAM1 ((long)(&__op_param1)) |
165 | 170 | #define PARAM2 ((long)(&__op_param2)) | ... | ... |
op-i386.c
... | ... | @@ -1605,12 +1605,22 @@ typedef union { |
1605 | 1605 | |
1606 | 1606 | void OPPROTO op_flds_FT0_A0(void) |
1607 | 1607 | { |
1608 | +#ifdef USE_FP_CONVERT | |
1609 | + FP_CONVERT.i32 = ldl((void *)A0); | |
1610 | + FT0 = FP_CONVERT.f; | |
1611 | +#else | |
1608 | 1612 | FT0 = ldfl((void *)A0); |
1613 | +#endif | |
1609 | 1614 | } |
1610 | 1615 | |
1611 | 1616 | void OPPROTO op_fldl_FT0_A0(void) |
1612 | 1617 | { |
1618 | +#ifdef USE_FP_CONVERT | |
1619 | + FP_CONVERT.i64 = ldq((void *)A0); | |
1620 | + FT0 = FP_CONVERT.d; | |
1621 | +#else | |
1613 | 1622 | FT0 = ldfq((void *)A0); |
1623 | +#endif | |
1614 | 1624 | } |
1615 | 1625 | |
1616 | 1626 | /* helpers are needed to avoid static constant reference. XXX: find a better way */ |
... | ... | @@ -1650,17 +1660,32 @@ void OPPROTO op_fildll_FT0_A0(void) |
1650 | 1660 | |
1651 | 1661 | void OPPROTO op_fild_FT0_A0(void) |
1652 | 1662 | { |
1663 | +#ifdef USE_FP_CONVERT | |
1664 | + FP_CONVERT.i32 = ldsw((void *)A0); | |
1665 | + FT0 = (CPU86_LDouble)FP_CONVERT.i32; | |
1666 | +#else | |
1653 | 1667 | FT0 = (CPU86_LDouble)ldsw((void *)A0); |
1668 | +#endif | |
1654 | 1669 | } |
1655 | 1670 | |
1656 | 1671 | void OPPROTO op_fildl_FT0_A0(void) |
1657 | 1672 | { |
1673 | +#ifdef USE_FP_CONVERT | |
1674 | + FP_CONVERT.i32 = (int32_t) ldl((void *)A0); | |
1675 | + FT0 = (CPU86_LDouble)FP_CONVERT.i32; | |
1676 | +#else | |
1658 | 1677 | FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0)); |
1678 | +#endif | |
1659 | 1679 | } |
1660 | 1680 | |
1661 | 1681 | void OPPROTO op_fildll_FT0_A0(void) |
1662 | 1682 | { |
1683 | +#ifdef USE_FP_CONVERT | |
1684 | + FP_CONVERT.i64 = (int64_t) ldq((void *)A0); | |
1685 | + FT0 = (CPU86_LDouble)FP_CONVERT.i64; | |
1686 | +#else | |
1663 | 1687 | FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0)); |
1688 | +#endif | |
1664 | 1689 | } |
1665 | 1690 | #endif |
1666 | 1691 | |
... | ... | @@ -1668,12 +1693,22 @@ void OPPROTO op_fildll_FT0_A0(void) |
1668 | 1693 | |
1669 | 1694 | void OPPROTO op_flds_ST0_A0(void) |
1670 | 1695 | { |
1696 | +#ifdef USE_FP_CONVERT | |
1697 | + FP_CONVERT.i32 = ldl((void *)A0); | |
1698 | + ST0 = FP_CONVERT.f; | |
1699 | +#else | |
1671 | 1700 | ST0 = ldfl((void *)A0); |
1701 | +#endif | |
1672 | 1702 | } |
1673 | 1703 | |
1674 | 1704 | void OPPROTO op_fldl_ST0_A0(void) |
1675 | 1705 | { |
1706 | +#ifdef USE_FP_CONVERT | |
1707 | + FP_CONVERT.i64 = ldq((void *)A0); | |
1708 | + ST0 = FP_CONVERT.d; | |
1709 | +#else | |
1676 | 1710 | ST0 = ldfq((void *)A0); |
1711 | +#endif | |
1677 | 1712 | } |
1678 | 1713 | |
1679 | 1714 | #ifdef USE_X86LDOUBLE |
... | ... | @@ -1738,17 +1773,32 @@ void OPPROTO op_fildll_ST0_A0(void) |
1738 | 1773 | |
1739 | 1774 | void OPPROTO op_fild_ST0_A0(void) |
1740 | 1775 | { |
1776 | +#ifdef USE_FP_CONVERT | |
1777 | + FP_CONVERT.i32 = ldsw((void *)A0); | |
1778 | + ST0 = (CPU86_LDouble)FP_CONVERT.i32; | |
1779 | +#else | |
1741 | 1780 | ST0 = (CPU86_LDouble)ldsw((void *)A0); |
1781 | +#endif | |
1742 | 1782 | } |
1743 | 1783 | |
1744 | 1784 | void OPPROTO op_fildl_ST0_A0(void) |
1745 | 1785 | { |
1786 | +#ifdef USE_FP_CONVERT | |
1787 | + FP_CONVERT.i32 = (int32_t) ldl((void *)A0); | |
1788 | + ST0 = (CPU86_LDouble)FP_CONVERT.i32; | |
1789 | +#else | |
1746 | 1790 | ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0)); |
1791 | +#endif | |
1747 | 1792 | } |
1748 | 1793 | |
1749 | 1794 | void OPPROTO op_fildll_ST0_A0(void) |
1750 | 1795 | { |
1796 | +#ifdef USE_FP_CONVERT | |
1797 | + FP_CONVERT.i64 = (int64_t) ldq((void *)A0); | |
1798 | + ST0 = (CPU86_LDouble)FP_CONVERT.i64; | |
1799 | +#else | |
1751 | 1800 | ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0)); |
1801 | +#endif | |
1752 | 1802 | } |
1753 | 1803 | |
1754 | 1804 | #endif |
... | ... | @@ -1757,7 +1807,12 @@ void OPPROTO op_fildll_ST0_A0(void) |
1757 | 1807 | |
1758 | 1808 | void OPPROTO op_fsts_ST0_A0(void) |
1759 | 1809 | { |
1810 | +#ifdef USE_FP_CONVERT | |
1811 | + FP_CONVERT.d = ST0; | |
1812 | + stfl((void *)A0, FP_CONVERT.f); | |
1813 | +#else | |
1760 | 1814 | stfl((void *)A0, (float)ST0); |
1815 | +#endif | |
1761 | 1816 | } |
1762 | 1817 | |
1763 | 1818 | void OPPROTO op_fstl_ST0_A0(void) |
... | ... | @@ -1792,22 +1847,43 @@ void OPPROTO op_fstt_ST0_A0(void) |
1792 | 1847 | |
1793 | 1848 | void OPPROTO op_fist_ST0_A0(void) |
1794 | 1849 | { |
1850 | +#if defined(__sparc__) && !defined(__sparc_v9__) | |
1851 | + register CPU86_LDouble d asm("o0"); | |
1852 | +#else | |
1853 | + CPU86_LDouble d; | |
1854 | +#endif | |
1795 | 1855 | int val; |
1796 | - val = lrint(ST0); | |
1856 | + | |
1857 | + d = ST0; | |
1858 | + val = lrint(d); | |
1797 | 1859 | stw((void *)A0, val); |
1798 | 1860 | } |
1799 | 1861 | |
1800 | 1862 | void OPPROTO op_fistl_ST0_A0(void) |
1801 | 1863 | { |
1864 | +#if defined(__sparc__) && !defined(__sparc_v9__) | |
1865 | + register CPU86_LDouble d asm("o0"); | |
1866 | +#else | |
1867 | + CPU86_LDouble d; | |
1868 | +#endif | |
1802 | 1869 | int val; |
1803 | - val = lrint(ST0); | |
1870 | + | |
1871 | + d = ST0; | |
1872 | + val = lrint(d); | |
1804 | 1873 | stl((void *)A0, val); |
1805 | 1874 | } |
1806 | 1875 | |
1807 | 1876 | void OPPROTO op_fistll_ST0_A0(void) |
1808 | 1877 | { |
1878 | +#if defined(__sparc__) && !defined(__sparc_v9__) | |
1879 | + register CPU86_LDouble d asm("o0"); | |
1880 | +#else | |
1881 | + CPU86_LDouble d; | |
1882 | +#endif | |
1809 | 1883 | int64_t val; |
1810 | - val = llrint(ST0); | |
1884 | + | |
1885 | + d = ST0; | |
1886 | + val = llrint(d); | |
1811 | 1887 | stq((void *)A0, val); |
1812 | 1888 | } |
1813 | 1889 | ... | ... |
translate-i386.c
... | ... | @@ -89,6 +89,21 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop) |
89 | 89 | } |
90 | 90 | #endif |
91 | 91 | |
92 | +#ifdef __sparc__ | |
93 | + | |
94 | +static void inline flush_icache_range(unsigned long start, unsigned long stop) | |
95 | +{ | |
96 | + unsigned long p; | |
97 | + | |
98 | + p = start & ~(8UL - 1UL); | |
99 | + stop = (stop + (8UL - 1UL)) & ~(8UL - 1UL); | |
100 | + | |
101 | + for (; p < stop; p += 8) | |
102 | + __asm__ __volatile__("flush\t%0" : : "r" (p)); | |
103 | +} | |
104 | + | |
105 | +#endif | |
106 | + | |
92 | 107 | extern FILE *logfile; |
93 | 108 | extern int loglevel; |
94 | 109 | ... | ... |