Commit c2bc0e388016a8a2a47c35334f1c11c85901bedc
1 parent
48318011
Remove someexplicit alignment checks (initial patch by Fabrice Bellard)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4431 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
112 additions
and
98 deletions
target-sparc/op_helper.c
| ... | ... | @@ -33,6 +33,12 @@ do { printf("ASI: " fmt , ##args); } while (0) |
| 33 | 33 | #define DPRINTF_ASI(fmt, args...) do {} while (0) |
| 34 | 34 | #endif |
| 35 | 35 | |
| 36 | +#ifdef TARGET_ABI32 | |
| 37 | +#define ABI32_MASK(addr) do { (addr) &= 0xffffffffULL; } while (0) | |
| 38 | +#else | |
| 39 | +#define ABI32_MASK(addr) do {} while (0) | |
| 40 | +#endif | |
| 41 | + | |
| 36 | 42 | void raise_exception(int tt) |
| 37 | 43 | { |
| 38 | 44 | env->exception_index = tt; |
| ... | ... | @@ -55,8 +61,13 @@ void helper_trapcc(target_ulong nb_trap, target_ulong do_trap) |
| 55 | 61 | |
| 56 | 62 | void helper_check_align(target_ulong addr, uint32_t align) |
| 57 | 63 | { |
| 58 | - if (addr & align) | |
| 64 | + if (addr & align) { | |
| 65 | +#ifdef DEBUG_UNALIGNED | |
| 66 | + printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx | |
| 67 | + "\n", addr, env->pc); | |
| 68 | +#endif | |
| 59 | 69 | raise_exception(TT_UNALIGNED); |
| 70 | + } | |
| 60 | 71 | } |
| 61 | 72 | |
| 62 | 73 | #define F_HELPER(name, p) void helper_f##name##p(void) |
| ... | ... | @@ -832,6 +843,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) |
| 832 | 843 | uint32_t last_addr = addr; |
| 833 | 844 | #endif |
| 834 | 845 | |
| 846 | + helper_check_align(addr, size - 1); | |
| 835 | 847 | switch (asi) { |
| 836 | 848 | case 2: /* SuperSparc MXCC registers */ |
| 837 | 849 | switch (addr) { |
| ... | ... | @@ -1030,6 +1042,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) |
| 1030 | 1042 | |
| 1031 | 1043 | void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size) |
| 1032 | 1044 | { |
| 1045 | + helper_check_align(addr, size - 1); | |
| 1033 | 1046 | switch(asi) { |
| 1034 | 1047 | case 2: /* SuperSparc MXCC registers */ |
| 1035 | 1048 | switch (addr) { |
| ... | ... | @@ -1335,6 +1348,9 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) |
| 1335 | 1348 | if (asi < 0x80) |
| 1336 | 1349 | raise_exception(TT_PRIV_ACT); |
| 1337 | 1350 | |
| 1351 | + helper_check_align(addr, size - 1); | |
| 1352 | + ABI32_MASK(addr); | |
| 1353 | + | |
| 1338 | 1354 | switch (asi) { |
| 1339 | 1355 | case 0x80: // Primary |
| 1340 | 1356 | case 0x82: // Primary no-fault |
| ... | ... | @@ -1421,6 +1437,9 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) |
| 1421 | 1437 | if (asi < 0x80) |
| 1422 | 1438 | raise_exception(TT_PRIV_ACT); |
| 1423 | 1439 | |
| 1440 | + helper_check_align(addr, size - 1); | |
| 1441 | + ABI32_MASK(addr); | |
| 1442 | + | |
| 1424 | 1443 | /* Convert to little endian */ |
| 1425 | 1444 | switch (asi) { |
| 1426 | 1445 | case 0x88: // Primary LE |
| ... | ... | @@ -1491,6 +1510,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) |
| 1491 | 1510 | || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) |
| 1492 | 1511 | raise_exception(TT_PRIV_ACT); |
| 1493 | 1512 | |
| 1513 | + helper_check_align(addr, size - 1); | |
| 1494 | 1514 | switch (asi) { |
| 1495 | 1515 | case 0x10: // As if user primary |
| 1496 | 1516 | case 0x18: // As if user primary LE |
| ... | ... | @@ -1714,6 +1734,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) |
| 1714 | 1734 | || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV))) |
| 1715 | 1735 | raise_exception(TT_PRIV_ACT); |
| 1716 | 1736 | |
| 1737 | + helper_check_align(addr, size - 1); | |
| 1717 | 1738 | /* Convert to little endian */ |
| 1718 | 1739 | switch (asi) { |
| 1719 | 1740 | case 0x0c: // Nucleus Little Endian (LE) |
| ... | ... | @@ -2009,6 +2030,7 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) |
| 2009 | 2030 | unsigned int i; |
| 2010 | 2031 | target_ulong val; |
| 2011 | 2032 | |
| 2033 | + helper_check_align(addr, 3); | |
| 2012 | 2034 | switch (asi) { |
| 2013 | 2035 | case 0xf0: // Block load primary |
| 2014 | 2036 | case 0xf1: // Block load secondary |
| ... | ... | @@ -2018,10 +2040,7 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) |
| 2018 | 2040 | raise_exception(TT_ILL_INSN); |
| 2019 | 2041 | return; |
| 2020 | 2042 | } |
| 2021 | - if (addr & 0x3f) { | |
| 2022 | - raise_exception(TT_UNALIGNED); | |
| 2023 | - return; | |
| 2024 | - } | |
| 2043 | + helper_check_align(addr, 0x3f); | |
| 2025 | 2044 | for (i = 0; i < 16; i++) { |
| 2026 | 2045 | *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, 0); |
| 2027 | 2046 | addr += 4; |
| ... | ... | @@ -2052,6 +2071,7 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd) |
| 2052 | 2071 | unsigned int i; |
| 2053 | 2072 | target_ulong val = 0; |
| 2054 | 2073 | |
| 2074 | + helper_check_align(addr, 3); | |
| 2055 | 2075 | switch (asi) { |
| 2056 | 2076 | case 0xf0: // Block store primary |
| 2057 | 2077 | case 0xf1: // Block store secondary |
| ... | ... | @@ -2061,10 +2081,7 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd) |
| 2061 | 2081 | raise_exception(TT_ILL_INSN); |
| 2062 | 2082 | return; |
| 2063 | 2083 | } |
| 2064 | - if (addr & 0x3f) { | |
| 2065 | - raise_exception(TT_UNALIGNED); | |
| 2066 | - return; | |
| 2067 | - } | |
| 2084 | + helper_check_align(addr, 0x3f); | |
| 2068 | 2085 | for (i = 0; i < 16; i++) { |
| 2069 | 2086 | val = *(uint32_t *)&env->fpr[rd++]; |
| 2070 | 2087 | helper_st_asi(addr, val, asi & 0x8f, 4); |
| ... | ... | @@ -2183,55 +2200,53 @@ uint64_t helper_pack64(target_ulong high, target_ulong low) |
| 2183 | 2200 | return ((uint64_t)high << 32) | (uint64_t)(low & 0xffffffff); |
| 2184 | 2201 | } |
| 2185 | 2202 | |
| 2186 | -#ifdef TARGET_ABI32 | |
| 2187 | -#define ADDR(x) ((x) & 0xffffffff) | |
| 2188 | -#else | |
| 2189 | -#define ADDR(x) (x) | |
| 2190 | -#endif | |
| 2191 | - | |
| 2192 | 2203 | void helper_stdf(target_ulong addr, int mem_idx) |
| 2193 | 2204 | { |
| 2205 | + helper_check_align(addr, 7); | |
| 2194 | 2206 | #if !defined(CONFIG_USER_ONLY) |
| 2195 | 2207 | switch (mem_idx) { |
| 2196 | 2208 | case 0: |
| 2197 | - stfq_user(ADDR(addr), DT0); | |
| 2209 | + stfq_user(addr, DT0); | |
| 2198 | 2210 | break; |
| 2199 | 2211 | case 1: |
| 2200 | - stfq_kernel(ADDR(addr), DT0); | |
| 2212 | + stfq_kernel(addr, DT0); | |
| 2201 | 2213 | break; |
| 2202 | 2214 | #ifdef TARGET_SPARC64 |
| 2203 | 2215 | case 2: |
| 2204 | - stfq_hypv(ADDR(addr), DT0); | |
| 2216 | + stfq_hypv(addr, DT0); | |
| 2205 | 2217 | break; |
| 2206 | 2218 | #endif |
| 2207 | 2219 | default: |
| 2208 | 2220 | break; |
| 2209 | 2221 | } |
| 2210 | 2222 | #else |
| 2211 | - stfq_raw(ADDR(addr), DT0); | |
| 2223 | + ABI32_MASK(addr); | |
| 2224 | + stfq_raw(addr, DT0); | |
| 2212 | 2225 | #endif |
| 2213 | 2226 | } |
| 2214 | 2227 | |
| 2215 | 2228 | void helper_lddf(target_ulong addr, int mem_idx) |
| 2216 | 2229 | { |
| 2230 | + helper_check_align(addr, 7); | |
| 2217 | 2231 | #if !defined(CONFIG_USER_ONLY) |
| 2218 | 2232 | switch (mem_idx) { |
| 2219 | 2233 | case 0: |
| 2220 | - DT0 = ldfq_user(ADDR(addr)); | |
| 2234 | + DT0 = ldfq_user(addr); | |
| 2221 | 2235 | break; |
| 2222 | 2236 | case 1: |
| 2223 | - DT0 = ldfq_kernel(ADDR(addr)); | |
| 2237 | + DT0 = ldfq_kernel(addr); | |
| 2224 | 2238 | break; |
| 2225 | 2239 | #ifdef TARGET_SPARC64 |
| 2226 | 2240 | case 2: |
| 2227 | - DT0 = ldfq_hypv(ADDR(addr)); | |
| 2241 | + DT0 = ldfq_hypv(addr); | |
| 2228 | 2242 | break; |
| 2229 | 2243 | #endif |
| 2230 | 2244 | default: |
| 2231 | 2245 | break; |
| 2232 | 2246 | } |
| 2233 | 2247 | #else |
| 2234 | - DT0 = ldfq_raw(ADDR(addr)); | |
| 2248 | + ABI32_MASK(addr); | |
| 2249 | + DT0 = ldfq_raw(addr); | |
| 2235 | 2250 | #endif |
| 2236 | 2251 | } |
| 2237 | 2252 | |
| ... | ... | @@ -2240,22 +2255,23 @@ void helper_ldqf(target_ulong addr, int mem_idx) |
| 2240 | 2255 | // XXX add 128 bit load |
| 2241 | 2256 | CPU_QuadU u; |
| 2242 | 2257 | |
| 2258 | + helper_check_align(addr, 7); | |
| 2243 | 2259 | #if !defined(CONFIG_USER_ONLY) |
| 2244 | 2260 | switch (mem_idx) { |
| 2245 | 2261 | case 0: |
| 2246 | - u.ll.upper = ldq_user(ADDR(addr)); | |
| 2247 | - u.ll.lower = ldq_user(ADDR(addr + 8)); | |
| 2262 | + u.ll.upper = ldq_user(addr); | |
| 2263 | + u.ll.lower = ldq_user(addr + 8); | |
| 2248 | 2264 | QT0 = u.q; |
| 2249 | 2265 | break; |
| 2250 | 2266 | case 1: |
| 2251 | - u.ll.upper = ldq_kernel(ADDR(addr)); | |
| 2252 | - u.ll.lower = ldq_kernel(ADDR(addr + 8)); | |
| 2267 | + u.ll.upper = ldq_kernel(addr); | |
| 2268 | + u.ll.lower = ldq_kernel(addr + 8); | |
| 2253 | 2269 | QT0 = u.q; |
| 2254 | 2270 | break; |
| 2255 | 2271 | #ifdef TARGET_SPARC64 |
| 2256 | 2272 | case 2: |
| 2257 | - u.ll.upper = ldq_hypv(ADDR(addr)); | |
| 2258 | - u.ll.lower = ldq_hypv(ADDR(addr + 8)); | |
| 2273 | + u.ll.upper = ldq_hypv(addr); | |
| 2274 | + u.ll.lower = ldq_hypv(addr + 8); | |
| 2259 | 2275 | QT0 = u.q; |
| 2260 | 2276 | break; |
| 2261 | 2277 | #endif |
| ... | ... | @@ -2263,8 +2279,9 @@ void helper_ldqf(target_ulong addr, int mem_idx) |
| 2263 | 2279 | break; |
| 2264 | 2280 | } |
| 2265 | 2281 | #else |
| 2266 | - u.ll.upper = ldq_raw(ADDR(addr)); | |
| 2267 | - u.ll.lower = ldq_raw(ADDR(addr + 8)); | |
| 2282 | + ABI32_MASK(addr); | |
| 2283 | + u.ll.upper = ldq_raw(addr); | |
| 2284 | + u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL); | |
| 2268 | 2285 | QT0 = u.q; |
| 2269 | 2286 | #endif |
| 2270 | 2287 | } |
| ... | ... | @@ -2274,23 +2291,24 @@ void helper_stqf(target_ulong addr, int mem_idx) |
| 2274 | 2291 | // XXX add 128 bit store |
| 2275 | 2292 | CPU_QuadU u; |
| 2276 | 2293 | |
| 2294 | + helper_check_align(addr, 7); | |
| 2277 | 2295 | #if !defined(CONFIG_USER_ONLY) |
| 2278 | 2296 | switch (mem_idx) { |
| 2279 | 2297 | case 0: |
| 2280 | 2298 | u.q = QT0; |
| 2281 | - stq_user(ADDR(addr), u.ll.upper); | |
| 2282 | - stq_user(ADDR(addr + 8), u.ll.lower); | |
| 2299 | + stq_user(addr, u.ll.upper); | |
| 2300 | + stq_user(addr + 8, u.ll.lower); | |
| 2283 | 2301 | break; |
| 2284 | 2302 | case 1: |
| 2285 | 2303 | u.q = QT0; |
| 2286 | - stq_kernel(ADDR(addr), u.ll.upper); | |
| 2287 | - stq_kernel(ADDR(addr + 8), u.ll.lower); | |
| 2304 | + stq_kernel(addr, u.ll.upper); | |
| 2305 | + stq_kernel(addr + 8, u.ll.lower); | |
| 2288 | 2306 | break; |
| 2289 | 2307 | #ifdef TARGET_SPARC64 |
| 2290 | 2308 | case 2: |
| 2291 | 2309 | u.q = QT0; |
| 2292 | - stq_hypv(ADDR(addr), u.ll.upper); | |
| 2293 | - stq_hypv(ADDR(addr + 8), u.ll.lower); | |
| 2310 | + stq_hypv(addr, u.ll.upper); | |
| 2311 | + stq_hypv(addr + 8, u.ll.lower); | |
| 2294 | 2312 | break; |
| 2295 | 2313 | #endif |
| 2296 | 2314 | default: |
| ... | ... | @@ -2298,13 +2316,12 @@ void helper_stqf(target_ulong addr, int mem_idx) |
| 2298 | 2316 | } |
| 2299 | 2317 | #else |
| 2300 | 2318 | u.q = QT0; |
| 2301 | - stq_raw(ADDR(addr), u.ll.upper); | |
| 2302 | - stq_raw(ADDR(addr + 8), u.ll.lower); | |
| 2319 | + ABI32_MASK(addr); | |
| 2320 | + stq_raw(addr, u.ll.upper); | |
| 2321 | + stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower); | |
| 2303 | 2322 | #endif |
| 2304 | 2323 | } |
| 2305 | 2324 | |
| 2306 | -#undef ADDR | |
| 2307 | - | |
| 2308 | 2325 | void helper_ldfsr(void) |
| 2309 | 2326 | { |
| 2310 | 2327 | int rnd_mode; |
| ... | ... | @@ -2833,12 +2850,32 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user, |
| 2833 | 2850 | #define SHIFT 3 |
| 2834 | 2851 | #include "softmmu_template.h" |
| 2835 | 2852 | |
| 2853 | +/* XXX: make it generic ? */ | |
| 2854 | +static void cpu_restore_state2(void *retaddr) | |
| 2855 | +{ | |
| 2856 | + TranslationBlock *tb; | |
| 2857 | + unsigned long pc; | |
| 2858 | + | |
| 2859 | + if (retaddr) { | |
| 2860 | + /* now we have a real cpu fault */ | |
| 2861 | + pc = (unsigned long)retaddr; | |
| 2862 | + tb = tb_find_pc(pc); | |
| 2863 | + if (tb) { | |
| 2864 | + /* the PC is inside the translated code. It means that we have | |
| 2865 | + a virtual CPU fault */ | |
| 2866 | + cpu_restore_state(tb, env, pc, (void *)(long)env->cond); | |
| 2867 | + } | |
| 2868 | + } | |
| 2869 | +} | |
| 2870 | + | |
| 2836 | 2871 | static void do_unaligned_access(target_ulong addr, int is_write, int is_user, |
| 2837 | 2872 | void *retaddr) |
| 2838 | 2873 | { |
| 2839 | 2874 | #ifdef DEBUG_UNALIGNED |
| 2840 | - printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc); | |
| 2875 | + printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx | |
| 2876 | + "\n", addr, env->pc); | |
| 2841 | 2877 | #endif |
| 2878 | + cpu_restore_state2(retaddr); | |
| 2842 | 2879 | raise_exception(TT_UNALIGNED); |
| 2843 | 2880 | } |
| 2844 | 2881 | |
| ... | ... | @@ -2848,9 +2885,7 @@ static void do_unaligned_access(target_ulong addr, int is_write, int is_user, |
| 2848 | 2885 | /* XXX: fix it to restore all registers */ |
| 2849 | 2886 | void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) |
| 2850 | 2887 | { |
| 2851 | - TranslationBlock *tb; | |
| 2852 | 2888 | int ret; |
| 2853 | - unsigned long pc; | |
| 2854 | 2889 | CPUState *saved_env; |
| 2855 | 2890 | |
| 2856 | 2891 | /* XXX: hack to restore env in all cases, even if not called from |
| ... | ... | @@ -2860,16 +2895,7 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr) |
| 2860 | 2895 | |
| 2861 | 2896 | ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1); |
| 2862 | 2897 | if (ret) { |
| 2863 | - if (retaddr) { | |
| 2864 | - /* now we have a real cpu fault */ | |
| 2865 | - pc = (unsigned long)retaddr; | |
| 2866 | - tb = tb_find_pc(pc); | |
| 2867 | - if (tb) { | |
| 2868 | - /* the PC is inside the translated code. It means that we have | |
| 2869 | - a virtual CPU fault */ | |
| 2870 | - cpu_restore_state(tb, env, pc, (void *)env->cond); | |
| 2871 | - } | |
| 2872 | - } | |
| 2898 | + cpu_restore_state2(retaddr); | |
| 2873 | 2899 | cpu_loop_exit(); |
| 2874 | 2900 | } |
| 2875 | 2901 | env = saved_env; | ... | ... |
target-sparc/translate.c
| ... | ... | @@ -3945,7 +3945,6 @@ static void disas_sparc_insn(DisasContext * dc) |
| 3945 | 3945 | { |
| 3946 | 3946 | unsigned int xop = GET_FIELD(insn, 7, 12); |
| 3947 | 3947 | |
| 3948 | - save_state(dc, cpu_cond); | |
| 3949 | 3948 | cpu_src1 = get_src1(insn, cpu_src1); |
| 3950 | 3949 | if (xop == 0x3c || xop == 0x3e) |
| 3951 | 3950 | { |
| ... | ... | @@ -3968,7 +3967,6 @@ static void disas_sparc_insn(DisasContext * dc) |
| 3968 | 3967 | (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) { |
| 3969 | 3968 | switch (xop) { |
| 3970 | 3969 | case 0x0: /* load unsigned word */ |
| 3971 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 3972 | 3970 | ABI32_MASK(cpu_addr); |
| 3973 | 3971 | tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx); |
| 3974 | 3972 | break; |
| ... | ... | @@ -3977,7 +3975,6 @@ static void disas_sparc_insn(DisasContext * dc) |
| 3977 | 3975 | tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx); |
| 3978 | 3976 | break; |
| 3979 | 3977 | case 0x2: /* load unsigned halfword */ |
| 3980 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(1)); | |
| 3981 | 3978 | ABI32_MASK(cpu_addr); |
| 3982 | 3979 | tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx); |
| 3983 | 3980 | break; |
| ... | ... | @@ -3985,7 +3982,9 @@ static void disas_sparc_insn(DisasContext * dc) |
| 3985 | 3982 | if (rd & 1) |
| 3986 | 3983 | goto illegal_insn; |
| 3987 | 3984 | else { |
| 3988 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); | |
| 3985 | + save_state(dc, cpu_cond); | |
| 3986 | + tcg_gen_helper_0_2(helper_check_align, cpu_addr, | |
| 3987 | + tcg_const_i32(7)); // XXX remove | |
| 3989 | 3988 | ABI32_MASK(cpu_addr); |
| 3990 | 3989 | tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx); |
| 3991 | 3990 | tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64); |
| ... | ... | @@ -4001,7 +4000,6 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4001 | 4000 | tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx); |
| 4002 | 4001 | break; |
| 4003 | 4002 | case 0xa: /* load signed halfword */ |
| 4004 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(1)); | |
| 4005 | 4003 | ABI32_MASK(cpu_addr); |
| 4006 | 4004 | tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx); |
| 4007 | 4005 | break; |
| ... | ... | @@ -4012,7 +4010,6 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4012 | 4010 | break; |
| 4013 | 4011 | case 0x0f: /* swap register with memory. Also atomically */ |
| 4014 | 4012 | CHECK_IU_FEATURE(dc, SWAP); |
| 4015 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4016 | 4013 | gen_movl_reg_TN(rd, cpu_val); |
| 4017 | 4014 | ABI32_MASK(cpu_addr); |
| 4018 | 4015 | tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx); |
| ... | ... | @@ -4027,7 +4024,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4027 | 4024 | if (!supervisor(dc)) |
| 4028 | 4025 | goto priv_insn; |
| 4029 | 4026 | #endif |
| 4030 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4027 | + save_state(dc, cpu_cond); | |
| 4031 | 4028 | gen_ld_asi(cpu_val, cpu_addr, insn, 4, 0); |
| 4032 | 4029 | break; |
| 4033 | 4030 | case 0x11: /* load unsigned byte alternate */ |
| ... | ... | @@ -4037,6 +4034,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4037 | 4034 | if (!supervisor(dc)) |
| 4038 | 4035 | goto priv_insn; |
| 4039 | 4036 | #endif |
| 4037 | + save_state(dc, cpu_cond); | |
| 4040 | 4038 | gen_ld_asi(cpu_val, cpu_addr, insn, 1, 0); |
| 4041 | 4039 | break; |
| 4042 | 4040 | case 0x12: /* load unsigned halfword alternate */ |
| ... | ... | @@ -4046,7 +4044,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4046 | 4044 | if (!supervisor(dc)) |
| 4047 | 4045 | goto priv_insn; |
| 4048 | 4046 | #endif |
| 4049 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(1)); | |
| 4047 | + save_state(dc, cpu_cond); | |
| 4050 | 4048 | gen_ld_asi(cpu_val, cpu_addr, insn, 2, 0); |
| 4051 | 4049 | break; |
| 4052 | 4050 | case 0x13: /* load double word alternate */ |
| ... | ... | @@ -4058,7 +4056,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4058 | 4056 | #endif |
| 4059 | 4057 | if (rd & 1) |
| 4060 | 4058 | goto illegal_insn; |
| 4061 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); | |
| 4059 | + save_state(dc, cpu_cond); | |
| 4062 | 4060 | gen_ldda_asi(cpu_tmp0, cpu_val, cpu_addr, insn); |
| 4063 | 4061 | gen_movl_TN_reg(rd + 1, cpu_tmp0); |
| 4064 | 4062 | break; |
| ... | ... | @@ -4069,6 +4067,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4069 | 4067 | if (!supervisor(dc)) |
| 4070 | 4068 | goto priv_insn; |
| 4071 | 4069 | #endif |
| 4070 | + save_state(dc, cpu_cond); | |
| 4072 | 4071 | gen_ld_asi(cpu_val, cpu_addr, insn, 1, 1); |
| 4073 | 4072 | break; |
| 4074 | 4073 | case 0x1a: /* load signed halfword alternate */ |
| ... | ... | @@ -4078,7 +4077,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4078 | 4077 | if (!supervisor(dc)) |
| 4079 | 4078 | goto priv_insn; |
| 4080 | 4079 | #endif |
| 4081 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(1)); | |
| 4080 | + save_state(dc, cpu_cond); | |
| 4082 | 4081 | gen_ld_asi(cpu_val, cpu_addr, insn, 2, 1); |
| 4083 | 4082 | break; |
| 4084 | 4083 | case 0x1d: /* ldstuba -- XXX: should be atomically */ |
| ... | ... | @@ -4088,6 +4087,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4088 | 4087 | if (!supervisor(dc)) |
| 4089 | 4088 | goto priv_insn; |
| 4090 | 4089 | #endif |
| 4090 | + save_state(dc, cpu_cond); | |
| 4091 | 4091 | gen_ldstub_asi(cpu_val, cpu_addr, insn); |
| 4092 | 4092 | break; |
| 4093 | 4093 | case 0x1f: /* swap reg with alt. memory. Also atomically */ |
| ... | ... | @@ -4098,7 +4098,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4098 | 4098 | if (!supervisor(dc)) |
| 4099 | 4099 | goto priv_insn; |
| 4100 | 4100 | #endif |
| 4101 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4101 | + save_state(dc, cpu_cond); | |
| 4102 | 4102 | gen_movl_reg_TN(rd, cpu_val); |
| 4103 | 4103 | gen_swap_asi(cpu_val, cpu_addr, insn); |
| 4104 | 4104 | break; |
| ... | ... | @@ -4112,38 +4112,36 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4112 | 4112 | #endif |
| 4113 | 4113 | #ifdef TARGET_SPARC64 |
| 4114 | 4114 | case 0x08: /* V9 ldsw */ |
| 4115 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4116 | 4115 | ABI32_MASK(cpu_addr); |
| 4117 | 4116 | tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx); |
| 4118 | 4117 | break; |
| 4119 | 4118 | case 0x0b: /* V9 ldx */ |
| 4120 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); | |
| 4121 | 4119 | ABI32_MASK(cpu_addr); |
| 4122 | 4120 | tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx); |
| 4123 | 4121 | break; |
| 4124 | 4122 | case 0x18: /* V9 ldswa */ |
| 4125 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4123 | + save_state(dc, cpu_cond); | |
| 4126 | 4124 | gen_ld_asi(cpu_val, cpu_addr, insn, 4, 1); |
| 4127 | 4125 | break; |
| 4128 | 4126 | case 0x1b: /* V9 ldxa */ |
| 4129 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); | |
| 4127 | + save_state(dc, cpu_cond); | |
| 4130 | 4128 | gen_ld_asi(cpu_val, cpu_addr, insn, 8, 0); |
| 4131 | 4129 | break; |
| 4132 | 4130 | case 0x2d: /* V9 prefetch, no effect */ |
| 4133 | 4131 | goto skip_move; |
| 4134 | 4132 | case 0x30: /* V9 ldfa */ |
| 4135 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4133 | + save_state(dc, cpu_cond); | |
| 4136 | 4134 | gen_ldf_asi(cpu_addr, insn, 4, rd); |
| 4137 | 4135 | goto skip_move; |
| 4138 | 4136 | case 0x33: /* V9 lddfa */ |
| 4139 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4137 | + save_state(dc, cpu_cond); | |
| 4140 | 4138 | gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd)); |
| 4141 | 4139 | goto skip_move; |
| 4142 | 4140 | case 0x3d: /* V9 prefetcha, no effect */ |
| 4143 | 4141 | goto skip_move; |
| 4144 | 4142 | case 0x32: /* V9 ldqfa */ |
| 4145 | 4143 | CHECK_FPU_FEATURE(dc, FLOAT128); |
| 4146 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4144 | + save_state(dc, cpu_cond); | |
| 4147 | 4145 | gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd)); |
| 4148 | 4146 | goto skip_move; |
| 4149 | 4147 | #endif |
| ... | ... | @@ -4157,15 +4155,16 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4157 | 4155 | } else if (xop >= 0x20 && xop < 0x24) { |
| 4158 | 4156 | if (gen_trap_ifnofpu(dc, cpu_cond)) |
| 4159 | 4157 | goto jmp_insn; |
| 4158 | + save_state(dc, cpu_cond); | |
| 4160 | 4159 | switch (xop) { |
| 4161 | 4160 | case 0x20: /* load fpreg */ |
| 4162 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4161 | + ABI32_MASK(cpu_addr); | |
| 4163 | 4162 | tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx); |
| 4164 | 4163 | tcg_gen_st_i32(cpu_tmp32, cpu_env, |
| 4165 | 4164 | offsetof(CPUState, fpr[rd])); |
| 4166 | 4165 | break; |
| 4167 | 4166 | case 0x21: /* load fsr */ |
| 4168 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4167 | + ABI32_MASK(cpu_addr); | |
| 4169 | 4168 | tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx); |
| 4170 | 4169 | tcg_gen_st_i32(cpu_tmp32, cpu_env, |
| 4171 | 4170 | offsetof(CPUState, ft0)); |
| ... | ... | @@ -4173,14 +4172,10 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4173 | 4172 | break; |
| 4174 | 4173 | case 0x22: /* load quad fpreg */ |
| 4175 | 4174 | CHECK_FPU_FEATURE(dc, FLOAT128); |
| 4176 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, | |
| 4177 | - tcg_const_i32(7)); | |
| 4178 | 4175 | tcg_gen_helper_0_2(helper_ldqf, cpu_addr, dc->mem_idx); |
| 4179 | 4176 | gen_op_store_QT0_fpr(QFPREG(rd)); |
| 4180 | 4177 | break; |
| 4181 | 4178 | case 0x23: /* load double fpreg */ |
| 4182 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, | |
| 4183 | - tcg_const_i32(7)); | |
| 4184 | 4179 | tcg_gen_helper_0_2(helper_lddf, cpu_addr, |
| 4185 | 4180 | tcg_const_i32(dc->mem_idx)); |
| 4186 | 4181 | gen_op_store_DT0_fpr(DFPREG(rd)); |
| ... | ... | @@ -4193,7 +4188,6 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4193 | 4188 | gen_movl_reg_TN(rd, cpu_val); |
| 4194 | 4189 | switch (xop) { |
| 4195 | 4190 | case 0x4: /* store word */ |
| 4196 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4197 | 4191 | ABI32_MASK(cpu_addr); |
| 4198 | 4192 | tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx); |
| 4199 | 4193 | break; |
| ... | ... | @@ -4202,7 +4196,6 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4202 | 4196 | tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx); |
| 4203 | 4197 | break; |
| 4204 | 4198 | case 0x6: /* store halfword */ |
| 4205 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(1)); | |
| 4206 | 4199 | ABI32_MASK(cpu_addr); |
| 4207 | 4200 | tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx); |
| 4208 | 4201 | break; |
| ... | ... | @@ -4212,7 +4205,10 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4212 | 4205 | else { |
| 4213 | 4206 | TCGv r_low; |
| 4214 | 4207 | |
| 4215 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); | |
| 4208 | + save_state(dc, cpu_cond); | |
| 4209 | + ABI32_MASK(cpu_addr); | |
| 4210 | + tcg_gen_helper_0_2(helper_check_align, cpu_addr, | |
| 4211 | + tcg_const_i32(7)); // XXX remove | |
| 4216 | 4212 | r_low = tcg_temp_new(TCG_TYPE_I32); |
| 4217 | 4213 | gen_movl_reg_TN(rd + 1, r_low); |
| 4218 | 4214 | tcg_gen_helper_1_2(helper_pack64, cpu_tmp64, cpu_val, |
| ... | ... | @@ -4228,7 +4224,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4228 | 4224 | if (!supervisor(dc)) |
| 4229 | 4225 | goto priv_insn; |
| 4230 | 4226 | #endif |
| 4231 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4227 | + save_state(dc, cpu_cond); | |
| 4232 | 4228 | gen_st_asi(cpu_val, cpu_addr, insn, 4); |
| 4233 | 4229 | break; |
| 4234 | 4230 | case 0x15: /* store byte alternate */ |
| ... | ... | @@ -4238,6 +4234,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4238 | 4234 | if (!supervisor(dc)) |
| 4239 | 4235 | goto priv_insn; |
| 4240 | 4236 | #endif |
| 4237 | + save_state(dc, cpu_cond); | |
| 4241 | 4238 | gen_st_asi(cpu_val, cpu_addr, insn, 1); |
| 4242 | 4239 | break; |
| 4243 | 4240 | case 0x16: /* store halfword alternate */ |
| ... | ... | @@ -4247,7 +4244,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4247 | 4244 | if (!supervisor(dc)) |
| 4248 | 4245 | goto priv_insn; |
| 4249 | 4246 | #endif |
| 4250 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(1)); | |
| 4247 | + save_state(dc, cpu_cond); | |
| 4251 | 4248 | gen_st_asi(cpu_val, cpu_addr, insn, 2); |
| 4252 | 4249 | break; |
| 4253 | 4250 | case 0x17: /* store double word alternate */ |
| ... | ... | @@ -4260,19 +4257,18 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4260 | 4257 | if (rd & 1) |
| 4261 | 4258 | goto illegal_insn; |
| 4262 | 4259 | else { |
| 4263 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); | |
| 4260 | + save_state(dc, cpu_cond); | |
| 4264 | 4261 | gen_stda_asi(cpu_val, cpu_addr, insn, rd); |
| 4265 | 4262 | } |
| 4266 | 4263 | break; |
| 4267 | 4264 | #endif |
| 4268 | 4265 | #ifdef TARGET_SPARC64 |
| 4269 | 4266 | case 0x0e: /* V9 stx */ |
| 4270 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); | |
| 4271 | 4267 | ABI32_MASK(cpu_addr); |
| 4272 | 4268 | tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx); |
| 4273 | 4269 | break; |
| 4274 | 4270 | case 0x1e: /* V9 stxa */ |
| 4275 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); | |
| 4271 | + save_state(dc, cpu_cond); | |
| 4276 | 4272 | gen_st_asi(cpu_val, cpu_addr, insn, 8); |
| 4277 | 4273 | break; |
| 4278 | 4274 | #endif |
| ... | ... | @@ -4282,17 +4278,16 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4282 | 4278 | } else if (xop > 0x23 && xop < 0x28) { |
| 4283 | 4279 | if (gen_trap_ifnofpu(dc, cpu_cond)) |
| 4284 | 4280 | goto jmp_insn; |
| 4281 | + save_state(dc, cpu_cond); | |
| 4285 | 4282 | switch (xop) { |
| 4286 | 4283 | case 0x24: /* store fpreg */ |
| 4287 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4284 | + ABI32_MASK(cpu_addr); | |
| 4288 | 4285 | tcg_gen_ld_i32(cpu_tmp32, cpu_env, |
| 4289 | 4286 | offsetof(CPUState, fpr[rd])); |
| 4290 | 4287 | tcg_gen_qemu_st32(cpu_tmp32, cpu_addr, dc->mem_idx); |
| 4291 | 4288 | break; |
| 4292 | 4289 | case 0x25: /* stfsr, V9 stxfsr */ |
| 4293 | -#ifdef CONFIG_USER_ONLY | |
| 4294 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4295 | -#endif | |
| 4290 | + ABI32_MASK(cpu_addr); | |
| 4296 | 4291 | tcg_gen_helper_0_0(helper_stfsr); |
| 4297 | 4292 | tcg_gen_ld_i32(cpu_tmp32, cpu_env, |
| 4298 | 4293 | offsetof(CPUState, ft0)); |
| ... | ... | @@ -4302,8 +4297,6 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4302 | 4297 | #ifdef TARGET_SPARC64 |
| 4303 | 4298 | /* V9 stqf, store quad fpreg */ |
| 4304 | 4299 | CHECK_FPU_FEATURE(dc, FLOAT128); |
| 4305 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, | |
| 4306 | - tcg_const_i32(7)); | |
| 4307 | 4300 | gen_op_load_fpr_QT0(QFPREG(rd)); |
| 4308 | 4301 | tcg_gen_helper_0_2(helper_stqf, cpu_addr, dc->mem_idx); |
| 4309 | 4302 | break; |
| ... | ... | @@ -4320,8 +4313,6 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4320 | 4313 | #endif |
| 4321 | 4314 | #endif |
| 4322 | 4315 | case 0x27: /* store double fpreg */ |
| 4323 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, | |
| 4324 | - tcg_const_i32(7)); | |
| 4325 | 4316 | gen_op_load_fpr_DT0(DFPREG(rd)); |
| 4326 | 4317 | tcg_gen_helper_0_2(helper_stdf, cpu_addr, |
| 4327 | 4318 | tcg_const_i32(dc->mem_idx)); |
| ... | ... | @@ -4330,10 +4321,10 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4330 | 4321 | goto illegal_insn; |
| 4331 | 4322 | } |
| 4332 | 4323 | } else if (xop > 0x33 && xop < 0x3f) { |
| 4324 | + save_state(dc, cpu_cond); | |
| 4333 | 4325 | switch (xop) { |
| 4334 | 4326 | #ifdef TARGET_SPARC64 |
| 4335 | 4327 | case 0x34: /* V9 stfa */ |
| 4336 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4337 | 4328 | gen_op_load_fpr_FT0(rd); |
| 4338 | 4329 | gen_stf_asi(cpu_addr, insn, 4, rd); |
| 4339 | 4330 | break; |
| ... | ... | @@ -4345,17 +4336,14 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4345 | 4336 | gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd)); |
| 4346 | 4337 | break; |
| 4347 | 4338 | case 0x37: /* V9 stdfa */ |
| 4348 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4349 | 4339 | gen_op_load_fpr_DT0(DFPREG(rd)); |
| 4350 | 4340 | gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd)); |
| 4351 | 4341 | break; |
| 4352 | 4342 | case 0x3c: /* V9 casa */ |
| 4353 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(3)); | |
| 4354 | 4343 | gen_cas_asi(cpu_val, cpu_addr, cpu_val, insn, rd); |
| 4355 | 4344 | gen_movl_TN_reg(rd, cpu_val); |
| 4356 | 4345 | break; |
| 4357 | 4346 | case 0x3e: /* V9 casxa */ |
| 4358 | - tcg_gen_helper_0_2(helper_check_align, cpu_addr, tcg_const_i32(7)); | |
| 4359 | 4347 | gen_casx_asi(cpu_val, cpu_addr, cpu_val, insn, rd); |
| 4360 | 4348 | gen_movl_TN_reg(rd, cpu_val); |
| 4361 | 4349 | break; | ... | ... |