Commit db166940e2cb4e6fc6e66cab465fc394bfac159b
1 parent
8571c055
Implement nucleus quad ldda
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4902 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
70 additions
and
20 deletions
target-sparc/helper.h
| @@ -22,6 +22,7 @@ DEF_HELPER(target_ulong, helper_array8, (target_ulong pixel_addr, \ | @@ -22,6 +22,7 @@ DEF_HELPER(target_ulong, helper_array8, (target_ulong pixel_addr, \ | ||
| 22 | DEF_HELPER(target_ulong, helper_alignaddr, (target_ulong addr, \ | 22 | DEF_HELPER(target_ulong, helper_alignaddr, (target_ulong addr, \ |
| 23 | target_ulong offset)) | 23 | target_ulong offset)) |
| 24 | DEF_HELPER(target_ulong, helper_popc, (target_ulong val)) | 24 | DEF_HELPER(target_ulong, helper_popc, (target_ulong val)) |
| 25 | +DEF_HELPER(void, helper_ldda_asi, (target_ulong addr, int asi, int rd)) | ||
| 25 | DEF_HELPER(void, helper_ldf_asi, (target_ulong addr, int asi, int size, int rd)) | 26 | DEF_HELPER(void, helper_ldf_asi, (target_ulong addr, int asi, int size, int rd)) |
| 26 | DEF_HELPER(void, helper_stf_asi, (target_ulong addr, int asi, int size, int rd)) | 27 | DEF_HELPER(void, helper_stf_asi, (target_ulong addr, int asi, int size, int rd)) |
| 27 | DEF_HELPER(target_ulong, helper_cas_asi, (target_ulong addr, \ | 28 | DEF_HELPER(target_ulong, helper_cas_asi, (target_ulong addr, \ |
target-sparc/op_helper.c
| @@ -1634,12 +1634,15 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) | @@ -1634,12 +1634,15 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) | ||
| 1634 | } | 1634 | } |
| 1635 | break; | 1635 | break; |
| 1636 | } | 1636 | } |
| 1637 | + case 0x24: // Nucleus quad LDD 128 bit atomic | ||
| 1638 | + case 0x2c: // Nucleus quad LDD 128 bit atomic LE | ||
| 1639 | + // Only ldda allowed | ||
| 1640 | + raise_exception(TT_ILL_INSN); | ||
| 1641 | + return 0; | ||
| 1637 | case 0x04: // Nucleus | 1642 | case 0x04: // Nucleus |
| 1638 | case 0x0c: // Nucleus Little Endian (LE) | 1643 | case 0x0c: // Nucleus Little Endian (LE) |
| 1639 | case 0x11: // As if user secondary | 1644 | case 0x11: // As if user secondary |
| 1640 | case 0x19: // As if user secondary LE | 1645 | case 0x19: // As if user secondary LE |
| 1641 | - case 0x24: // Nucleus quad LDD 128 bit atomic | ||
| 1642 | - case 0x2c: // Nucleus quad LDD 128 bit atomic | ||
| 1643 | case 0x4a: // UPA config | 1646 | case 0x4a: // UPA config |
| 1644 | case 0x81: // Secondary | 1647 | case 0x81: // Secondary |
| 1645 | case 0x83: // Secondary no-fault | 1648 | case 0x83: // Secondary no-fault |
| @@ -1943,12 +1946,15 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) | @@ -1943,12 +1946,15 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) | ||
| 1943 | } | 1946 | } |
| 1944 | } | 1947 | } |
| 1945 | return; | 1948 | return; |
| 1949 | + case 0x24: // Nucleus quad LDD 128 bit atomic | ||
| 1950 | + case 0x2c: // Nucleus quad LDD 128 bit atomic LE | ||
| 1951 | + // Only ldda allowed | ||
| 1952 | + raise_exception(TT_ILL_INSN); | ||
| 1953 | + return; | ||
| 1946 | case 0x04: // Nucleus | 1954 | case 0x04: // Nucleus |
| 1947 | case 0x0c: // Nucleus Little Endian (LE) | 1955 | case 0x0c: // Nucleus Little Endian (LE) |
| 1948 | case 0x11: // As if user secondary | 1956 | case 0x11: // As if user secondary |
| 1949 | case 0x19: // As if user secondary LE | 1957 | case 0x19: // As if user secondary LE |
| 1950 | - case 0x24: // Nucleus quad LDD 128 bit atomic | ||
| 1951 | - case 0x2c: // Nucleus quad LDD 128 bit atomic | ||
| 1952 | case 0x4a: // UPA config | 1958 | case 0x4a: // UPA config |
| 1953 | case 0x81: // Secondary | 1959 | case 0x81: // Secondary |
| 1954 | case 0x89: // Secondary LE | 1960 | case 0x89: // Secondary LE |
| @@ -2144,6 +2150,53 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) | @@ -2144,6 +2150,53 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) | ||
| 2144 | } | 2150 | } |
| 2145 | #endif /* CONFIG_USER_ONLY */ | 2151 | #endif /* CONFIG_USER_ONLY */ |
| 2146 | 2152 | ||
| 2153 | +void helper_ldda_asi(target_ulong addr, int asi, int rd) | ||
| 2154 | +{ | ||
| 2155 | + unsigned int i; | ||
| 2156 | + | ||
| 2157 | + if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0) | ||
| 2158 | + || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) | ||
| 2159 | + raise_exception(TT_PRIV_ACT); | ||
| 2160 | + | ||
| 2161 | + switch (asi) { | ||
| 2162 | + case 0x24: // Nucleus quad LDD 128 bit atomic | ||
| 2163 | + case 0x2c: // Nucleus quad LDD 128 bit atomic LE | ||
| 2164 | + helper_check_align(addr, 0xf); | ||
| 2165 | + if (rd == 0) { | ||
| 2166 | + env->gregs[1] = ldq_kernel(addr + 8); | ||
| 2167 | + if (asi == 0x2c) | ||
| 2168 | + bswap64s(&env->gregs[1]); | ||
| 2169 | + } else if (rd < 8) { | ||
| 2170 | + env->gregs[rd] = ldq_kernel(addr); | ||
| 2171 | + env->gregs[rd + 1] = ldq_kernel(addr + 8); | ||
| 2172 | + if (asi == 0x2c) { | ||
| 2173 | + bswap64s(&env->gregs[rd]); | ||
| 2174 | + bswap64s(&env->gregs[rd + 1]); | ||
| 2175 | + } | ||
| 2176 | + } else { | ||
| 2177 | + env->regwptr[rd] = ldq_kernel(addr); | ||
| 2178 | + env->regwptr[rd + 1] = ldq_kernel(addr + 8); | ||
| 2179 | + if (asi == 0x2c) { | ||
| 2180 | + bswap64s(&env->regwptr[rd]); | ||
| 2181 | + bswap64s(&env->regwptr[rd + 1]); | ||
| 2182 | + } | ||
| 2183 | + } | ||
| 2184 | + break; | ||
| 2185 | + default: | ||
| 2186 | + helper_check_align(addr, 0x3); | ||
| 2187 | + if (rd == 0) | ||
| 2188 | + env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0); | ||
| 2189 | + else if (rd < 8) { | ||
| 2190 | + env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0); | ||
| 2191 | + env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0); | ||
| 2192 | + } else { | ||
| 2193 | + env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0); | ||
| 2194 | + env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0); | ||
| 2195 | + } | ||
| 2196 | + break; | ||
| 2197 | + } | ||
| 2198 | +} | ||
| 2199 | + | ||
| 2147 | void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) | 2200 | void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) |
| 2148 | { | 2201 | { |
| 2149 | unsigned int i; | 2202 | unsigned int i; |
target-sparc/translate.c
| @@ -1722,20 +1722,15 @@ static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn) | @@ -1722,20 +1722,15 @@ static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn) | ||
| 1722 | tcg_gen_trunc_i64_tl(dst, cpu_tmp64); | 1722 | tcg_gen_trunc_i64_tl(dst, cpu_tmp64); |
| 1723 | } | 1723 | } |
| 1724 | 1724 | ||
| 1725 | -static inline void gen_ldda_asi(TCGv lo, TCGv hi, TCGv addr, int insn) | 1725 | +static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd) |
| 1726 | { | 1726 | { |
| 1727 | - TCGv r_asi, r_size, r_sign; | 1727 | + TCGv r_asi, r_rd; |
| 1728 | 1728 | ||
| 1729 | r_asi = gen_get_asi(insn, addr); | 1729 | r_asi = gen_get_asi(insn, addr); |
| 1730 | - r_size = tcg_const_i32(8); | ||
| 1731 | - r_sign = tcg_const_i32(0); | ||
| 1732 | - tcg_gen_helper_1_4(helper_ld_asi, cpu_tmp64, addr, r_asi, r_size, r_sign); | ||
| 1733 | - tcg_temp_free(r_sign); | ||
| 1734 | - tcg_temp_free(r_size); | 1730 | + r_rd = tcg_const_i32(rd); |
| 1731 | + tcg_gen_helper_0_3(helper_ldda_asi, addr, r_asi, r_rd); | ||
| 1732 | + tcg_temp_free(r_rd); | ||
| 1735 | tcg_temp_free(r_asi); | 1733 | tcg_temp_free(r_asi); |
| 1736 | - tcg_gen_andi_i64(lo, cpu_tmp64, 0xffffffffULL); | ||
| 1737 | - tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32); | ||
| 1738 | - tcg_gen_andi_i64(hi, cpu_tmp64, 0xffffffffULL); | ||
| 1739 | } | 1734 | } |
| 1740 | 1735 | ||
| 1741 | static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd) | 1736 | static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd) |
| @@ -1822,7 +1817,7 @@ static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn) | @@ -1822,7 +1817,7 @@ static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn) | ||
| 1822 | tcg_gen_trunc_i64_tl(dst, cpu_tmp64); | 1817 | tcg_gen_trunc_i64_tl(dst, cpu_tmp64); |
| 1823 | } | 1818 | } |
| 1824 | 1819 | ||
| 1825 | -static inline void gen_ldda_asi(TCGv lo, TCGv hi, TCGv addr, int insn) | 1820 | +static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd) |
| 1826 | { | 1821 | { |
| 1827 | TCGv r_asi, r_size, r_sign; | 1822 | TCGv r_asi, r_size, r_sign; |
| 1828 | 1823 | ||
| @@ -1833,9 +1828,11 @@ static inline void gen_ldda_asi(TCGv lo, TCGv hi, TCGv addr, int insn) | @@ -1833,9 +1828,11 @@ static inline void gen_ldda_asi(TCGv lo, TCGv hi, TCGv addr, int insn) | ||
| 1833 | tcg_temp_free(r_sign); | 1828 | tcg_temp_free(r_sign); |
| 1834 | tcg_temp_free(r_size); | 1829 | tcg_temp_free(r_size); |
| 1835 | tcg_temp_free(r_asi); | 1830 | tcg_temp_free(r_asi); |
| 1836 | - tcg_gen_trunc_i64_tl(lo, cpu_tmp64); | 1831 | + tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64); |
| 1832 | + gen_movl_TN_reg(rd + 1, cpu_tmp0); | ||
| 1837 | tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32); | 1833 | tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32); |
| 1838 | tcg_gen_trunc_i64_tl(hi, cpu_tmp64); | 1834 | tcg_gen_trunc_i64_tl(hi, cpu_tmp64); |
| 1835 | + gen_movl_TN_reg(rd, hi); | ||
| 1839 | } | 1836 | } |
| 1840 | 1837 | ||
| 1841 | static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd) | 1838 | static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd) |
| @@ -4310,9 +4307,8 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -4310,9 +4307,8 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 4310 | if (rd & 1) | 4307 | if (rd & 1) |
| 4311 | goto illegal_insn; | 4308 | goto illegal_insn; |
| 4312 | save_state(dc, cpu_cond); | 4309 | save_state(dc, cpu_cond); |
| 4313 | - gen_ldda_asi(cpu_tmp0, cpu_val, cpu_addr, insn); | ||
| 4314 | - gen_movl_TN_reg(rd + 1, cpu_tmp0); | ||
| 4315 | - break; | 4310 | + gen_ldda_asi(cpu_val, cpu_addr, insn, rd); |
| 4311 | + goto skip_move; | ||
| 4316 | case 0x19: /* load signed byte alternate */ | 4312 | case 0x19: /* load signed byte alternate */ |
| 4317 | #ifndef TARGET_SPARC64 | 4313 | #ifndef TARGET_SPARC64 |
| 4318 | if (IS_IMM) | 4314 | if (IS_IMM) |
| @@ -4403,7 +4399,7 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -4403,7 +4399,7 @@ static void disas_sparc_insn(DisasContext * dc) | ||
| 4403 | goto illegal_insn; | 4399 | goto illegal_insn; |
| 4404 | } | 4400 | } |
| 4405 | gen_movl_TN_reg(rd, cpu_val); | 4401 | gen_movl_TN_reg(rd, cpu_val); |
| 4406 | -#ifdef TARGET_SPARC64 | 4402 | +#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) |
| 4407 | skip_move: ; | 4403 | skip_move: ; |
| 4408 | #endif | 4404 | #endif |
| 4409 | } else if (xop >= 0x20 && xop < 0x24) { | 4405 | } else if (xop >= 0x20 && xop < 0x24) { |