Commit d014c98c8dce88c3b6cc19bd2e0e558900f5c1d0

Authored by bellard
1 parent a98fd896

sparc support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@119 c046a42c-6fe2-441c-8c8c-71466251a162
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(&quot;l0&quot;);
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(&quot;r27&quot;);
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  
... ...