Commit 81ad8ba242815e27f990e18778c7cdca2e7e7522
1 parent
43febf49
Rework ASI instructions (Aurelien Jarno)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3205 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
727 additions
and
204 deletions
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; | ... | ... |