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 | 22 | DEF_HELPER(target_ulong, helper_alignaddr, (target_ulong addr, \ |
23 | 23 | target_ulong offset)) |
24 | 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 | 26 | DEF_HELPER(void, helper_ldf_asi, (target_ulong addr, int asi, int size, int rd)) |
26 | 27 | DEF_HELPER(void, helper_stf_asi, (target_ulong addr, int asi, int size, int rd)) |
27 | 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 | 1634 | } |
1635 | 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 | 1642 | case 0x04: // Nucleus |
1638 | 1643 | case 0x0c: // Nucleus Little Endian (LE) |
1639 | 1644 | case 0x11: // As if user secondary |
1640 | 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 | 1646 | case 0x4a: // UPA config |
1644 | 1647 | case 0x81: // Secondary |
1645 | 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 | 1946 | } |
1944 | 1947 | } |
1945 | 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 | 1954 | case 0x04: // Nucleus |
1947 | 1955 | case 0x0c: // Nucleus Little Endian (LE) |
1948 | 1956 | case 0x11: // As if user secondary |
1949 | 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 | 1958 | case 0x4a: // UPA config |
1953 | 1959 | case 0x81: // Secondary |
1954 | 1960 | case 0x89: // Secondary LE |
... | ... | @@ -2144,6 +2150,53 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) |
2144 | 2150 | } |
2145 | 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 | 2200 | void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) |
2148 | 2201 | { |
2149 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 1828 | tcg_temp_free(r_sign); |
1834 | 1829 | tcg_temp_free(r_size); |
1835 | 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 | 1833 | tcg_gen_shri_i64(cpu_tmp64, cpu_tmp64, 32); |
1838 | 1834 | tcg_gen_trunc_i64_tl(hi, cpu_tmp64); |
1835 | + gen_movl_TN_reg(rd, hi); | |
1839 | 1836 | } |
1840 | 1837 | |
1841 | 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 | 4307 | if (rd & 1) |
4311 | 4308 | goto illegal_insn; |
4312 | 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 | 4312 | case 0x19: /* load signed byte alternate */ |
4317 | 4313 | #ifndef TARGET_SPARC64 |
4318 | 4314 | if (IS_IMM) |
... | ... | @@ -4403,7 +4399,7 @@ static void disas_sparc_insn(DisasContext * dc) |
4403 | 4399 | goto illegal_insn; |
4404 | 4400 | } |
4405 | 4401 | gen_movl_TN_reg(rd, cpu_val); |
4406 | -#ifdef TARGET_SPARC64 | |
4402 | +#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) | |
4407 | 4403 | skip_move: ; |
4408 | 4404 | #endif |
4409 | 4405 | } else if (xop >= 0x20 && xop < 0x24) { | ... | ... |