Revision c2bc0e38 target-sparc/op_helper.c

b/target-sparc/op_helper.c
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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;

Also available in: Unified diff