Commit 81ad8ba242815e27f990e18778c7cdca2e7e7522

Authored by blueswir1
1 parent 43febf49

Rework ASI instructions (Aurelien Jarno)

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3205 c046a42c-6fe2-441c-8c8c-71466251a162
target-sparc/exec.h
... ... @@ -50,7 +50,7 @@ void cpu_unlock(void);
50 50 void cpu_loop_exit(void);
51 51 void helper_flush(target_ulong addr);
52 52 void helper_ld_asi(int asi, int size, int sign);
53   -void helper_st_asi(int asi, int size, int sign);
  53 +void helper_st_asi(int asi, int size);
54 54 void helper_rett(void);
55 55 void helper_ldfsr(void);
56 56 void set_cwp(int new_cwp);
... ...
target-sparc/op.c
... ... @@ -1862,10 +1862,126 @@ void OPPROTO op_ld_asi_reg()
1862 1862 void OPPROTO op_st_asi_reg()
1863 1863 {
1864 1864 T0 += PARAM1;
1865   - helper_st_asi(env->asi, PARAM2, PARAM3);
  1865 + helper_st_asi(env->asi, PARAM2);
  1866 +}
  1867 +
  1868 +void OPPROTO op_ldstub_asi_reg() /* XXX: should be atomically */
  1869 +{
  1870 + target_ulong tmp;
  1871 +
  1872 + T0 += PARAM1;
  1873 + helper_ld_asi(env->asi, 1, 0);
  1874 + tmp = T1;
  1875 + T1 = 0xff;
  1876 + helper_st_asi(env->asi, 1);
  1877 + T1 = tmp;
  1878 +}
  1879 +
  1880 +void OPPROTO op_swap_asi_reg() /* XXX: should be atomically */
  1881 +{
  1882 + target_ulong tmp1, tmp2;
  1883 +
  1884 + T0 += PARAM1;
  1885 + tmp1 = T1;
  1886 + helper_ld_asi(env->asi, 4, 0);
  1887 + tmp2 = T1;
  1888 + T1 = tmp1;
  1889 + helper_st_asi(env->asi, 4);
  1890 + T1 = tmp2;
  1891 +}
  1892 +
  1893 +void OPPROTO op_ldda_asi()
  1894 +{
  1895 + helper_ld_asi(PARAM1, 8, 0);
  1896 + T0 = T1 & 0xffffffffUL;
  1897 + T1 >>= 32;
  1898 +}
  1899 +
  1900 +void OPPROTO op_ldda_asi_reg()
  1901 +{
  1902 + T0 += PARAM1;
  1903 + helper_ld_asi(env->asi, 8, 0);
  1904 + T0 = T1 & 0xffffffffUL;
  1905 + T1 >>= 32;
  1906 +}
  1907 +
  1908 +void OPPROTO op_stda_asi()
  1909 +{
  1910 + T1 <<= 32;
  1911 + T1 += T2 & 0xffffffffUL;
  1912 + helper_st_asi(PARAM1, 8);
  1913 +}
  1914 +
  1915 +void OPPROTO op_stda_asi_reg()
  1916 +{
  1917 + T0 += PARAM1;
  1918 + T1 <<= 32;
  1919 + T1 += T2 & 0xffffffffUL;
  1920 + helper_st_asi(env->asi, 8);
  1921 +}
  1922 +
  1923 +void OPPROTO op_cas_asi() /* XXX: should be atomically */
  1924 +{
  1925 + target_ulong tmp;
  1926 +
  1927 + tmp = T1 & 0xffffffffUL;
  1928 + helper_ld_asi(PARAM1, 4, 0);
  1929 + if (tmp == T1) {
  1930 + tmp = T1;
  1931 + T1 = T2 & 0xffffffffUL;
  1932 + helper_st_asi(PARAM1, 4);
  1933 + T1 = tmp;
  1934 + }
  1935 + T1 &= 0xffffffffUL;
  1936 +}
  1937 +
  1938 +void OPPROTO op_cas_asi_reg() /* XXX: should be atomically */
  1939 +{
  1940 + target_ulong tmp;
  1941 +
  1942 + T0 += PARAM1;
  1943 + tmp = T1 & 0xffffffffUL;
  1944 + helper_ld_asi(env->asi, 4, 0);
  1945 + if (tmp == T1) {
  1946 + tmp = T1;
  1947 + T1 = T2 & 0xffffffffUL;
  1948 + helper_st_asi(env->asi, 4);
  1949 + T1 = tmp;
  1950 + }
  1951 + T1 &= 0xffffffffUL;
  1952 +}
  1953 +
  1954 +void OPPROTO op_casx_asi() /* XXX: should be atomically */
  1955 +{
  1956 + target_ulong tmp;
  1957 +
  1958 + tmp = T1;
  1959 + helper_ld_asi(PARAM1, 8, 0);
  1960 + if (tmp == T1) {
  1961 + tmp = T1;
  1962 + T1 = T2;
  1963 + helper_st_asi(PARAM1, 8);
  1964 + T1 = tmp;
  1965 + }
  1966 +}
  1967 +
  1968 +void OPPROTO op_casx_asi_reg() /* XXX: should be atomically */
  1969 +{
  1970 + target_ulong tmp;
  1971 +
  1972 + T0 += PARAM1;
  1973 + tmp = T1;
  1974 + helper_ld_asi(env->asi, 8, 0);
  1975 + if (tmp == T1) {
  1976 + tmp = T1;
  1977 + T1 = T2;
  1978 + helper_st_asi(env->asi, 8);
  1979 + T1 = tmp;
  1980 + }
1866 1981 }
1867 1982 #endif
1868 1983  
  1984 +#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
1869 1985 void OPPROTO op_ld_asi()
1870 1986 {
1871 1987 helper_ld_asi(PARAM1, PARAM2, PARAM3);
... ... @@ -1873,9 +1989,33 @@ void OPPROTO op_ld_asi()
1873 1989  
1874 1990 void OPPROTO op_st_asi()
1875 1991 {
1876   - helper_st_asi(PARAM1, PARAM2, PARAM3);
  1992 + helper_st_asi(PARAM1, PARAM2);
1877 1993 }
1878 1994  
  1995 +void OPPROTO op_ldstub_asi() /* XXX: should be atomically */
  1996 +{
  1997 + target_ulong tmp;
  1998 +
  1999 + helper_ld_asi(PARAM1, 1, 0);
  2000 + tmp = T1;
  2001 + T1 = 0xff;
  2002 + helper_st_asi(PARAM1, 1);
  2003 + T1 = tmp;
  2004 +}
  2005 +
  2006 +void OPPROTO op_swap_asi() /* XXX: should be atomically */
  2007 +{
  2008 + target_ulong tmp1, tmp2;
  2009 +
  2010 + tmp1 = T1;
  2011 + helper_ld_asi(PARAM1, 4, 0);
  2012 + tmp2 = T1;
  2013 + T1 = tmp1;
  2014 + helper_st_asi(PARAM1, 4);
  2015 + T1 = tmp2;
  2016 +}
  2017 +#endif
  2018 +
1879 2019 #ifdef TARGET_SPARC64
1880 2020 // This function uses non-native bit order
1881 2021 #define GET_FIELD(X, FROM, TO) \
... ...
target-sparc/op_helper.c
... ... @@ -137,16 +137,8 @@ GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
137 137 GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
138 138 #endif
139 139  
140   -#if defined(CONFIG_USER_ONLY)
141   -void helper_ld_asi(int asi, int size, int sign)
142   -{
143   -}
144   -
145   -void helper_st_asi(int asi, int size, int sign)
146   -{
147   -}
148   -#else
149 140 #ifndef TARGET_SPARC64
  141 +#ifndef CONFIG_USER_ONLY
150 142 void helper_ld_asi(int asi, int size, int sign)
151 143 {
152 144 uint32_t ret = 0;
... ... @@ -200,6 +192,42 @@ void helper_ld_asi(int asi, int size, int sign)
200 192 break;
201 193 }
202 194 break;
  195 + case 0xa: /* User data access */
  196 + switch(size) {
  197 + case 1:
  198 + ret = ldub_user(T0);
  199 + break;
  200 + case 2:
  201 + ret = lduw_user(T0 & ~1);
  202 + break;
  203 + default:
  204 + case 4:
  205 + ret = ldl_user(T0 & ~3);
  206 + break;
  207 + case 8:
  208 + ret = ldl_user(T0 & ~3);
  209 + T0 = ldl_user((T0 + 4) & ~3);
  210 + break;
  211 + }
  212 + break;
  213 + case 0xb: /* Supervisor data access */
  214 + switch(size) {
  215 + case 1:
  216 + ret = ldub_kernel(T0);
  217 + break;
  218 + case 2:
  219 + ret = lduw_kernel(T0 & ~1);
  220 + break;
  221 + default:
  222 + case 4:
  223 + ret = ldl_kernel(T0 & ~3);
  224 + break;
  225 + case 8:
  226 + ret = ldl_kernel(T0 & ~3);
  227 + T0 = ldl_kernel((T0 + 4) & ~3);
  228 + break;
  229 + }
  230 + break;
203 231 case 0xc: /* I-cache tag */
204 232 case 0xd: /* I-cache data */
205 233 case 0xe: /* D-cache tag */
... ... @@ -253,10 +281,22 @@ void helper_ld_asi(int asi, int size, int sign)
253 281 ret = 0;
254 282 break;
255 283 }
256   - T1 = ret;
  284 + if (sign) {
  285 + switch(size) {
  286 + case 1:
  287 + T1 = (int8_t) ret;
  288 + case 2:
  289 + T1 = (int16_t) ret;
  290 + default:
  291 + T1 = ret;
  292 + break;
  293 + }
  294 + }
  295 + else
  296 + T1 = ret;
257 297 }
258 298  
259   -void helper_st_asi(int asi, int size, int sign)
  299 +void helper_st_asi(int asi, int size)
260 300 {
261 301 switch(asi) {
262 302 case 2: /* SuperSparc MXCC registers */
... ... @@ -325,6 +365,42 @@ void helper_st_asi(int asi, int size, int sign)
325 365 #endif
326 366 return;
327 367 }
  368 + case 0xa: /* User data access */
  369 + switch(size) {
  370 + case 1:
  371 + stb_user(T0, T1);
  372 + break;
  373 + case 2:
  374 + stw_user(T0 & ~1, T1);
  375 + break;
  376 + default:
  377 + case 4:
  378 + stl_user(T0 & ~3, T1);
  379 + break;
  380 + case 8:
  381 + stl_user(T0 & ~3, T1);
  382 + stl_user((T0 + 4) & ~3, T2);
  383 + break;
  384 + }
  385 + break;
  386 + case 0xb: /* Supervisor data access */
  387 + switch(size) {
  388 + case 1:
  389 + stb_kernel(T0, T1);
  390 + break;
  391 + case 2:
  392 + stw_kernel(T0 & ~1, T1);
  393 + break;
  394 + default:
  395 + case 4:
  396 + stl_kernel(T0 & ~3, T1);
  397 + break;
  398 + case 8:
  399 + stl_kernel(T0 & ~3, T1);
  400 + stl_kernel((T0 + 4) & ~3, T2);
  401 + break;
  402 + }
  403 + break;
328 404 case 0xc: /* I-cache tag */
329 405 case 0xd: /* I-cache data */
330 406 case 0xe: /* D-cache tag */
... ... @@ -422,7 +498,146 @@ void helper_st_asi(int asi, int size, int sign)
422 498 }
423 499 }
424 500  
425   -#else
  501 +#endif /* CONFIG_USER_ONLY */
  502 +#else /* TARGET_SPARC64 */
  503 +
  504 +#ifdef CONFIG_USER_ONLY
  505 +void helper_ld_asi(int asi, int size, int sign)
  506 +{
  507 + uint64_t ret = 0;
  508 +
  509 + if (asi < 0x80)
  510 + raise_exception(TT_PRIV_ACT);
  511 +
  512 + switch (asi) {
  513 + case 0x80: // Primary
  514 + case 0x82: // Primary no-fault
  515 + case 0x88: // Primary LE
  516 + case 0x8a: // Primary no-fault LE
  517 + {
  518 + switch(size) {
  519 + case 1:
  520 + ret = ldub_raw(T0);
  521 + break;
  522 + case 2:
  523 + ret = lduw_raw(T0 & ~1);
  524 + break;
  525 + case 4:
  526 + ret = ldl_raw(T0 & ~3);
  527 + break;
  528 + default:
  529 + case 8:
  530 + ret = ldq_raw(T0 & ~7);
  531 + break;
  532 + }
  533 + }
  534 + break;
  535 + case 0x81: // Secondary
  536 + case 0x83: // Secondary no-fault
  537 + case 0x89: // Secondary LE
  538 + case 0x8b: // Secondary no-fault LE
  539 + // XXX
  540 + break;
  541 + default:
  542 + break;
  543 + }
  544 +
  545 + /* Convert from little endian */
  546 + switch (asi) {
  547 + case 0x88: // Primary LE
  548 + case 0x89: // Secondary LE
  549 + case 0x8a: // Primary no-fault LE
  550 + case 0x8b: // Secondary no-fault LE
  551 + switch(size) {
  552 + case 2:
  553 + ret = bswap16(ret);
  554 + case 4:
  555 + ret = bswap32(ret);
  556 + case 8:
  557 + ret = bswap64(ret);
  558 + default:
  559 + break;
  560 + }
  561 + default:
  562 + break;
  563 + }
  564 +
  565 + /* Convert to signed number */
  566 + if (sign) {
  567 + switch(size) {
  568 + case 1:
  569 + ret = (int8_t) ret;
  570 + case 2:
  571 + ret = (int16_t) ret;
  572 + case 4:
  573 + ret = (int32_t) ret;
  574 + default:
  575 + break;
  576 + }
  577 + }
  578 + T1 = ret;
  579 +}
  580 +
  581 +void helper_st_asi(int asi, int size)
  582 +{
  583 + if (asi < 0x80)
  584 + raise_exception(TT_PRIV_ACT);
  585 +
  586 + /* Convert to little endian */
  587 + switch (asi) {
  588 + case 0x88: // Primary LE
  589 + case 0x89: // Secondary LE
  590 + switch(size) {
  591 + case 2:
  592 + T0 = bswap16(T0);
  593 + case 4:
  594 + T0 = bswap32(T0);
  595 + case 8:
  596 + T0 = bswap64(T0);
  597 + default:
  598 + break;
  599 + }
  600 + default:
  601 + break;
  602 + }
  603 +
  604 + switch(asi) {
  605 + case 0x80: // Primary
  606 + case 0x88: // Primary LE
  607 + {
  608 + switch(size) {
  609 + case 1:
  610 + stb_raw(T0, T1);
  611 + break;
  612 + case 2:
  613 + stw_raw(T0 & ~1, T1);
  614 + break;
  615 + case 4:
  616 + stl_raw(T0 & ~3, T1);
  617 + break;
  618 + case 8:
  619 + default:
  620 + stq_raw(T0 & ~7, T1);
  621 + break;
  622 + }
  623 + }
  624 + break;
  625 + case 0x81: // Secondary
  626 + case 0x89: // Secondary LE
  627 + // XXX
  628 + return;
  629 +
  630 + case 0x82: // Primary no-fault, RO
  631 + case 0x83: // Secondary no-fault, RO
  632 + case 0x8a: // Primary no-fault LE, RO
  633 + case 0x8b: // Secondary no-fault LE, RO
  634 + default:
  635 + do_unassigned_access(T0, 1, 0, 1);
  636 + return;
  637 + }
  638 +}
  639 +
  640 +#else /* CONFIG_USER_ONLY */
426 641  
427 642 void helper_ld_asi(int asi, int size, int sign)
428 643 {
... ... @@ -432,8 +647,50 @@ void helper_ld_asi(int asi, int size, int sign)
432 647 raise_exception(TT_PRIV_ACT);
433 648  
434 649 switch (asi) {
  650 + case 0x10: // As if user primary
  651 + case 0x18: // As if user primary LE
  652 + case 0x80: // Primary
  653 + case 0x82: // Primary no-fault
  654 + case 0x88: // Primary LE
  655 + case 0x8a: // Primary no-fault LE
  656 + if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
  657 + switch(size) {
  658 + case 1:
  659 + ret = ldub_kernel(T0);
  660 + break;
  661 + case 2:
  662 + ret = lduw_kernel(T0 & ~1);
  663 + break;
  664 + case 4:
  665 + ret = ldl_kernel(T0 & ~3);
  666 + break;
  667 + default:
  668 + case 8:
  669 + ret = ldq_kernel(T0 & ~7);
  670 + break;
  671 + }
  672 + } else {
  673 + switch(size) {
  674 + case 1:
  675 + ret = ldub_user(T0);
  676 + break;
  677 + case 2:
  678 + ret = lduw_user(T0 & ~1);
  679 + break;
  680 + case 4:
  681 + ret = ldl_user(T0 & ~3);
  682 + break;
  683 + default:
  684 + case 8:
  685 + ret = ldq_user(T0 & ~7);
  686 + break;
  687 + }
  688 + }
  689 + break;
435 690 case 0x14: // Bypass
436 691 case 0x15: // Bypass, non-cacheable
  692 + case 0x1c: // Bypass LE
  693 + case 0x1d: // Bypass, non-cacheable LE
437 694 {
438 695 switch(size) {
439 696 case 1:
... ... @@ -454,20 +711,14 @@ void helper_ld_asi(int asi, int size, int sign)
454 711 }
455 712 case 0x04: // Nucleus
456 713 case 0x0c: // Nucleus Little Endian (LE)
457   - case 0x10: // As if user primary
458 714 case 0x11: // As if user secondary
459   - case 0x18: // As if user primary LE
460 715 case 0x19: // As if user secondary LE
461   - case 0x1c: // Bypass LE
462   - case 0x1d: // Bypass, non-cacheable LE
463 716 case 0x24: // Nucleus quad LDD 128 bit atomic
464 717 case 0x2c: // Nucleus quad LDD 128 bit atomic
465 718 case 0x4a: // UPA config
466   - case 0x82: // Primary no-fault
  719 + case 0x81: // Secondary
467 720 case 0x83: // Secondary no-fault
468   - case 0x88: // Primary LE
469 721 case 0x89: // Secondary LE
470   - case 0x8a: // Primary no-fault LE
471 722 case 0x8b: // Secondary no-fault LE
472 723 // XXX
473 724 break;
... ... @@ -540,17 +791,120 @@ void helper_ld_asi(int asi, int size, int sign)
540 791 ret = 0;
541 792 break;
542 793 }
  794 +
  795 + /* Convert from little endian */
  796 + switch (asi) {
  797 + case 0x0c: // Nucleus Little Endian (LE)
  798 + case 0x18: // As if user primary LE
  799 + case 0x19: // As if user secondary LE
  800 + case 0x1c: // Bypass LE
  801 + case 0x1d: // Bypass, non-cacheable LE
  802 + case 0x88: // Primary LE
  803 + case 0x89: // Secondary LE
  804 + case 0x8a: // Primary no-fault LE
  805 + case 0x8b: // Secondary no-fault LE
  806 + switch(size) {
  807 + case 2:
  808 + ret = bswap16(ret);
  809 + case 4:
  810 + ret = bswap32(ret);
  811 + case 8:
  812 + ret = bswap64(ret);
  813 + default:
  814 + break;
  815 + }
  816 + default:
  817 + break;
  818 + }
  819 +
  820 + /* Convert to signed number */
  821 + if (sign) {
  822 + switch(size) {
  823 + case 1:
  824 + ret = (int8_t) ret;
  825 + case 2:
  826 + ret = (int16_t) ret;
  827 + case 4:
  828 + ret = (int32_t) ret;
  829 + default:
  830 + break;
  831 + }
  832 + }
543 833 T1 = ret;
544 834 }
545 835  
546   -void helper_st_asi(int asi, int size, int sign)
  836 +void helper_st_asi(int asi, int size)
547 837 {
548 838 if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
549 839 raise_exception(TT_PRIV_ACT);
550 840  
  841 + /* Convert to little endian */
  842 + switch (asi) {
  843 + case 0x0c: // Nucleus Little Endian (LE)
  844 + case 0x18: // As if user primary LE
  845 + case 0x19: // As if user secondary LE
  846 + case 0x1c: // Bypass LE
  847 + case 0x1d: // Bypass, non-cacheable LE
  848 + case 0x81: // Secondary
  849 + case 0x88: // Primary LE
  850 + case 0x89: // Secondary LE
  851 + switch(size) {
  852 + case 2:
  853 + T0 = bswap16(T0);
  854 + case 4:
  855 + T0 = bswap32(T0);
  856 + case 8:
  857 + T0 = bswap64(T0);
  858 + default:
  859 + break;
  860 + }
  861 + default:
  862 + break;
  863 + }
  864 +
551 865 switch(asi) {
  866 + case 0x10: // As if user primary
  867 + case 0x18: // As if user primary LE
  868 + case 0x80: // Primary
  869 + case 0x88: // Primary LE
  870 + if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
  871 + switch(size) {
  872 + case 1:
  873 + stb_kernel(T0, T1);
  874 + break;
  875 + case 2:
  876 + stw_kernel(T0 & ~1, T1);
  877 + break;
  878 + case 4:
  879 + stl_kernel(T0 & ~3, T1);
  880 + break;
  881 + case 8:
  882 + default:
  883 + stq_kernel(T0 & ~7, T1);
  884 + break;
  885 + }
  886 + } else {
  887 + switch(size) {
  888 + case 1:
  889 + stb_user(T0, T1);
  890 + break;
  891 + case 2:
  892 + stw_user(T0 & ~1, T1);
  893 + break;
  894 + case 4:
  895 + stl_user(T0 & ~3, T1);
  896 + break;
  897 + case 8:
  898 + default:
  899 + stq_user(T0 & ~7, T1);
  900 + break;
  901 + }
  902 + }
  903 + break;
552 904 case 0x14: // Bypass
553 905 case 0x15: // Bypass, non-cacheable
  906 + case 0x1c: // Bypass LE
  907 + case 0x1d: // Bypass, non-cacheable LE
554 908 {
555 909 switch(size) {
556 910 case 1:
... ... @@ -571,16 +925,11 @@ void helper_st_asi(int asi, int size, int sign)
571 925 return;
572 926 case 0x04: // Nucleus
573 927 case 0x0c: // Nucleus Little Endian (LE)
574   - case 0x10: // As if user primary
575 928 case 0x11: // As if user secondary
576   - case 0x18: // As if user primary LE
577 929 case 0x19: // As if user secondary LE
578   - case 0x1c: // Bypass LE
579   - case 0x1d: // Bypass, non-cacheable LE
580 930 case 0x24: // Nucleus quad LDD 128 bit atomic
581 931 case 0x2c: // Nucleus quad LDD 128 bit atomic
582 932 case 0x4a: // UPA config
583   - case 0x88: // Primary LE
584 933 case 0x89: // Secondary LE
585 934 // XXX
586 935 return;
... ... @@ -756,8 +1105,8 @@ void helper_st_asi(int asi, int size, int sign)
756 1105 return;
757 1106 }
758 1107 }
759   -#endif
760   -#endif /* !CONFIG_USER_ONLY */
  1108 +#endif /* CONFIG_USER_ONLY */
  1109 +#endif /* TARGET_SPARC64 */
761 1110  
762 1111 #ifndef TARGET_SPARC64
763 1112 void helper_rett()
... ...
target-sparc/op_mem.h
... ... @@ -76,33 +76,6 @@ void OPPROTO glue(op_lddf, MEMSUFFIX) (void)
76 76 }
77 77  
78 78 #ifdef TARGET_SPARC64
79   -/* XXX: Should be Atomically */
80   -/* XXX: There are no cas[x] instructions, only cas[x]a */
81   -void OPPROTO glue(op_cas, MEMSUFFIX)(void)
82   -{
83   - uint32_t tmp;
84   -
85   - tmp = glue(ldl, MEMSUFFIX)(T0);
86   - T2 &= 0xffffffffULL;
87   - if (tmp == (T1 & 0xffffffffULL)) {
88   - glue(stl, MEMSUFFIX)(T0, T2);
89   - }
90   - T2 = tmp;
91   -}
92   -
93   -void OPPROTO glue(op_casx, MEMSUFFIX)(void)
94   -{
95   - uint64_t tmp;
96   -
97   - // XXX
98   - tmp = (uint64_t)glue(ldl, MEMSUFFIX)(T0) << 32;
99   - tmp |= glue(ldl, MEMSUFFIX)(T0);
100   - if (tmp == T1) {
101   - glue(stq, MEMSUFFIX)(T0, T2);
102   - }
103   - T2 = tmp;
104   -}
105   -
106 79 void OPPROTO glue(op_lduw, MEMSUFFIX)(void)
107 80 {
108 81 T1 = (uint64_t)(glue(ldl, MEMSUFFIX)(T0) & 0xffffffff);
... ...
target-sparc/translate.c
... ... @@ -353,112 +353,27 @@ GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
353 353 #endif
354 354 #endif
355 355  
356   -#ifdef TARGET_SPARC64
357   -// 'a' versions allowed to user depending on asi
358   -#if defined(CONFIG_USER_ONLY)
  356 +/* moves */
  357 +#ifdef CONFIG_USER_ONLY
359 358 #define supervisor(dc) 0
  359 +#ifdef TARGET_SPARC64
360 360 #define hypervisor(dc) 0
  361 +#endif
361 362 #define gen_op_ldst(name) gen_op_##name##_raw()
362   -#define OP_LD_TABLE(width) \
363   - static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
364   - { \
365   - int asi, offset; \
366   - \
367   - if (IS_IMM) { \
368   - offset = GET_FIELD(insn, 25, 31); \
369   - if (is_ld) \
370   - gen_op_ld_asi_reg(offset, size, sign); \
371   - else \
372   - gen_op_st_asi_reg(offset, size, sign); \
373   - return; \
374   - } \
375   - asi = GET_FIELD(insn, 19, 26); \
376   - switch (asi) { \
377   - case 0x80: /* Primary address space */ \
378   - gen_op_##width##_raw(); \
379   - break; \
380   - case 0x82: /* Primary address space, non-faulting load */ \
381   - gen_op_##width##_raw(); \
382   - break; \
383   - default: \
384   - break; \
385   - } \
386   - }
387   -
388 363 #else
  364 +#define supervisor(dc) (dc->mem_idx == 1)
  365 +#ifdef TARGET_SPARC64
  366 +#define hypervisor(dc) (dc->mem_idx == 2)
  367 +#endif
389 368 #define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()
390 369 #define OP_LD_TABLE(width) \
391 370 static GenOpFunc * const gen_op_##width[] = { \
392 371 &gen_op_##width##_user, \
393 372 &gen_op_##width##_kernel, \
394   - }; \
395   - \
396   - static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
397   - { \
398   - int asi, offset; \
399   - \
400   - if (IS_IMM) { \
401   - offset = GET_FIELD(insn, 25, 31); \
402   - if (is_ld) \
403   - gen_op_ld_asi_reg(offset, size, sign); \
404   - else \
405   - gen_op_st_asi_reg(offset, size, sign); \
406   - return; \
407   - } \
408   - asi = GET_FIELD(insn, 19, 26); \
409   - if (is_ld) \
410   - gen_op_ld_asi(asi, size, sign); \
411   - else \
412   - gen_op_st_asi(asi, size, sign); \
413   - }
414   -
415   -#define supervisor(dc) (dc->mem_idx == 1)
416   -#define hypervisor(dc) (dc->mem_idx == 2)
417   -#endif
418   -#else
419   -#if defined(CONFIG_USER_ONLY)
420   -#define gen_op_ldst(name) gen_op_##name##_raw()
421   -#define OP_LD_TABLE(width)
422   -#define supervisor(dc) 0
423   -#else
424   -#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()
425   -#define OP_LD_TABLE(width) \
426   -static GenOpFunc * const gen_op_##width[] = { \
427   - &gen_op_##width##_user, \
428   - &gen_op_##width##_kernel, \
429   -}; \
430   - \
431   -static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
432   -{ \
433   - int asi; \
434   - \
435   - asi = GET_FIELD(insn, 19, 26); \
436   - switch (asi) { \
437   - case 10: /* User data access */ \
438   - gen_op_##width##_user(); \
439   - break; \
440   - case 11: /* Supervisor data access */ \
441   - gen_op_##width##_kernel(); \
442   - break; \
443   - case 0x20 ... 0x2f: /* MMU passthrough */ \
444   - if (is_ld) \
445   - gen_op_ld_asi(asi, size, sign); \
446   - else \
447   - gen_op_st_asi(asi, size, sign); \
448   - break; \
449   - default: \
450   - if (is_ld) \
451   - gen_op_ld_asi(asi, size, sign); \
452   - else \
453   - gen_op_st_asi(asi, size, sign); \
454   - break; \
455   - } \
456   -}
457   -
458   -#define supervisor(dc) (dc->mem_idx == 1)
459   -#endif
  373 + };
460 374 #endif
461 375  
  376 +#ifndef CONFIG_USER_ONLY
462 377 OP_LD_TABLE(ld);
463 378 OP_LD_TABLE(st);
464 379 OP_LD_TABLE(ldub);
... ... @@ -481,8 +396,164 @@ OP_LD_TABLE(lduw);
481 396 OP_LD_TABLE(ldsw);
482 397 OP_LD_TABLE(ldx);
483 398 OP_LD_TABLE(stx);
484   -OP_LD_TABLE(cas);
485   -OP_LD_TABLE(casx);
  399 +#endif
  400 +#endif
  401 +
  402 +/* asi moves */
  403 +#ifdef TARGET_SPARC64
  404 +static inline void gen_ld_asi(int insn, int size, int sign)
  405 +{
  406 + int asi, offset;
  407 +
  408 + if (IS_IMM) {
  409 + offset = GET_FIELD(insn, 25, 31);
  410 + gen_op_ld_asi_reg(offset, size, sign);
  411 + } else {
  412 + asi = GET_FIELD(insn, 19, 26);
  413 + gen_op_ld_asi(asi, size, sign);
  414 + }
  415 +}
  416 +
  417 +static inline void gen_st_asi(int insn, int size)
  418 +{
  419 + int asi, offset;
  420 +
  421 + if (IS_IMM) {
  422 + offset = GET_FIELD(insn, 25, 31);
  423 + gen_op_st_asi_reg(offset, size);
  424 + } else {
  425 + asi = GET_FIELD(insn, 19, 26);
  426 + gen_op_st_asi(asi, size);
  427 + }
  428 +}
  429 +
  430 +static inline void gen_swap_asi(int insn)
  431 +{
  432 + int asi, offset;
  433 +
  434 + if (IS_IMM) {
  435 + offset = GET_FIELD(insn, 25, 31);
  436 + gen_op_swap_asi_reg(offset);
  437 + } else {
  438 + asi = GET_FIELD(insn, 19, 26);
  439 + gen_op_swap_asi(asi);
  440 + }
  441 +}
  442 +
  443 +static inline void gen_ldstub_asi(int insn)
  444 +{
  445 + int asi, offset;
  446 +
  447 + if (IS_IMM) {
  448 + offset = GET_FIELD(insn, 25, 31);
  449 + gen_op_ldstub_asi_reg(offset);
  450 + } else {
  451 + asi = GET_FIELD(insn, 19, 26);
  452 + gen_op_ldstub_asi(asi);
  453 + }
  454 +}
  455 +
  456 +static inline void gen_ldda_asi(int insn)
  457 +{
  458 + int asi, offset;
  459 +
  460 + if (IS_IMM) {
  461 + offset = GET_FIELD(insn, 25, 31);
  462 + gen_op_ldda_asi_reg(offset);
  463 + } else {
  464 + asi = GET_FIELD(insn, 19, 26);
  465 + gen_op_ldda_asi(asi);
  466 + }
  467 +}
  468 +
  469 +static inline void gen_stda_asi(int insn)
  470 +{
  471 + int asi, offset;
  472 +
  473 + if (IS_IMM) {
  474 + offset = GET_FIELD(insn, 25, 31);
  475 + gen_op_stda_asi_reg(offset);
  476 + } else {
  477 + asi = GET_FIELD(insn, 19, 26);
  478 + gen_op_stda_asi(asi);
  479 + }
  480 +}
  481 +
  482 +static inline void gen_cas_asi(int insn)
  483 +{
  484 + int asi, offset;
  485 +
  486 + if (IS_IMM) {
  487 + offset = GET_FIELD(insn, 25, 31);
  488 + gen_op_cas_asi_reg(offset);
  489 + } else {
  490 + asi = GET_FIELD(insn, 19, 26);
  491 + gen_op_cas_asi(asi);
  492 + }
  493 +}
  494 +
  495 +static inline void gen_casx_asi(int insn)
  496 +{
  497 + int asi, offset;
  498 +
  499 + if (IS_IMM) {
  500 + offset = GET_FIELD(insn, 25, 31);
  501 + gen_op_casx_asi_reg(offset);
  502 + } else {
  503 + asi = GET_FIELD(insn, 19, 26);
  504 + gen_op_casx_asi(asi);
  505 + }
  506 +}
  507 +
  508 +#elif !defined(CONFIG_USER_ONLY)
  509 +
  510 +static inline void gen_ld_asi(int insn, int size, int sign)
  511 +{
  512 + int asi;
  513 +
  514 + asi = GET_FIELD(insn, 19, 26);
  515 + gen_op_ld_asi(asi, size, sign);
  516 +}
  517 +
  518 +static inline void gen_st_asi(int insn, int size)
  519 +{
  520 + int asi;
  521 +
  522 + asi = GET_FIELD(insn, 19, 26);
  523 + gen_op_st_asi(asi, size);
  524 +}
  525 +
  526 +static inline void gen_ldstub_asi(int insn)
  527 +{
  528 + int asi;
  529 +
  530 + asi = GET_FIELD(insn, 19, 26);
  531 + gen_op_ldstub_asi(asi);
  532 +}
  533 +
  534 +static inline void gen_swap_asi(int insn)
  535 +{
  536 + int asi;
  537 +
  538 + asi = GET_FIELD(insn, 19, 26);
  539 + gen_op_swap_asi(asi);
  540 +}
  541 +
  542 +static inline void gen_ldda_asi(int insn)
  543 +{
  544 + int asi;
  545 +
  546 + asi = GET_FIELD(insn, 19, 26);
  547 + gen_op_ld_asi(asi, 8, 0);
  548 +}
  549 +
  550 +static inline void gen_stda_asi(int insn)
  551 +{
  552 + int asi;
  553 +
  554 + asi = GET_FIELD(insn, 19, 26);
  555 + gen_op_st_asi(asi, 8);
  556 +}
486 557 #endif
487 558  
488 559 static inline void gen_movl_imm_TN(int reg, uint32_t imm)
... ... @@ -2796,7 +2867,12 @@ static void disas_sparc_insn(DisasContext * dc)
2796 2867 rs1 = GET_FIELD(insn, 13, 17);
2797 2868 save_state(dc);
2798 2869 gen_movl_reg_T0(rs1);
2799   - if (IS_IMM) { /* immediate */
  2870 + if (xop == 0x3c || xop == 0x3e)
  2871 + {
  2872 + rs2 = GET_FIELD(insn, 27, 31);
  2873 + gen_movl_reg_T1(rs2);
  2874 + }
  2875 + else if (IS_IMM) { /* immediate */
2800 2876 rs2 = GET_FIELDs(insn, 19, 31);
2801 2877 #if defined(OPTIM)
2802 2878 if (rs2 != 0) {
... ... @@ -2873,16 +2949,10 @@ static void disas_sparc_insn(DisasContext * dc)
2873 2949 goto illegal_insn;
2874 2950 if (!supervisor(dc))
2875 2951 goto priv_insn;
2876   -#ifdef CONFIG_USER_ONLY
  2952 +#elif CONFIG_USER_ONLY
2877 2953 gen_op_check_align_T0_3();
2878 2954 #endif
2879   - gen_op_lda(insn, 1, 4, 0);
2880   -#else
2881   -#ifdef CONFIG_USER_ONLY
2882   - gen_op_check_align_T0_3();
2883   -#endif
2884   - gen_op_lduwa(insn, 1, 4, 0);
2885   -#endif
  2955 + gen_ld_asi(insn, 4, 0);
2886 2956 break;
2887 2957 case 0x11: /* load unsigned byte alternate */
2888 2958 #ifndef TARGET_SPARC64
... ... @@ -2891,7 +2961,7 @@ static void disas_sparc_insn(DisasContext * dc)
2891 2961 if (!supervisor(dc))
2892 2962 goto priv_insn;
2893 2963 #endif
2894   - gen_op_lduba(insn, 1, 1, 0);
  2964 + gen_ld_asi(insn, 1, 0);
2895 2965 break;
2896 2966 case 0x12: /* load unsigned halfword alternate */
2897 2967 #ifndef TARGET_SPARC64
... ... @@ -2899,11 +2969,10 @@ static void disas_sparc_insn(DisasContext * dc)
2899 2969 goto illegal_insn;
2900 2970 if (!supervisor(dc))
2901 2971 goto priv_insn;
2902   -#endif
2903   -#ifdef CONFIG_USER_ONLY
  2972 +#elif CONFIG_USER_ONLY
2904 2973 gen_op_check_align_T0_1();
2905 2974 #endif
2906   - gen_op_lduha(insn, 1, 2, 0);
  2975 + gen_ld_asi(insn, 2, 0);
2907 2976 break;
2908 2977 case 0x13: /* load double word alternate */
2909 2978 #ifndef TARGET_SPARC64
... ... @@ -2915,7 +2984,7 @@ static void disas_sparc_insn(DisasContext * dc)
2915 2984 if (rd & 1)
2916 2985 goto illegal_insn;
2917 2986 gen_op_check_align_T0_7();
2918   - gen_op_ldda(insn, 1, 8, 0);
  2987 + gen_ldda_asi(insn);
2919 2988 gen_movl_T0_reg(rd + 1);
2920 2989 break;
2921 2990 case 0x19: /* load signed byte alternate */
... ... @@ -2925,7 +2994,7 @@ static void disas_sparc_insn(DisasContext * dc)
2925 2994 if (!supervisor(dc))
2926 2995 goto priv_insn;
2927 2996 #endif
2928   - gen_op_ldsba(insn, 1, 1, 1);
  2997 + gen_ld_asi(insn, 1, 1);
2929 2998 break;
2930 2999 case 0x1a: /* load signed halfword alternate */
2931 3000 #ifndef TARGET_SPARC64
... ... @@ -2933,11 +3002,10 @@ static void disas_sparc_insn(DisasContext * dc)
2933 3002 goto illegal_insn;
2934 3003 if (!supervisor(dc))
2935 3004 goto priv_insn;
2936   -#endif
2937   -#ifdef CONFIG_USER_ONLY
  3005 +#elif CONFIG_USER_ONLY
2938 3006 gen_op_check_align_T0_1();
2939 3007 #endif
2940   - gen_op_ldsha(insn, 1, 2 ,1);
  3008 + gen_ld_asi(insn, 2, 1);
2941 3009 break;
2942 3010 case 0x1d: /* ldstuba -- XXX: should be atomically */
2943 3011 #ifndef TARGET_SPARC64
... ... @@ -2946,7 +3014,7 @@ static void disas_sparc_insn(DisasContext * dc)
2946 3014 if (!supervisor(dc))
2947 3015 goto priv_insn;
2948 3016 #endif
2949   - gen_op_ldstuba(insn, 1, 1, 0);
  3017 + gen_ldstub_asi(insn);
2950 3018 break;
2951 3019 case 0x1f: /* swap reg with alt. memory. Also atomically */
2952 3020 #ifndef TARGET_SPARC64
... ... @@ -2954,12 +3022,11 @@ static void disas_sparc_insn(DisasContext * dc)
2954 3022 goto illegal_insn;
2955 3023 if (!supervisor(dc))
2956 3024 goto priv_insn;
2957   -#endif
2958   - gen_movl_reg_T1(rd);
2959   -#ifdef CONFIG_USER_ONLY
  3025 +#elif CONFIG_USER_ONLY
2960 3026 gen_op_check_align_T0_3();
2961 3027 #endif
2962   - gen_op_swapa(insn, 1, 4, 0);
  3028 + gen_movl_reg_T1(rd);
  3029 + gen_swap_asi(insn);
2963 3030 break;
2964 3031  
2965 3032 #ifndef TARGET_SPARC64
... ... @@ -2967,17 +3034,6 @@ static void disas_sparc_insn(DisasContext * dc)
2967 3034 case 0x31: /* ldcsr */
2968 3035 case 0x33: /* lddc */
2969 3036 goto ncp_insn;
2970   - /* avoid warnings */
2971   - (void) &gen_op_stfa;
2972   - (void) &gen_op_stdfa;
2973   - (void) &gen_op_ldfa;
2974   - (void) &gen_op_lddfa;
2975   -#else
2976   - (void) &gen_op_lda;
2977   -#if !defined(CONFIG_USER_ONLY)
2978   - (void) &gen_op_cas;
2979   - (void) &gen_op_casx;
2980   -#endif
2981 3037 #endif
2982 3038 #endif
2983 3039 #ifdef TARGET_SPARC64
... ... @@ -2995,11 +3051,11 @@ static void disas_sparc_insn(DisasContext * dc)
2995 3051 #ifdef CONFIG_USER_ONLY
2996 3052 gen_op_check_align_T0_3();
2997 3053 #endif
2998   - gen_op_ldswa(insn, 1, 4, 1);
  3054 + gen_ld_asi(insn, 4, 1);
2999 3055 break;
3000 3056 case 0x1b: /* V9 ldxa */
3001 3057 gen_op_check_align_T0_7();
3002   - gen_op_ldxa(insn, 1, 8, 0);
  3058 + gen_ld_asi(insn, 8, 0);
3003 3059 break;
3004 3060 case 0x2d: /* V9 prefetch, no effect */
3005 3061 goto skip_move;
... ... @@ -3007,13 +3063,12 @@ static void disas_sparc_insn(DisasContext * dc)
3007 3063 #ifdef CONFIG_USER_ONLY
3008 3064 gen_op_check_align_T0_3();
3009 3065 #endif
3010   - gen_op_ldfa(insn, 1, 8, 0); // XXX
3011   - break;
  3066 + gen_ld_asi(insn, 8, 0); // XXX
  3067 + goto skip_move;
3012 3068 case 0x33: /* V9 lddfa */
3013 3069 gen_op_check_align_T0_7();
3014   - gen_op_lddfa(insn, 1, 8, 0); // XXX
3015   -
3016   - break;
  3070 + gen_ld_asi(insn, 8, 0); // XXX
  3071 + goto skip_move;
3017 3072 case 0x3d: /* V9 prefetcha, no effect */
3018 3073 goto skip_move;
3019 3074 case 0x32: /* V9 ldqfa */
... ... @@ -3092,7 +3147,7 @@ static void disas_sparc_insn(DisasContext * dc)
3092 3147 #ifdef CONFIG_USER_ONLY
3093 3148 gen_op_check_align_T0_3();
3094 3149 #endif
3095   - gen_op_sta(insn, 0, 4, 0);
  3150 + gen_st_asi(insn, 4);
3096 3151 break;
3097 3152 case 0x15:
3098 3153 #ifndef TARGET_SPARC64
... ... @@ -3101,7 +3156,7 @@ static void disas_sparc_insn(DisasContext * dc)
3101 3156 if (!supervisor(dc))
3102 3157 goto priv_insn;
3103 3158 #endif
3104   - gen_op_stba(insn, 0, 1, 0);
  3159 + gen_st_asi(insn, 1);
3105 3160 break;
3106 3161 case 0x16:
3107 3162 #ifndef TARGET_SPARC64
... ... @@ -3113,7 +3168,7 @@ static void disas_sparc_insn(DisasContext * dc)
3113 3168 #ifdef CONFIG_USER_ONLY
3114 3169 gen_op_check_align_T0_1();
3115 3170 #endif
3116   - gen_op_stha(insn, 0, 2, 0);
  3171 + gen_st_asi(insn, 2);
3117 3172 break;
3118 3173 case 0x17:
3119 3174 #ifndef TARGET_SPARC64
... ... @@ -3127,7 +3182,7 @@ static void disas_sparc_insn(DisasContext * dc)
3127 3182 gen_op_check_align_T0_7();
3128 3183 flush_T2(dc);
3129 3184 gen_movl_reg_T2(rd + 1);
3130   - gen_op_stda(insn, 0, 8, 0);
  3185 + gen_stda_asi(insn);
3131 3186 break;
3132 3187 #endif
3133 3188 #ifdef TARGET_SPARC64
... ... @@ -3137,7 +3192,7 @@ static void disas_sparc_insn(DisasContext * dc)
3137 3192 break;
3138 3193 case 0x1e: /* V9 stxa */
3139 3194 gen_op_check_align_T0_7();
3140   - gen_op_stxa(insn, 0, 8, 0); // XXX
  3195 + gen_st_asi(insn, 8);
3141 3196 break;
3142 3197 #endif
3143 3198 default:
... ... @@ -3184,21 +3239,27 @@ static void disas_sparc_insn(DisasContext * dc)
3184 3239 #ifdef CONFIG_USER_ONLY
3185 3240 gen_op_check_align_T0_3();
3186 3241 #endif
3187   - gen_op_stfa(insn, 0, 0, 0); // XXX
  3242 + gen_st_asi(insn, 0); // XXX
3188 3243 break;
3189 3244 case 0x37: /* V9 stdfa */
3190 3245 gen_op_check_align_T0_7();
3191   - gen_op_stdfa(insn, 0, 0, 0); // XXX
  3246 + gen_st_asi(insn, 0); // XXX
3192 3247 break;
3193 3248 case 0x3c: /* V9 casa */
3194 3249 #ifdef CONFIG_USER_ONLY
3195 3250 gen_op_check_align_T0_3();
3196 3251 #endif
3197   - gen_op_casa(insn, 0, 4, 0); // XXX
  3252 + flush_T2(dc);
  3253 + gen_movl_reg_T2(rd);
  3254 + gen_cas_asi(insn);
  3255 + gen_movl_T1_reg(rd);
3198 3256 break;
3199 3257 case 0x3e: /* V9 casxa */
3200 3258 gen_op_check_align_T0_7();
3201   - gen_op_casxa(insn, 0, 8, 0); // XXX
  3259 + flush_T2(dc);
  3260 + gen_movl_reg_T2(rd);
  3261 + gen_casx_asi(insn);
  3262 + gen_movl_T1_reg(rd);
3202 3263 break;
3203 3264 case 0x36: /* V9 stqfa */
3204 3265 goto nfpu_insn;
... ...