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,7 +50,7 @@ void cpu_unlock(void); | ||
| 50 | void cpu_loop_exit(void); | 50 | void cpu_loop_exit(void); |
| 51 | void helper_flush(target_ulong addr); | 51 | void helper_flush(target_ulong addr); |
| 52 | void helper_ld_asi(int asi, int size, int sign); | 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 | void helper_rett(void); | 54 | void helper_rett(void); |
| 55 | void helper_ldfsr(void); | 55 | void helper_ldfsr(void); |
| 56 | void set_cwp(int new_cwp); | 56 | void set_cwp(int new_cwp); |
target-sparc/op.c
| @@ -1862,10 +1862,126 @@ void OPPROTO op_ld_asi_reg() | @@ -1862,10 +1862,126 @@ void OPPROTO op_ld_asi_reg() | ||
| 1862 | void OPPROTO op_st_asi_reg() | 1862 | void OPPROTO op_st_asi_reg() |
| 1863 | { | 1863 | { |
| 1864 | T0 += PARAM1; | 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 | #endif | 1982 | #endif |
| 1868 | 1983 | ||
| 1984 | +#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) | ||
| 1869 | void OPPROTO op_ld_asi() | 1985 | void OPPROTO op_ld_asi() |
| 1870 | { | 1986 | { |
| 1871 | helper_ld_asi(PARAM1, PARAM2, PARAM3); | 1987 | helper_ld_asi(PARAM1, PARAM2, PARAM3); |
| @@ -1873,9 +1989,33 @@ void OPPROTO op_ld_asi() | @@ -1873,9 +1989,33 @@ void OPPROTO op_ld_asi() | ||
| 1873 | 1989 | ||
| 1874 | void OPPROTO op_st_asi() | 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 | #ifdef TARGET_SPARC64 | 2019 | #ifdef TARGET_SPARC64 |
| 1880 | // This function uses non-native bit order | 2020 | // This function uses non-native bit order |
| 1881 | #define GET_FIELD(X, FROM, TO) \ | 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,16 +137,8 @@ GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1); | ||
| 137 | GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1); | 137 | GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1); |
| 138 | #endif | 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 | #ifndef TARGET_SPARC64 | 140 | #ifndef TARGET_SPARC64 |
| 141 | +#ifndef CONFIG_USER_ONLY | ||
| 150 | void helper_ld_asi(int asi, int size, int sign) | 142 | void helper_ld_asi(int asi, int size, int sign) |
| 151 | { | 143 | { |
| 152 | uint32_t ret = 0; | 144 | uint32_t ret = 0; |
| @@ -200,6 +192,42 @@ void helper_ld_asi(int asi, int size, int sign) | @@ -200,6 +192,42 @@ void helper_ld_asi(int asi, int size, int sign) | ||
| 200 | break; | 192 | break; |
| 201 | } | 193 | } |
| 202 | break; | 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 | case 0xc: /* I-cache tag */ | 231 | case 0xc: /* I-cache tag */ |
| 204 | case 0xd: /* I-cache data */ | 232 | case 0xd: /* I-cache data */ |
| 205 | case 0xe: /* D-cache tag */ | 233 | case 0xe: /* D-cache tag */ |
| @@ -253,10 +281,22 @@ void helper_ld_asi(int asi, int size, int sign) | @@ -253,10 +281,22 @@ void helper_ld_asi(int asi, int size, int sign) | ||
| 253 | ret = 0; | 281 | ret = 0; |
| 254 | break; | 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 | switch(asi) { | 301 | switch(asi) { |
| 262 | case 2: /* SuperSparc MXCC registers */ | 302 | case 2: /* SuperSparc MXCC registers */ |
| @@ -325,6 +365,42 @@ void helper_st_asi(int asi, int size, int sign) | @@ -325,6 +365,42 @@ void helper_st_asi(int asi, int size, int sign) | ||
| 325 | #endif | 365 | #endif |
| 326 | return; | 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 | case 0xc: /* I-cache tag */ | 404 | case 0xc: /* I-cache tag */ |
| 329 | case 0xd: /* I-cache data */ | 405 | case 0xd: /* I-cache data */ |
| 330 | case 0xe: /* D-cache tag */ | 406 | case 0xe: /* D-cache tag */ |
| @@ -422,7 +498,146 @@ void helper_st_asi(int asi, int size, int sign) | @@ -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 | void helper_ld_asi(int asi, int size, int sign) | 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,8 +647,50 @@ void helper_ld_asi(int asi, int size, int sign) | ||
| 432 | raise_exception(TT_PRIV_ACT); | 647 | raise_exception(TT_PRIV_ACT); |
| 433 | 648 | ||
| 434 | switch (asi) { | 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 | case 0x14: // Bypass | 690 | case 0x14: // Bypass |
| 436 | case 0x15: // Bypass, non-cacheable | 691 | case 0x15: // Bypass, non-cacheable |
| 692 | + case 0x1c: // Bypass LE | ||
| 693 | + case 0x1d: // Bypass, non-cacheable LE | ||
| 437 | { | 694 | { |
| 438 | switch(size) { | 695 | switch(size) { |
| 439 | case 1: | 696 | case 1: |
| @@ -454,20 +711,14 @@ void helper_ld_asi(int asi, int size, int sign) | @@ -454,20 +711,14 @@ void helper_ld_asi(int asi, int size, int sign) | ||
| 454 | } | 711 | } |
| 455 | case 0x04: // Nucleus | 712 | case 0x04: // Nucleus |
| 456 | case 0x0c: // Nucleus Little Endian (LE) | 713 | case 0x0c: // Nucleus Little Endian (LE) |
| 457 | - case 0x10: // As if user primary | ||
| 458 | case 0x11: // As if user secondary | 714 | case 0x11: // As if user secondary |
| 459 | - case 0x18: // As if user primary LE | ||
| 460 | case 0x19: // As if user secondary LE | 715 | case 0x19: // As if user secondary LE |
| 461 | - case 0x1c: // Bypass LE | ||
| 462 | - case 0x1d: // Bypass, non-cacheable LE | ||
| 463 | case 0x24: // Nucleus quad LDD 128 bit atomic | 716 | case 0x24: // Nucleus quad LDD 128 bit atomic |
| 464 | case 0x2c: // Nucleus quad LDD 128 bit atomic | 717 | case 0x2c: // Nucleus quad LDD 128 bit atomic |
| 465 | case 0x4a: // UPA config | 718 | case 0x4a: // UPA config |
| 466 | - case 0x82: // Primary no-fault | 719 | + case 0x81: // Secondary |
| 467 | case 0x83: // Secondary no-fault | 720 | case 0x83: // Secondary no-fault |
| 468 | - case 0x88: // Primary LE | ||
| 469 | case 0x89: // Secondary LE | 721 | case 0x89: // Secondary LE |
| 470 | - case 0x8a: // Primary no-fault LE | ||
| 471 | case 0x8b: // Secondary no-fault LE | 722 | case 0x8b: // Secondary no-fault LE |
| 472 | // XXX | 723 | // XXX |
| 473 | break; | 724 | break; |
| @@ -540,17 +791,120 @@ void helper_ld_asi(int asi, int size, int sign) | @@ -540,17 +791,120 @@ void helper_ld_asi(int asi, int size, int sign) | ||
| 540 | ret = 0; | 791 | ret = 0; |
| 541 | break; | 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 | T1 = ret; | 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 | if (asi < 0x80 && (env->pstate & PS_PRIV) == 0) | 838 | if (asi < 0x80 && (env->pstate & PS_PRIV) == 0) |
| 549 | raise_exception(TT_PRIV_ACT); | 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 | switch(asi) { | 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 | case 0x14: // Bypass | 904 | case 0x14: // Bypass |
| 553 | case 0x15: // Bypass, non-cacheable | 905 | case 0x15: // Bypass, non-cacheable |
| 906 | + case 0x1c: // Bypass LE | ||
| 907 | + case 0x1d: // Bypass, non-cacheable LE | ||
| 554 | { | 908 | { |
| 555 | switch(size) { | 909 | switch(size) { |
| 556 | case 1: | 910 | case 1: |
| @@ -571,16 +925,11 @@ void helper_st_asi(int asi, int size, int sign) | @@ -571,16 +925,11 @@ void helper_st_asi(int asi, int size, int sign) | ||
| 571 | return; | 925 | return; |
| 572 | case 0x04: // Nucleus | 926 | case 0x04: // Nucleus |
| 573 | case 0x0c: // Nucleus Little Endian (LE) | 927 | case 0x0c: // Nucleus Little Endian (LE) |
| 574 | - case 0x10: // As if user primary | ||
| 575 | case 0x11: // As if user secondary | 928 | case 0x11: // As if user secondary |
| 576 | - case 0x18: // As if user primary LE | ||
| 577 | case 0x19: // As if user secondary LE | 929 | case 0x19: // As if user secondary LE |
| 578 | - case 0x1c: // Bypass LE | ||
| 579 | - case 0x1d: // Bypass, non-cacheable LE | ||
| 580 | case 0x24: // Nucleus quad LDD 128 bit atomic | 930 | case 0x24: // Nucleus quad LDD 128 bit atomic |
| 581 | case 0x2c: // Nucleus quad LDD 128 bit atomic | 931 | case 0x2c: // Nucleus quad LDD 128 bit atomic |
| 582 | case 0x4a: // UPA config | 932 | case 0x4a: // UPA config |
| 583 | - case 0x88: // Primary LE | ||
| 584 | case 0x89: // Secondary LE | 933 | case 0x89: // Secondary LE |
| 585 | // XXX | 934 | // XXX |
| 586 | return; | 935 | return; |
| @@ -756,8 +1105,8 @@ void helper_st_asi(int asi, int size, int sign) | @@ -756,8 +1105,8 @@ void helper_st_asi(int asi, int size, int sign) | ||
| 756 | return; | 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 | #ifndef TARGET_SPARC64 | 1111 | #ifndef TARGET_SPARC64 |
| 763 | void helper_rett() | 1112 | void helper_rett() |
target-sparc/op_mem.h
| @@ -76,33 +76,6 @@ void OPPROTO glue(op_lddf, MEMSUFFIX) (void) | @@ -76,33 +76,6 @@ void OPPROTO glue(op_lddf, MEMSUFFIX) (void) | ||
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | #ifdef TARGET_SPARC64 | 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 | void OPPROTO glue(op_lduw, MEMSUFFIX)(void) | 79 | void OPPROTO glue(op_lduw, MEMSUFFIX)(void) |
| 107 | { | 80 | { |
| 108 | T1 = (uint64_t)(glue(ldl, MEMSUFFIX)(T0) & 0xffffffff); | 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,112 +353,27 @@ GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf); | ||
| 353 | #endif | 353 | #endif |
| 354 | #endif | 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 | #define supervisor(dc) 0 | 358 | #define supervisor(dc) 0 |
| 359 | +#ifdef TARGET_SPARC64 | ||
| 360 | #define hypervisor(dc) 0 | 360 | #define hypervisor(dc) 0 |
| 361 | +#endif | ||
| 361 | #define gen_op_ldst(name) gen_op_##name##_raw() | 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 | #else | 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 | #define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])() | 368 | #define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])() |
| 390 | #define OP_LD_TABLE(width) \ | 369 | #define OP_LD_TABLE(width) \ |
| 391 | static GenOpFunc * const gen_op_##width[] = { \ | 370 | static GenOpFunc * const gen_op_##width[] = { \ |
| 392 | &gen_op_##width##_user, \ | 371 | &gen_op_##width##_user, \ |
| 393 | &gen_op_##width##_kernel, \ | 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 | #endif | 374 | #endif |
| 461 | 375 | ||
| 376 | +#ifndef CONFIG_USER_ONLY | ||
| 462 | OP_LD_TABLE(ld); | 377 | OP_LD_TABLE(ld); |
| 463 | OP_LD_TABLE(st); | 378 | OP_LD_TABLE(st); |
| 464 | OP_LD_TABLE(ldub); | 379 | OP_LD_TABLE(ldub); |
| @@ -481,8 +396,164 @@ OP_LD_TABLE(lduw); | @@ -481,8 +396,164 @@ OP_LD_TABLE(lduw); | ||
| 481 | OP_LD_TABLE(ldsw); | 396 | OP_LD_TABLE(ldsw); |
| 482 | OP_LD_TABLE(ldx); | 397 | OP_LD_TABLE(ldx); |
| 483 | OP_LD_TABLE(stx); | 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 | #endif | 557 | #endif |
| 487 | 558 | ||
| 488 | static inline void gen_movl_imm_TN(int reg, uint32_t imm) | 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,7 +2867,12 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 2796 | rs1 = GET_FIELD(insn, 13, 17); | 2867 | rs1 = GET_FIELD(insn, 13, 17); |
| 2797 | save_state(dc); | 2868 | save_state(dc); |
| 2798 | gen_movl_reg_T0(rs1); | 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 | rs2 = GET_FIELDs(insn, 19, 31); | 2876 | rs2 = GET_FIELDs(insn, 19, 31); |
| 2801 | #if defined(OPTIM) | 2877 | #if defined(OPTIM) |
| 2802 | if (rs2 != 0) { | 2878 | if (rs2 != 0) { |
| @@ -2873,16 +2949,10 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -2873,16 +2949,10 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 2873 | goto illegal_insn; | 2949 | goto illegal_insn; |
| 2874 | if (!supervisor(dc)) | 2950 | if (!supervisor(dc)) |
| 2875 | goto priv_insn; | 2951 | goto priv_insn; |
| 2876 | -#ifdef CONFIG_USER_ONLY | 2952 | +#elif CONFIG_USER_ONLY |
| 2877 | gen_op_check_align_T0_3(); | 2953 | gen_op_check_align_T0_3(); |
| 2878 | #endif | 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 | break; | 2956 | break; |
| 2887 | case 0x11: /* load unsigned byte alternate */ | 2957 | case 0x11: /* load unsigned byte alternate */ |
| 2888 | #ifndef TARGET_SPARC64 | 2958 | #ifndef TARGET_SPARC64 |
| @@ -2891,7 +2961,7 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -2891,7 +2961,7 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 2891 | if (!supervisor(dc)) | 2961 | if (!supervisor(dc)) |
| 2892 | goto priv_insn; | 2962 | goto priv_insn; |
| 2893 | #endif | 2963 | #endif |
| 2894 | - gen_op_lduba(insn, 1, 1, 0); | 2964 | + gen_ld_asi(insn, 1, 0); |
| 2895 | break; | 2965 | break; |
| 2896 | case 0x12: /* load unsigned halfword alternate */ | 2966 | case 0x12: /* load unsigned halfword alternate */ |
| 2897 | #ifndef TARGET_SPARC64 | 2967 | #ifndef TARGET_SPARC64 |
| @@ -2899,11 +2969,10 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -2899,11 +2969,10 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 2899 | goto illegal_insn; | 2969 | goto illegal_insn; |
| 2900 | if (!supervisor(dc)) | 2970 | if (!supervisor(dc)) |
| 2901 | goto priv_insn; | 2971 | goto priv_insn; |
| 2902 | -#endif | ||
| 2903 | -#ifdef CONFIG_USER_ONLY | 2972 | +#elif CONFIG_USER_ONLY |
| 2904 | gen_op_check_align_T0_1(); | 2973 | gen_op_check_align_T0_1(); |
| 2905 | #endif | 2974 | #endif |
| 2906 | - gen_op_lduha(insn, 1, 2, 0); | 2975 | + gen_ld_asi(insn, 2, 0); |
| 2907 | break; | 2976 | break; |
| 2908 | case 0x13: /* load double word alternate */ | 2977 | case 0x13: /* load double word alternate */ |
| 2909 | #ifndef TARGET_SPARC64 | 2978 | #ifndef TARGET_SPARC64 |
| @@ -2915,7 +2984,7 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -2915,7 +2984,7 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 2915 | if (rd & 1) | 2984 | if (rd & 1) |
| 2916 | goto illegal_insn; | 2985 | goto illegal_insn; |
| 2917 | gen_op_check_align_T0_7(); | 2986 | gen_op_check_align_T0_7(); |
| 2918 | - gen_op_ldda(insn, 1, 8, 0); | 2987 | + gen_ldda_asi(insn); |
| 2919 | gen_movl_T0_reg(rd + 1); | 2988 | gen_movl_T0_reg(rd + 1); |
| 2920 | break; | 2989 | break; |
| 2921 | case 0x19: /* load signed byte alternate */ | 2990 | case 0x19: /* load signed byte alternate */ |
| @@ -2925,7 +2994,7 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -2925,7 +2994,7 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 2925 | if (!supervisor(dc)) | 2994 | if (!supervisor(dc)) |
| 2926 | goto priv_insn; | 2995 | goto priv_insn; |
| 2927 | #endif | 2996 | #endif |
| 2928 | - gen_op_ldsba(insn, 1, 1, 1); | 2997 | + gen_ld_asi(insn, 1, 1); |
| 2929 | break; | 2998 | break; |
| 2930 | case 0x1a: /* load signed halfword alternate */ | 2999 | case 0x1a: /* load signed halfword alternate */ |
| 2931 | #ifndef TARGET_SPARC64 | 3000 | #ifndef TARGET_SPARC64 |
| @@ -2933,11 +3002,10 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -2933,11 +3002,10 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 2933 | goto illegal_insn; | 3002 | goto illegal_insn; |
| 2934 | if (!supervisor(dc)) | 3003 | if (!supervisor(dc)) |
| 2935 | goto priv_insn; | 3004 | goto priv_insn; |
| 2936 | -#endif | ||
| 2937 | -#ifdef CONFIG_USER_ONLY | 3005 | +#elif CONFIG_USER_ONLY |
| 2938 | gen_op_check_align_T0_1(); | 3006 | gen_op_check_align_T0_1(); |
| 2939 | #endif | 3007 | #endif |
| 2940 | - gen_op_ldsha(insn, 1, 2 ,1); | 3008 | + gen_ld_asi(insn, 2, 1); |
| 2941 | break; | 3009 | break; |
| 2942 | case 0x1d: /* ldstuba -- XXX: should be atomically */ | 3010 | case 0x1d: /* ldstuba -- XXX: should be atomically */ |
| 2943 | #ifndef TARGET_SPARC64 | 3011 | #ifndef TARGET_SPARC64 |
| @@ -2946,7 +3014,7 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -2946,7 +3014,7 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 2946 | if (!supervisor(dc)) | 3014 | if (!supervisor(dc)) |
| 2947 | goto priv_insn; | 3015 | goto priv_insn; |
| 2948 | #endif | 3016 | #endif |
| 2949 | - gen_op_ldstuba(insn, 1, 1, 0); | 3017 | + gen_ldstub_asi(insn); |
| 2950 | break; | 3018 | break; |
| 2951 | case 0x1f: /* swap reg with alt. memory. Also atomically */ | 3019 | case 0x1f: /* swap reg with alt. memory. Also atomically */ |
| 2952 | #ifndef TARGET_SPARC64 | 3020 | #ifndef TARGET_SPARC64 |
| @@ -2954,12 +3022,11 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -2954,12 +3022,11 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 2954 | goto illegal_insn; | 3022 | goto illegal_insn; |
| 2955 | if (!supervisor(dc)) | 3023 | if (!supervisor(dc)) |
| 2956 | goto priv_insn; | 3024 | goto priv_insn; |
| 2957 | -#endif | ||
| 2958 | - gen_movl_reg_T1(rd); | ||
| 2959 | -#ifdef CONFIG_USER_ONLY | 3025 | +#elif CONFIG_USER_ONLY |
| 2960 | gen_op_check_align_T0_3(); | 3026 | gen_op_check_align_T0_3(); |
| 2961 | #endif | 3027 | #endif |
| 2962 | - gen_op_swapa(insn, 1, 4, 0); | 3028 | + gen_movl_reg_T1(rd); |
| 3029 | + gen_swap_asi(insn); | ||
| 2963 | break; | 3030 | break; |
| 2964 | 3031 | ||
| 2965 | #ifndef TARGET_SPARC64 | 3032 | #ifndef TARGET_SPARC64 |
| @@ -2967,17 +3034,6 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -2967,17 +3034,6 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 2967 | case 0x31: /* ldcsr */ | 3034 | case 0x31: /* ldcsr */ |
| 2968 | case 0x33: /* lddc */ | 3035 | case 0x33: /* lddc */ |
| 2969 | goto ncp_insn; | 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 | #endif | 3037 | #endif |
| 2982 | #endif | 3038 | #endif |
| 2983 | #ifdef TARGET_SPARC64 | 3039 | #ifdef TARGET_SPARC64 |
| @@ -2995,11 +3051,11 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -2995,11 +3051,11 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 2995 | #ifdef CONFIG_USER_ONLY | 3051 | #ifdef CONFIG_USER_ONLY |
| 2996 | gen_op_check_align_T0_3(); | 3052 | gen_op_check_align_T0_3(); |
| 2997 | #endif | 3053 | #endif |
| 2998 | - gen_op_ldswa(insn, 1, 4, 1); | 3054 | + gen_ld_asi(insn, 4, 1); |
| 2999 | break; | 3055 | break; |
| 3000 | case 0x1b: /* V9 ldxa */ | 3056 | case 0x1b: /* V9 ldxa */ |
| 3001 | gen_op_check_align_T0_7(); | 3057 | gen_op_check_align_T0_7(); |
| 3002 | - gen_op_ldxa(insn, 1, 8, 0); | 3058 | + gen_ld_asi(insn, 8, 0); |
| 3003 | break; | 3059 | break; |
| 3004 | case 0x2d: /* V9 prefetch, no effect */ | 3060 | case 0x2d: /* V9 prefetch, no effect */ |
| 3005 | goto skip_move; | 3061 | goto skip_move; |
| @@ -3007,13 +3063,12 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -3007,13 +3063,12 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 3007 | #ifdef CONFIG_USER_ONLY | 3063 | #ifdef CONFIG_USER_ONLY |
| 3008 | gen_op_check_align_T0_3(); | 3064 | gen_op_check_align_T0_3(); |
| 3009 | #endif | 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 | case 0x33: /* V9 lddfa */ | 3068 | case 0x33: /* V9 lddfa */ |
| 3013 | gen_op_check_align_T0_7(); | 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 | case 0x3d: /* V9 prefetcha, no effect */ | 3072 | case 0x3d: /* V9 prefetcha, no effect */ |
| 3018 | goto skip_move; | 3073 | goto skip_move; |
| 3019 | case 0x32: /* V9 ldqfa */ | 3074 | case 0x32: /* V9 ldqfa */ |
| @@ -3092,7 +3147,7 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -3092,7 +3147,7 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 3092 | #ifdef CONFIG_USER_ONLY | 3147 | #ifdef CONFIG_USER_ONLY |
| 3093 | gen_op_check_align_T0_3(); | 3148 | gen_op_check_align_T0_3(); |
| 3094 | #endif | 3149 | #endif |
| 3095 | - gen_op_sta(insn, 0, 4, 0); | 3150 | + gen_st_asi(insn, 4); |
| 3096 | break; | 3151 | break; |
| 3097 | case 0x15: | 3152 | case 0x15: |
| 3098 | #ifndef TARGET_SPARC64 | 3153 | #ifndef TARGET_SPARC64 |
| @@ -3101,7 +3156,7 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -3101,7 +3156,7 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 3101 | if (!supervisor(dc)) | 3156 | if (!supervisor(dc)) |
| 3102 | goto priv_insn; | 3157 | goto priv_insn; |
| 3103 | #endif | 3158 | #endif |
| 3104 | - gen_op_stba(insn, 0, 1, 0); | 3159 | + gen_st_asi(insn, 1); |
| 3105 | break; | 3160 | break; |
| 3106 | case 0x16: | 3161 | case 0x16: |
| 3107 | #ifndef TARGET_SPARC64 | 3162 | #ifndef TARGET_SPARC64 |
| @@ -3113,7 +3168,7 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -3113,7 +3168,7 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 3113 | #ifdef CONFIG_USER_ONLY | 3168 | #ifdef CONFIG_USER_ONLY |
| 3114 | gen_op_check_align_T0_1(); | 3169 | gen_op_check_align_T0_1(); |
| 3115 | #endif | 3170 | #endif |
| 3116 | - gen_op_stha(insn, 0, 2, 0); | 3171 | + gen_st_asi(insn, 2); |
| 3117 | break; | 3172 | break; |
| 3118 | case 0x17: | 3173 | case 0x17: |
| 3119 | #ifndef TARGET_SPARC64 | 3174 | #ifndef TARGET_SPARC64 |
| @@ -3127,7 +3182,7 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -3127,7 +3182,7 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 3127 | gen_op_check_align_T0_7(); | 3182 | gen_op_check_align_T0_7(); |
| 3128 | flush_T2(dc); | 3183 | flush_T2(dc); |
| 3129 | gen_movl_reg_T2(rd + 1); | 3184 | gen_movl_reg_T2(rd + 1); |
| 3130 | - gen_op_stda(insn, 0, 8, 0); | 3185 | + gen_stda_asi(insn); |
| 3131 | break; | 3186 | break; |
| 3132 | #endif | 3187 | #endif |
| 3133 | #ifdef TARGET_SPARC64 | 3188 | #ifdef TARGET_SPARC64 |
| @@ -3137,7 +3192,7 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -3137,7 +3192,7 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 3137 | break; | 3192 | break; |
| 3138 | case 0x1e: /* V9 stxa */ | 3193 | case 0x1e: /* V9 stxa */ |
| 3139 | gen_op_check_align_T0_7(); | 3194 | gen_op_check_align_T0_7(); |
| 3140 | - gen_op_stxa(insn, 0, 8, 0); // XXX | 3195 | + gen_st_asi(insn, 8); |
| 3141 | break; | 3196 | break; |
| 3142 | #endif | 3197 | #endif |
| 3143 | default: | 3198 | default: |
| @@ -3184,21 +3239,27 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -3184,21 +3239,27 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 3184 | #ifdef CONFIG_USER_ONLY | 3239 | #ifdef CONFIG_USER_ONLY |
| 3185 | gen_op_check_align_T0_3(); | 3240 | gen_op_check_align_T0_3(); |
| 3186 | #endif | 3241 | #endif |
| 3187 | - gen_op_stfa(insn, 0, 0, 0); // XXX | 3242 | + gen_st_asi(insn, 0); // XXX |
| 3188 | break; | 3243 | break; |
| 3189 | case 0x37: /* V9 stdfa */ | 3244 | case 0x37: /* V9 stdfa */ |
| 3190 | gen_op_check_align_T0_7(); | 3245 | gen_op_check_align_T0_7(); |
| 3191 | - gen_op_stdfa(insn, 0, 0, 0); // XXX | 3246 | + gen_st_asi(insn, 0); // XXX |
| 3192 | break; | 3247 | break; |
| 3193 | case 0x3c: /* V9 casa */ | 3248 | case 0x3c: /* V9 casa */ |
| 3194 | #ifdef CONFIG_USER_ONLY | 3249 | #ifdef CONFIG_USER_ONLY |
| 3195 | gen_op_check_align_T0_3(); | 3250 | gen_op_check_align_T0_3(); |
| 3196 | #endif | 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 | break; | 3256 | break; |
| 3199 | case 0x3e: /* V9 casxa */ | 3257 | case 0x3e: /* V9 casxa */ |
| 3200 | gen_op_check_align_T0_7(); | 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 | break; | 3263 | break; |
| 3203 | case 0x36: /* V9 stqfa */ | 3264 | case 0x36: /* V9 stqfa */ |
| 3204 | goto nfpu_insn; | 3265 | goto nfpu_insn; |