Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 060718c1

History | View | Annotate | Download (104.9 kB)

1 e8af50a3 bellard
#include "exec.h"
2 eed152bb blueswir1
#include "host-utils.h"
3 1a2fb1c0 blueswir1
#include "helper.h"
4 0828b448 blueswir1
#if !defined(CONFIG_USER_ONLY)
5 0828b448 blueswir1
#include "softmmu_exec.h"
6 0828b448 blueswir1
#endif /* !defined(CONFIG_USER_ONLY) */
7 e8af50a3 bellard
8 e80cfcfc bellard
//#define DEBUG_MMU
9 952a328f blueswir1
//#define DEBUG_MXCC
10 94554550 blueswir1
//#define DEBUG_UNALIGNED
11 6c36d3fa blueswir1
//#define DEBUG_UNASSIGNED
12 8543e2cf blueswir1
//#define DEBUG_ASI
13 d81fd722 blueswir1
//#define DEBUG_PCALL
14 7e8695ed Igor V. Kovalenko
//#define DEBUG_PSTATE
15 e80cfcfc bellard
16 952a328f blueswir1
#ifdef DEBUG_MMU
17 001faf32 Blue Swirl
#define DPRINTF_MMU(fmt, ...)                                   \
18 001faf32 Blue Swirl
    do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0)
19 952a328f blueswir1
#else
20 001faf32 Blue Swirl
#define DPRINTF_MMU(fmt, ...) do {} while (0)
21 952a328f blueswir1
#endif
22 952a328f blueswir1
23 952a328f blueswir1
#ifdef DEBUG_MXCC
24 001faf32 Blue Swirl
#define DPRINTF_MXCC(fmt, ...)                                  \
25 001faf32 Blue Swirl
    do { printf("MXCC: " fmt , ## __VA_ARGS__); } while (0)
26 952a328f blueswir1
#else
27 001faf32 Blue Swirl
#define DPRINTF_MXCC(fmt, ...) do {} while (0)
28 952a328f blueswir1
#endif
29 952a328f blueswir1
30 8543e2cf blueswir1
#ifdef DEBUG_ASI
31 001faf32 Blue Swirl
#define DPRINTF_ASI(fmt, ...)                                   \
32 001faf32 Blue Swirl
    do { printf("ASI: " fmt , ## __VA_ARGS__); } while (0)
33 8543e2cf blueswir1
#endif
34 8543e2cf blueswir1
35 7e8695ed Igor V. Kovalenko
#ifdef DEBUG_PSTATE
36 7e8695ed Igor V. Kovalenko
#define DPRINTF_PSTATE(fmt, ...)                                   \
37 7e8695ed Igor V. Kovalenko
    do { printf("PSTATE: " fmt , ## __VA_ARGS__); } while (0)
38 7e8695ed Igor V. Kovalenko
#else
39 7e8695ed Igor V. Kovalenko
#define DPRINTF_PSTATE(fmt, ...) do {} while (0)
40 7e8695ed Igor V. Kovalenko
#endif
41 7e8695ed Igor V. Kovalenko
42 2cade6a3 blueswir1
#ifdef TARGET_SPARC64
43 2cade6a3 blueswir1
#ifndef TARGET_ABI32
44 2cade6a3 blueswir1
#define AM_CHECK(env1) ((env1)->pstate & PS_AM)
45 c2bc0e38 blueswir1
#else
46 2cade6a3 blueswir1
#define AM_CHECK(env1) (1)
47 2cade6a3 blueswir1
#endif
48 c2bc0e38 blueswir1
#endif
49 c2bc0e38 blueswir1
50 3c7b48b7 Paul Brook
#if defined(CONFIG_USER_ONLY) && defined(TARGET_SPARC64)
51 3c7b48b7 Paul Brook
static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
52 3c7b48b7 Paul Brook
                          int is_asi, int size);
53 3c7b48b7 Paul Brook
#endif
54 3c7b48b7 Paul Brook
55 9c22a623 Blue Swirl
#if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
56 697a77e6 Igor Kovalenko
// Calculates TSB pointer value for fault page size 8k or 64k
57 697a77e6 Igor Kovalenko
static uint64_t ultrasparc_tsb_pointer(uint64_t tsb_register,
58 697a77e6 Igor Kovalenko
                                       uint64_t tag_access_register,
59 697a77e6 Igor Kovalenko
                                       int page_size)
60 697a77e6 Igor Kovalenko
{
61 697a77e6 Igor Kovalenko
    uint64_t tsb_base = tsb_register & ~0x1fffULL;
62 6e8e7d4c Igor Kovalenko
    int tsb_split = (tsb_register & 0x1000ULL) ? 1 : 0;
63 6e8e7d4c Igor Kovalenko
    int tsb_size  = tsb_register & 0xf;
64 697a77e6 Igor Kovalenko
65 697a77e6 Igor Kovalenko
    // discard lower 13 bits which hold tag access context
66 697a77e6 Igor Kovalenko
    uint64_t tag_access_va = tag_access_register & ~0x1fffULL;
67 697a77e6 Igor Kovalenko
68 697a77e6 Igor Kovalenko
    // now reorder bits
69 697a77e6 Igor Kovalenko
    uint64_t tsb_base_mask = ~0x1fffULL;
70 697a77e6 Igor Kovalenko
    uint64_t va = tag_access_va;
71 697a77e6 Igor Kovalenko
72 697a77e6 Igor Kovalenko
    // move va bits to correct position
73 697a77e6 Igor Kovalenko
    if (page_size == 8*1024) {
74 697a77e6 Igor Kovalenko
        va >>= 9;
75 697a77e6 Igor Kovalenko
    } else if (page_size == 64*1024) {
76 697a77e6 Igor Kovalenko
        va >>= 12;
77 697a77e6 Igor Kovalenko
    }
78 697a77e6 Igor Kovalenko
79 697a77e6 Igor Kovalenko
    if (tsb_size) {
80 697a77e6 Igor Kovalenko
        tsb_base_mask <<= tsb_size;
81 697a77e6 Igor Kovalenko
    }
82 697a77e6 Igor Kovalenko
83 697a77e6 Igor Kovalenko
    // calculate tsb_base mask and adjust va if split is in use
84 697a77e6 Igor Kovalenko
    if (tsb_split) {
85 697a77e6 Igor Kovalenko
        if (page_size == 8*1024) {
86 697a77e6 Igor Kovalenko
            va &= ~(1ULL << (13 + tsb_size));
87 697a77e6 Igor Kovalenko
        } else if (page_size == 64*1024) {
88 697a77e6 Igor Kovalenko
            va |= (1ULL << (13 + tsb_size));
89 697a77e6 Igor Kovalenko
        }
90 697a77e6 Igor Kovalenko
        tsb_base_mask <<= 1;
91 697a77e6 Igor Kovalenko
    }
92 697a77e6 Igor Kovalenko
93 697a77e6 Igor Kovalenko
    return ((tsb_base & tsb_base_mask) | (va & ~tsb_base_mask)) & ~0xfULL;
94 697a77e6 Igor Kovalenko
}
95 697a77e6 Igor Kovalenko
96 697a77e6 Igor Kovalenko
// Calculates tag target register value by reordering bits
97 697a77e6 Igor Kovalenko
// in tag access register
98 697a77e6 Igor Kovalenko
static uint64_t ultrasparc_tag_target(uint64_t tag_access_register)
99 697a77e6 Igor Kovalenko
{
100 697a77e6 Igor Kovalenko
    return ((tag_access_register & 0x1fff) << 48) | (tag_access_register >> 22);
101 697a77e6 Igor Kovalenko
}
102 697a77e6 Igor Kovalenko
103 f707726e Igor Kovalenko
static void replace_tlb_entry(SparcTLBEntry *tlb,
104 f707726e Igor Kovalenko
                              uint64_t tlb_tag, uint64_t tlb_tte,
105 f707726e Igor Kovalenko
                              CPUState *env1)
106 6e8e7d4c Igor Kovalenko
{
107 6e8e7d4c Igor Kovalenko
    target_ulong mask, size, va, offset;
108 6e8e7d4c Igor Kovalenko
109 6e8e7d4c Igor Kovalenko
    // flush page range if translation is valid
110 f707726e Igor Kovalenko
    if (TTE_IS_VALID(tlb->tte)) {
111 6e8e7d4c Igor Kovalenko
112 6e8e7d4c Igor Kovalenko
        mask = 0xffffffffffffe000ULL;
113 6e8e7d4c Igor Kovalenko
        mask <<= 3 * ((tlb->tte >> 61) & 3);
114 6e8e7d4c Igor Kovalenko
        size = ~mask + 1;
115 6e8e7d4c Igor Kovalenko
116 6e8e7d4c Igor Kovalenko
        va = tlb->tag & mask;
117 6e8e7d4c Igor Kovalenko
118 6e8e7d4c Igor Kovalenko
        for (offset = 0; offset < size; offset += TARGET_PAGE_SIZE) {
119 6e8e7d4c Igor Kovalenko
            tlb_flush_page(env1, va + offset);
120 6e8e7d4c Igor Kovalenko
        }
121 6e8e7d4c Igor Kovalenko
    }
122 6e8e7d4c Igor Kovalenko
123 6e8e7d4c Igor Kovalenko
    tlb->tag = tlb_tag;
124 6e8e7d4c Igor Kovalenko
    tlb->tte = tlb_tte;
125 6e8e7d4c Igor Kovalenko
}
126 6e8e7d4c Igor Kovalenko
127 6e8e7d4c Igor Kovalenko
static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
128 f707726e Igor Kovalenko
                      const char* strmmu, CPUState *env1)
129 6e8e7d4c Igor Kovalenko
{
130 6e8e7d4c Igor Kovalenko
    unsigned int i;
131 6e8e7d4c Igor Kovalenko
    target_ulong mask;
132 6e8e7d4c Igor Kovalenko
133 6e8e7d4c Igor Kovalenko
    for (i = 0; i < 64; i++) {
134 f707726e Igor Kovalenko
        if (TTE_IS_VALID(tlb[i].tte)) {
135 6e8e7d4c Igor Kovalenko
136 6e8e7d4c Igor Kovalenko
            mask = 0xffffffffffffe000ULL;
137 6e8e7d4c Igor Kovalenko
            mask <<= 3 * ((tlb[i].tte >> 61) & 3);
138 6e8e7d4c Igor Kovalenko
139 6e8e7d4c Igor Kovalenko
            if ((demap_addr & mask) == (tlb[i].tag & mask)) {
140 f707726e Igor Kovalenko
                replace_tlb_entry(&tlb[i], 0, 0, env1);
141 6e8e7d4c Igor Kovalenko
#ifdef DEBUG_MMU
142 f707726e Igor Kovalenko
                DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
143 f707726e Igor Kovalenko
                dump_mmu(env1);
144 6e8e7d4c Igor Kovalenko
#endif
145 6e8e7d4c Igor Kovalenko
            }
146 6e8e7d4c Igor Kovalenko
            //return;
147 6e8e7d4c Igor Kovalenko
        }
148 6e8e7d4c Igor Kovalenko
    }
149 6e8e7d4c Igor Kovalenko
150 6e8e7d4c Igor Kovalenko
}
151 6e8e7d4c Igor Kovalenko
152 f707726e Igor Kovalenko
static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
153 f707726e Igor Kovalenko
                                 uint64_t tlb_tag, uint64_t tlb_tte,
154 f707726e Igor Kovalenko
                                 const char* strmmu, CPUState *env1)
155 f707726e Igor Kovalenko
{
156 f707726e Igor Kovalenko
    unsigned int i, replace_used;
157 f707726e Igor Kovalenko
158 f707726e Igor Kovalenko
    // Try replacing invalid entry
159 f707726e Igor Kovalenko
    for (i = 0; i < 64; i++) {
160 f707726e Igor Kovalenko
        if (!TTE_IS_VALID(tlb[i].tte)) {
161 f707726e Igor Kovalenko
            replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
162 f707726e Igor Kovalenko
#ifdef DEBUG_MMU
163 f707726e Igor Kovalenko
            DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu, i);
164 f707726e Igor Kovalenko
            dump_mmu(env1);
165 f707726e Igor Kovalenko
#endif
166 f707726e Igor Kovalenko
            return;
167 f707726e Igor Kovalenko
        }
168 f707726e Igor Kovalenko
    }
169 f707726e Igor Kovalenko
170 f707726e Igor Kovalenko
    // All entries are valid, try replacing unlocked entry
171 f707726e Igor Kovalenko
172 f707726e Igor Kovalenko
    for (replace_used = 0; replace_used < 2; ++replace_used) {
173 f707726e Igor Kovalenko
174 f707726e Igor Kovalenko
        // Used entries are not replaced on first pass
175 f707726e Igor Kovalenko
176 f707726e Igor Kovalenko
        for (i = 0; i < 64; i++) {
177 f707726e Igor Kovalenko
            if (!TTE_IS_LOCKED(tlb[i].tte) && !TTE_IS_USED(tlb[i].tte)) {
178 f707726e Igor Kovalenko
179 f707726e Igor Kovalenko
                replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
180 f707726e Igor Kovalenko
#ifdef DEBUG_MMU
181 f707726e Igor Kovalenko
                DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
182 f707726e Igor Kovalenko
                            strmmu, (replace_used?"used":"unused"), i);
183 f707726e Igor Kovalenko
                dump_mmu(env1);
184 f707726e Igor Kovalenko
#endif
185 f707726e Igor Kovalenko
                return;
186 f707726e Igor Kovalenko
            }
187 f707726e Igor Kovalenko
        }
188 f707726e Igor Kovalenko
189 f707726e Igor Kovalenko
        // Now reset used bit and search for unused entries again
190 f707726e Igor Kovalenko
191 f707726e Igor Kovalenko
        for (i = 0; i < 64; i++) {
192 f707726e Igor Kovalenko
            TTE_SET_UNUSED(tlb[i].tte);
193 f707726e Igor Kovalenko
        }
194 f707726e Igor Kovalenko
    }
195 f707726e Igor Kovalenko
196 f707726e Igor Kovalenko
#ifdef DEBUG_MMU
197 f707726e Igor Kovalenko
    DPRINTF_MMU("%s lru replacement failed: no entries available\n", strmmu);
198 f707726e Igor Kovalenko
#endif
199 f707726e Igor Kovalenko
    // error state?
200 f707726e Igor Kovalenko
}
201 f707726e Igor Kovalenko
202 697a77e6 Igor Kovalenko
#endif
203 697a77e6 Igor Kovalenko
204 41db525e Richard Henderson
static inline target_ulong address_mask(CPUState *env1, target_ulong addr)
205 2cade6a3 blueswir1
{
206 2cade6a3 blueswir1
#ifdef TARGET_SPARC64
207 2cade6a3 blueswir1
    if (AM_CHECK(env1))
208 41db525e Richard Henderson
        addr &= 0xffffffffULL;
209 2cade6a3 blueswir1
#endif
210 41db525e Richard Henderson
    return addr;
211 2cade6a3 blueswir1
}
212 2cade6a3 blueswir1
213 f4a5a5ba blueswir1
static void raise_exception(int tt)
214 9d893301 bellard
{
215 9d893301 bellard
    env->exception_index = tt;
216 9d893301 bellard
    cpu_loop_exit();
217 3b46e624 ths
}
218 9d893301 bellard
219 a7812ae4 pbrook
void HELPER(raise_exception)(int tt)
220 a7812ae4 pbrook
{
221 a7812ae4 pbrook
    raise_exception(tt);
222 a7812ae4 pbrook
}
223 a7812ae4 pbrook
224 91736d37 blueswir1
static inline void set_cwp(int new_cwp)
225 91736d37 blueswir1
{
226 91736d37 blueswir1
    cpu_set_cwp(env, new_cwp);
227 91736d37 blueswir1
}
228 91736d37 blueswir1
229 2b29924f blueswir1
void helper_check_align(target_ulong addr, uint32_t align)
230 2b29924f blueswir1
{
231 c2bc0e38 blueswir1
    if (addr & align) {
232 c2bc0e38 blueswir1
#ifdef DEBUG_UNALIGNED
233 c2bc0e38 blueswir1
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
234 c2bc0e38 blueswir1
           "\n", addr, env->pc);
235 c2bc0e38 blueswir1
#endif
236 2b29924f blueswir1
        raise_exception(TT_UNALIGNED);
237 c2bc0e38 blueswir1
    }
238 2b29924f blueswir1
}
239 2b29924f blueswir1
240 44e7757c blueswir1
#define F_HELPER(name, p) void helper_f##name##p(void)
241 44e7757c blueswir1
242 44e7757c blueswir1
#define F_BINOP(name)                                           \
243 714547bb blueswir1
    float32 helper_f ## name ## s (float32 src1, float32 src2)  \
244 44e7757c blueswir1
    {                                                           \
245 714547bb blueswir1
        return float32_ ## name (src1, src2, &env->fp_status);  \
246 44e7757c blueswir1
    }                                                           \
247 44e7757c blueswir1
    F_HELPER(name, d)                                           \
248 44e7757c blueswir1
    {                                                           \
249 44e7757c blueswir1
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
250 4e14008f blueswir1
    }                                                           \
251 4e14008f blueswir1
    F_HELPER(name, q)                                           \
252 4e14008f blueswir1
    {                                                           \
253 4e14008f blueswir1
        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
254 44e7757c blueswir1
    }
255 44e7757c blueswir1
256 44e7757c blueswir1
F_BINOP(add);
257 44e7757c blueswir1
F_BINOP(sub);
258 44e7757c blueswir1
F_BINOP(mul);
259 44e7757c blueswir1
F_BINOP(div);
260 44e7757c blueswir1
#undef F_BINOP
261 44e7757c blueswir1
262 d84763bc blueswir1
void helper_fsmuld(float32 src1, float32 src2)
263 1a2fb1c0 blueswir1
{
264 d84763bc blueswir1
    DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
265 d84763bc blueswir1
                      float32_to_float64(src2, &env->fp_status),
266 44e7757c blueswir1
                      &env->fp_status);
267 44e7757c blueswir1
}
268 1a2fb1c0 blueswir1
269 4e14008f blueswir1
void helper_fdmulq(void)
270 4e14008f blueswir1
{
271 4e14008f blueswir1
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
272 4e14008f blueswir1
                       float64_to_float128(DT1, &env->fp_status),
273 4e14008f blueswir1
                       &env->fp_status);
274 4e14008f blueswir1
}
275 4e14008f blueswir1
276 714547bb blueswir1
float32 helper_fnegs(float32 src)
277 44e7757c blueswir1
{
278 714547bb blueswir1
    return float32_chs(src);
279 417454b0 blueswir1
}
280 417454b0 blueswir1
281 44e7757c blueswir1
#ifdef TARGET_SPARC64
282 44e7757c blueswir1
F_HELPER(neg, d)
283 7e8c2b6c blueswir1
{
284 44e7757c blueswir1
    DT0 = float64_chs(DT1);
285 7e8c2b6c blueswir1
}
286 4e14008f blueswir1
287 4e14008f blueswir1
F_HELPER(neg, q)
288 4e14008f blueswir1
{
289 4e14008f blueswir1
    QT0 = float128_chs(QT1);
290 4e14008f blueswir1
}
291 4e14008f blueswir1
#endif
292 44e7757c blueswir1
293 44e7757c blueswir1
/* Integer to float conversion.  */
294 714547bb blueswir1
float32 helper_fitos(int32_t src)
295 a0c4cb4a bellard
{
296 714547bb blueswir1
    return int32_to_float32(src, &env->fp_status);
297 a0c4cb4a bellard
}
298 a0c4cb4a bellard
299 d84763bc blueswir1
void helper_fitod(int32_t src)
300 a0c4cb4a bellard
{
301 d84763bc blueswir1
    DT0 = int32_to_float64(src, &env->fp_status);
302 a0c4cb4a bellard
}
303 9c2b428e blueswir1
304 c5d04e99 blueswir1
void helper_fitoq(int32_t src)
305 4e14008f blueswir1
{
306 c5d04e99 blueswir1
    QT0 = int32_to_float128(src, &env->fp_status);
307 4e14008f blueswir1
}
308 4e14008f blueswir1
309 1e64e78d blueswir1
#ifdef TARGET_SPARC64
310 d84763bc blueswir1
float32 helper_fxtos(void)
311 1e64e78d blueswir1
{
312 d84763bc blueswir1
    return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
313 1e64e78d blueswir1
}
314 1e64e78d blueswir1
315 44e7757c blueswir1
F_HELPER(xto, d)
316 1e64e78d blueswir1
{
317 1e64e78d blueswir1
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
318 1e64e78d blueswir1
}
319 64a88d5d blueswir1
320 4e14008f blueswir1
F_HELPER(xto, q)
321 4e14008f blueswir1
{
322 4e14008f blueswir1
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
323 4e14008f blueswir1
}
324 4e14008f blueswir1
#endif
325 44e7757c blueswir1
#undef F_HELPER
326 44e7757c blueswir1
327 44e7757c blueswir1
/* floating point conversion */
328 d84763bc blueswir1
float32 helper_fdtos(void)
329 44e7757c blueswir1
{
330 d84763bc blueswir1
    return float64_to_float32(DT1, &env->fp_status);
331 44e7757c blueswir1
}
332 44e7757c blueswir1
333 d84763bc blueswir1
void helper_fstod(float32 src)
334 44e7757c blueswir1
{
335 d84763bc blueswir1
    DT0 = float32_to_float64(src, &env->fp_status);
336 44e7757c blueswir1
}
337 9c2b428e blueswir1
338 c5d04e99 blueswir1
float32 helper_fqtos(void)
339 4e14008f blueswir1
{
340 c5d04e99 blueswir1
    return float128_to_float32(QT1, &env->fp_status);
341 4e14008f blueswir1
}
342 4e14008f blueswir1
343 c5d04e99 blueswir1
void helper_fstoq(float32 src)
344 4e14008f blueswir1
{
345 c5d04e99 blueswir1
    QT0 = float32_to_float128(src, &env->fp_status);
346 4e14008f blueswir1
}
347 4e14008f blueswir1
348 4e14008f blueswir1
void helper_fqtod(void)
349 4e14008f blueswir1
{
350 4e14008f blueswir1
    DT0 = float128_to_float64(QT1, &env->fp_status);
351 4e14008f blueswir1
}
352 4e14008f blueswir1
353 4e14008f blueswir1
void helper_fdtoq(void)
354 4e14008f blueswir1
{
355 4e14008f blueswir1
    QT0 = float64_to_float128(DT1, &env->fp_status);
356 4e14008f blueswir1
}
357 4e14008f blueswir1
358 44e7757c blueswir1
/* Float to integer conversion.  */
359 714547bb blueswir1
int32_t helper_fstoi(float32 src)
360 44e7757c blueswir1
{
361 714547bb blueswir1
    return float32_to_int32_round_to_zero(src, &env->fp_status);
362 44e7757c blueswir1
}
363 44e7757c blueswir1
364 d84763bc blueswir1
int32_t helper_fdtoi(void)
365 44e7757c blueswir1
{
366 d84763bc blueswir1
    return float64_to_int32_round_to_zero(DT1, &env->fp_status);
367 44e7757c blueswir1
}
368 44e7757c blueswir1
369 c5d04e99 blueswir1
int32_t helper_fqtoi(void)
370 4e14008f blueswir1
{
371 c5d04e99 blueswir1
    return float128_to_int32_round_to_zero(QT1, &env->fp_status);
372 4e14008f blueswir1
}
373 4e14008f blueswir1
374 44e7757c blueswir1
#ifdef TARGET_SPARC64
375 d84763bc blueswir1
void helper_fstox(float32 src)
376 44e7757c blueswir1
{
377 d84763bc blueswir1
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
378 44e7757c blueswir1
}
379 44e7757c blueswir1
380 44e7757c blueswir1
void helper_fdtox(void)
381 44e7757c blueswir1
{
382 44e7757c blueswir1
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
383 44e7757c blueswir1
}
384 44e7757c blueswir1
385 4e14008f blueswir1
void helper_fqtox(void)
386 4e14008f blueswir1
{
387 4e14008f blueswir1
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
388 4e14008f blueswir1
}
389 4e14008f blueswir1
390 44e7757c blueswir1
void helper_faligndata(void)
391 44e7757c blueswir1
{
392 44e7757c blueswir1
    uint64_t tmp;
393 44e7757c blueswir1
394 44e7757c blueswir1
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
395 06057e6f blueswir1
    /* on many architectures a shift of 64 does nothing */
396 06057e6f blueswir1
    if ((env->gsr & 7) != 0) {
397 06057e6f blueswir1
        tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
398 06057e6f blueswir1
    }
399 44e7757c blueswir1
    *((uint64_t *)&DT0) = tmp;
400 44e7757c blueswir1
}
401 44e7757c blueswir1
402 e2542fe2 Juan Quintela
#ifdef HOST_WORDS_BIGENDIAN
403 44e7757c blueswir1
#define VIS_B64(n) b[7 - (n)]
404 44e7757c blueswir1
#define VIS_W64(n) w[3 - (n)]
405 44e7757c blueswir1
#define VIS_SW64(n) sw[3 - (n)]
406 44e7757c blueswir1
#define VIS_L64(n) l[1 - (n)]
407 44e7757c blueswir1
#define VIS_B32(n) b[3 - (n)]
408 44e7757c blueswir1
#define VIS_W32(n) w[1 - (n)]
409 44e7757c blueswir1
#else
410 44e7757c blueswir1
#define VIS_B64(n) b[n]
411 44e7757c blueswir1
#define VIS_W64(n) w[n]
412 44e7757c blueswir1
#define VIS_SW64(n) sw[n]
413 44e7757c blueswir1
#define VIS_L64(n) l[n]
414 44e7757c blueswir1
#define VIS_B32(n) b[n]
415 44e7757c blueswir1
#define VIS_W32(n) w[n]
416 44e7757c blueswir1
#endif
417 44e7757c blueswir1
418 44e7757c blueswir1
typedef union {
419 44e7757c blueswir1
    uint8_t b[8];
420 44e7757c blueswir1
    uint16_t w[4];
421 44e7757c blueswir1
    int16_t sw[4];
422 44e7757c blueswir1
    uint32_t l[2];
423 44e7757c blueswir1
    float64 d;
424 44e7757c blueswir1
} vis64;
425 44e7757c blueswir1
426 44e7757c blueswir1
typedef union {
427 44e7757c blueswir1
    uint8_t b[4];
428 44e7757c blueswir1
    uint16_t w[2];
429 44e7757c blueswir1
    uint32_t l;
430 44e7757c blueswir1
    float32 f;
431 44e7757c blueswir1
} vis32;
432 44e7757c blueswir1
433 44e7757c blueswir1
void helper_fpmerge(void)
434 44e7757c blueswir1
{
435 44e7757c blueswir1
    vis64 s, d;
436 44e7757c blueswir1
437 44e7757c blueswir1
    s.d = DT0;
438 44e7757c blueswir1
    d.d = DT1;
439 44e7757c blueswir1
440 44e7757c blueswir1
    // Reverse calculation order to handle overlap
441 44e7757c blueswir1
    d.VIS_B64(7) = s.VIS_B64(3);
442 44e7757c blueswir1
    d.VIS_B64(6) = d.VIS_B64(3);
443 44e7757c blueswir1
    d.VIS_B64(5) = s.VIS_B64(2);
444 44e7757c blueswir1
    d.VIS_B64(4) = d.VIS_B64(2);
445 44e7757c blueswir1
    d.VIS_B64(3) = s.VIS_B64(1);
446 44e7757c blueswir1
    d.VIS_B64(2) = d.VIS_B64(1);
447 44e7757c blueswir1
    d.VIS_B64(1) = s.VIS_B64(0);
448 44e7757c blueswir1
    //d.VIS_B64(0) = d.VIS_B64(0);
449 44e7757c blueswir1
450 44e7757c blueswir1
    DT0 = d.d;
451 44e7757c blueswir1
}
452 44e7757c blueswir1
453 44e7757c blueswir1
void helper_fmul8x16(void)
454 44e7757c blueswir1
{
455 44e7757c blueswir1
    vis64 s, d;
456 44e7757c blueswir1
    uint32_t tmp;
457 44e7757c blueswir1
458 44e7757c blueswir1
    s.d = DT0;
459 44e7757c blueswir1
    d.d = DT1;
460 44e7757c blueswir1
461 44e7757c blueswir1
#define PMUL(r)                                                 \
462 44e7757c blueswir1
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
463 44e7757c blueswir1
    if ((tmp & 0xff) > 0x7f)                                    \
464 44e7757c blueswir1
        tmp += 0x100;                                           \
465 44e7757c blueswir1
    d.VIS_W64(r) = tmp >> 8;
466 44e7757c blueswir1
467 44e7757c blueswir1
    PMUL(0);
468 44e7757c blueswir1
    PMUL(1);
469 44e7757c blueswir1
    PMUL(2);
470 44e7757c blueswir1
    PMUL(3);
471 44e7757c blueswir1
#undef PMUL
472 44e7757c blueswir1
473 44e7757c blueswir1
    DT0 = d.d;
474 44e7757c blueswir1
}
475 44e7757c blueswir1
476 44e7757c blueswir1
void helper_fmul8x16al(void)
477 44e7757c blueswir1
{
478 44e7757c blueswir1
    vis64 s, d;
479 44e7757c blueswir1
    uint32_t tmp;
480 44e7757c blueswir1
481 44e7757c blueswir1
    s.d = DT0;
482 44e7757c blueswir1
    d.d = DT1;
483 44e7757c blueswir1
484 44e7757c blueswir1
#define PMUL(r)                                                 \
485 44e7757c blueswir1
    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
486 44e7757c blueswir1
    if ((tmp & 0xff) > 0x7f)                                    \
487 44e7757c blueswir1
        tmp += 0x100;                                           \
488 44e7757c blueswir1
    d.VIS_W64(r) = tmp >> 8;
489 44e7757c blueswir1
490 44e7757c blueswir1
    PMUL(0);
491 44e7757c blueswir1
    PMUL(1);
492 44e7757c blueswir1
    PMUL(2);
493 44e7757c blueswir1
    PMUL(3);
494 44e7757c blueswir1
#undef PMUL
495 44e7757c blueswir1
496 44e7757c blueswir1
    DT0 = d.d;
497 44e7757c blueswir1
}
498 44e7757c blueswir1
499 44e7757c blueswir1
void helper_fmul8x16au(void)
500 44e7757c blueswir1
{
501 44e7757c blueswir1
    vis64 s, d;
502 44e7757c blueswir1
    uint32_t tmp;
503 44e7757c blueswir1
504 44e7757c blueswir1
    s.d = DT0;
505 44e7757c blueswir1
    d.d = DT1;
506 44e7757c blueswir1
507 44e7757c blueswir1
#define PMUL(r)                                                 \
508 44e7757c blueswir1
    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
509 44e7757c blueswir1
    if ((tmp & 0xff) > 0x7f)                                    \
510 44e7757c blueswir1
        tmp += 0x100;                                           \
511 44e7757c blueswir1
    d.VIS_W64(r) = tmp >> 8;
512 44e7757c blueswir1
513 44e7757c blueswir1
    PMUL(0);
514 44e7757c blueswir1
    PMUL(1);
515 44e7757c blueswir1
    PMUL(2);
516 44e7757c blueswir1
    PMUL(3);
517 44e7757c blueswir1
#undef PMUL
518 44e7757c blueswir1
519 44e7757c blueswir1
    DT0 = d.d;
520 44e7757c blueswir1
}
521 44e7757c blueswir1
522 44e7757c blueswir1
void helper_fmul8sux16(void)
523 44e7757c blueswir1
{
524 44e7757c blueswir1
    vis64 s, d;
525 44e7757c blueswir1
    uint32_t tmp;
526 44e7757c blueswir1
527 44e7757c blueswir1
    s.d = DT0;
528 44e7757c blueswir1
    d.d = DT1;
529 44e7757c blueswir1
530 44e7757c blueswir1
#define PMUL(r)                                                         \
531 44e7757c blueswir1
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
532 44e7757c blueswir1
    if ((tmp & 0xff) > 0x7f)                                            \
533 44e7757c blueswir1
        tmp += 0x100;                                                   \
534 44e7757c blueswir1
    d.VIS_W64(r) = tmp >> 8;
535 44e7757c blueswir1
536 44e7757c blueswir1
    PMUL(0);
537 44e7757c blueswir1
    PMUL(1);
538 44e7757c blueswir1
    PMUL(2);
539 44e7757c blueswir1
    PMUL(3);
540 44e7757c blueswir1
#undef PMUL
541 44e7757c blueswir1
542 44e7757c blueswir1
    DT0 = d.d;
543 44e7757c blueswir1
}
544 44e7757c blueswir1
545 44e7757c blueswir1
void helper_fmul8ulx16(void)
546 44e7757c blueswir1
{
547 44e7757c blueswir1
    vis64 s, d;
548 44e7757c blueswir1
    uint32_t tmp;
549 44e7757c blueswir1
550 44e7757c blueswir1
    s.d = DT0;
551 44e7757c blueswir1
    d.d = DT1;
552 44e7757c blueswir1
553 44e7757c blueswir1
#define PMUL(r)                                                         \
554 44e7757c blueswir1
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
555 44e7757c blueswir1
    if ((tmp & 0xff) > 0x7f)                                            \
556 44e7757c blueswir1
        tmp += 0x100;                                                   \
557 44e7757c blueswir1
    d.VIS_W64(r) = tmp >> 8;
558 44e7757c blueswir1
559 44e7757c blueswir1
    PMUL(0);
560 44e7757c blueswir1
    PMUL(1);
561 44e7757c blueswir1
    PMUL(2);
562 44e7757c blueswir1
    PMUL(3);
563 44e7757c blueswir1
#undef PMUL
564 44e7757c blueswir1
565 44e7757c blueswir1
    DT0 = d.d;
566 44e7757c blueswir1
}
567 44e7757c blueswir1
568 44e7757c blueswir1
void helper_fmuld8sux16(void)
569 44e7757c blueswir1
{
570 44e7757c blueswir1
    vis64 s, d;
571 44e7757c blueswir1
    uint32_t tmp;
572 44e7757c blueswir1
573 44e7757c blueswir1
    s.d = DT0;
574 44e7757c blueswir1
    d.d = DT1;
575 44e7757c blueswir1
576 44e7757c blueswir1
#define PMUL(r)                                                         \
577 44e7757c blueswir1
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
578 44e7757c blueswir1
    if ((tmp & 0xff) > 0x7f)                                            \
579 44e7757c blueswir1
        tmp += 0x100;                                                   \
580 44e7757c blueswir1
    d.VIS_L64(r) = tmp;
581 44e7757c blueswir1
582 44e7757c blueswir1
    // Reverse calculation order to handle overlap
583 44e7757c blueswir1
    PMUL(1);
584 44e7757c blueswir1
    PMUL(0);
585 44e7757c blueswir1
#undef PMUL
586 44e7757c blueswir1
587 44e7757c blueswir1
    DT0 = d.d;
588 44e7757c blueswir1
}
589 44e7757c blueswir1
590 44e7757c blueswir1
void helper_fmuld8ulx16(void)
591 44e7757c blueswir1
{
592 44e7757c blueswir1
    vis64 s, d;
593 44e7757c blueswir1
    uint32_t tmp;
594 44e7757c blueswir1
595 44e7757c blueswir1
    s.d = DT0;
596 44e7757c blueswir1
    d.d = DT1;
597 44e7757c blueswir1
598 44e7757c blueswir1
#define PMUL(r)                                                         \
599 44e7757c blueswir1
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
600 44e7757c blueswir1
    if ((tmp & 0xff) > 0x7f)                                            \
601 44e7757c blueswir1
        tmp += 0x100;                                                   \
602 44e7757c blueswir1
    d.VIS_L64(r) = tmp;
603 44e7757c blueswir1
604 44e7757c blueswir1
    // Reverse calculation order to handle overlap
605 44e7757c blueswir1
    PMUL(1);
606 44e7757c blueswir1
    PMUL(0);
607 44e7757c blueswir1
#undef PMUL
608 44e7757c blueswir1
609 44e7757c blueswir1
    DT0 = d.d;
610 44e7757c blueswir1
}
611 44e7757c blueswir1
612 44e7757c blueswir1
void helper_fexpand(void)
613 44e7757c blueswir1
{
614 44e7757c blueswir1
    vis32 s;
615 44e7757c blueswir1
    vis64 d;
616 44e7757c blueswir1
617 44e7757c blueswir1
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
618 44e7757c blueswir1
    d.d = DT1;
619 c55bda30 blueswir1
    d.VIS_W64(0) = s.VIS_B32(0) << 4;
620 c55bda30 blueswir1
    d.VIS_W64(1) = s.VIS_B32(1) << 4;
621 c55bda30 blueswir1
    d.VIS_W64(2) = s.VIS_B32(2) << 4;
622 c55bda30 blueswir1
    d.VIS_W64(3) = s.VIS_B32(3) << 4;
623 44e7757c blueswir1
624 44e7757c blueswir1
    DT0 = d.d;
625 44e7757c blueswir1
}
626 44e7757c blueswir1
627 44e7757c blueswir1
#define VIS_HELPER(name, F)                             \
628 44e7757c blueswir1
    void name##16(void)                                 \
629 44e7757c blueswir1
    {                                                   \
630 44e7757c blueswir1
        vis64 s, d;                                     \
631 44e7757c blueswir1
                                                        \
632 44e7757c blueswir1
        s.d = DT0;                                      \
633 44e7757c blueswir1
        d.d = DT1;                                      \
634 44e7757c blueswir1
                                                        \
635 44e7757c blueswir1
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
636 44e7757c blueswir1
        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
637 44e7757c blueswir1
        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
638 44e7757c blueswir1
        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
639 44e7757c blueswir1
                                                        \
640 44e7757c blueswir1
        DT0 = d.d;                                      \
641 44e7757c blueswir1
    }                                                   \
642 44e7757c blueswir1
                                                        \
643 1d01299d blueswir1
    uint32_t name##16s(uint32_t src1, uint32_t src2)    \
644 44e7757c blueswir1
    {                                                   \
645 44e7757c blueswir1
        vis32 s, d;                                     \
646 44e7757c blueswir1
                                                        \
647 1d01299d blueswir1
        s.l = src1;                                     \
648 1d01299d blueswir1
        d.l = src2;                                     \
649 44e7757c blueswir1
                                                        \
650 44e7757c blueswir1
        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
651 44e7757c blueswir1
        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
652 44e7757c blueswir1
                                                        \
653 1d01299d blueswir1
        return d.l;                                     \
654 44e7757c blueswir1
    }                                                   \
655 44e7757c blueswir1
                                                        \
656 44e7757c blueswir1
    void name##32(void)                                 \
657 44e7757c blueswir1
    {                                                   \
658 44e7757c blueswir1
        vis64 s, d;                                     \
659 44e7757c blueswir1
                                                        \
660 44e7757c blueswir1
        s.d = DT0;                                      \
661 44e7757c blueswir1
        d.d = DT1;                                      \
662 44e7757c blueswir1
                                                        \
663 44e7757c blueswir1
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
664 44e7757c blueswir1
        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
665 44e7757c blueswir1
                                                        \
666 44e7757c blueswir1
        DT0 = d.d;                                      \
667 44e7757c blueswir1
    }                                                   \
668 44e7757c blueswir1
                                                        \
669 1d01299d blueswir1
    uint32_t name##32s(uint32_t src1, uint32_t src2)    \
670 44e7757c blueswir1
    {                                                   \
671 44e7757c blueswir1
        vis32 s, d;                                     \
672 44e7757c blueswir1
                                                        \
673 1d01299d blueswir1
        s.l = src1;                                     \
674 1d01299d blueswir1
        d.l = src2;                                     \
675 44e7757c blueswir1
                                                        \
676 44e7757c blueswir1
        d.l = F(d.l, s.l);                              \
677 44e7757c blueswir1
                                                        \
678 1d01299d blueswir1
        return d.l;                                     \
679 44e7757c blueswir1
    }
680 44e7757c blueswir1
681 44e7757c blueswir1
#define FADD(a, b) ((a) + (b))
682 44e7757c blueswir1
#define FSUB(a, b) ((a) - (b))
683 44e7757c blueswir1
VIS_HELPER(helper_fpadd, FADD)
684 44e7757c blueswir1
VIS_HELPER(helper_fpsub, FSUB)
685 44e7757c blueswir1
686 44e7757c blueswir1
#define VIS_CMPHELPER(name, F)                                        \
687 44e7757c blueswir1
    void name##16(void)                                           \
688 44e7757c blueswir1
    {                                                             \
689 44e7757c blueswir1
        vis64 s, d;                                               \
690 44e7757c blueswir1
                                                                  \
691 44e7757c blueswir1
        s.d = DT0;                                                \
692 44e7757c blueswir1
        d.d = DT1;                                                \
693 44e7757c blueswir1
                                                                  \
694 44e7757c blueswir1
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
695 44e7757c blueswir1
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
696 44e7757c blueswir1
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
697 44e7757c blueswir1
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
698 44e7757c blueswir1
                                                                  \
699 44e7757c blueswir1
        DT0 = d.d;                                                \
700 44e7757c blueswir1
    }                                                             \
701 44e7757c blueswir1
                                                                  \
702 44e7757c blueswir1
    void name##32(void)                                           \
703 44e7757c blueswir1
    {                                                             \
704 44e7757c blueswir1
        vis64 s, d;                                               \
705 44e7757c blueswir1
                                                                  \
706 44e7757c blueswir1
        s.d = DT0;                                                \
707 44e7757c blueswir1
        d.d = DT1;                                                \
708 44e7757c blueswir1
                                                                  \
709 44e7757c blueswir1
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
710 44e7757c blueswir1
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
711 44e7757c blueswir1
                                                                  \
712 44e7757c blueswir1
        DT0 = d.d;                                                \
713 44e7757c blueswir1
    }
714 44e7757c blueswir1
715 44e7757c blueswir1
#define FCMPGT(a, b) ((a) > (b))
716 44e7757c blueswir1
#define FCMPEQ(a, b) ((a) == (b))
717 44e7757c blueswir1
#define FCMPLE(a, b) ((a) <= (b))
718 44e7757c blueswir1
#define FCMPNE(a, b) ((a) != (b))
719 44e7757c blueswir1
720 44e7757c blueswir1
VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
721 44e7757c blueswir1
VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
722 44e7757c blueswir1
VIS_CMPHELPER(helper_fcmple, FCMPLE)
723 44e7757c blueswir1
VIS_CMPHELPER(helper_fcmpne, FCMPNE)
724 44e7757c blueswir1
#endif
725 44e7757c blueswir1
726 44e7757c blueswir1
void helper_check_ieee_exceptions(void)
727 44e7757c blueswir1
{
728 44e7757c blueswir1
    target_ulong status;
729 44e7757c blueswir1
730 44e7757c blueswir1
    status = get_float_exception_flags(&env->fp_status);
731 44e7757c blueswir1
    if (status) {
732 44e7757c blueswir1
        /* Copy IEEE 754 flags into FSR */
733 44e7757c blueswir1
        if (status & float_flag_invalid)
734 44e7757c blueswir1
            env->fsr |= FSR_NVC;
735 44e7757c blueswir1
        if (status & float_flag_overflow)
736 44e7757c blueswir1
            env->fsr |= FSR_OFC;
737 44e7757c blueswir1
        if (status & float_flag_underflow)
738 44e7757c blueswir1
            env->fsr |= FSR_UFC;
739 44e7757c blueswir1
        if (status & float_flag_divbyzero)
740 44e7757c blueswir1
            env->fsr |= FSR_DZC;
741 44e7757c blueswir1
        if (status & float_flag_inexact)
742 44e7757c blueswir1
            env->fsr |= FSR_NXC;
743 44e7757c blueswir1
744 44e7757c blueswir1
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
745 44e7757c blueswir1
            /* Unmasked exception, generate a trap */
746 44e7757c blueswir1
            env->fsr |= FSR_FTT_IEEE_EXCP;
747 44e7757c blueswir1
            raise_exception(TT_FP_EXCP);
748 44e7757c blueswir1
        } else {
749 44e7757c blueswir1
            /* Accumulate exceptions */
750 44e7757c blueswir1
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
751 44e7757c blueswir1
        }
752 44e7757c blueswir1
    }
753 44e7757c blueswir1
}
754 44e7757c blueswir1
755 44e7757c blueswir1
void helper_clear_float_exceptions(void)
756 44e7757c blueswir1
{
757 44e7757c blueswir1
    set_float_exception_flags(0, &env->fp_status);
758 44e7757c blueswir1
}
759 44e7757c blueswir1
760 714547bb blueswir1
float32 helper_fabss(float32 src)
761 e8af50a3 bellard
{
762 714547bb blueswir1
    return float32_abs(src);
763 e8af50a3 bellard
}
764 e8af50a3 bellard
765 3475187d bellard
#ifdef TARGET_SPARC64
766 7e8c2b6c blueswir1
void helper_fabsd(void)
767 3475187d bellard
{
768 3475187d bellard
    DT0 = float64_abs(DT1);
769 3475187d bellard
}
770 4e14008f blueswir1
771 4e14008f blueswir1
void helper_fabsq(void)
772 4e14008f blueswir1
{
773 4e14008f blueswir1
    QT0 = float128_abs(QT1);
774 4e14008f blueswir1
}
775 4e14008f blueswir1
#endif
776 3475187d bellard
777 714547bb blueswir1
float32 helper_fsqrts(float32 src)
778 e8af50a3 bellard
{
779 714547bb blueswir1
    return float32_sqrt(src, &env->fp_status);
780 e8af50a3 bellard
}
781 e8af50a3 bellard
782 7e8c2b6c blueswir1
void helper_fsqrtd(void)
783 e8af50a3 bellard
{
784 7a0e1f41 bellard
    DT0 = float64_sqrt(DT1, &env->fp_status);
785 e8af50a3 bellard
}
786 e8af50a3 bellard
787 4e14008f blueswir1
void helper_fsqrtq(void)
788 4e14008f blueswir1
{
789 4e14008f blueswir1
    QT0 = float128_sqrt(QT1, &env->fp_status);
790 4e14008f blueswir1
}
791 4e14008f blueswir1
792 417454b0 blueswir1
#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
793 7e8c2b6c blueswir1
    void glue(helper_, name) (void)                                     \
794 65ce8c2f bellard
    {                                                                   \
795 1a2fb1c0 blueswir1
        target_ulong new_fsr;                                           \
796 1a2fb1c0 blueswir1
                                                                        \
797 65ce8c2f bellard
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
798 65ce8c2f bellard
        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
799 65ce8c2f bellard
        case float_relation_unordered:                                  \
800 1a2fb1c0 blueswir1
            new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
801 417454b0 blueswir1
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
802 1a2fb1c0 blueswir1
                env->fsr |= new_fsr;                                    \
803 417454b0 blueswir1
                env->fsr |= FSR_NVC;                                    \
804 417454b0 blueswir1
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
805 65ce8c2f bellard
                raise_exception(TT_FP_EXCP);                            \
806 65ce8c2f bellard
            } else {                                                    \
807 65ce8c2f bellard
                env->fsr |= FSR_NVA;                                    \
808 65ce8c2f bellard
            }                                                           \
809 65ce8c2f bellard
            break;                                                      \
810 65ce8c2f bellard
        case float_relation_less:                                       \
811 1a2fb1c0 blueswir1
            new_fsr = FSR_FCC0 << FS;                                   \
812 65ce8c2f bellard
            break;                                                      \
813 65ce8c2f bellard
        case float_relation_greater:                                    \
814 1a2fb1c0 blueswir1
            new_fsr = FSR_FCC1 << FS;                                   \
815 65ce8c2f bellard
            break;                                                      \
816 65ce8c2f bellard
        default:                                                        \
817 1a2fb1c0 blueswir1
            new_fsr = 0;                                                \
818 65ce8c2f bellard
            break;                                                      \
819 65ce8c2f bellard
        }                                                               \
820 1a2fb1c0 blueswir1
        env->fsr |= new_fsr;                                            \
821 e8af50a3 bellard
    }
822 714547bb blueswir1
#define GEN_FCMPS(name, size, FS, TRAP)                                 \
823 714547bb blueswir1
    void glue(helper_, name)(float32 src1, float32 src2)                \
824 714547bb blueswir1
    {                                                                   \
825 714547bb blueswir1
        target_ulong new_fsr;                                           \
826 714547bb blueswir1
                                                                        \
827 714547bb blueswir1
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
828 714547bb blueswir1
        switch (glue(size, _compare) (src1, src2, &env->fp_status)) {   \
829 714547bb blueswir1
        case float_relation_unordered:                                  \
830 714547bb blueswir1
            new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
831 714547bb blueswir1
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
832 714547bb blueswir1
                env->fsr |= new_fsr;                                    \
833 714547bb blueswir1
                env->fsr |= FSR_NVC;                                    \
834 714547bb blueswir1
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
835 714547bb blueswir1
                raise_exception(TT_FP_EXCP);                            \
836 714547bb blueswir1
            } else {                                                    \
837 714547bb blueswir1
                env->fsr |= FSR_NVA;                                    \
838 714547bb blueswir1
            }                                                           \
839 714547bb blueswir1
            break;                                                      \
840 714547bb blueswir1
        case float_relation_less:                                       \
841 714547bb blueswir1
            new_fsr = FSR_FCC0 << FS;                                   \
842 714547bb blueswir1
            break;                                                      \
843 714547bb blueswir1
        case float_relation_greater:                                    \
844 714547bb blueswir1
            new_fsr = FSR_FCC1 << FS;                                   \
845 714547bb blueswir1
            break;                                                      \
846 714547bb blueswir1
        default:                                                        \
847 714547bb blueswir1
            new_fsr = 0;                                                \
848 714547bb blueswir1
            break;                                                      \
849 714547bb blueswir1
        }                                                               \
850 714547bb blueswir1
        env->fsr |= new_fsr;                                            \
851 714547bb blueswir1
    }
852 e8af50a3 bellard
853 714547bb blueswir1
GEN_FCMPS(fcmps, float32, 0, 0);
854 417454b0 blueswir1
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
855 417454b0 blueswir1
856 714547bb blueswir1
GEN_FCMPS(fcmpes, float32, 0, 1);
857 417454b0 blueswir1
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
858 3475187d bellard
859 4e14008f blueswir1
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
860 4e14008f blueswir1
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
861 4e14008f blueswir1
862 8393617c Blue Swirl
static uint32_t compute_all_flags(void)
863 8393617c Blue Swirl
{
864 8393617c Blue Swirl
    return env->psr & PSR_ICC;
865 8393617c Blue Swirl
}
866 8393617c Blue Swirl
867 8393617c Blue Swirl
static uint32_t compute_C_flags(void)
868 8393617c Blue Swirl
{
869 8393617c Blue Swirl
    return env->psr & PSR_CARRY;
870 8393617c Blue Swirl
}
871 8393617c Blue Swirl
872 bdf9f35d Blue Swirl
static inline uint32_t get_NZ_icc(target_ulong dst)
873 bdf9f35d Blue Swirl
{
874 bdf9f35d Blue Swirl
    uint32_t ret = 0;
875 bdf9f35d Blue Swirl
876 bdf9f35d Blue Swirl
    if (!(dst & 0xffffffffULL))
877 bdf9f35d Blue Swirl
        ret |= PSR_ZERO;
878 bdf9f35d Blue Swirl
    if ((int32_t) (dst & 0xffffffffULL) < 0)
879 bdf9f35d Blue Swirl
        ret |= PSR_NEG;
880 bdf9f35d Blue Swirl
    return ret;
881 bdf9f35d Blue Swirl
}
882 bdf9f35d Blue Swirl
883 8393617c Blue Swirl
#ifdef TARGET_SPARC64
884 8393617c Blue Swirl
static uint32_t compute_all_flags_xcc(void)
885 8393617c Blue Swirl
{
886 8393617c Blue Swirl
    return env->xcc & PSR_ICC;
887 8393617c Blue Swirl
}
888 8393617c Blue Swirl
889 8393617c Blue Swirl
static uint32_t compute_C_flags_xcc(void)
890 8393617c Blue Swirl
{
891 8393617c Blue Swirl
    return env->xcc & PSR_CARRY;
892 8393617c Blue Swirl
}
893 8393617c Blue Swirl
894 bdf9f35d Blue Swirl
static inline uint32_t get_NZ_xcc(target_ulong dst)
895 bdf9f35d Blue Swirl
{
896 bdf9f35d Blue Swirl
    uint32_t ret = 0;
897 bdf9f35d Blue Swirl
898 bdf9f35d Blue Swirl
    if (!dst)
899 bdf9f35d Blue Swirl
        ret |= PSR_ZERO;
900 bdf9f35d Blue Swirl
    if ((int64_t)dst < 0)
901 bdf9f35d Blue Swirl
        ret |= PSR_NEG;
902 bdf9f35d Blue Swirl
    return ret;
903 bdf9f35d Blue Swirl
}
904 bdf9f35d Blue Swirl
#endif
905 bdf9f35d Blue Swirl
906 6c78ea32 Blue Swirl
static inline uint32_t get_V_div_icc(target_ulong src2)
907 6c78ea32 Blue Swirl
{
908 6c78ea32 Blue Swirl
    uint32_t ret = 0;
909 6c78ea32 Blue Swirl
910 6c78ea32 Blue Swirl
    if (src2 != 0)
911 6c78ea32 Blue Swirl
        ret |= PSR_OVF;
912 6c78ea32 Blue Swirl
    return ret;
913 6c78ea32 Blue Swirl
}
914 6c78ea32 Blue Swirl
915 6c78ea32 Blue Swirl
static uint32_t compute_all_div(void)
916 6c78ea32 Blue Swirl
{
917 6c78ea32 Blue Swirl
    uint32_t ret;
918 6c78ea32 Blue Swirl
919 6c78ea32 Blue Swirl
    ret = get_NZ_icc(CC_DST);
920 6c78ea32 Blue Swirl
    ret |= get_V_div_icc(CC_SRC2);
921 6c78ea32 Blue Swirl
    return ret;
922 6c78ea32 Blue Swirl
}
923 6c78ea32 Blue Swirl
924 6c78ea32 Blue Swirl
static uint32_t compute_C_div(void)
925 6c78ea32 Blue Swirl
{
926 6c78ea32 Blue Swirl
    return 0;
927 6c78ea32 Blue Swirl
}
928 6c78ea32 Blue Swirl
929 3e6ba503 Artyom Tarasenko
/* carry = (src1[31] & src2[31]) | ( ~dst[31] & (src1[31] | src2[31])) */
930 3e6ba503 Artyom Tarasenko
static inline uint32_t get_C_add_icc(target_ulong dst, target_ulong src1,
931 3e6ba503 Artyom Tarasenko
                                     target_ulong src2)
932 bdf9f35d Blue Swirl
{
933 bdf9f35d Blue Swirl
    uint32_t ret = 0;
934 bdf9f35d Blue Swirl
935 3e6ba503 Artyom Tarasenko
    if (((src1 & (1ULL << 31)) & (src2 & (1ULL << 31)))
936 3e6ba503 Artyom Tarasenko
        | ((~(dst & (1ULL << 31)))
937 3e6ba503 Artyom Tarasenko
           & ((src1 & (1ULL << 31)) | (src2 & (1ULL << 31)))))
938 bdf9f35d Blue Swirl
        ret |= PSR_CARRY;
939 bdf9f35d Blue Swirl
    return ret;
940 bdf9f35d Blue Swirl
}
941 bdf9f35d Blue Swirl
942 bdf9f35d Blue Swirl
static inline uint32_t get_V_add_icc(target_ulong dst, target_ulong src1,
943 bdf9f35d Blue Swirl
                                         target_ulong src2)
944 bdf9f35d Blue Swirl
{
945 bdf9f35d Blue Swirl
    uint32_t ret = 0;
946 bdf9f35d Blue Swirl
947 bdf9f35d Blue Swirl
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 31))
948 bdf9f35d Blue Swirl
        ret |= PSR_OVF;
949 bdf9f35d Blue Swirl
    return ret;
950 bdf9f35d Blue Swirl
}
951 bdf9f35d Blue Swirl
952 bdf9f35d Blue Swirl
#ifdef TARGET_SPARC64
953 bdf9f35d Blue Swirl
static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
954 bdf9f35d Blue Swirl
{
955 bdf9f35d Blue Swirl
    uint32_t ret = 0;
956 bdf9f35d Blue Swirl
957 bdf9f35d Blue Swirl
    if (dst < src1)
958 bdf9f35d Blue Swirl
        ret |= PSR_CARRY;
959 bdf9f35d Blue Swirl
    return ret;
960 bdf9f35d Blue Swirl
}
961 bdf9f35d Blue Swirl
962 bdf9f35d Blue Swirl
static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
963 bdf9f35d Blue Swirl
                                         target_ulong src2)
964 bdf9f35d Blue Swirl
{
965 bdf9f35d Blue Swirl
    uint32_t ret = 0;
966 bdf9f35d Blue Swirl
967 bdf9f35d Blue Swirl
    if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63))
968 bdf9f35d Blue Swirl
        ret |= PSR_OVF;
969 bdf9f35d Blue Swirl
    return ret;
970 bdf9f35d Blue Swirl
}
971 bdf9f35d Blue Swirl
972 bdf9f35d Blue Swirl
static uint32_t compute_all_add_xcc(void)
973 bdf9f35d Blue Swirl
{
974 bdf9f35d Blue Swirl
    uint32_t ret;
975 bdf9f35d Blue Swirl
976 bdf9f35d Blue Swirl
    ret = get_NZ_xcc(CC_DST);
977 bdf9f35d Blue Swirl
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
978 bdf9f35d Blue Swirl
    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
979 bdf9f35d Blue Swirl
    return ret;
980 bdf9f35d Blue Swirl
}
981 bdf9f35d Blue Swirl
982 bdf9f35d Blue Swirl
static uint32_t compute_C_add_xcc(void)
983 bdf9f35d Blue Swirl
{
984 bdf9f35d Blue Swirl
    return get_C_add_xcc(CC_DST, CC_SRC);
985 bdf9f35d Blue Swirl
}
986 8393617c Blue Swirl
#endif
987 8393617c Blue Swirl
988 3e6ba503 Artyom Tarasenko
static uint32_t compute_all_add(void)
989 789c91ef Blue Swirl
{
990 789c91ef Blue Swirl
    uint32_t ret;
991 789c91ef Blue Swirl
992 789c91ef Blue Swirl
    ret = get_NZ_icc(CC_DST);
993 3e6ba503 Artyom Tarasenko
    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
994 789c91ef Blue Swirl
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
995 789c91ef Blue Swirl
    return ret;
996 789c91ef Blue Swirl
}
997 789c91ef Blue Swirl
998 3e6ba503 Artyom Tarasenko
static uint32_t compute_C_add(void)
999 789c91ef Blue Swirl
{
1000 3e6ba503 Artyom Tarasenko
    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1001 789c91ef Blue Swirl
}
1002 789c91ef Blue Swirl
1003 789c91ef Blue Swirl
#ifdef TARGET_SPARC64
1004 789c91ef Blue Swirl
static uint32_t compute_all_addx_xcc(void)
1005 789c91ef Blue Swirl
{
1006 789c91ef Blue Swirl
    uint32_t ret;
1007 789c91ef Blue Swirl
1008 789c91ef Blue Swirl
    ret = get_NZ_xcc(CC_DST);
1009 789c91ef Blue Swirl
    ret |= get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
1010 789c91ef Blue Swirl
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
1011 789c91ef Blue Swirl
    ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
1012 789c91ef Blue Swirl
    return ret;
1013 789c91ef Blue Swirl
}
1014 789c91ef Blue Swirl
1015 789c91ef Blue Swirl
static uint32_t compute_C_addx_xcc(void)
1016 789c91ef Blue Swirl
{
1017 789c91ef Blue Swirl
    uint32_t ret;
1018 789c91ef Blue Swirl
1019 789c91ef Blue Swirl
    ret = get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
1020 789c91ef Blue Swirl
    ret |= get_C_add_xcc(CC_DST, CC_SRC);
1021 789c91ef Blue Swirl
    return ret;
1022 789c91ef Blue Swirl
}
1023 789c91ef Blue Swirl
#endif
1024 789c91ef Blue Swirl
1025 3b2d1e92 Blue Swirl
static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
1026 3b2d1e92 Blue Swirl
{
1027 3b2d1e92 Blue Swirl
    uint32_t ret = 0;
1028 3b2d1e92 Blue Swirl
1029 3b2d1e92 Blue Swirl
    if ((src1 | src2) & 0x3)
1030 3b2d1e92 Blue Swirl
        ret |= PSR_OVF;
1031 3b2d1e92 Blue Swirl
    return ret;
1032 3b2d1e92 Blue Swirl
}
1033 3b2d1e92 Blue Swirl
1034 3b2d1e92 Blue Swirl
static uint32_t compute_all_tadd(void)
1035 3b2d1e92 Blue Swirl
{
1036 3b2d1e92 Blue Swirl
    uint32_t ret;
1037 3b2d1e92 Blue Swirl
1038 3b2d1e92 Blue Swirl
    ret = get_NZ_icc(CC_DST);
1039 3e6ba503 Artyom Tarasenko
    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1040 3b2d1e92 Blue Swirl
    ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
1041 3b2d1e92 Blue Swirl
    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1042 3b2d1e92 Blue Swirl
    return ret;
1043 3b2d1e92 Blue Swirl
}
1044 3b2d1e92 Blue Swirl
1045 3b2d1e92 Blue Swirl
static uint32_t compute_C_tadd(void)
1046 3b2d1e92 Blue Swirl
{
1047 3e6ba503 Artyom Tarasenko
    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1048 3b2d1e92 Blue Swirl
}
1049 3b2d1e92 Blue Swirl
1050 3b2d1e92 Blue Swirl
static uint32_t compute_all_taddtv(void)
1051 3b2d1e92 Blue Swirl
{
1052 3b2d1e92 Blue Swirl
    uint32_t ret;
1053 3b2d1e92 Blue Swirl
1054 3b2d1e92 Blue Swirl
    ret = get_NZ_icc(CC_DST);
1055 3e6ba503 Artyom Tarasenko
    ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1056 3b2d1e92 Blue Swirl
    return ret;
1057 3b2d1e92 Blue Swirl
}
1058 3b2d1e92 Blue Swirl
1059 3b2d1e92 Blue Swirl
static uint32_t compute_C_taddtv(void)
1060 3b2d1e92 Blue Swirl
{
1061 3e6ba503 Artyom Tarasenko
    return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
1062 3b2d1e92 Blue Swirl
}
1063 3b2d1e92 Blue Swirl
1064 3e6ba503 Artyom Tarasenko
/* carry = (~src1[31] & src2[31]) | ( dst[31]  & (~src1[31] | src2[31])) */
1065 3e6ba503 Artyom Tarasenko
static inline uint32_t get_C_sub_icc(target_ulong dst, target_ulong src1,
1066 3e6ba503 Artyom Tarasenko
                                     target_ulong src2)
1067 d4b0d468 Blue Swirl
{
1068 d4b0d468 Blue Swirl
    uint32_t ret = 0;
1069 d4b0d468 Blue Swirl
1070 3e6ba503 Artyom Tarasenko
    if (((~(src1 & (1ULL << 31))) & (src2 & (1ULL << 31)))
1071 3e6ba503 Artyom Tarasenko
        | ((dst & (1ULL << 31)) & (( ~(src1 & (1ULL << 31)))
1072 3e6ba503 Artyom Tarasenko
                                   | (src2 & (1ULL << 31)))))
1073 d4b0d468 Blue Swirl
        ret |= PSR_CARRY;
1074 d4b0d468 Blue Swirl
    return ret;
1075 d4b0d468 Blue Swirl
}
1076 d4b0d468 Blue Swirl
1077 d4b0d468 Blue Swirl
static inline uint32_t get_V_sub_icc(target_ulong dst, target_ulong src1,
1078 d4b0d468 Blue Swirl
                                     target_ulong src2)
1079 d4b0d468 Blue Swirl
{
1080 d4b0d468 Blue Swirl
    uint32_t ret = 0;
1081 d4b0d468 Blue Swirl
1082 d4b0d468 Blue Swirl
    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 31))
1083 d4b0d468 Blue Swirl
        ret |= PSR_OVF;
1084 d4b0d468 Blue Swirl
    return ret;
1085 d4b0d468 Blue Swirl
}
1086 d4b0d468 Blue Swirl
1087 d4b0d468 Blue Swirl
1088 d4b0d468 Blue Swirl
#ifdef TARGET_SPARC64
1089 d4b0d468 Blue Swirl
static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
1090 d4b0d468 Blue Swirl
{
1091 d4b0d468 Blue Swirl
    uint32_t ret = 0;
1092 d4b0d468 Blue Swirl
1093 d4b0d468 Blue Swirl
    if (src1 < src2)
1094 d4b0d468 Blue Swirl
        ret |= PSR_CARRY;
1095 d4b0d468 Blue Swirl
    return ret;
1096 d4b0d468 Blue Swirl
}
1097 d4b0d468 Blue Swirl
1098 d4b0d468 Blue Swirl
static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
1099 d4b0d468 Blue Swirl
                                     target_ulong src2)
1100 d4b0d468 Blue Swirl
{
1101 d4b0d468 Blue Swirl
    uint32_t ret = 0;
1102 d4b0d468 Blue Swirl
1103 d4b0d468 Blue Swirl
    if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63))
1104 d4b0d468 Blue Swirl
        ret |= PSR_OVF;
1105 d4b0d468 Blue Swirl
    return ret;
1106 d4b0d468 Blue Swirl
}
1107 d4b0d468 Blue Swirl
1108 d4b0d468 Blue Swirl
static uint32_t compute_all_sub_xcc(void)
1109 d4b0d468 Blue Swirl
{
1110 d4b0d468 Blue Swirl
    uint32_t ret;
1111 d4b0d468 Blue Swirl
1112 d4b0d468 Blue Swirl
    ret = get_NZ_xcc(CC_DST);
1113 d4b0d468 Blue Swirl
    ret |= get_C_sub_xcc(CC_SRC, CC_SRC2);
1114 d4b0d468 Blue Swirl
    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1115 d4b0d468 Blue Swirl
    return ret;
1116 d4b0d468 Blue Swirl
}
1117 d4b0d468 Blue Swirl
1118 d4b0d468 Blue Swirl
static uint32_t compute_C_sub_xcc(void)
1119 d4b0d468 Blue Swirl
{
1120 d4b0d468 Blue Swirl
    return get_C_sub_xcc(CC_SRC, CC_SRC2);
1121 d4b0d468 Blue Swirl
}
1122 d4b0d468 Blue Swirl
#endif
1123 d4b0d468 Blue Swirl
1124 3e6ba503 Artyom Tarasenko
static uint32_t compute_all_sub(void)
1125 2ca1d92b Blue Swirl
{
1126 2ca1d92b Blue Swirl
    uint32_t ret;
1127 2ca1d92b Blue Swirl
1128 2ca1d92b Blue Swirl
    ret = get_NZ_icc(CC_DST);
1129 3e6ba503 Artyom Tarasenko
    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1130 2ca1d92b Blue Swirl
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1131 2ca1d92b Blue Swirl
    return ret;
1132 2ca1d92b Blue Swirl
}
1133 2ca1d92b Blue Swirl
1134 3e6ba503 Artyom Tarasenko
static uint32_t compute_C_sub(void)
1135 2ca1d92b Blue Swirl
{
1136 3e6ba503 Artyom Tarasenko
    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1137 2ca1d92b Blue Swirl
}
1138 2ca1d92b Blue Swirl
1139 2ca1d92b Blue Swirl
#ifdef TARGET_SPARC64
1140 2ca1d92b Blue Swirl
static uint32_t compute_all_subx_xcc(void)
1141 2ca1d92b Blue Swirl
{
1142 2ca1d92b Blue Swirl
    uint32_t ret;
1143 2ca1d92b Blue Swirl
1144 2ca1d92b Blue Swirl
    ret = get_NZ_xcc(CC_DST);
1145 2ca1d92b Blue Swirl
    ret |= get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
1146 2ca1d92b Blue Swirl
    ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
1147 2ca1d92b Blue Swirl
    ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
1148 2ca1d92b Blue Swirl
    return ret;
1149 2ca1d92b Blue Swirl
}
1150 2ca1d92b Blue Swirl
1151 2ca1d92b Blue Swirl
static uint32_t compute_C_subx_xcc(void)
1152 2ca1d92b Blue Swirl
{
1153 2ca1d92b Blue Swirl
    uint32_t ret;
1154 2ca1d92b Blue Swirl
1155 2ca1d92b Blue Swirl
    ret = get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
1156 2ca1d92b Blue Swirl
    ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
1157 2ca1d92b Blue Swirl
    return ret;
1158 2ca1d92b Blue Swirl
}
1159 2ca1d92b Blue Swirl
#endif
1160 2ca1d92b Blue Swirl
1161 3b2d1e92 Blue Swirl
static uint32_t compute_all_tsub(void)
1162 3b2d1e92 Blue Swirl
{
1163 3b2d1e92 Blue Swirl
    uint32_t ret;
1164 3b2d1e92 Blue Swirl
1165 3b2d1e92 Blue Swirl
    ret = get_NZ_icc(CC_DST);
1166 3e6ba503 Artyom Tarasenko
    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1167 3b2d1e92 Blue Swirl
    ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1168 3b2d1e92 Blue Swirl
    ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
1169 3b2d1e92 Blue Swirl
    return ret;
1170 3b2d1e92 Blue Swirl
}
1171 3b2d1e92 Blue Swirl
1172 3b2d1e92 Blue Swirl
static uint32_t compute_C_tsub(void)
1173 3b2d1e92 Blue Swirl
{
1174 3e6ba503 Artyom Tarasenko
    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1175 3b2d1e92 Blue Swirl
}
1176 3b2d1e92 Blue Swirl
1177 3b2d1e92 Blue Swirl
static uint32_t compute_all_tsubtv(void)
1178 3b2d1e92 Blue Swirl
{
1179 3b2d1e92 Blue Swirl
    uint32_t ret;
1180 3b2d1e92 Blue Swirl
1181 3b2d1e92 Blue Swirl
    ret = get_NZ_icc(CC_DST);
1182 3e6ba503 Artyom Tarasenko
    ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1183 3b2d1e92 Blue Swirl
    return ret;
1184 3b2d1e92 Blue Swirl
}
1185 3b2d1e92 Blue Swirl
1186 3b2d1e92 Blue Swirl
static uint32_t compute_C_tsubtv(void)
1187 3b2d1e92 Blue Swirl
{
1188 3e6ba503 Artyom Tarasenko
    return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
1189 3b2d1e92 Blue Swirl
}
1190 3b2d1e92 Blue Swirl
1191 38482a77 Blue Swirl
static uint32_t compute_all_logic(void)
1192 38482a77 Blue Swirl
{
1193 38482a77 Blue Swirl
    return get_NZ_icc(CC_DST);
1194 38482a77 Blue Swirl
}
1195 38482a77 Blue Swirl
1196 38482a77 Blue Swirl
static uint32_t compute_C_logic(void)
1197 38482a77 Blue Swirl
{
1198 38482a77 Blue Swirl
    return 0;
1199 38482a77 Blue Swirl
}
1200 38482a77 Blue Swirl
1201 38482a77 Blue Swirl
#ifdef TARGET_SPARC64
1202 38482a77 Blue Swirl
static uint32_t compute_all_logic_xcc(void)
1203 38482a77 Blue Swirl
{
1204 38482a77 Blue Swirl
    return get_NZ_xcc(CC_DST);
1205 38482a77 Blue Swirl
}
1206 38482a77 Blue Swirl
#endif
1207 38482a77 Blue Swirl
1208 8393617c Blue Swirl
typedef struct CCTable {
1209 8393617c Blue Swirl
    uint32_t (*compute_all)(void); /* return all the flags */
1210 8393617c Blue Swirl
    uint32_t (*compute_c)(void);  /* return the C flag */
1211 8393617c Blue Swirl
} CCTable;
1212 8393617c Blue Swirl
1213 8393617c Blue Swirl
static const CCTable icc_table[CC_OP_NB] = {
1214 8393617c Blue Swirl
    /* CC_OP_DYNAMIC should never happen */
1215 8393617c Blue Swirl
    [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
1216 6c78ea32 Blue Swirl
    [CC_OP_DIV] = { compute_all_div, compute_C_div },
1217 bdf9f35d Blue Swirl
    [CC_OP_ADD] = { compute_all_add, compute_C_add },
1218 3e6ba503 Artyom Tarasenko
    [CC_OP_ADDX] = { compute_all_add, compute_C_add },
1219 3b2d1e92 Blue Swirl
    [CC_OP_TADD] = { compute_all_tadd, compute_C_tadd },
1220 3b2d1e92 Blue Swirl
    [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_taddtv },
1221 d4b0d468 Blue Swirl
    [CC_OP_SUB] = { compute_all_sub, compute_C_sub },
1222 3e6ba503 Artyom Tarasenko
    [CC_OP_SUBX] = { compute_all_sub, compute_C_sub },
1223 3b2d1e92 Blue Swirl
    [CC_OP_TSUB] = { compute_all_tsub, compute_C_tsub },
1224 3b2d1e92 Blue Swirl
    [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_tsubtv },
1225 38482a77 Blue Swirl
    [CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
1226 8393617c Blue Swirl
};
1227 8393617c Blue Swirl
1228 8393617c Blue Swirl
#ifdef TARGET_SPARC64
1229 8393617c Blue Swirl
static const CCTable xcc_table[CC_OP_NB] = {
1230 8393617c Blue Swirl
    /* CC_OP_DYNAMIC should never happen */
1231 8393617c Blue Swirl
    [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
1232 6c78ea32 Blue Swirl
    [CC_OP_DIV] = { compute_all_logic_xcc, compute_C_logic },
1233 bdf9f35d Blue Swirl
    [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
1234 789c91ef Blue Swirl
    [CC_OP_ADDX] = { compute_all_addx_xcc, compute_C_addx_xcc },
1235 3b2d1e92 Blue Swirl
    [CC_OP_TADD] = { compute_all_add_xcc, compute_C_add_xcc },
1236 3b2d1e92 Blue Swirl
    [CC_OP_TADDTV] = { compute_all_add_xcc, compute_C_add_xcc },
1237 d4b0d468 Blue Swirl
    [CC_OP_SUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
1238 2ca1d92b Blue Swirl
    [CC_OP_SUBX] = { compute_all_subx_xcc, compute_C_subx_xcc },
1239 3b2d1e92 Blue Swirl
    [CC_OP_TSUB] = { compute_all_sub_xcc, compute_C_sub_xcc },
1240 3b2d1e92 Blue Swirl
    [CC_OP_TSUBTV] = { compute_all_sub_xcc, compute_C_sub_xcc },
1241 38482a77 Blue Swirl
    [CC_OP_LOGIC] = { compute_all_logic_xcc, compute_C_logic },
1242 8393617c Blue Swirl
};
1243 8393617c Blue Swirl
#endif
1244 8393617c Blue Swirl
1245 8393617c Blue Swirl
void helper_compute_psr(void)
1246 8393617c Blue Swirl
{
1247 8393617c Blue Swirl
    uint32_t new_psr;
1248 8393617c Blue Swirl
1249 8393617c Blue Swirl
    new_psr = icc_table[CC_OP].compute_all();
1250 8393617c Blue Swirl
    env->psr = new_psr;
1251 8393617c Blue Swirl
#ifdef TARGET_SPARC64
1252 8393617c Blue Swirl
    new_psr = xcc_table[CC_OP].compute_all();
1253 8393617c Blue Swirl
    env->xcc = new_psr;
1254 8393617c Blue Swirl
#endif
1255 8393617c Blue Swirl
    CC_OP = CC_OP_FLAGS;
1256 8393617c Blue Swirl
}
1257 8393617c Blue Swirl
1258 8393617c Blue Swirl
uint32_t helper_compute_C_icc(void)
1259 8393617c Blue Swirl
{
1260 8393617c Blue Swirl
    uint32_t ret;
1261 8393617c Blue Swirl
1262 8393617c Blue Swirl
    ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
1263 8393617c Blue Swirl
    return ret;
1264 8393617c Blue Swirl
}
1265 8393617c Blue Swirl
1266 3475187d bellard
#ifdef TARGET_SPARC64
1267 714547bb blueswir1
GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
1268 417454b0 blueswir1
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
1269 64a88d5d blueswir1
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
1270 417454b0 blueswir1
1271 714547bb blueswir1
GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
1272 417454b0 blueswir1
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
1273 64a88d5d blueswir1
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
1274 417454b0 blueswir1
1275 714547bb blueswir1
GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
1276 417454b0 blueswir1
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
1277 64a88d5d blueswir1
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
1278 417454b0 blueswir1
1279 714547bb blueswir1
GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
1280 417454b0 blueswir1
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
1281 64a88d5d blueswir1
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
1282 3475187d bellard
1283 714547bb blueswir1
GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
1284 417454b0 blueswir1
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
1285 64a88d5d blueswir1
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
1286 3475187d bellard
1287 714547bb blueswir1
GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
1288 417454b0 blueswir1
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
1289 4e14008f blueswir1
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
1290 4e14008f blueswir1
#endif
1291 714547bb blueswir1
#undef GEN_FCMPS
1292 3475187d bellard
1293 77f193da blueswir1
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
1294 77f193da blueswir1
    defined(DEBUG_MXCC)
1295 952a328f blueswir1
static void dump_mxcc(CPUState *env)
1296 952a328f blueswir1
{
1297 0bf9e31a Blue Swirl
    printf("mxccdata: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1298 0bf9e31a Blue Swirl
           "\n",
1299 77f193da blueswir1
           env->mxccdata[0], env->mxccdata[1],
1300 77f193da blueswir1
           env->mxccdata[2], env->mxccdata[3]);
1301 0bf9e31a Blue Swirl
    printf("mxccregs: %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1302 0bf9e31a Blue Swirl
           "\n"
1303 0bf9e31a Blue Swirl
           "          %016" PRIx64 " %016" PRIx64 " %016" PRIx64 " %016" PRIx64
1304 0bf9e31a Blue Swirl
           "\n",
1305 77f193da blueswir1
           env->mxccregs[0], env->mxccregs[1],
1306 77f193da blueswir1
           env->mxccregs[2], env->mxccregs[3],
1307 77f193da blueswir1
           env->mxccregs[4], env->mxccregs[5],
1308 77f193da blueswir1
           env->mxccregs[6], env->mxccregs[7]);
1309 952a328f blueswir1
}
1310 952a328f blueswir1
#endif
1311 952a328f blueswir1
1312 1a2fb1c0 blueswir1
#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
1313 1a2fb1c0 blueswir1
    && defined(DEBUG_ASI)
1314 1a2fb1c0 blueswir1
static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
1315 1a2fb1c0 blueswir1
                     uint64_t r1)
1316 8543e2cf blueswir1
{
1317 8543e2cf blueswir1
    switch (size)
1318 8543e2cf blueswir1
    {
1319 8543e2cf blueswir1
    case 1:
1320 1a2fb1c0 blueswir1
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
1321 1a2fb1c0 blueswir1
                    addr, asi, r1 & 0xff);
1322 8543e2cf blueswir1
        break;
1323 8543e2cf blueswir1
    case 2:
1324 1a2fb1c0 blueswir1
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
1325 1a2fb1c0 blueswir1
                    addr, asi, r1 & 0xffff);
1326 8543e2cf blueswir1
        break;
1327 8543e2cf blueswir1
    case 4:
1328 1a2fb1c0 blueswir1
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
1329 1a2fb1c0 blueswir1
                    addr, asi, r1 & 0xffffffff);
1330 8543e2cf blueswir1
        break;
1331 8543e2cf blueswir1
    case 8:
1332 1a2fb1c0 blueswir1
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
1333 1a2fb1c0 blueswir1
                    addr, asi, r1);
1334 8543e2cf blueswir1
        break;
1335 8543e2cf blueswir1
    }
1336 8543e2cf blueswir1
}
1337 8543e2cf blueswir1
#endif
1338 8543e2cf blueswir1
1339 1a2fb1c0 blueswir1
#ifndef TARGET_SPARC64
1340 1a2fb1c0 blueswir1
#ifndef CONFIG_USER_ONLY
1341 1a2fb1c0 blueswir1
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1342 e8af50a3 bellard
{
1343 1a2fb1c0 blueswir1
    uint64_t ret = 0;
1344 8543e2cf blueswir1
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
1345 1a2fb1c0 blueswir1
    uint32_t last_addr = addr;
1346 952a328f blueswir1
#endif
1347 e80cfcfc bellard
1348 c2bc0e38 blueswir1
    helper_check_align(addr, size - 1);
1349 e80cfcfc bellard
    switch (asi) {
1350 6c36d3fa blueswir1
    case 2: /* SuperSparc MXCC registers */
1351 1a2fb1c0 blueswir1
        switch (addr) {
1352 952a328f blueswir1
        case 0x01c00a00: /* MXCC control register */
1353 1a2fb1c0 blueswir1
            if (size == 8)
1354 1a2fb1c0 blueswir1
                ret = env->mxccregs[3];
1355 1a2fb1c0 blueswir1
            else
1356 77f193da blueswir1
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1357 77f193da blueswir1
                             size);
1358 952a328f blueswir1
            break;
1359 952a328f blueswir1
        case 0x01c00a04: /* MXCC control register */
1360 952a328f blueswir1
            if (size == 4)
1361 952a328f blueswir1
                ret = env->mxccregs[3];
1362 952a328f blueswir1
            else
1363 77f193da blueswir1
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1364 77f193da blueswir1
                             size);
1365 952a328f blueswir1
            break;
1366 295db113 blueswir1
        case 0x01c00c00: /* Module reset register */
1367 295db113 blueswir1
            if (size == 8) {
1368 1a2fb1c0 blueswir1
                ret = env->mxccregs[5];
1369 295db113 blueswir1
                // should we do something here?
1370 295db113 blueswir1
            } else
1371 77f193da blueswir1
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1372 77f193da blueswir1
                             size);
1373 295db113 blueswir1
            break;
1374 952a328f blueswir1
        case 0x01c00f00: /* MBus port address register */
1375 1a2fb1c0 blueswir1
            if (size == 8)
1376 1a2fb1c0 blueswir1
                ret = env->mxccregs[7];
1377 1a2fb1c0 blueswir1
            else
1378 77f193da blueswir1
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1379 77f193da blueswir1
                             size);
1380 952a328f blueswir1
            break;
1381 952a328f blueswir1
        default:
1382 77f193da blueswir1
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1383 77f193da blueswir1
                         size);
1384 952a328f blueswir1
            break;
1385 952a328f blueswir1
        }
1386 77f193da blueswir1
        DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
1387 9827e450 blueswir1
                     "addr = %08x -> ret = %" PRIx64 ","
1388 1a2fb1c0 blueswir1
                     "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
1389 952a328f blueswir1
#ifdef DEBUG_MXCC
1390 952a328f blueswir1
        dump_mxcc(env);
1391 952a328f blueswir1
#endif
1392 6c36d3fa blueswir1
        break;
1393 e8af50a3 bellard
    case 3: /* MMU probe */
1394 0f8a249a blueswir1
        {
1395 0f8a249a blueswir1
            int mmulev;
1396 0f8a249a blueswir1
1397 1a2fb1c0 blueswir1
            mmulev = (addr >> 8) & 15;
1398 0f8a249a blueswir1
            if (mmulev > 4)
1399 0f8a249a blueswir1
                ret = 0;
1400 1a2fb1c0 blueswir1
            else
1401 1a2fb1c0 blueswir1
                ret = mmu_probe(env, addr, mmulev);
1402 1a2fb1c0 blueswir1
            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
1403 1a2fb1c0 blueswir1
                        addr, mmulev, ret);
1404 0f8a249a blueswir1
        }
1405 0f8a249a blueswir1
        break;
1406 e8af50a3 bellard
    case 4: /* read MMU regs */
1407 0f8a249a blueswir1
        {
1408 1a2fb1c0 blueswir1
            int reg = (addr >> 8) & 0x1f;
1409 3b46e624 ths
1410 0f8a249a blueswir1
            ret = env->mmuregs[reg];
1411 0f8a249a blueswir1
            if (reg == 3) /* Fault status cleared on read */
1412 3dd9a152 blueswir1
                env->mmuregs[3] = 0;
1413 3dd9a152 blueswir1
            else if (reg == 0x13) /* Fault status read */
1414 3dd9a152 blueswir1
                ret = env->mmuregs[3];
1415 3dd9a152 blueswir1
            else if (reg == 0x14) /* Fault address read */
1416 3dd9a152 blueswir1
                ret = env->mmuregs[4];
1417 1a2fb1c0 blueswir1
            DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
1418 0f8a249a blueswir1
        }
1419 0f8a249a blueswir1
        break;
1420 045380be blueswir1
    case 5: // Turbosparc ITLB Diagnostic
1421 045380be blueswir1
    case 6: // Turbosparc DTLB Diagnostic
1422 045380be blueswir1
    case 7: // Turbosparc IOTLB Diagnostic
1423 045380be blueswir1
        break;
1424 6c36d3fa blueswir1
    case 9: /* Supervisor code access */
1425 6c36d3fa blueswir1
        switch(size) {
1426 6c36d3fa blueswir1
        case 1:
1427 1a2fb1c0 blueswir1
            ret = ldub_code(addr);
1428 6c36d3fa blueswir1
            break;
1429 6c36d3fa blueswir1
        case 2:
1430 a4e7dd52 blueswir1
            ret = lduw_code(addr);
1431 6c36d3fa blueswir1
            break;
1432 6c36d3fa blueswir1
        default:
1433 6c36d3fa blueswir1
        case 4:
1434 a4e7dd52 blueswir1
            ret = ldl_code(addr);
1435 6c36d3fa blueswir1
            break;
1436 6c36d3fa blueswir1
        case 8:
1437 a4e7dd52 blueswir1
            ret = ldq_code(addr);
1438 6c36d3fa blueswir1
            break;
1439 6c36d3fa blueswir1
        }
1440 6c36d3fa blueswir1
        break;
1441 81ad8ba2 blueswir1
    case 0xa: /* User data access */
1442 81ad8ba2 blueswir1
        switch(size) {
1443 81ad8ba2 blueswir1
        case 1:
1444 1a2fb1c0 blueswir1
            ret = ldub_user(addr);
1445 81ad8ba2 blueswir1
            break;
1446 81ad8ba2 blueswir1
        case 2:
1447 a4e7dd52 blueswir1
            ret = lduw_user(addr);
1448 81ad8ba2 blueswir1
            break;
1449 81ad8ba2 blueswir1
        default:
1450 81ad8ba2 blueswir1
        case 4:
1451 a4e7dd52 blueswir1
            ret = ldl_user(addr);
1452 81ad8ba2 blueswir1
            break;
1453 81ad8ba2 blueswir1
        case 8:
1454 a4e7dd52 blueswir1
            ret = ldq_user(addr);
1455 81ad8ba2 blueswir1
            break;
1456 81ad8ba2 blueswir1
        }
1457 81ad8ba2 blueswir1
        break;
1458 81ad8ba2 blueswir1
    case 0xb: /* Supervisor data access */
1459 81ad8ba2 blueswir1
        switch(size) {
1460 81ad8ba2 blueswir1
        case 1:
1461 1a2fb1c0 blueswir1
            ret = ldub_kernel(addr);
1462 81ad8ba2 blueswir1
            break;
1463 81ad8ba2 blueswir1
        case 2:
1464 a4e7dd52 blueswir1
            ret = lduw_kernel(addr);
1465 81ad8ba2 blueswir1
            break;
1466 81ad8ba2 blueswir1
        default:
1467 81ad8ba2 blueswir1
        case 4:
1468 a4e7dd52 blueswir1
            ret = ldl_kernel(addr);
1469 81ad8ba2 blueswir1
            break;
1470 81ad8ba2 blueswir1
        case 8:
1471 a4e7dd52 blueswir1
            ret = ldq_kernel(addr);
1472 81ad8ba2 blueswir1
            break;
1473 81ad8ba2 blueswir1
        }
1474 81ad8ba2 blueswir1
        break;
1475 6c36d3fa blueswir1
    case 0xc: /* I-cache tag */
1476 6c36d3fa blueswir1
    case 0xd: /* I-cache data */
1477 6c36d3fa blueswir1
    case 0xe: /* D-cache tag */
1478 6c36d3fa blueswir1
    case 0xf: /* D-cache data */
1479 6c36d3fa blueswir1
        break;
1480 6c36d3fa blueswir1
    case 0x20: /* MMU passthrough */
1481 02aab46a bellard
        switch(size) {
1482 02aab46a bellard
        case 1:
1483 1a2fb1c0 blueswir1
            ret = ldub_phys(addr);
1484 02aab46a bellard
            break;
1485 02aab46a bellard
        case 2:
1486 a4e7dd52 blueswir1
            ret = lduw_phys(addr);
1487 02aab46a bellard
            break;
1488 02aab46a bellard
        default:
1489 02aab46a bellard
        case 4:
1490 a4e7dd52 blueswir1
            ret = ldl_phys(addr);
1491 02aab46a bellard
            break;
1492 9e61bde5 bellard
        case 8:
1493 a4e7dd52 blueswir1
            ret = ldq_phys(addr);
1494 0f8a249a blueswir1
            break;
1495 02aab46a bellard
        }
1496 0f8a249a blueswir1
        break;
1497 7d85892b blueswir1
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1498 5dcb6b91 blueswir1
        switch(size) {
1499 5dcb6b91 blueswir1
        case 1:
1500 c227f099 Anthony Liguori
            ret = ldub_phys((target_phys_addr_t)addr
1501 c227f099 Anthony Liguori
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1502 5dcb6b91 blueswir1
            break;
1503 5dcb6b91 blueswir1
        case 2:
1504 c227f099 Anthony Liguori
            ret = lduw_phys((target_phys_addr_t)addr
1505 c227f099 Anthony Liguori
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1506 5dcb6b91 blueswir1
            break;
1507 5dcb6b91 blueswir1
        default:
1508 5dcb6b91 blueswir1
        case 4:
1509 c227f099 Anthony Liguori
            ret = ldl_phys((target_phys_addr_t)addr
1510 c227f099 Anthony Liguori
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
1511 5dcb6b91 blueswir1
            break;
1512 5dcb6b91 blueswir1
        case 8:
1513 c227f099 Anthony Liguori
            ret = ldq_phys((target_phys_addr_t)addr
1514 c227f099 Anthony Liguori
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
1515 0f8a249a blueswir1
            break;
1516 5dcb6b91 blueswir1
        }
1517 0f8a249a blueswir1
        break;
1518 045380be blueswir1
    case 0x30: // Turbosparc secondary cache diagnostic
1519 045380be blueswir1
    case 0x31: // Turbosparc RAM snoop
1520 045380be blueswir1
    case 0x32: // Turbosparc page table descriptor diagnostic
1521 666c87aa blueswir1
    case 0x39: /* data cache diagnostic register */
1522 666c87aa blueswir1
        ret = 0;
1523 666c87aa blueswir1
        break;
1524 4017190e blueswir1
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
1525 4017190e blueswir1
        {
1526 4017190e blueswir1
            int reg = (addr >> 8) & 3;
1527 4017190e blueswir1
1528 4017190e blueswir1
            switch(reg) {
1529 4017190e blueswir1
            case 0: /* Breakpoint Value (Addr) */
1530 4017190e blueswir1
                ret = env->mmubpregs[reg];
1531 4017190e blueswir1
                break;
1532 4017190e blueswir1
            case 1: /* Breakpoint Mask */
1533 4017190e blueswir1
                ret = env->mmubpregs[reg];
1534 4017190e blueswir1
                break;
1535 4017190e blueswir1
            case 2: /* Breakpoint Control */
1536 4017190e blueswir1
                ret = env->mmubpregs[reg];
1537 4017190e blueswir1
                break;
1538 4017190e blueswir1
            case 3: /* Breakpoint Status */
1539 4017190e blueswir1
                ret = env->mmubpregs[reg];
1540 4017190e blueswir1
                env->mmubpregs[reg] = 0ULL;
1541 4017190e blueswir1
                break;
1542 4017190e blueswir1
            }
1543 0bf9e31a Blue Swirl
            DPRINTF_MMU("read breakpoint reg[%d] 0x%016" PRIx64 "\n", reg,
1544 0bf9e31a Blue Swirl
                        ret);
1545 4017190e blueswir1
        }
1546 4017190e blueswir1
        break;
1547 045380be blueswir1
    case 8: /* User code access, XXX */
1548 e8af50a3 bellard
    default:
1549 e18231a3 blueswir1
        do_unassigned_access(addr, 0, 0, asi, size);
1550 0f8a249a blueswir1
        ret = 0;
1551 0f8a249a blueswir1
        break;
1552 e8af50a3 bellard
    }
1553 81ad8ba2 blueswir1
    if (sign) {
1554 81ad8ba2 blueswir1
        switch(size) {
1555 81ad8ba2 blueswir1
        case 1:
1556 1a2fb1c0 blueswir1
            ret = (int8_t) ret;
1557 e32664fb blueswir1
            break;
1558 81ad8ba2 blueswir1
        case 2:
1559 1a2fb1c0 blueswir1
            ret = (int16_t) ret;
1560 1a2fb1c0 blueswir1
            break;
1561 1a2fb1c0 blueswir1
        case 4:
1562 1a2fb1c0 blueswir1
            ret = (int32_t) ret;
1563 e32664fb blueswir1
            break;
1564 81ad8ba2 blueswir1
        default:
1565 81ad8ba2 blueswir1
            break;
1566 81ad8ba2 blueswir1
        }
1567 81ad8ba2 blueswir1
    }
1568 8543e2cf blueswir1
#ifdef DEBUG_ASI
1569 1a2fb1c0 blueswir1
    dump_asi("read ", last_addr, asi, size, ret);
1570 8543e2cf blueswir1
#endif
1571 1a2fb1c0 blueswir1
    return ret;
1572 e8af50a3 bellard
}
1573 e8af50a3 bellard
1574 1a2fb1c0 blueswir1
void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
1575 e8af50a3 bellard
{
1576 c2bc0e38 blueswir1
    helper_check_align(addr, size - 1);
1577 e8af50a3 bellard
    switch(asi) {
1578 6c36d3fa blueswir1
    case 2: /* SuperSparc MXCC registers */
1579 1a2fb1c0 blueswir1
        switch (addr) {
1580 952a328f blueswir1
        case 0x01c00000: /* MXCC stream data register 0 */
1581 952a328f blueswir1
            if (size == 8)
1582 1a2fb1c0 blueswir1
                env->mxccdata[0] = val;
1583 952a328f blueswir1
            else
1584 77f193da blueswir1
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1585 77f193da blueswir1
                             size);
1586 952a328f blueswir1
            break;
1587 952a328f blueswir1
        case 0x01c00008: /* MXCC stream data register 1 */
1588 952a328f blueswir1
            if (size == 8)
1589 1a2fb1c0 blueswir1
                env->mxccdata[1] = val;
1590 952a328f blueswir1
            else
1591 77f193da blueswir1
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1592 77f193da blueswir1
                             size);
1593 952a328f blueswir1
            break;
1594 952a328f blueswir1
        case 0x01c00010: /* MXCC stream data register 2 */
1595 952a328f blueswir1
            if (size == 8)
1596 1a2fb1c0 blueswir1
                env->mxccdata[2] = val;
1597 952a328f blueswir1
            else
1598 77f193da blueswir1
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1599 77f193da blueswir1
                             size);
1600 952a328f blueswir1
            break;
1601 952a328f blueswir1
        case 0x01c00018: /* MXCC stream data register 3 */
1602 952a328f blueswir1
            if (size == 8)
1603 1a2fb1c0 blueswir1
                env->mxccdata[3] = val;
1604 952a328f blueswir1
            else
1605 77f193da blueswir1
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1606 77f193da blueswir1
                             size);
1607 952a328f blueswir1
            break;
1608 952a328f blueswir1
        case 0x01c00100: /* MXCC stream source */
1609 952a328f blueswir1
            if (size == 8)
1610 1a2fb1c0 blueswir1
                env->mxccregs[0] = val;
1611 952a328f blueswir1
            else
1612 77f193da blueswir1
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1613 77f193da blueswir1
                             size);
1614 77f193da blueswir1
            env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1615 77f193da blueswir1
                                        0);
1616 77f193da blueswir1
            env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1617 77f193da blueswir1
                                        8);
1618 77f193da blueswir1
            env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1619 77f193da blueswir1
                                        16);
1620 77f193da blueswir1
            env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1621 77f193da blueswir1
                                        24);
1622 952a328f blueswir1
            break;
1623 952a328f blueswir1
        case 0x01c00200: /* MXCC stream destination */
1624 952a328f blueswir1
            if (size == 8)
1625 1a2fb1c0 blueswir1
                env->mxccregs[1] = val;
1626 952a328f blueswir1
            else
1627 77f193da blueswir1
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1628 77f193da blueswir1
                             size);
1629 77f193da blueswir1
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0,
1630 77f193da blueswir1
                     env->mxccdata[0]);
1631 77f193da blueswir1
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8,
1632 77f193da blueswir1
                     env->mxccdata[1]);
1633 77f193da blueswir1
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
1634 77f193da blueswir1
                     env->mxccdata[2]);
1635 77f193da blueswir1
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
1636 77f193da blueswir1
                     env->mxccdata[3]);
1637 952a328f blueswir1
            break;
1638 952a328f blueswir1
        case 0x01c00a00: /* MXCC control register */
1639 952a328f blueswir1
            if (size == 8)
1640 1a2fb1c0 blueswir1
                env->mxccregs[3] = val;
1641 952a328f blueswir1
            else
1642 77f193da blueswir1
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1643 77f193da blueswir1
                             size);
1644 952a328f blueswir1
            break;
1645 952a328f blueswir1
        case 0x01c00a04: /* MXCC control register */
1646 952a328f blueswir1
            if (size == 4)
1647 9f4576f0 blueswir1
                env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
1648 77f193da blueswir1
                    | val;
1649 952a328f blueswir1
            else
1650 77f193da blueswir1
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1651 77f193da blueswir1
                             size);
1652 952a328f blueswir1
            break;
1653 952a328f blueswir1
        case 0x01c00e00: /* MXCC error register  */
1654 bbf7d96b blueswir1
            // writing a 1 bit clears the error
1655 952a328f blueswir1
            if (size == 8)
1656 1a2fb1c0 blueswir1
                env->mxccregs[6] &= ~val;
1657 952a328f blueswir1
            else
1658 77f193da blueswir1
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1659 77f193da blueswir1
                             size);
1660 952a328f blueswir1
            break;
1661 952a328f blueswir1
        case 0x01c00f00: /* MBus port address register */
1662 952a328f blueswir1
            if (size == 8)
1663 1a2fb1c0 blueswir1
                env->mxccregs[7] = val;
1664 952a328f blueswir1
            else
1665 77f193da blueswir1
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1666 77f193da blueswir1
                             size);
1667 952a328f blueswir1
            break;
1668 952a328f blueswir1
        default:
1669 77f193da blueswir1
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1670 77f193da blueswir1
                         size);
1671 952a328f blueswir1
            break;
1672 952a328f blueswir1
        }
1673 9827e450 blueswir1
        DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
1674 9827e450 blueswir1
                     asi, size, addr, val);
1675 952a328f blueswir1
#ifdef DEBUG_MXCC
1676 952a328f blueswir1
        dump_mxcc(env);
1677 952a328f blueswir1
#endif
1678 6c36d3fa blueswir1
        break;
1679 e8af50a3 bellard
    case 3: /* MMU flush */
1680 0f8a249a blueswir1
        {
1681 0f8a249a blueswir1
            int mmulev;
1682 e80cfcfc bellard
1683 1a2fb1c0 blueswir1
            mmulev = (addr >> 8) & 15;
1684 952a328f blueswir1
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
1685 0f8a249a blueswir1
            switch (mmulev) {
1686 0f8a249a blueswir1
            case 0: // flush page
1687 1a2fb1c0 blueswir1
                tlb_flush_page(env, addr & 0xfffff000);
1688 0f8a249a blueswir1
                break;
1689 0f8a249a blueswir1
            case 1: // flush segment (256k)
1690 0f8a249a blueswir1
            case 2: // flush region (16M)
1691 0f8a249a blueswir1
            case 3: // flush context (4G)
1692 0f8a249a blueswir1
            case 4: // flush entire
1693 0f8a249a blueswir1
                tlb_flush(env, 1);
1694 0f8a249a blueswir1
                break;
1695 0f8a249a blueswir1
            default:
1696 0f8a249a blueswir1
                break;
1697 0f8a249a blueswir1
            }
1698 55754d9e bellard
#ifdef DEBUG_MMU
1699 0f8a249a blueswir1
            dump_mmu(env);
1700 55754d9e bellard
#endif
1701 0f8a249a blueswir1
        }
1702 8543e2cf blueswir1
        break;
1703 e8af50a3 bellard
    case 4: /* write MMU regs */
1704 0f8a249a blueswir1
        {
1705 1a2fb1c0 blueswir1
            int reg = (addr >> 8) & 0x1f;
1706 0f8a249a blueswir1
            uint32_t oldreg;
1707 3b46e624 ths
1708 0f8a249a blueswir1
            oldreg = env->mmuregs[reg];
1709 55754d9e bellard
            switch(reg) {
1710 3deaeab7 blueswir1
            case 0: // Control Register
1711 3dd9a152 blueswir1
                env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
1712 1a2fb1c0 blueswir1
                                    (val & 0x00ffffff);
1713 0f8a249a blueswir1
                // Mappings generated during no-fault mode or MMU
1714 0f8a249a blueswir1
                // disabled mode are invalid in normal mode
1715 5578ceab blueswir1
                if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
1716 5578ceab blueswir1
                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
1717 55754d9e bellard
                    tlb_flush(env, 1);
1718 55754d9e bellard
                break;
1719 3deaeab7 blueswir1
            case 1: // Context Table Pointer Register
1720 5578ceab blueswir1
                env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
1721 3deaeab7 blueswir1
                break;
1722 3deaeab7 blueswir1
            case 2: // Context Register
1723 5578ceab blueswir1
                env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
1724 55754d9e bellard
                if (oldreg != env->mmuregs[reg]) {
1725 55754d9e bellard
                    /* we flush when the MMU context changes because
1726 55754d9e bellard
                       QEMU has no MMU context support */
1727 55754d9e bellard
                    tlb_flush(env, 1);
1728 55754d9e bellard
                }
1729 55754d9e bellard
                break;
1730 3deaeab7 blueswir1
            case 3: // Synchronous Fault Status Register with Clear
1731 3deaeab7 blueswir1
            case 4: // Synchronous Fault Address Register
1732 3deaeab7 blueswir1
                break;
1733 3deaeab7 blueswir1
            case 0x10: // TLB Replacement Control Register
1734 5578ceab blueswir1
                env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
1735 55754d9e bellard
                break;
1736 3deaeab7 blueswir1
            case 0x13: // Synchronous Fault Status Register with Read and Clear
1737 5578ceab blueswir1
                env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
1738 3dd9a152 blueswir1
                break;
1739 3deaeab7 blueswir1
            case 0x14: // Synchronous Fault Address Register
1740 1a2fb1c0 blueswir1
                env->mmuregs[4] = val;
1741 3dd9a152 blueswir1
                break;
1742 55754d9e bellard
            default:
1743 1a2fb1c0 blueswir1
                env->mmuregs[reg] = val;
1744 55754d9e bellard
                break;
1745 55754d9e bellard
            }
1746 55754d9e bellard
            if (oldreg != env->mmuregs[reg]) {
1747 77f193da blueswir1
                DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
1748 77f193da blueswir1
                            reg, oldreg, env->mmuregs[reg]);
1749 55754d9e bellard
            }
1750 952a328f blueswir1
#ifdef DEBUG_MMU
1751 0f8a249a blueswir1
            dump_mmu(env);
1752 55754d9e bellard
#endif
1753 0f8a249a blueswir1
        }
1754 8543e2cf blueswir1
        break;
1755 045380be blueswir1
    case 5: // Turbosparc ITLB Diagnostic
1756 045380be blueswir1
    case 6: // Turbosparc DTLB Diagnostic
1757 045380be blueswir1
    case 7: // Turbosparc IOTLB Diagnostic
1758 045380be blueswir1
        break;
1759 81ad8ba2 blueswir1
    case 0xa: /* User data access */
1760 81ad8ba2 blueswir1
        switch(size) {
1761 81ad8ba2 blueswir1
        case 1:
1762 1a2fb1c0 blueswir1
            stb_user(addr, val);
1763 81ad8ba2 blueswir1
            break;
1764 81ad8ba2 blueswir1
        case 2:
1765 a4e7dd52 blueswir1
            stw_user(addr, val);
1766 81ad8ba2 blueswir1
            break;
1767 81ad8ba2 blueswir1
        default:
1768 81ad8ba2 blueswir1
        case 4:
1769 a4e7dd52 blueswir1
            stl_user(addr, val);
1770 81ad8ba2 blueswir1
            break;
1771 81ad8ba2 blueswir1
        case 8:
1772 a4e7dd52 blueswir1
            stq_user(addr, val);
1773 81ad8ba2 blueswir1
            break;
1774 81ad8ba2 blueswir1
        }
1775 81ad8ba2 blueswir1
        break;
1776 81ad8ba2 blueswir1
    case 0xb: /* Supervisor data access */
1777 81ad8ba2 blueswir1
        switch(size) {
1778 81ad8ba2 blueswir1
        case 1:
1779 1a2fb1c0 blueswir1
            stb_kernel(addr, val);
1780 81ad8ba2 blueswir1
            break;
1781 81ad8ba2 blueswir1
        case 2:
1782 a4e7dd52 blueswir1
            stw_kernel(addr, val);
1783 81ad8ba2 blueswir1
            break;
1784 81ad8ba2 blueswir1
        default:
1785 81ad8ba2 blueswir1
        case 4:
1786 a4e7dd52 blueswir1
            stl_kernel(addr, val);
1787 81ad8ba2 blueswir1
            break;
1788 81ad8ba2 blueswir1
        case 8:
1789 a4e7dd52 blueswir1
            stq_kernel(addr, val);
1790 81ad8ba2 blueswir1
            break;
1791 81ad8ba2 blueswir1
        }
1792 81ad8ba2 blueswir1
        break;
1793 6c36d3fa blueswir1
    case 0xc: /* I-cache tag */
1794 6c36d3fa blueswir1
    case 0xd: /* I-cache data */
1795 6c36d3fa blueswir1
    case 0xe: /* D-cache tag */
1796 6c36d3fa blueswir1
    case 0xf: /* D-cache data */
1797 6c36d3fa blueswir1
    case 0x10: /* I/D-cache flush page */
1798 6c36d3fa blueswir1
    case 0x11: /* I/D-cache flush segment */
1799 6c36d3fa blueswir1
    case 0x12: /* I/D-cache flush region */
1800 6c36d3fa blueswir1
    case 0x13: /* I/D-cache flush context */
1801 6c36d3fa blueswir1
    case 0x14: /* I/D-cache flush user */
1802 6c36d3fa blueswir1
        break;
1803 e80cfcfc bellard
    case 0x17: /* Block copy, sta access */
1804 0f8a249a blueswir1
        {
1805 1a2fb1c0 blueswir1
            // val = src
1806 1a2fb1c0 blueswir1
            // addr = dst
1807 0f8a249a blueswir1
            // copy 32 bytes
1808 6c36d3fa blueswir1
            unsigned int i;
1809 1a2fb1c0 blueswir1
            uint32_t src = val & ~3, dst = addr & ~3, temp;
1810 3b46e624 ths
1811 6c36d3fa blueswir1
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1812 6c36d3fa blueswir1
                temp = ldl_kernel(src);
1813 6c36d3fa blueswir1
                stl_kernel(dst, temp);
1814 6c36d3fa blueswir1
            }
1815 0f8a249a blueswir1
        }
1816 8543e2cf blueswir1
        break;
1817 e80cfcfc bellard
    case 0x1f: /* Block fill, stda access */
1818 0f8a249a blueswir1
        {
1819 1a2fb1c0 blueswir1
            // addr = dst
1820 1a2fb1c0 blueswir1
            // fill 32 bytes with val
1821 6c36d3fa blueswir1
            unsigned int i;
1822 1a2fb1c0 blueswir1
            uint32_t dst = addr & 7;
1823 6c36d3fa blueswir1
1824 6c36d3fa blueswir1
            for (i = 0; i < 32; i += 8, dst += 8)
1825 6c36d3fa blueswir1
                stq_kernel(dst, val);
1826 0f8a249a blueswir1
        }
1827 8543e2cf blueswir1
        break;
1828 6c36d3fa blueswir1
    case 0x20: /* MMU passthrough */
1829 0f8a249a blueswir1
        {
1830 02aab46a bellard
            switch(size) {
1831 02aab46a bellard
            case 1:
1832 1a2fb1c0 blueswir1
                stb_phys(addr, val);
1833 02aab46a bellard
                break;
1834 02aab46a bellard
            case 2:
1835 a4e7dd52 blueswir1
                stw_phys(addr, val);
1836 02aab46a bellard
                break;
1837 02aab46a bellard
            case 4:
1838 02aab46a bellard
            default:
1839 a4e7dd52 blueswir1
                stl_phys(addr, val);
1840 02aab46a bellard
                break;
1841 9e61bde5 bellard
            case 8:
1842 a4e7dd52 blueswir1
                stq_phys(addr, val);
1843 9e61bde5 bellard
                break;
1844 02aab46a bellard
            }
1845 0f8a249a blueswir1
        }
1846 8543e2cf blueswir1
        break;
1847 045380be blueswir1
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1848 0f8a249a blueswir1
        {
1849 5dcb6b91 blueswir1
            switch(size) {
1850 5dcb6b91 blueswir1
            case 1:
1851 c227f099 Anthony Liguori
                stb_phys((target_phys_addr_t)addr
1852 c227f099 Anthony Liguori
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1853 5dcb6b91 blueswir1
                break;
1854 5dcb6b91 blueswir1
            case 2:
1855 c227f099 Anthony Liguori
                stw_phys((target_phys_addr_t)addr
1856 c227f099 Anthony Liguori
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1857 5dcb6b91 blueswir1
                break;
1858 5dcb6b91 blueswir1
            case 4:
1859 5dcb6b91 blueswir1
            default:
1860 c227f099 Anthony Liguori
                stl_phys((target_phys_addr_t)addr
1861 c227f099 Anthony Liguori
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1862 5dcb6b91 blueswir1
                break;
1863 5dcb6b91 blueswir1
            case 8:
1864 c227f099 Anthony Liguori
                stq_phys((target_phys_addr_t)addr
1865 c227f099 Anthony Liguori
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1866 5dcb6b91 blueswir1
                break;
1867 5dcb6b91 blueswir1
            }
1868 0f8a249a blueswir1
        }
1869 8543e2cf blueswir1
        break;
1870 045380be blueswir1
    case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
1871 045380be blueswir1
    case 0x31: // store buffer data, Ross RT620 I-cache flush or
1872 045380be blueswir1
               // Turbosparc snoop RAM
1873 77f193da blueswir1
    case 0x32: // store buffer control or Turbosparc page table
1874 77f193da blueswir1
               // descriptor diagnostic
1875 6c36d3fa blueswir1
    case 0x36: /* I-cache flash clear */
1876 6c36d3fa blueswir1
    case 0x37: /* D-cache flash clear */
1877 666c87aa blueswir1
    case 0x4c: /* breakpoint action */
1878 6c36d3fa blueswir1
        break;
1879 4017190e blueswir1
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
1880 4017190e blueswir1
        {
1881 4017190e blueswir1
            int reg = (addr >> 8) & 3;
1882 4017190e blueswir1
1883 4017190e blueswir1
            switch(reg) {
1884 4017190e blueswir1
            case 0: /* Breakpoint Value (Addr) */
1885 4017190e blueswir1
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
1886 4017190e blueswir1
                break;
1887 4017190e blueswir1
            case 1: /* Breakpoint Mask */
1888 4017190e blueswir1
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
1889 4017190e blueswir1
                break;
1890 4017190e blueswir1
            case 2: /* Breakpoint Control */
1891 4017190e blueswir1
                env->mmubpregs[reg] = (val & 0x7fULL);
1892 4017190e blueswir1
                break;
1893 4017190e blueswir1
            case 3: /* Breakpoint Status */
1894 4017190e blueswir1
                env->mmubpregs[reg] = (val & 0xfULL);
1895 4017190e blueswir1
                break;
1896 4017190e blueswir1
            }
1897 0bf9e31a Blue Swirl
            DPRINTF_MMU("write breakpoint reg[%d] 0x%016x\n", reg,
1898 4017190e blueswir1
                        env->mmuregs[reg]);
1899 4017190e blueswir1
        }
1900 4017190e blueswir1
        break;
1901 045380be blueswir1
    case 8: /* User code access, XXX */
1902 6c36d3fa blueswir1
    case 9: /* Supervisor code access, XXX */
1903 e8af50a3 bellard
    default:
1904 e18231a3 blueswir1
        do_unassigned_access(addr, 1, 0, asi, size);
1905 8543e2cf blueswir1
        break;
1906 e8af50a3 bellard
    }
1907 8543e2cf blueswir1
#ifdef DEBUG_ASI
1908 1a2fb1c0 blueswir1
    dump_asi("write", addr, asi, size, val);
1909 8543e2cf blueswir1
#endif
1910 e8af50a3 bellard
}
1911 e8af50a3 bellard
1912 81ad8ba2 blueswir1
#endif /* CONFIG_USER_ONLY */
1913 81ad8ba2 blueswir1
#else /* TARGET_SPARC64 */
1914 81ad8ba2 blueswir1
1915 81ad8ba2 blueswir1
#ifdef CONFIG_USER_ONLY
1916 1a2fb1c0 blueswir1
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1917 81ad8ba2 blueswir1
{
1918 81ad8ba2 blueswir1
    uint64_t ret = 0;
1919 1a2fb1c0 blueswir1
#if defined(DEBUG_ASI)
1920 1a2fb1c0 blueswir1
    target_ulong last_addr = addr;
1921 1a2fb1c0 blueswir1
#endif
1922 81ad8ba2 blueswir1
1923 81ad8ba2 blueswir1
    if (asi < 0x80)
1924 81ad8ba2 blueswir1
        raise_exception(TT_PRIV_ACT);
1925 81ad8ba2 blueswir1
1926 c2bc0e38 blueswir1
    helper_check_align(addr, size - 1);
1927 41db525e Richard Henderson
    addr = address_mask(env, addr);
1928 c2bc0e38 blueswir1
1929 81ad8ba2 blueswir1
    switch (asi) {
1930 81ad8ba2 blueswir1
    case 0x82: // Primary no-fault
1931 81ad8ba2 blueswir1
    case 0x8a: // Primary no-fault LE
1932 e83ce550 blueswir1
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1933 e83ce550 blueswir1
#ifdef DEBUG_ASI
1934 e83ce550 blueswir1
            dump_asi("read ", last_addr, asi, size, ret);
1935 e83ce550 blueswir1
#endif
1936 e83ce550 blueswir1
            return 0;
1937 e83ce550 blueswir1
        }
1938 e83ce550 blueswir1
        // Fall through
1939 e83ce550 blueswir1
    case 0x80: // Primary
1940 e83ce550 blueswir1
    case 0x88: // Primary LE
1941 81ad8ba2 blueswir1
        {
1942 81ad8ba2 blueswir1
            switch(size) {
1943 81ad8ba2 blueswir1
            case 1:
1944 1a2fb1c0 blueswir1
                ret = ldub_raw(addr);
1945 81ad8ba2 blueswir1
                break;
1946 81ad8ba2 blueswir1
            case 2:
1947 a4e7dd52 blueswir1
                ret = lduw_raw(addr);
1948 81ad8ba2 blueswir1
                break;
1949 81ad8ba2 blueswir1
            case 4:
1950 a4e7dd52 blueswir1
                ret = ldl_raw(addr);
1951 81ad8ba2 blueswir1
                break;
1952 81ad8ba2 blueswir1
            default:
1953 81ad8ba2 blueswir1
            case 8:
1954 a4e7dd52 blueswir1
                ret = ldq_raw(addr);
1955 81ad8ba2 blueswir1
                break;
1956 81ad8ba2 blueswir1
            }
1957 81ad8ba2 blueswir1
        }
1958 81ad8ba2 blueswir1
        break;
1959 81ad8ba2 blueswir1
    case 0x83: // Secondary no-fault
1960 81ad8ba2 blueswir1
    case 0x8b: // Secondary no-fault LE
1961 e83ce550 blueswir1
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1962 e83ce550 blueswir1
#ifdef DEBUG_ASI
1963 e83ce550 blueswir1
            dump_asi("read ", last_addr, asi, size, ret);
1964 e83ce550 blueswir1
#endif
1965 e83ce550 blueswir1
            return 0;
1966 e83ce550 blueswir1
        }
1967 e83ce550 blueswir1
        // Fall through
1968 e83ce550 blueswir1
    case 0x81: // Secondary
1969 e83ce550 blueswir1
    case 0x89: // Secondary LE
1970 81ad8ba2 blueswir1
        // XXX
1971 81ad8ba2 blueswir1
        break;
1972 81ad8ba2 blueswir1
    default:
1973 81ad8ba2 blueswir1
        break;
1974 81ad8ba2 blueswir1
    }
1975 81ad8ba2 blueswir1
1976 81ad8ba2 blueswir1
    /* Convert from little endian */
1977 81ad8ba2 blueswir1
    switch (asi) {
1978 81ad8ba2 blueswir1
    case 0x88: // Primary LE
1979 81ad8ba2 blueswir1
    case 0x89: // Secondary LE
1980 81ad8ba2 blueswir1
    case 0x8a: // Primary no-fault LE
1981 81ad8ba2 blueswir1
    case 0x8b: // Secondary no-fault LE
1982 81ad8ba2 blueswir1
        switch(size) {
1983 81ad8ba2 blueswir1
        case 2:
1984 81ad8ba2 blueswir1
            ret = bswap16(ret);
1985 e32664fb blueswir1
            break;
1986 81ad8ba2 blueswir1
        case 4:
1987 81ad8ba2 blueswir1
            ret = bswap32(ret);
1988 e32664fb blueswir1
            break;
1989 81ad8ba2 blueswir1
        case 8:
1990 81ad8ba2 blueswir1
            ret = bswap64(ret);
1991 e32664fb blueswir1
            break;
1992 81ad8ba2 blueswir1
        default:
1993 81ad8ba2 blueswir1
            break;
1994 81ad8ba2 blueswir1
        }
1995 81ad8ba2 blueswir1
    default:
1996 81ad8ba2 blueswir1
        break;
1997 81ad8ba2 blueswir1
    }
1998 81ad8ba2 blueswir1
1999 81ad8ba2 blueswir1
    /* Convert to signed number */
2000 81ad8ba2 blueswir1
    if (sign) {
2001 81ad8ba2 blueswir1
        switch(size) {
2002 81ad8ba2 blueswir1
        case 1:
2003 81ad8ba2 blueswir1
            ret = (int8_t) ret;
2004 e32664fb blueswir1
            break;
2005 81ad8ba2 blueswir1
        case 2:
2006 81ad8ba2 blueswir1
            ret = (int16_t) ret;
2007 e32664fb blueswir1
            break;
2008 81ad8ba2 blueswir1
        case 4:
2009 81ad8ba2 blueswir1
            ret = (int32_t) ret;
2010 e32664fb blueswir1
            break;
2011 81ad8ba2 blueswir1
        default:
2012 81ad8ba2 blueswir1
            break;
2013 81ad8ba2 blueswir1
        }
2014 81ad8ba2 blueswir1
    }
2015 1a2fb1c0 blueswir1
#ifdef DEBUG_ASI
2016 1a2fb1c0 blueswir1
    dump_asi("read ", last_addr, asi, size, ret);
2017 1a2fb1c0 blueswir1
#endif
2018 1a2fb1c0 blueswir1
    return ret;
2019 81ad8ba2 blueswir1
}
2020 81ad8ba2 blueswir1
2021 1a2fb1c0 blueswir1
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2022 81ad8ba2 blueswir1
{
2023 1a2fb1c0 blueswir1
#ifdef DEBUG_ASI
2024 1a2fb1c0 blueswir1
    dump_asi("write", addr, asi, size, val);
2025 1a2fb1c0 blueswir1
#endif
2026 81ad8ba2 blueswir1
    if (asi < 0x80)
2027 81ad8ba2 blueswir1
        raise_exception(TT_PRIV_ACT);
2028 81ad8ba2 blueswir1
2029 c2bc0e38 blueswir1
    helper_check_align(addr, size - 1);
2030 41db525e Richard Henderson
    addr = address_mask(env, addr);
2031 c2bc0e38 blueswir1
2032 81ad8ba2 blueswir1
    /* Convert to little endian */
2033 81ad8ba2 blueswir1
    switch (asi) {
2034 81ad8ba2 blueswir1
    case 0x88: // Primary LE
2035 81ad8ba2 blueswir1
    case 0x89: // Secondary LE
2036 81ad8ba2 blueswir1
        switch(size) {
2037 81ad8ba2 blueswir1
        case 2:
2038 5b0f0bec Igor Kovalenko
            val = bswap16(val);
2039 e32664fb blueswir1
            break;
2040 81ad8ba2 blueswir1
        case 4:
2041 5b0f0bec Igor Kovalenko
            val = bswap32(val);
2042 e32664fb blueswir1
            break;
2043 81ad8ba2 blueswir1
        case 8:
2044 5b0f0bec Igor Kovalenko
            val = bswap64(val);
2045 e32664fb blueswir1
            break;
2046 81ad8ba2 blueswir1
        default:
2047 81ad8ba2 blueswir1
            break;
2048 81ad8ba2 blueswir1
        }
2049 81ad8ba2 blueswir1
    default:
2050 81ad8ba2 blueswir1
        break;
2051 81ad8ba2 blueswir1
    }
2052 81ad8ba2 blueswir1
2053 81ad8ba2 blueswir1
    switch(asi) {
2054 81ad8ba2 blueswir1
    case 0x80: // Primary
2055 81ad8ba2 blueswir1
    case 0x88: // Primary LE
2056 81ad8ba2 blueswir1
        {
2057 81ad8ba2 blueswir1
            switch(size) {
2058 81ad8ba2 blueswir1
            case 1:
2059 1a2fb1c0 blueswir1
                stb_raw(addr, val);
2060 81ad8ba2 blueswir1
                break;
2061 81ad8ba2 blueswir1
            case 2:
2062 a4e7dd52 blueswir1
                stw_raw(addr, val);
2063 81ad8ba2 blueswir1
                break;
2064 81ad8ba2 blueswir1
            case 4:
2065 a4e7dd52 blueswir1
                stl_raw(addr, val);
2066 81ad8ba2 blueswir1
                break;
2067 81ad8ba2 blueswir1
            case 8:
2068 81ad8ba2 blueswir1
            default:
2069 a4e7dd52 blueswir1
                stq_raw(addr, val);
2070 81ad8ba2 blueswir1
                break;
2071 81ad8ba2 blueswir1
            }
2072 81ad8ba2 blueswir1
        }
2073 81ad8ba2 blueswir1
        break;
2074 81ad8ba2 blueswir1
    case 0x81: // Secondary
2075 81ad8ba2 blueswir1
    case 0x89: // Secondary LE
2076 81ad8ba2 blueswir1
        // XXX
2077 81ad8ba2 blueswir1
        return;
2078 81ad8ba2 blueswir1
2079 81ad8ba2 blueswir1
    case 0x82: // Primary no-fault, RO
2080 81ad8ba2 blueswir1
    case 0x83: // Secondary no-fault, RO
2081 81ad8ba2 blueswir1
    case 0x8a: // Primary no-fault LE, RO
2082 81ad8ba2 blueswir1
    case 0x8b: // Secondary no-fault LE, RO
2083 81ad8ba2 blueswir1
    default:
2084 e18231a3 blueswir1
        do_unassigned_access(addr, 1, 0, 1, size);
2085 81ad8ba2 blueswir1
        return;
2086 81ad8ba2 blueswir1
    }
2087 81ad8ba2 blueswir1
}
2088 81ad8ba2 blueswir1
2089 81ad8ba2 blueswir1
#else /* CONFIG_USER_ONLY */
2090 3475187d bellard
2091 1a2fb1c0 blueswir1
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
2092 3475187d bellard
{
2093 83469015 bellard
    uint64_t ret = 0;
2094 1a2fb1c0 blueswir1
#if defined(DEBUG_ASI)
2095 1a2fb1c0 blueswir1
    target_ulong last_addr = addr;
2096 1a2fb1c0 blueswir1
#endif
2097 3475187d bellard
2098 01b5d4e5 Igor V. Kovalenko
    asi &= 0xff;
2099 01b5d4e5 Igor V. Kovalenko
2100 6f27aba6 blueswir1
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2101 5578ceab blueswir1
        || ((env->def->features & CPU_FEATURE_HYPV)
2102 5578ceab blueswir1
            && asi >= 0x30 && asi < 0x80
2103 fb79ceb9 blueswir1
            && !(env->hpstate & HS_PRIV)))
2104 0f8a249a blueswir1
        raise_exception(TT_PRIV_ACT);
2105 3475187d bellard
2106 c2bc0e38 blueswir1
    helper_check_align(addr, size - 1);
2107 3475187d bellard
    switch (asi) {
2108 e83ce550 blueswir1
    case 0x82: // Primary no-fault
2109 e83ce550 blueswir1
    case 0x8a: // Primary no-fault LE
2110 e83ce550 blueswir1
        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
2111 e83ce550 blueswir1
#ifdef DEBUG_ASI
2112 e83ce550 blueswir1
            dump_asi("read ", last_addr, asi, size, ret);
2113 e83ce550 blueswir1
#endif
2114 e83ce550 blueswir1
            return 0;
2115 e83ce550 blueswir1
        }
2116 e83ce550 blueswir1
        // Fall through
2117 81ad8ba2 blueswir1
    case 0x10: // As if user primary
2118 81ad8ba2 blueswir1
    case 0x18: // As if user primary LE
2119 81ad8ba2 blueswir1
    case 0x80: // Primary
2120 81ad8ba2 blueswir1
    case 0x88: // Primary LE
2121 c99657d3 blueswir1
    case 0xe2: // UA2007 Primary block init
2122 c99657d3 blueswir1
    case 0xe3: // UA2007 Secondary block init
2123 81ad8ba2 blueswir1
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
2124 5578ceab blueswir1
            if ((env->def->features & CPU_FEATURE_HYPV)
2125 5578ceab blueswir1
                && env->hpstate & HS_PRIV) {
2126 6f27aba6 blueswir1
                switch(size) {
2127 6f27aba6 blueswir1
                case 1:
2128 1a2fb1c0 blueswir1
                    ret = ldub_hypv(addr);
2129 6f27aba6 blueswir1
                    break;
2130 6f27aba6 blueswir1
                case 2:
2131 a4e7dd52 blueswir1
                    ret = lduw_hypv(addr);
2132 6f27aba6 blueswir1
                    break;
2133 6f27aba6 blueswir1
                case 4:
2134 a4e7dd52 blueswir1
                    ret = ldl_hypv(addr);
2135 6f27aba6 blueswir1
                    break;
2136 6f27aba6 blueswir1
                default:
2137 6f27aba6 blueswir1
                case 8:
2138 a4e7dd52 blueswir1
                    ret = ldq_hypv(addr);
2139 6f27aba6 blueswir1
                    break;
2140 6f27aba6 blueswir1
                }
2141 6f27aba6 blueswir1
            } else {
2142 6f27aba6 blueswir1
                switch(size) {
2143 6f27aba6 blueswir1
                case 1:
2144 1a2fb1c0 blueswir1
                    ret = ldub_kernel(addr);
2145 6f27aba6 blueswir1
                    break;
2146 6f27aba6 blueswir1
                case 2:
2147 a4e7dd52 blueswir1
                    ret = lduw_kernel(addr);
2148 6f27aba6 blueswir1
                    break;
2149 6f27aba6 blueswir1
                case 4:
2150 a4e7dd52 blueswir1
                    ret = ldl_kernel(addr);
2151 6f27aba6 blueswir1
                    break;
2152 6f27aba6 blueswir1
                default:
2153 6f27aba6 blueswir1
                case 8:
2154 a4e7dd52 blueswir1
                    ret = ldq_kernel(addr);
2155 6f27aba6 blueswir1
                    break;
2156 6f27aba6 blueswir1
                }
2157 81ad8ba2 blueswir1
            }
2158 81ad8ba2 blueswir1
        } else {
2159 81ad8ba2 blueswir1
            switch(size) {
2160 81ad8ba2 blueswir1
            case 1:
2161 1a2fb1c0 blueswir1
                ret = ldub_user(addr);
2162 81ad8ba2 blueswir1
                break;
2163 81ad8ba2 blueswir1
            case 2:
2164 a4e7dd52 blueswir1
                ret = lduw_user(addr);
2165 81ad8ba2 blueswir1
                break;
2166 81ad8ba2 blueswir1
            case 4:
2167 a4e7dd52 blueswir1
                ret = ldl_user(addr);
2168 81ad8ba2 blueswir1
                break;
2169 81ad8ba2 blueswir1
            default:
2170 81ad8ba2 blueswir1
            case 8:
2171 a4e7dd52 blueswir1
                ret = ldq_user(addr);
2172 81ad8ba2 blueswir1
                break;
2173 81ad8ba2 blueswir1
            }
2174 81ad8ba2 blueswir1
        }
2175 81ad8ba2 blueswir1
        break;
2176 3475187d bellard
    case 0x14: // Bypass
2177 3475187d bellard
    case 0x15: // Bypass, non-cacheable
2178 81ad8ba2 blueswir1
    case 0x1c: // Bypass LE
2179 81ad8ba2 blueswir1
    case 0x1d: // Bypass, non-cacheable LE
2180 0f8a249a blueswir1
        {
2181 02aab46a bellard
            switch(size) {
2182 02aab46a bellard
            case 1:
2183 1a2fb1c0 blueswir1
                ret = ldub_phys(addr);
2184 02aab46a bellard
                break;
2185 02aab46a bellard
            case 2:
2186 a4e7dd52 blueswir1
                ret = lduw_phys(addr);
2187 02aab46a bellard
                break;
2188 02aab46a bellard
            case 4:
2189 a4e7dd52 blueswir1
                ret = ldl_phys(addr);
2190 02aab46a bellard
                break;
2191 02aab46a bellard
            default:
2192 02aab46a bellard
            case 8:
2193 a4e7dd52 blueswir1
                ret = ldq_phys(addr);
2194 02aab46a bellard
                break;
2195 02aab46a bellard
            }
2196 0f8a249a blueswir1
            break;
2197 0f8a249a blueswir1
        }
2198 db166940 blueswir1
    case 0x24: // Nucleus quad LDD 128 bit atomic
2199 db166940 blueswir1
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2200 db166940 blueswir1
        //  Only ldda allowed
2201 db166940 blueswir1
        raise_exception(TT_ILL_INSN);
2202 db166940 blueswir1
        return 0;
2203 e83ce550 blueswir1
    case 0x83: // Secondary no-fault
2204 e83ce550 blueswir1
    case 0x8b: // Secondary no-fault LE
2205 e83ce550 blueswir1
        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
2206 e83ce550 blueswir1
#ifdef DEBUG_ASI
2207 e83ce550 blueswir1
            dump_asi("read ", last_addr, asi, size, ret);
2208 e83ce550 blueswir1
#endif
2209 e83ce550 blueswir1
            return 0;
2210 e83ce550 blueswir1
        }
2211 e83ce550 blueswir1
        // Fall through
2212 83469015 bellard
    case 0x04: // Nucleus
2213 83469015 bellard
    case 0x0c: // Nucleus Little Endian (LE)
2214 83469015 bellard
    case 0x11: // As if user secondary
2215 83469015 bellard
    case 0x19: // As if user secondary LE
2216 83469015 bellard
    case 0x4a: // UPA config
2217 81ad8ba2 blueswir1
    case 0x81: // Secondary
2218 83469015 bellard
    case 0x89: // Secondary LE
2219 0f8a249a blueswir1
        // XXX
2220 0f8a249a blueswir1
        break;
2221 3475187d bellard
    case 0x45: // LSU
2222 0f8a249a blueswir1
        ret = env->lsu;
2223 0f8a249a blueswir1
        break;
2224 3475187d bellard
    case 0x50: // I-MMU regs
2225 0f8a249a blueswir1
        {
2226 1a2fb1c0 blueswir1
            int reg = (addr >> 3) & 0xf;
2227 3475187d bellard
2228 697a77e6 Igor Kovalenko
            if (reg == 0) {
2229 697a77e6 Igor Kovalenko
                // I-TSB Tag Target register
2230 6e8e7d4c Igor Kovalenko
                ret = ultrasparc_tag_target(env->immu.tag_access);
2231 697a77e6 Igor Kovalenko
            } else {
2232 697a77e6 Igor Kovalenko
                ret = env->immuregs[reg];
2233 697a77e6 Igor Kovalenko
            }
2234 697a77e6 Igor Kovalenko
2235 0f8a249a blueswir1
            break;
2236 0f8a249a blueswir1
        }
2237 3475187d bellard
    case 0x51: // I-MMU 8k TSB pointer
2238 697a77e6 Igor Kovalenko
        {
2239 697a77e6 Igor Kovalenko
            // env->immuregs[5] holds I-MMU TSB register value
2240 697a77e6 Igor Kovalenko
            // env->immuregs[6] holds I-MMU Tag Access register value
2241 6e8e7d4c Igor Kovalenko
            ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
2242 697a77e6 Igor Kovalenko
                                         8*1024);
2243 697a77e6 Igor Kovalenko
            break;
2244 697a77e6 Igor Kovalenko
        }
2245 3475187d bellard
    case 0x52: // I-MMU 64k TSB pointer
2246 697a77e6 Igor Kovalenko
        {
2247 697a77e6 Igor Kovalenko
            // env->immuregs[5] holds I-MMU TSB register value
2248 697a77e6 Igor Kovalenko
            // env->immuregs[6] holds I-MMU Tag Access register value
2249 6e8e7d4c Igor Kovalenko
            ret = ultrasparc_tsb_pointer(env->immu.tsb, env->immu.tag_access,
2250 697a77e6 Igor Kovalenko
                                         64*1024);
2251 697a77e6 Igor Kovalenko
            break;
2252 697a77e6 Igor Kovalenko
        }
2253 a5a52cf2 blueswir1
    case 0x55: // I-MMU data access
2254 a5a52cf2 blueswir1
        {
2255 a5a52cf2 blueswir1
            int reg = (addr >> 3) & 0x3f;
2256 a5a52cf2 blueswir1
2257 6e8e7d4c Igor Kovalenko
            ret = env->itlb[reg].tte;
2258 a5a52cf2 blueswir1
            break;
2259 a5a52cf2 blueswir1
        }
2260 83469015 bellard
    case 0x56: // I-MMU tag read
2261 0f8a249a blueswir1
        {
2262 43e9e742 blueswir1
            int reg = (addr >> 3) & 0x3f;
2263 0f8a249a blueswir1
2264 6e8e7d4c Igor Kovalenko
            ret = env->itlb[reg].tag;
2265 0f8a249a blueswir1
            break;
2266 0f8a249a blueswir1
        }
2267 3475187d bellard
    case 0x58: // D-MMU regs
2268 0f8a249a blueswir1
        {
2269 1a2fb1c0 blueswir1
            int reg = (addr >> 3) & 0xf;
2270 3475187d bellard
2271 697a77e6 Igor Kovalenko
            if (reg == 0) {
2272 697a77e6 Igor Kovalenko
                // D-TSB Tag Target register
2273 6e8e7d4c Igor Kovalenko
                ret = ultrasparc_tag_target(env->dmmu.tag_access);
2274 697a77e6 Igor Kovalenko
            } else {
2275 697a77e6 Igor Kovalenko
                ret = env->dmmuregs[reg];
2276 697a77e6 Igor Kovalenko
            }
2277 697a77e6 Igor Kovalenko
            break;
2278 697a77e6 Igor Kovalenko
        }
2279 697a77e6 Igor Kovalenko
    case 0x59: // D-MMU 8k TSB pointer
2280 697a77e6 Igor Kovalenko
        {
2281 697a77e6 Igor Kovalenko
            // env->dmmuregs[5] holds D-MMU TSB register value
2282 697a77e6 Igor Kovalenko
            // env->dmmuregs[6] holds D-MMU Tag Access register value
2283 6e8e7d4c Igor Kovalenko
            ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
2284 697a77e6 Igor Kovalenko
                                         8*1024);
2285 697a77e6 Igor Kovalenko
            break;
2286 697a77e6 Igor Kovalenko
        }
2287 697a77e6 Igor Kovalenko
    case 0x5a: // D-MMU 64k TSB pointer
2288 697a77e6 Igor Kovalenko
        {
2289 697a77e6 Igor Kovalenko
            // env->dmmuregs[5] holds D-MMU TSB register value
2290 697a77e6 Igor Kovalenko
            // env->dmmuregs[6] holds D-MMU Tag Access register value
2291 6e8e7d4c Igor Kovalenko
            ret = ultrasparc_tsb_pointer(env->dmmu.tsb, env->dmmu.tag_access,
2292 697a77e6 Igor Kovalenko
                                         64*1024);
2293 0f8a249a blueswir1
            break;
2294 0f8a249a blueswir1
        }
2295 a5a52cf2 blueswir1
    case 0x5d: // D-MMU data access
2296 a5a52cf2 blueswir1
        {
2297 a5a52cf2 blueswir1
            int reg = (addr >> 3) & 0x3f;
2298 a5a52cf2 blueswir1
2299 6e8e7d4c Igor Kovalenko
            ret = env->dtlb[reg].tte;
2300 a5a52cf2 blueswir1
            break;
2301 a5a52cf2 blueswir1
        }
2302 83469015 bellard
    case 0x5e: // D-MMU tag read
2303 0f8a249a blueswir1
        {
2304 43e9e742 blueswir1
            int reg = (addr >> 3) & 0x3f;
2305 0f8a249a blueswir1
2306 6e8e7d4c Igor Kovalenko
            ret = env->dtlb[reg].tag;
2307 0f8a249a blueswir1
            break;
2308 0f8a249a blueswir1
        }
2309 f7350b47 blueswir1
    case 0x46: // D-cache data
2310 f7350b47 blueswir1
    case 0x47: // D-cache tag access
2311 a5a52cf2 blueswir1
    case 0x4b: // E-cache error enable
2312 a5a52cf2 blueswir1
    case 0x4c: // E-cache asynchronous fault status
2313 a5a52cf2 blueswir1
    case 0x4d: // E-cache asynchronous fault address
2314 f7350b47 blueswir1
    case 0x4e: // E-cache tag data
2315 f7350b47 blueswir1
    case 0x66: // I-cache instruction access
2316 f7350b47 blueswir1
    case 0x67: // I-cache tag access
2317 f7350b47 blueswir1
    case 0x6e: // I-cache predecode
2318 f7350b47 blueswir1
    case 0x6f: // I-cache LRU etc.
2319 f7350b47 blueswir1
    case 0x76: // E-cache tag
2320 f7350b47 blueswir1
    case 0x7e: // E-cache tag
2321 f7350b47 blueswir1
        break;
2322 3475187d bellard
    case 0x5b: // D-MMU data pointer
2323 83469015 bellard
    case 0x48: // Interrupt dispatch, RO
2324 83469015 bellard
    case 0x49: // Interrupt data receive
2325 83469015 bellard
    case 0x7f: // Incoming interrupt vector, RO
2326 0f8a249a blueswir1
        // XXX
2327 0f8a249a blueswir1
        break;
2328 3475187d bellard
    case 0x54: // I-MMU data in, WO
2329 3475187d bellard
    case 0x57: // I-MMU demap, WO
2330 3475187d bellard
    case 0x5c: // D-MMU data in, WO
2331 3475187d bellard
    case 0x5f: // D-MMU demap, WO
2332 83469015 bellard
    case 0x77: // Interrupt vector, WO
2333 3475187d bellard
    default:
2334 e18231a3 blueswir1
        do_unassigned_access(addr, 0, 0, 1, size);
2335 0f8a249a blueswir1
        ret = 0;
2336 0f8a249a blueswir1
        break;
2337 3475187d bellard
    }
2338 81ad8ba2 blueswir1
2339 81ad8ba2 blueswir1
    /* Convert from little endian */
2340 81ad8ba2 blueswir1
    switch (asi) {
2341 81ad8ba2 blueswir1
    case 0x0c: // Nucleus Little Endian (LE)
2342 81ad8ba2 blueswir1
    case 0x18: // As if user primary LE
2343 81ad8ba2 blueswir1
    case 0x19: // As if user secondary LE
2344 81ad8ba2 blueswir1
    case 0x1c: // Bypass LE
2345 81ad8ba2 blueswir1
    case 0x1d: // Bypass, non-cacheable LE
2346 81ad8ba2 blueswir1
    case 0x88: // Primary LE
2347 81ad8ba2 blueswir1
    case 0x89: // Secondary LE
2348 81ad8ba2 blueswir1
    case 0x8a: // Primary no-fault LE
2349 81ad8ba2 blueswir1
    case 0x8b: // Secondary no-fault LE
2350 81ad8ba2 blueswir1
        switch(size) {
2351 81ad8ba2 blueswir1
        case 2:
2352 81ad8ba2 blueswir1
            ret = bswap16(ret);
2353 e32664fb blueswir1
            break;
2354 81ad8ba2 blueswir1
        case 4:
2355 81ad8ba2 blueswir1
            ret = bswap32(ret);
2356 e32664fb blueswir1
            break;
2357 81ad8ba2 blueswir1
        case 8:
2358 81ad8ba2 blueswir1
            ret = bswap64(ret);
2359 e32664fb blueswir1
            break;
2360 81ad8ba2 blueswir1
        default:
2361 81ad8ba2 blueswir1
            break;
2362 81ad8ba2 blueswir1
        }
2363 81ad8ba2 blueswir1
    default:
2364 81ad8ba2 blueswir1
        break;
2365 81ad8ba2 blueswir1
    }
2366 81ad8ba2 blueswir1
2367 81ad8ba2 blueswir1
    /* Convert to signed number */
2368 81ad8ba2 blueswir1
    if (sign) {
2369 81ad8ba2 blueswir1
        switch(size) {
2370 81ad8ba2 blueswir1
        case 1:
2371 81ad8ba2 blueswir1
            ret = (int8_t) ret;
2372 e32664fb blueswir1
            break;
2373 81ad8ba2 blueswir1
        case 2:
2374 81ad8ba2 blueswir1
            ret = (int16_t) ret;
2375 e32664fb blueswir1
            break;
2376 81ad8ba2 blueswir1
        case 4:
2377 81ad8ba2 blueswir1
            ret = (int32_t) ret;
2378 e32664fb blueswir1
            break;
2379 81ad8ba2 blueswir1
        default:
2380 81ad8ba2 blueswir1
            break;
2381 81ad8ba2 blueswir1
        }
2382 81ad8ba2 blueswir1
    }
2383 1a2fb1c0 blueswir1
#ifdef DEBUG_ASI
2384 1a2fb1c0 blueswir1
    dump_asi("read ", last_addr, asi, size, ret);
2385 1a2fb1c0 blueswir1
#endif
2386 1a2fb1c0 blueswir1
    return ret;
2387 3475187d bellard
}
2388 3475187d bellard
2389 1a2fb1c0 blueswir1
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2390 3475187d bellard
{
2391 1a2fb1c0 blueswir1
#ifdef DEBUG_ASI
2392 1a2fb1c0 blueswir1
    dump_asi("write", addr, asi, size, val);
2393 1a2fb1c0 blueswir1
#endif
2394 01b5d4e5 Igor V. Kovalenko
2395 01b5d4e5 Igor V. Kovalenko
    asi &= 0xff;
2396 01b5d4e5 Igor V. Kovalenko
2397 6f27aba6 blueswir1
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2398 5578ceab blueswir1
        || ((env->def->features & CPU_FEATURE_HYPV)
2399 5578ceab blueswir1
            && asi >= 0x30 && asi < 0x80
2400 fb79ceb9 blueswir1
            && !(env->hpstate & HS_PRIV)))
2401 0f8a249a blueswir1
        raise_exception(TT_PRIV_ACT);
2402 3475187d bellard
2403 c2bc0e38 blueswir1
    helper_check_align(addr, size - 1);
2404 81ad8ba2 blueswir1
    /* Convert to little endian */
2405 81ad8ba2 blueswir1
    switch (asi) {
2406 81ad8ba2 blueswir1
    case 0x0c: // Nucleus Little Endian (LE)
2407 81ad8ba2 blueswir1
    case 0x18: // As if user primary LE
2408 81ad8ba2 blueswir1
    case 0x19: // As if user secondary LE
2409 81ad8ba2 blueswir1
    case 0x1c: // Bypass LE
2410 81ad8ba2 blueswir1
    case 0x1d: // Bypass, non-cacheable LE
2411 81ad8ba2 blueswir1
    case 0x88: // Primary LE
2412 81ad8ba2 blueswir1
    case 0x89: // Secondary LE
2413 81ad8ba2 blueswir1
        switch(size) {
2414 81ad8ba2 blueswir1
        case 2:
2415 5b0f0bec Igor Kovalenko
            val = bswap16(val);
2416 e32664fb blueswir1
            break;
2417 81ad8ba2 blueswir1
        case 4:
2418 5b0f0bec Igor Kovalenko
            val = bswap32(val);
2419 e32664fb blueswir1
            break;
2420 81ad8ba2 blueswir1
        case 8:
2421 5b0f0bec Igor Kovalenko
            val = bswap64(val);
2422 e32664fb blueswir1
            break;
2423 81ad8ba2 blueswir1
        default:
2424 81ad8ba2 blueswir1
            break;
2425 81ad8ba2 blueswir1
        }
2426 81ad8ba2 blueswir1
    default:
2427 81ad8ba2 blueswir1
        break;
2428 81ad8ba2 blueswir1
    }
2429 81ad8ba2 blueswir1
2430 3475187d bellard
    switch(asi) {
2431 81ad8ba2 blueswir1
    case 0x10: // As if user primary
2432 81ad8ba2 blueswir1
    case 0x18: // As if user primary LE
2433 81ad8ba2 blueswir1
    case 0x80: // Primary
2434 81ad8ba2 blueswir1
    case 0x88: // Primary LE
2435 c99657d3 blueswir1
    case 0xe2: // UA2007 Primary block init
2436 c99657d3 blueswir1
    case 0xe3: // UA2007 Secondary block init
2437 81ad8ba2 blueswir1
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
2438 5578ceab blueswir1
            if ((env->def->features & CPU_FEATURE_HYPV)
2439 5578ceab blueswir1
                && env->hpstate & HS_PRIV) {
2440 6f27aba6 blueswir1
                switch(size) {
2441 6f27aba6 blueswir1
                case 1:
2442 1a2fb1c0 blueswir1
                    stb_hypv(addr, val);
2443 6f27aba6 blueswir1
                    break;
2444 6f27aba6 blueswir1
                case 2:
2445 a4e7dd52 blueswir1
                    stw_hypv(addr, val);
2446 6f27aba6 blueswir1
                    break;
2447 6f27aba6 blueswir1
                case 4:
2448 a4e7dd52 blueswir1
                    stl_hypv(addr, val);
2449 6f27aba6 blueswir1
                    break;
2450 6f27aba6 blueswir1
                case 8:
2451 6f27aba6 blueswir1
                default:
2452 a4e7dd52 blueswir1
                    stq_hypv(addr, val);
2453 6f27aba6 blueswir1
                    break;
2454 6f27aba6 blueswir1
                }
2455 6f27aba6 blueswir1
            } else {
2456 6f27aba6 blueswir1
                switch(size) {
2457 6f27aba6 blueswir1
                case 1:
2458 1a2fb1c0 blueswir1
                    stb_kernel(addr, val);
2459 6f27aba6 blueswir1
                    break;
2460 6f27aba6 blueswir1
                case 2:
2461 a4e7dd52 blueswir1
                    stw_kernel(addr, val);
2462 6f27aba6 blueswir1
                    break;
2463 6f27aba6 blueswir1
                case 4:
2464 a4e7dd52 blueswir1
                    stl_kernel(addr, val);
2465 6f27aba6 blueswir1
                    break;
2466 6f27aba6 blueswir1
                case 8:
2467 6f27aba6 blueswir1
                default:
2468 a4e7dd52 blueswir1
                    stq_kernel(addr, val);
2469 6f27aba6 blueswir1
                    break;
2470 6f27aba6 blueswir1
                }
2471 81ad8ba2 blueswir1
            }
2472 81ad8ba2 blueswir1
        } else {
2473 81ad8ba2 blueswir1
            switch(size) {
2474 81ad8ba2 blueswir1
            case 1:
2475 1a2fb1c0 blueswir1
                stb_user(addr, val);
2476 81ad8ba2 blueswir1
                break;
2477 81ad8ba2 blueswir1
            case 2:
2478 a4e7dd52 blueswir1
                stw_user(addr, val);
2479 81ad8ba2 blueswir1
                break;
2480 81ad8ba2 blueswir1
            case 4:
2481 a4e7dd52 blueswir1
                stl_user(addr, val);
2482 81ad8ba2 blueswir1
                break;
2483 81ad8ba2 blueswir1
            case 8:
2484 81ad8ba2 blueswir1
            default:
2485 a4e7dd52 blueswir1
                stq_user(addr, val);
2486 81ad8ba2 blueswir1
                break;
2487 81ad8ba2 blueswir1
            }
2488 81ad8ba2 blueswir1
        }
2489 81ad8ba2 blueswir1
        break;
2490 3475187d bellard
    case 0x14: // Bypass
2491 3475187d bellard
    case 0x15: // Bypass, non-cacheable
2492 81ad8ba2 blueswir1
    case 0x1c: // Bypass LE
2493 81ad8ba2 blueswir1
    case 0x1d: // Bypass, non-cacheable LE
2494 0f8a249a blueswir1
        {
2495 02aab46a bellard
            switch(size) {
2496 02aab46a bellard
            case 1:
2497 1a2fb1c0 blueswir1
                stb_phys(addr, val);
2498 02aab46a bellard
                break;
2499 02aab46a bellard
            case 2:
2500 a4e7dd52 blueswir1
                stw_phys(addr, val);
2501 02aab46a bellard
                break;
2502 02aab46a bellard
            case 4:
2503 a4e7dd52 blueswir1
                stl_phys(addr, val);
2504 02aab46a bellard
                break;
2505 02aab46a bellard
            case 8:
2506 02aab46a bellard
            default:
2507 a4e7dd52 blueswir1
                stq_phys(addr, val);
2508 02aab46a bellard
                break;
2509 02aab46a bellard
            }
2510 0f8a249a blueswir1
        }
2511 0f8a249a blueswir1
        return;
2512 db166940 blueswir1
    case 0x24: // Nucleus quad LDD 128 bit atomic
2513 db166940 blueswir1
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2514 db166940 blueswir1
        //  Only ldda allowed
2515 db166940 blueswir1
        raise_exception(TT_ILL_INSN);
2516 db166940 blueswir1
        return;
2517 83469015 bellard
    case 0x04: // Nucleus
2518 83469015 bellard
    case 0x0c: // Nucleus Little Endian (LE)
2519 83469015 bellard
    case 0x11: // As if user secondary
2520 83469015 bellard
    case 0x19: // As if user secondary LE
2521 83469015 bellard
    case 0x4a: // UPA config
2522 51996525 blueswir1
    case 0x81: // Secondary
2523 83469015 bellard
    case 0x89: // Secondary LE
2524 0f8a249a blueswir1
        // XXX
2525 0f8a249a blueswir1
        return;
2526 3475187d bellard
    case 0x45: // LSU
2527 0f8a249a blueswir1
        {
2528 0f8a249a blueswir1
            uint64_t oldreg;
2529 0f8a249a blueswir1
2530 0f8a249a blueswir1
            oldreg = env->lsu;
2531 1a2fb1c0 blueswir1
            env->lsu = val & (DMMU_E | IMMU_E);
2532 0f8a249a blueswir1
            // Mappings generated during D/I MMU disabled mode are
2533 0f8a249a blueswir1
            // invalid in normal mode
2534 0f8a249a blueswir1
            if (oldreg != env->lsu) {
2535 77f193da blueswir1
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
2536 77f193da blueswir1
                            oldreg, env->lsu);
2537 83469015 bellard
#ifdef DEBUG_MMU
2538 0f8a249a blueswir1
                dump_mmu(env);
2539 83469015 bellard
#endif
2540 0f8a249a blueswir1
                tlb_flush(env, 1);
2541 0f8a249a blueswir1
            }
2542 0f8a249a blueswir1
            return;
2543 0f8a249a blueswir1
        }
2544 3475187d bellard
    case 0x50: // I-MMU regs
2545 0f8a249a blueswir1
        {
2546 1a2fb1c0 blueswir1
            int reg = (addr >> 3) & 0xf;
2547 0f8a249a blueswir1
            uint64_t oldreg;
2548 3b46e624 ths
2549 0f8a249a blueswir1
            oldreg = env->immuregs[reg];
2550 3475187d bellard
            switch(reg) {
2551 3475187d bellard
            case 0: // RO
2552 3475187d bellard
                return;
2553 3475187d bellard
            case 1: // Not in I-MMU
2554 3475187d bellard
            case 2:
2555 3475187d bellard
                return;
2556 3475187d bellard
            case 3: // SFSR
2557 1a2fb1c0 blueswir1
                if ((val & 1) == 0)
2558 1a2fb1c0 blueswir1
                    val = 0; // Clear SFSR
2559 6e8e7d4c Igor Kovalenko
                env->immu.sfsr = val;
2560 3475187d bellard
                break;
2561 6e8e7d4c Igor Kovalenko
            case 4: // RO
2562 6e8e7d4c Igor Kovalenko
                return;
2563 3475187d bellard
            case 5: // TSB access
2564 6e8e7d4c Igor Kovalenko
                DPRINTF_MMU("immu TSB write: 0x%016" PRIx64 " -> 0x%016"
2565 6e8e7d4c Igor Kovalenko
                            PRIx64 "\n", env->immu.tsb, val);
2566 6e8e7d4c Igor Kovalenko
                env->immu.tsb = val;
2567 6e8e7d4c Igor Kovalenko
                break;
2568 3475187d bellard
            case 6: // Tag access
2569 6e8e7d4c Igor Kovalenko
                env->immu.tag_access = val;
2570 6e8e7d4c Igor Kovalenko
                break;
2571 6e8e7d4c Igor Kovalenko
            case 7:
2572 6e8e7d4c Igor Kovalenko
            case 8:
2573 6e8e7d4c Igor Kovalenko
                return;
2574 3475187d bellard
            default:
2575 3475187d bellard
                break;
2576 3475187d bellard
            }
2577 6e8e7d4c Igor Kovalenko
2578 3475187d bellard
            if (oldreg != env->immuregs[reg]) {
2579 6e8e7d4c Igor Kovalenko
                DPRINTF_MMU("immu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
2580 77f193da blueswir1
                            PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
2581 3475187d bellard
            }
2582 952a328f blueswir1
#ifdef DEBUG_MMU
2583 0f8a249a blueswir1
            dump_mmu(env);
2584 3475187d bellard
#endif
2585 0f8a249a blueswir1
            return;
2586 0f8a249a blueswir1
        }
2587 3475187d bellard
    case 0x54: // I-MMU data in
2588 f707726e Igor Kovalenko
        replace_tlb_1bit_lru(env->itlb, env->immu.tag_access, val, "immu", env);
2589 f707726e Igor Kovalenko
        return;
2590 3475187d bellard
    case 0x55: // I-MMU data access
2591 0f8a249a blueswir1
        {
2592 cc6747f4 blueswir1
            // TODO: auto demap
2593 cc6747f4 blueswir1
2594 1a2fb1c0 blueswir1
            unsigned int i = (addr >> 3) & 0x3f;
2595 3475187d bellard
2596 f707726e Igor Kovalenko
            replace_tlb_entry(&env->itlb[i], env->immu.tag_access, val, env);
2597 6e8e7d4c Igor Kovalenko
2598 6e8e7d4c Igor Kovalenko
#ifdef DEBUG_MMU
2599 f707726e Igor Kovalenko
            DPRINTF_MMU("immu data access replaced entry [%i]\n", i);
2600 6e8e7d4c Igor Kovalenko
            dump_mmu(env);
2601 6e8e7d4c Igor Kovalenko
#endif
2602 0f8a249a blueswir1
            return;
2603 0f8a249a blueswir1
        }
2604 3475187d bellard
    case 0x57: // I-MMU demap
2605 f707726e Igor Kovalenko
        demap_tlb(env->itlb, val, "immu", env);
2606 0f8a249a blueswir1
        return;
2607 3475187d bellard
    case 0x58: // D-MMU regs
2608 0f8a249a blueswir1
        {
2609 1a2fb1c0 blueswir1
            int reg = (addr >> 3) & 0xf;
2610 0f8a249a blueswir1
            uint64_t oldreg;
2611 3b46e624 ths
2612 0f8a249a blueswir1
            oldreg = env->dmmuregs[reg];
2613 3475187d bellard
            switch(reg) {
2614 3475187d bellard
            case 0: // RO
2615 3475187d bellard
            case 4:
2616 3475187d bellard
                return;
2617 3475187d bellard
            case 3: // SFSR
2618 1a2fb1c0 blueswir1
                if ((val & 1) == 0) {
2619 1a2fb1c0 blueswir1
                    val = 0; // Clear SFSR, Fault address
2620 6e8e7d4c Igor Kovalenko
                    env->dmmu.sfar = 0;
2621 0f8a249a blueswir1
                }
2622 6e8e7d4c Igor Kovalenko
                env->dmmu.sfsr = val;
2623 3475187d bellard
                break;
2624 3475187d bellard
            case 1: // Primary context
2625 6e8e7d4c Igor Kovalenko
                env->dmmu.mmu_primary_context = val;
2626 6e8e7d4c Igor Kovalenko
                break;
2627 3475187d bellard
            case 2: // Secondary context
2628 6e8e7d4c Igor Kovalenko
                env->dmmu.mmu_secondary_context = val;
2629 6e8e7d4c Igor Kovalenko
                break;
2630 3475187d bellard
            case 5: // TSB access
2631 6e8e7d4c Igor Kovalenko
                DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64 " -> 0x%016"
2632 6e8e7d4c Igor Kovalenko
                            PRIx64 "\n", env->dmmu.tsb, val);
2633 6e8e7d4c Igor Kovalenko
                env->dmmu.tsb = val;
2634 6e8e7d4c Igor Kovalenko
                break;
2635 3475187d bellard
            case 6: // Tag access
2636 6e8e7d4c Igor Kovalenko
                env->dmmu.tag_access = val;
2637 6e8e7d4c Igor Kovalenko
                break;
2638 3475187d bellard
            case 7: // Virtual Watchpoint
2639 3475187d bellard
            case 8: // Physical Watchpoint
2640 3475187d bellard
            default:
2641 6e8e7d4c Igor Kovalenko
                env->dmmuregs[reg] = val;
2642 3475187d bellard
                break;
2643 3475187d bellard
            }
2644 6e8e7d4c Igor Kovalenko
2645 3475187d bellard
            if (oldreg != env->dmmuregs[reg]) {
2646 6e8e7d4c Igor Kovalenko
                DPRINTF_MMU("dmmu change reg[%d]: 0x%016" PRIx64 " -> 0x%016"
2647 77f193da blueswir1
                            PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
2648 3475187d bellard
            }
2649 952a328f blueswir1
#ifdef DEBUG_MMU
2650 0f8a249a blueswir1
            dump_mmu(env);
2651 3475187d bellard
#endif
2652 0f8a249a blueswir1
            return;
2653 0f8a249a blueswir1
        }
2654 3475187d bellard
    case 0x5c: // D-MMU data in
2655 f707726e Igor Kovalenko
        replace_tlb_1bit_lru(env->dtlb, env->dmmu.tag_access, val, "dmmu", env);
2656 f707726e Igor Kovalenko
        return;
2657 3475187d bellard
    case 0x5d: // D-MMU data access
2658 0f8a249a blueswir1
        {
2659 1a2fb1c0 blueswir1
            unsigned int i = (addr >> 3) & 0x3f;
2660 3475187d bellard
2661 f707726e Igor Kovalenko
            replace_tlb_entry(&env->dtlb[i], env->dmmu.tag_access, val, env);
2662 f707726e Igor Kovalenko
2663 6e8e7d4c Igor Kovalenko
#ifdef DEBUG_MMU
2664 f707726e Igor Kovalenko
            DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i);
2665 6e8e7d4c Igor Kovalenko
            dump_mmu(env);
2666 6e8e7d4c Igor Kovalenko
#endif
2667 0f8a249a blueswir1
            return;
2668 0f8a249a blueswir1
        }
2669 3475187d bellard
    case 0x5f: // D-MMU demap
2670 f707726e Igor Kovalenko
        demap_tlb(env->dtlb, val, "dmmu", env);
2671 cc6747f4 blueswir1
        return;
2672 83469015 bellard
    case 0x49: // Interrupt data receive
2673 0f8a249a blueswir1
        // XXX
2674 0f8a249a blueswir1
        return;
2675 f7350b47 blueswir1
    case 0x46: // D-cache data
2676 f7350b47 blueswir1
    case 0x47: // D-cache tag access
2677 a5a52cf2 blueswir1
    case 0x4b: // E-cache error enable
2678 a5a52cf2 blueswir1
    case 0x4c: // E-cache asynchronous fault status
2679 a5a52cf2 blueswir1
    case 0x4d: // E-cache asynchronous fault address
2680 f7350b47 blueswir1
    case 0x4e: // E-cache tag data
2681 f7350b47 blueswir1
    case 0x66: // I-cache instruction access
2682 f7350b47 blueswir1
    case 0x67: // I-cache tag access
2683 f7350b47 blueswir1
    case 0x6e: // I-cache predecode
2684 f7350b47 blueswir1
    case 0x6f: // I-cache LRU etc.
2685 f7350b47 blueswir1
    case 0x76: // E-cache tag
2686 f7350b47 blueswir1
    case 0x7e: // E-cache tag
2687 f7350b47 blueswir1
        return;
2688 3475187d bellard
    case 0x51: // I-MMU 8k TSB pointer, RO
2689 3475187d bellard
    case 0x52: // I-MMU 64k TSB pointer, RO
2690 3475187d bellard
    case 0x56: // I-MMU tag read, RO
2691 3475187d bellard
    case 0x59: // D-MMU 8k TSB pointer, RO
2692 3475187d bellard
    case 0x5a: // D-MMU 64k TSB pointer, RO
2693 3475187d bellard
    case 0x5b: // D-MMU data pointer, RO
2694 3475187d bellard
    case 0x5e: // D-MMU tag read, RO
2695 83469015 bellard
    case 0x48: // Interrupt dispatch, RO
2696 83469015 bellard
    case 0x7f: // Incoming interrupt vector, RO
2697 83469015 bellard
    case 0x82: // Primary no-fault, RO
2698 83469015 bellard
    case 0x83: // Secondary no-fault, RO
2699 83469015 bellard
    case 0x8a: // Primary no-fault LE, RO
2700 83469015 bellard
    case 0x8b: // Secondary no-fault LE, RO
2701 3475187d bellard
    default:
2702 e18231a3 blueswir1
        do_unassigned_access(addr, 1, 0, 1, size);
2703 0f8a249a blueswir1
        return;
2704 3475187d bellard
    }
2705 3475187d bellard
}
2706 81ad8ba2 blueswir1
#endif /* CONFIG_USER_ONLY */
2707 3391c818 blueswir1
2708 db166940 blueswir1
void helper_ldda_asi(target_ulong addr, int asi, int rd)
2709 db166940 blueswir1
{
2710 db166940 blueswir1
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2711 5578ceab blueswir1
        || ((env->def->features & CPU_FEATURE_HYPV)
2712 5578ceab blueswir1
            && asi >= 0x30 && asi < 0x80
2713 fb79ceb9 blueswir1
            && !(env->hpstate & HS_PRIV)))
2714 db166940 blueswir1
        raise_exception(TT_PRIV_ACT);
2715 db166940 blueswir1
2716 db166940 blueswir1
    switch (asi) {
2717 db166940 blueswir1
    case 0x24: // Nucleus quad LDD 128 bit atomic
2718 db166940 blueswir1
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2719 db166940 blueswir1
        helper_check_align(addr, 0xf);
2720 db166940 blueswir1
        if (rd == 0) {
2721 db166940 blueswir1
            env->gregs[1] = ldq_kernel(addr + 8);
2722 db166940 blueswir1
            if (asi == 0x2c)
2723 db166940 blueswir1
                bswap64s(&env->gregs[1]);
2724 db166940 blueswir1
        } else if (rd < 8) {
2725 db166940 blueswir1
            env->gregs[rd] = ldq_kernel(addr);
2726 db166940 blueswir1
            env->gregs[rd + 1] = ldq_kernel(addr + 8);
2727 db166940 blueswir1
            if (asi == 0x2c) {
2728 db166940 blueswir1
                bswap64s(&env->gregs[rd]);
2729 db166940 blueswir1
                bswap64s(&env->gregs[rd + 1]);
2730 db166940 blueswir1
            }
2731 db166940 blueswir1
        } else {
2732 db166940 blueswir1
            env->regwptr[rd] = ldq_kernel(addr);
2733 db166940 blueswir1
            env->regwptr[rd + 1] = ldq_kernel(addr + 8);
2734 db166940 blueswir1
            if (asi == 0x2c) {
2735 db166940 blueswir1
                bswap64s(&env->regwptr[rd]);
2736 db166940 blueswir1
                bswap64s(&env->regwptr[rd + 1]);
2737 db166940 blueswir1
            }
2738 db166940 blueswir1
        }
2739 db166940 blueswir1
        break;
2740 db166940 blueswir1
    default:
2741 db166940 blueswir1
        helper_check_align(addr, 0x3);
2742 db166940 blueswir1
        if (rd == 0)
2743 db166940 blueswir1
            env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
2744 db166940 blueswir1
        else if (rd < 8) {
2745 db166940 blueswir1
            env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
2746 db166940 blueswir1
            env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2747 db166940 blueswir1
        } else {
2748 db166940 blueswir1
            env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
2749 db166940 blueswir1
            env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2750 db166940 blueswir1
        }
2751 db166940 blueswir1
        break;
2752 db166940 blueswir1
    }
2753 db166940 blueswir1
}
2754 db166940 blueswir1
2755 1a2fb1c0 blueswir1
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2756 3391c818 blueswir1
{
2757 3391c818 blueswir1
    unsigned int i;
2758 1a2fb1c0 blueswir1
    target_ulong val;
2759 3391c818 blueswir1
2760 c2bc0e38 blueswir1
    helper_check_align(addr, 3);
2761 3391c818 blueswir1
    switch (asi) {
2762 3391c818 blueswir1
    case 0xf0: // Block load primary
2763 3391c818 blueswir1
    case 0xf1: // Block load secondary
2764 3391c818 blueswir1
    case 0xf8: // Block load primary LE
2765 3391c818 blueswir1
    case 0xf9: // Block load secondary LE
2766 51996525 blueswir1
        if (rd & 7) {
2767 51996525 blueswir1
            raise_exception(TT_ILL_INSN);
2768 51996525 blueswir1
            return;
2769 51996525 blueswir1
        }
2770 c2bc0e38 blueswir1
        helper_check_align(addr, 0x3f);
2771 51996525 blueswir1
        for (i = 0; i < 16; i++) {
2772 77f193da blueswir1
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
2773 77f193da blueswir1
                                                         0);
2774 1a2fb1c0 blueswir1
            addr += 4;
2775 3391c818 blueswir1
        }
2776 3391c818 blueswir1
2777 3391c818 blueswir1
        return;
2778 3391c818 blueswir1
    default:
2779 3391c818 blueswir1
        break;
2780 3391c818 blueswir1
    }
2781 3391c818 blueswir1
2782 1a2fb1c0 blueswir1
    val = helper_ld_asi(addr, asi, size, 0);
2783 3391c818 blueswir1
    switch(size) {
2784 3391c818 blueswir1
    default:
2785 3391c818 blueswir1
    case 4:
2786 714547bb blueswir1
        *((uint32_t *)&env->fpr[rd]) = val;
2787 3391c818 blueswir1
        break;
2788 3391c818 blueswir1
    case 8:
2789 1a2fb1c0 blueswir1
        *((int64_t *)&DT0) = val;
2790 3391c818 blueswir1
        break;
2791 1f587329 blueswir1
    case 16:
2792 1f587329 blueswir1
        // XXX
2793 1f587329 blueswir1
        break;
2794 3391c818 blueswir1
    }
2795 3391c818 blueswir1
}
2796 3391c818 blueswir1
2797 1a2fb1c0 blueswir1
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2798 3391c818 blueswir1
{
2799 3391c818 blueswir1
    unsigned int i;
2800 1a2fb1c0 blueswir1
    target_ulong val = 0;
2801 3391c818 blueswir1
2802 c2bc0e38 blueswir1
    helper_check_align(addr, 3);
2803 3391c818 blueswir1
    switch (asi) {
2804 c99657d3 blueswir1
    case 0xe0: // UA2007 Block commit store primary (cache flush)
2805 c99657d3 blueswir1
    case 0xe1: // UA2007 Block commit store secondary (cache flush)
2806 3391c818 blueswir1
    case 0xf0: // Block store primary
2807 3391c818 blueswir1
    case 0xf1: // Block store secondary
2808 3391c818 blueswir1
    case 0xf8: // Block store primary LE
2809 3391c818 blueswir1
    case 0xf9: // Block store secondary LE
2810 51996525 blueswir1
        if (rd & 7) {
2811 51996525 blueswir1
            raise_exception(TT_ILL_INSN);
2812 51996525 blueswir1
            return;
2813 51996525 blueswir1
        }
2814 c2bc0e38 blueswir1
        helper_check_align(addr, 0x3f);
2815 51996525 blueswir1
        for (i = 0; i < 16; i++) {
2816 1a2fb1c0 blueswir1
            val = *(uint32_t *)&env->fpr[rd++];
2817 1a2fb1c0 blueswir1
            helper_st_asi(addr, val, asi & 0x8f, 4);
2818 1a2fb1c0 blueswir1
            addr += 4;
2819 3391c818 blueswir1
        }
2820 3391c818 blueswir1
2821 3391c818 blueswir1
        return;
2822 3391c818 blueswir1
    default:
2823 3391c818 blueswir1
        break;
2824 3391c818 blueswir1
    }
2825 3391c818 blueswir1
2826 3391c818 blueswir1
    switch(size) {
2827 3391c818 blueswir1
    default:
2828 3391c818 blueswir1
    case 4:
2829 714547bb blueswir1
        val = *((uint32_t *)&env->fpr[rd]);
2830 3391c818 blueswir1
        break;
2831 3391c818 blueswir1
    case 8:
2832 1a2fb1c0 blueswir1
        val = *((int64_t *)&DT0);
2833 3391c818 blueswir1
        break;
2834 1f587329 blueswir1
    case 16:
2835 1f587329 blueswir1
        // XXX
2836 1f587329 blueswir1
        break;
2837 3391c818 blueswir1
    }
2838 1a2fb1c0 blueswir1
    helper_st_asi(addr, val, asi, size);
2839 1a2fb1c0 blueswir1
}
2840 1a2fb1c0 blueswir1
2841 1a2fb1c0 blueswir1
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2842 1a2fb1c0 blueswir1
                            target_ulong val2, uint32_t asi)
2843 1a2fb1c0 blueswir1
{
2844 1a2fb1c0 blueswir1
    target_ulong ret;
2845 1a2fb1c0 blueswir1
2846 1121f879 blueswir1
    val2 &= 0xffffffffUL;
2847 1a2fb1c0 blueswir1
    ret = helper_ld_asi(addr, asi, 4, 0);
2848 1a2fb1c0 blueswir1
    ret &= 0xffffffffUL;
2849 1121f879 blueswir1
    if (val2 == ret)
2850 1121f879 blueswir1
        helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
2851 1a2fb1c0 blueswir1
    return ret;
2852 3391c818 blueswir1
}
2853 3391c818 blueswir1
2854 1a2fb1c0 blueswir1
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2855 1a2fb1c0 blueswir1
                             target_ulong val2, uint32_t asi)
2856 1a2fb1c0 blueswir1
{
2857 1a2fb1c0 blueswir1
    target_ulong ret;
2858 1a2fb1c0 blueswir1
2859 1a2fb1c0 blueswir1
    ret = helper_ld_asi(addr, asi, 8, 0);
2860 1121f879 blueswir1
    if (val2 == ret)
2861 1121f879 blueswir1
        helper_st_asi(addr, val1, asi, 8);
2862 1a2fb1c0 blueswir1
    return ret;
2863 1a2fb1c0 blueswir1
}
2864 81ad8ba2 blueswir1
#endif /* TARGET_SPARC64 */
2865 3475187d bellard
2866 3475187d bellard
#ifndef TARGET_SPARC64
2867 1a2fb1c0 blueswir1
void helper_rett(void)
2868 e8af50a3 bellard
{
2869 af7bf89b bellard
    unsigned int cwp;
2870 af7bf89b bellard
2871 d4218d99 blueswir1
    if (env->psret == 1)
2872 d4218d99 blueswir1
        raise_exception(TT_ILL_INSN);
2873 d4218d99 blueswir1
2874 e8af50a3 bellard
    env->psret = 1;
2875 1a14026e blueswir1
    cwp = cpu_cwp_inc(env, env->cwp + 1) ;
2876 e8af50a3 bellard
    if (env->wim & (1 << cwp)) {
2877 e8af50a3 bellard
        raise_exception(TT_WIN_UNF);
2878 e8af50a3 bellard
    }
2879 e8af50a3 bellard
    set_cwp(cwp);
2880 e8af50a3 bellard
    env->psrs = env->psrps;
2881 e8af50a3 bellard
}
2882 3475187d bellard
#endif
2883 e8af50a3 bellard
2884 3b89f26c blueswir1
target_ulong helper_udiv(target_ulong a, target_ulong b)
2885 3b89f26c blueswir1
{
2886 3b89f26c blueswir1
    uint64_t x0;
2887 3b89f26c blueswir1
    uint32_t x1;
2888 3b89f26c blueswir1
2889 7621a90d blueswir1
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2890 3b89f26c blueswir1
    x1 = b;
2891 3b89f26c blueswir1
2892 3b89f26c blueswir1
    if (x1 == 0) {
2893 3b89f26c blueswir1
        raise_exception(TT_DIV_ZERO);
2894 3b89f26c blueswir1
    }
2895 3b89f26c blueswir1
2896 3b89f26c blueswir1
    x0 = x0 / x1;
2897 3b89f26c blueswir1
    if (x0 > 0xffffffff) {
2898 3b89f26c blueswir1
        env->cc_src2 = 1;
2899 3b89f26c blueswir1
        return 0xffffffff;
2900 3b89f26c blueswir1
    } else {
2901 3b89f26c blueswir1
        env->cc_src2 = 0;
2902 3b89f26c blueswir1
        return x0;
2903 3b89f26c blueswir1
    }
2904 3b89f26c blueswir1
}
2905 3b89f26c blueswir1
2906 3b89f26c blueswir1
target_ulong helper_sdiv(target_ulong a, target_ulong b)
2907 3b89f26c blueswir1
{
2908 3b89f26c blueswir1
    int64_t x0;
2909 3b89f26c blueswir1
    int32_t x1;
2910 3b89f26c blueswir1
2911 7621a90d blueswir1
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2912 3b89f26c blueswir1
    x1 = b;
2913 3b89f26c blueswir1
2914 3b89f26c blueswir1
    if (x1 == 0) {
2915 3b89f26c blueswir1
        raise_exception(TT_DIV_ZERO);
2916 3b89f26c blueswir1
    }
2917 3b89f26c blueswir1
2918 3b89f26c blueswir1
    x0 = x0 / x1;
2919 3b89f26c blueswir1
    if ((int32_t) x0 != x0) {
2920 3b89f26c blueswir1
        env->cc_src2 = 1;
2921 3b89f26c blueswir1
        return x0 < 0? 0x80000000: 0x7fffffff;
2922 3b89f26c blueswir1
    } else {
2923 3b89f26c blueswir1
        env->cc_src2 = 0;
2924 3b89f26c blueswir1
        return x0;
2925 3b89f26c blueswir1
    }
2926 3b89f26c blueswir1
}
2927 3b89f26c blueswir1
2928 7fa76c0b blueswir1
void helper_stdf(target_ulong addr, int mem_idx)
2929 7fa76c0b blueswir1
{
2930 c2bc0e38 blueswir1
    helper_check_align(addr, 7);
2931 7fa76c0b blueswir1
#if !defined(CONFIG_USER_ONLY)
2932 7fa76c0b blueswir1
    switch (mem_idx) {
2933 7fa76c0b blueswir1
    case 0:
2934 c2bc0e38 blueswir1
        stfq_user(addr, DT0);
2935 7fa76c0b blueswir1
        break;
2936 7fa76c0b blueswir1
    case 1:
2937 c2bc0e38 blueswir1
        stfq_kernel(addr, DT0);
2938 7fa76c0b blueswir1
        break;
2939 7fa76c0b blueswir1
#ifdef TARGET_SPARC64
2940 7fa76c0b blueswir1
    case 2:
2941 c2bc0e38 blueswir1
        stfq_hypv(addr, DT0);
2942 7fa76c0b blueswir1
        break;
2943 7fa76c0b blueswir1
#endif
2944 7fa76c0b blueswir1
    default:
2945 7fa76c0b blueswir1
        break;
2946 7fa76c0b blueswir1
    }
2947 7fa76c0b blueswir1
#else
2948 41db525e Richard Henderson
    stfq_raw(address_mask(env, addr), DT0);
2949 7fa76c0b blueswir1
#endif
2950 7fa76c0b blueswir1
}
2951 7fa76c0b blueswir1
2952 7fa76c0b blueswir1
void helper_lddf(target_ulong addr, int mem_idx)
2953 7fa76c0b blueswir1
{
2954 c2bc0e38 blueswir1
    helper_check_align(addr, 7);
2955 7fa76c0b blueswir1
#if !defined(CONFIG_USER_ONLY)
2956 7fa76c0b blueswir1
    switch (mem_idx) {
2957 7fa76c0b blueswir1
    case 0:
2958 c2bc0e38 blueswir1
        DT0 = ldfq_user(addr);
2959 7fa76c0b blueswir1
        break;
2960 7fa76c0b blueswir1
    case 1:
2961 c2bc0e38 blueswir1
        DT0 = ldfq_kernel(addr);
2962 7fa76c0b blueswir1
        break;
2963 7fa76c0b blueswir1
#ifdef TARGET_SPARC64
2964 7fa76c0b blueswir1
    case 2:
2965 c2bc0e38 blueswir1
        DT0 = ldfq_hypv(addr);
2966 7fa76c0b blueswir1
        break;
2967 7fa76c0b blueswir1
#endif
2968 7fa76c0b blueswir1
    default:
2969 7fa76c0b blueswir1
        break;
2970 7fa76c0b blueswir1
    }
2971 7fa76c0b blueswir1
#else
2972 41db525e Richard Henderson
    DT0 = ldfq_raw(address_mask(env, addr));
2973 7fa76c0b blueswir1
#endif
2974 7fa76c0b blueswir1
}
2975 7fa76c0b blueswir1
2976 64a88d5d blueswir1
void helper_ldqf(target_ulong addr, int mem_idx)
2977 7fa76c0b blueswir1
{
2978 7fa76c0b blueswir1
    // XXX add 128 bit load
2979 7fa76c0b blueswir1
    CPU_QuadU u;
2980 7fa76c0b blueswir1
2981 c2bc0e38 blueswir1
    helper_check_align(addr, 7);
2982 64a88d5d blueswir1
#if !defined(CONFIG_USER_ONLY)
2983 64a88d5d blueswir1
    switch (mem_idx) {
2984 64a88d5d blueswir1
    case 0:
2985 c2bc0e38 blueswir1
        u.ll.upper = ldq_user(addr);
2986 c2bc0e38 blueswir1
        u.ll.lower = ldq_user(addr + 8);
2987 64a88d5d blueswir1
        QT0 = u.q;
2988 64a88d5d blueswir1
        break;
2989 64a88d5d blueswir1
    case 1:
2990 c2bc0e38 blueswir1
        u.ll.upper = ldq_kernel(addr);
2991 c2bc0e38 blueswir1
        u.ll.lower = ldq_kernel(addr + 8);
2992 64a88d5d blueswir1
        QT0 = u.q;
2993 64a88d5d blueswir1
        break;
2994 64a88d5d blueswir1
#ifdef TARGET_SPARC64
2995 64a88d5d blueswir1
    case 2:
2996 c2bc0e38 blueswir1
        u.ll.upper = ldq_hypv(addr);
2997 c2bc0e38 blueswir1
        u.ll.lower = ldq_hypv(addr + 8);
2998 64a88d5d blueswir1
        QT0 = u.q;
2999 64a88d5d blueswir1
        break;
3000 64a88d5d blueswir1
#endif
3001 64a88d5d blueswir1
    default:
3002 64a88d5d blueswir1
        break;
3003 64a88d5d blueswir1
    }
3004 64a88d5d blueswir1
#else
3005 41db525e Richard Henderson
    u.ll.upper = ldq_raw(address_mask(env, addr));
3006 41db525e Richard Henderson
    u.ll.lower = ldq_raw(address_mask(env, addr + 8));
3007 7fa76c0b blueswir1
    QT0 = u.q;
3008 64a88d5d blueswir1
#endif
3009 7fa76c0b blueswir1
}
3010 7fa76c0b blueswir1
3011 64a88d5d blueswir1
void helper_stqf(target_ulong addr, int mem_idx)
3012 7fa76c0b blueswir1
{
3013 7fa76c0b blueswir1
    // XXX add 128 bit store
3014 7fa76c0b blueswir1
    CPU_QuadU u;
3015 7fa76c0b blueswir1
3016 c2bc0e38 blueswir1
    helper_check_align(addr, 7);
3017 64a88d5d blueswir1
#if !defined(CONFIG_USER_ONLY)
3018 64a88d5d blueswir1
    switch (mem_idx) {
3019 64a88d5d blueswir1
    case 0:
3020 64a88d5d blueswir1
        u.q = QT0;
3021 c2bc0e38 blueswir1
        stq_user(addr, u.ll.upper);
3022 c2bc0e38 blueswir1
        stq_user(addr + 8, u.ll.lower);
3023 64a88d5d blueswir1
        break;
3024 64a88d5d blueswir1
    case 1:
3025 64a88d5d blueswir1
        u.q = QT0;
3026 c2bc0e38 blueswir1
        stq_kernel(addr, u.ll.upper);
3027 c2bc0e38 blueswir1
        stq_kernel(addr + 8, u.ll.lower);
3028 64a88d5d blueswir1
        break;
3029 64a88d5d blueswir1
#ifdef TARGET_SPARC64
3030 64a88d5d blueswir1
    case 2:
3031 64a88d5d blueswir1
        u.q = QT0;
3032 c2bc0e38 blueswir1
        stq_hypv(addr, u.ll.upper);
3033 c2bc0e38 blueswir1
        stq_hypv(addr + 8, u.ll.lower);
3034 64a88d5d blueswir1
        break;
3035 64a88d5d blueswir1
#endif
3036 64a88d5d blueswir1
    default:
3037 64a88d5d blueswir1
        break;
3038 64a88d5d blueswir1
    }
3039 64a88d5d blueswir1
#else
3040 7fa76c0b blueswir1
    u.q = QT0;
3041 41db525e Richard Henderson
    stq_raw(address_mask(env, addr), u.ll.upper);
3042 41db525e Richard Henderson
    stq_raw(address_mask(env, addr + 8), u.ll.lower);
3043 7fa76c0b blueswir1
#endif
3044 64a88d5d blueswir1
}
3045 7fa76c0b blueswir1
3046 3a3b925d blueswir1
static inline void set_fsr(void)
3047 e8af50a3 bellard
{
3048 7a0e1f41 bellard
    int rnd_mode;
3049 bb5529bb blueswir1
3050 e8af50a3 bellard
    switch (env->fsr & FSR_RD_MASK) {
3051 e8af50a3 bellard
    case FSR_RD_NEAREST:
3052 7a0e1f41 bellard
        rnd_mode = float_round_nearest_even;
3053 0f8a249a blueswir1
        break;
3054 ed910241 bellard
    default:
3055 e8af50a3 bellard
    case FSR_RD_ZERO:
3056 7a0e1f41 bellard
        rnd_mode = float_round_to_zero;
3057 0f8a249a blueswir1
        break;
3058 e8af50a3 bellard
    case FSR_RD_POS:
3059 7a0e1f41 bellard
        rnd_mode = float_round_up;
3060 0f8a249a blueswir1
        break;
3061 e8af50a3 bellard
    case FSR_RD_NEG:
3062 7a0e1f41 bellard
        rnd_mode = float_round_down;
3063 0f8a249a blueswir1
        break;
3064 e8af50a3 bellard
    }
3065 7a0e1f41 bellard
    set_float_rounding_mode(rnd_mode, &env->fp_status);
3066 e8af50a3 bellard
}
3067 e80cfcfc bellard
3068 3a3b925d blueswir1
void helper_ldfsr(uint32_t new_fsr)
3069 bb5529bb blueswir1
{
3070 3a3b925d blueswir1
    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
3071 3a3b925d blueswir1
    set_fsr();
3072 bb5529bb blueswir1
}
3073 bb5529bb blueswir1
3074 3a3b925d blueswir1
#ifdef TARGET_SPARC64
3075 3a3b925d blueswir1
void helper_ldxfsr(uint64_t new_fsr)
3076 3a3b925d blueswir1
{
3077 3a3b925d blueswir1
    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
3078 3a3b925d blueswir1
    set_fsr();
3079 3a3b925d blueswir1
}
3080 3a3b925d blueswir1
#endif
3081 3a3b925d blueswir1
3082 bb5529bb blueswir1
void helper_debug(void)
3083 e80cfcfc bellard
{
3084 e80cfcfc bellard
    env->exception_index = EXCP_DEBUG;
3085 e80cfcfc bellard
    cpu_loop_exit();
3086 e80cfcfc bellard
}
3087 af7bf89b bellard
3088 3475187d bellard
#ifndef TARGET_SPARC64
3089 72a9747b blueswir1
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3090 72a9747b blueswir1
   handling ? */
3091 72a9747b blueswir1
void helper_save(void)
3092 72a9747b blueswir1
{
3093 72a9747b blueswir1
    uint32_t cwp;
3094 72a9747b blueswir1
3095 1a14026e blueswir1
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3096 72a9747b blueswir1
    if (env->wim & (1 << cwp)) {
3097 72a9747b blueswir1
        raise_exception(TT_WIN_OVF);
3098 72a9747b blueswir1
    }
3099 72a9747b blueswir1
    set_cwp(cwp);
3100 72a9747b blueswir1
}
3101 72a9747b blueswir1
3102 72a9747b blueswir1
void helper_restore(void)
3103 72a9747b blueswir1
{
3104 72a9747b blueswir1
    uint32_t cwp;
3105 72a9747b blueswir1
3106 1a14026e blueswir1
    cwp = cpu_cwp_inc(env, env->cwp + 1);
3107 72a9747b blueswir1
    if (env->wim & (1 << cwp)) {
3108 72a9747b blueswir1
        raise_exception(TT_WIN_UNF);
3109 72a9747b blueswir1
    }
3110 72a9747b blueswir1
    set_cwp(cwp);
3111 72a9747b blueswir1
}
3112 72a9747b blueswir1
3113 1a2fb1c0 blueswir1
void helper_wrpsr(target_ulong new_psr)
3114 af7bf89b bellard
{
3115 1a14026e blueswir1
    if ((new_psr & PSR_CWP) >= env->nwindows)
3116 d4218d99 blueswir1
        raise_exception(TT_ILL_INSN);
3117 d4218d99 blueswir1
    else
3118 1a2fb1c0 blueswir1
        PUT_PSR(env, new_psr);
3119 af7bf89b bellard
}
3120 af7bf89b bellard
3121 1a2fb1c0 blueswir1
target_ulong helper_rdpsr(void)
3122 af7bf89b bellard
{
3123 1a2fb1c0 blueswir1
    return GET_PSR(env);
3124 af7bf89b bellard
}
3125 3475187d bellard
3126 3475187d bellard
#else
3127 72a9747b blueswir1
/* XXX: use another pointer for %iN registers to avoid slow wrapping
3128 72a9747b blueswir1
   handling ? */
3129 72a9747b blueswir1
void helper_save(void)
3130 72a9747b blueswir1
{
3131 72a9747b blueswir1
    uint32_t cwp;
3132 72a9747b blueswir1
3133 1a14026e blueswir1
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3134 72a9747b blueswir1
    if (env->cansave == 0) {
3135 72a9747b blueswir1
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
3136 72a9747b blueswir1
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3137 72a9747b blueswir1
                                    ((env->wstate & 0x7) << 2)));
3138 72a9747b blueswir1
    } else {
3139 72a9747b blueswir1
        if (env->cleanwin - env->canrestore == 0) {
3140 72a9747b blueswir1
            // XXX Clean windows without trap
3141 72a9747b blueswir1
            raise_exception(TT_CLRWIN);
3142 72a9747b blueswir1
        } else {
3143 72a9747b blueswir1
            env->cansave--;
3144 72a9747b blueswir1
            env->canrestore++;
3145 72a9747b blueswir1
            set_cwp(cwp);
3146 72a9747b blueswir1
        }
3147 72a9747b blueswir1
    }
3148 72a9747b blueswir1
}
3149 72a9747b blueswir1
3150 72a9747b blueswir1
void helper_restore(void)
3151 72a9747b blueswir1
{
3152 72a9747b blueswir1
    uint32_t cwp;
3153 72a9747b blueswir1
3154 1a14026e blueswir1
    cwp = cpu_cwp_inc(env, env->cwp + 1);
3155 72a9747b blueswir1
    if (env->canrestore == 0) {
3156 72a9747b blueswir1
        raise_exception(TT_FILL | (env->otherwin != 0 ?
3157 72a9747b blueswir1
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3158 72a9747b blueswir1
                                   ((env->wstate & 0x7) << 2)));
3159 72a9747b blueswir1
    } else {
3160 72a9747b blueswir1
        env->cansave++;
3161 72a9747b blueswir1
        env->canrestore--;
3162 72a9747b blueswir1
        set_cwp(cwp);
3163 72a9747b blueswir1
    }
3164 72a9747b blueswir1
}
3165 72a9747b blueswir1
3166 72a9747b blueswir1
void helper_flushw(void)
3167 72a9747b blueswir1
{
3168 1a14026e blueswir1
    if (env->cansave != env->nwindows - 2) {
3169 72a9747b blueswir1
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
3170 72a9747b blueswir1
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
3171 72a9747b blueswir1
                                    ((env->wstate & 0x7) << 2)));
3172 72a9747b blueswir1
    }
3173 72a9747b blueswir1
}
3174 72a9747b blueswir1
3175 72a9747b blueswir1
void helper_saved(void)
3176 72a9747b blueswir1
{
3177 72a9747b blueswir1
    env->cansave++;
3178 72a9747b blueswir1
    if (env->otherwin == 0)
3179 72a9747b blueswir1
        env->canrestore--;
3180 72a9747b blueswir1
    else
3181 72a9747b blueswir1
        env->otherwin--;
3182 72a9747b blueswir1
}
3183 72a9747b blueswir1
3184 72a9747b blueswir1
void helper_restored(void)
3185 72a9747b blueswir1
{
3186 72a9747b blueswir1
    env->canrestore++;
3187 1a14026e blueswir1
    if (env->cleanwin < env->nwindows - 1)
3188 72a9747b blueswir1
        env->cleanwin++;
3189 72a9747b blueswir1
    if (env->otherwin == 0)
3190 72a9747b blueswir1
        env->cansave--;
3191 72a9747b blueswir1
    else
3192 72a9747b blueswir1
        env->otherwin--;
3193 72a9747b blueswir1
}
3194 72a9747b blueswir1
3195 d35527d9 blueswir1
target_ulong helper_rdccr(void)
3196 d35527d9 blueswir1
{
3197 d35527d9 blueswir1
    return GET_CCR(env);
3198 d35527d9 blueswir1
}
3199 d35527d9 blueswir1
3200 d35527d9 blueswir1
void helper_wrccr(target_ulong new_ccr)
3201 d35527d9 blueswir1
{
3202 d35527d9 blueswir1
    PUT_CCR(env, new_ccr);
3203 d35527d9 blueswir1
}
3204 d35527d9 blueswir1
3205 d35527d9 blueswir1
// CWP handling is reversed in V9, but we still use the V8 register
3206 d35527d9 blueswir1
// order.
3207 d35527d9 blueswir1
target_ulong helper_rdcwp(void)
3208 d35527d9 blueswir1
{
3209 d35527d9 blueswir1
    return GET_CWP64(env);
3210 d35527d9 blueswir1
}
3211 d35527d9 blueswir1
3212 d35527d9 blueswir1
void helper_wrcwp(target_ulong new_cwp)
3213 d35527d9 blueswir1
{
3214 d35527d9 blueswir1
    PUT_CWP64(env, new_cwp);
3215 d35527d9 blueswir1
}
3216 3475187d bellard
3217 1f5063fb blueswir1
// This function uses non-native bit order
3218 1f5063fb blueswir1
#define GET_FIELD(X, FROM, TO)                                  \
3219 1f5063fb blueswir1
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
3220 1f5063fb blueswir1
3221 1f5063fb blueswir1
// This function uses the order in the manuals, i.e. bit 0 is 2^0
3222 1f5063fb blueswir1
#define GET_FIELD_SP(X, FROM, TO)               \
3223 1f5063fb blueswir1
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
3224 1f5063fb blueswir1
3225 1f5063fb blueswir1
target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
3226 1f5063fb blueswir1
{
3227 1f5063fb blueswir1
    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
3228 1f5063fb blueswir1
        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
3229 1f5063fb blueswir1
        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
3230 1f5063fb blueswir1
        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
3231 1f5063fb blueswir1
        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
3232 1f5063fb blueswir1
        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
3233 1f5063fb blueswir1
        (((pixel_addr >> 55) & 1) << 4) |
3234 1f5063fb blueswir1
        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
3235 1f5063fb blueswir1
        GET_FIELD_SP(pixel_addr, 11, 12);
3236 1f5063fb blueswir1
}
3237 1f5063fb blueswir1
3238 1f5063fb blueswir1
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
3239 1f5063fb blueswir1
{
3240 1f5063fb blueswir1
    uint64_t tmp;
3241 1f5063fb blueswir1
3242 1f5063fb blueswir1
    tmp = addr + offset;
3243 1f5063fb blueswir1
    env->gsr &= ~7ULL;
3244 1f5063fb blueswir1
    env->gsr |= tmp & 7ULL;
3245 1f5063fb blueswir1
    return tmp & ~7ULL;
3246 1f5063fb blueswir1
}
3247 1f5063fb blueswir1
3248 1a2fb1c0 blueswir1
target_ulong helper_popc(target_ulong val)
3249 3475187d bellard
{
3250 1a2fb1c0 blueswir1
    return ctpop64(val);
3251 3475187d bellard
}
3252 83469015 bellard
3253 d780a466 Igor V. Kovalenko
static inline uint64_t *get_gregset(uint32_t pstate)
3254 83469015 bellard
{
3255 83469015 bellard
    switch (pstate) {
3256 83469015 bellard
    default:
3257 7e8695ed Igor V. Kovalenko
        DPRINTF_PSTATE("ERROR in get_gregset: active pstate bits=%x%s%s%s\n",
3258 7e8695ed Igor V. Kovalenko
                pstate,
3259 7e8695ed Igor V. Kovalenko
                (pstate & PS_IG) ? " IG" : "",
3260 7e8695ed Igor V. Kovalenko
                (pstate & PS_MG) ? " MG" : "",
3261 7e8695ed Igor V. Kovalenko
                (pstate & PS_AG) ? " AG" : "");
3262 7e8695ed Igor V. Kovalenko
        /* pass through to normal set of global registers */
3263 83469015 bellard
    case 0:
3264 0f8a249a blueswir1
        return env->bgregs;
3265 83469015 bellard
    case PS_AG:
3266 0f8a249a blueswir1
        return env->agregs;
3267 83469015 bellard
    case PS_MG:
3268 0f8a249a blueswir1
        return env->mgregs;
3269 83469015 bellard
    case PS_IG:
3270 0f8a249a blueswir1
        return env->igregs;
3271 83469015 bellard
    }
3272 83469015 bellard
}
3273 83469015 bellard
3274 d780a466 Igor V. Kovalenko
static inline void change_pstate(uint32_t new_pstate)
3275 83469015 bellard
{
3276 d780a466 Igor V. Kovalenko
    uint32_t pstate_regs, new_pstate_regs;
3277 83469015 bellard
    uint64_t *src, *dst;
3278 83469015 bellard
3279 5210977a Igor Kovalenko
    if (env->def->features & CPU_FEATURE_GL) {
3280 5210977a Igor Kovalenko
        // PS_AG is not implemented in this case
3281 5210977a Igor Kovalenko
        new_pstate &= ~PS_AG;
3282 5210977a Igor Kovalenko
    }
3283 5210977a Igor Kovalenko
3284 83469015 bellard
    pstate_regs = env->pstate & 0xc01;
3285 83469015 bellard
    new_pstate_regs = new_pstate & 0xc01;
3286 5210977a Igor Kovalenko
3287 83469015 bellard
    if (new_pstate_regs != pstate_regs) {
3288 7e8695ed Igor V. Kovalenko
        DPRINTF_PSTATE("change_pstate: switching regs old=%x new=%x\n",
3289 7e8695ed Igor V. Kovalenko
                       pstate_regs, new_pstate_regs);
3290 0f8a249a blueswir1
        // Switch global register bank
3291 0f8a249a blueswir1
        src = get_gregset(new_pstate_regs);
3292 0f8a249a blueswir1
        dst = get_gregset(pstate_regs);
3293 0f8a249a blueswir1
        memcpy32(dst, env->gregs);
3294 0f8a249a blueswir1
        memcpy32(env->gregs, src);
3295 83469015 bellard
    }
3296 7e8695ed Igor V. Kovalenko
    else {
3297 7e8695ed Igor V. Kovalenko
        DPRINTF_PSTATE("change_pstate: regs new=%x (unchanged)\n",
3298 7e8695ed Igor V. Kovalenko
                       new_pstate_regs);
3299 7e8695ed Igor V. Kovalenko
    }
3300 83469015 bellard
    env->pstate = new_pstate;
3301 83469015 bellard
}
3302 83469015 bellard
3303 1a2fb1c0 blueswir1
void helper_wrpstate(target_ulong new_state)
3304 8f1f22f6 blueswir1
{
3305 5210977a Igor Kovalenko
    change_pstate(new_state & 0xf3f);
3306 4dc28134 Igor V. Kovalenko
3307 4dc28134 Igor V. Kovalenko
#if !defined(CONFIG_USER_ONLY)
3308 4dc28134 Igor V. Kovalenko
    if (cpu_interrupts_enabled(env)) {
3309 4dc28134 Igor V. Kovalenko
        cpu_check_irqs(env);
3310 4dc28134 Igor V. Kovalenko
    }
3311 4dc28134 Igor V. Kovalenko
#endif
3312 8f1f22f6 blueswir1
}
3313 8f1f22f6 blueswir1
3314 1fae7b70 Igor V. Kovalenko
void helper_wrpil(target_ulong new_pil)
3315 1fae7b70 Igor V. Kovalenko
{
3316 1fae7b70 Igor V. Kovalenko
#if !defined(CONFIG_USER_ONLY)
3317 1fae7b70 Igor V. Kovalenko
    DPRINTF_PSTATE("helper_wrpil old=%x new=%x\n",
3318 1fae7b70 Igor V. Kovalenko
                   env->psrpil, (uint32_t)new_pil);
3319 1fae7b70 Igor V. Kovalenko
3320 1fae7b70 Igor V. Kovalenko
    env->psrpil = new_pil;
3321 1fae7b70 Igor V. Kovalenko
3322 1fae7b70 Igor V. Kovalenko
    if (cpu_interrupts_enabled(env)) {
3323 1fae7b70 Igor V. Kovalenko
        cpu_check_irqs(env);
3324 1fae7b70 Igor V. Kovalenko
    }
3325 1fae7b70 Igor V. Kovalenko
#endif
3326 1fae7b70 Igor V. Kovalenko
}
3327 1fae7b70 Igor V. Kovalenko
3328 1a2fb1c0 blueswir1
void helper_done(void)
3329 83469015 bellard
{
3330 8194f35a Igor Kovalenko
    trap_state* tsptr = cpu_tsptr(env);
3331 8194f35a Igor Kovalenko
3332 3723cd09 Igor V. Kovalenko
    env->pc = tsptr->tnpc;
3333 8194f35a Igor Kovalenko
    env->npc = tsptr->tnpc + 4;
3334 8194f35a Igor Kovalenko
    PUT_CCR(env, tsptr->tstate >> 32);
3335 8194f35a Igor Kovalenko
    env->asi = (tsptr->tstate >> 24) & 0xff;
3336 8194f35a Igor Kovalenko
    change_pstate((tsptr->tstate >> 8) & 0xf3f);
3337 8194f35a Igor Kovalenko
    PUT_CWP64(env, tsptr->tstate & 0xff);
3338 e6bf7d70 blueswir1
    env->tl--;
3339 4dc28134 Igor V. Kovalenko
3340 4dc28134 Igor V. Kovalenko
    DPRINTF_PSTATE("... helper_done tl=%d\n", env->tl);
3341 4dc28134 Igor V. Kovalenko
3342 4dc28134 Igor V. Kovalenko
#if !defined(CONFIG_USER_ONLY)
3343 4dc28134 Igor V. Kovalenko
    if (cpu_interrupts_enabled(env)) {
3344 4dc28134 Igor V. Kovalenko
        cpu_check_irqs(env);
3345 4dc28134 Igor V. Kovalenko
    }
3346 4dc28134 Igor V. Kovalenko
#endif
3347 83469015 bellard
}
3348 83469015 bellard
3349 1a2fb1c0 blueswir1
void helper_retry(void)
3350 83469015 bellard
{
3351 8194f35a Igor Kovalenko
    trap_state* tsptr = cpu_tsptr(env);
3352 8194f35a Igor Kovalenko
3353 8194f35a Igor Kovalenko
    env->pc = tsptr->tpc;
3354 8194f35a Igor Kovalenko
    env->npc = tsptr->tnpc;
3355 8194f35a Igor Kovalenko
    PUT_CCR(env, tsptr->tstate >> 32);
3356 8194f35a Igor Kovalenko
    env->asi = (tsptr->tstate >> 24) & 0xff;
3357 8194f35a Igor Kovalenko
    change_pstate((tsptr->tstate >> 8) & 0xf3f);
3358 8194f35a Igor Kovalenko
    PUT_CWP64(env, tsptr->tstate & 0xff);
3359 e6bf7d70 blueswir1
    env->tl--;
3360 4dc28134 Igor V. Kovalenko
3361 4dc28134 Igor V. Kovalenko
    DPRINTF_PSTATE("... helper_retry tl=%d\n", env->tl);
3362 4dc28134 Igor V. Kovalenko
3363 4dc28134 Igor V. Kovalenko
#if !defined(CONFIG_USER_ONLY)
3364 4dc28134 Igor V. Kovalenko
    if (cpu_interrupts_enabled(env)) {
3365 4dc28134 Igor V. Kovalenko
        cpu_check_irqs(env);
3366 4dc28134 Igor V. Kovalenko
    }
3367 4dc28134 Igor V. Kovalenko
#endif
3368 4dc28134 Igor V. Kovalenko
}
3369 4dc28134 Igor V. Kovalenko
3370 4dc28134 Igor V. Kovalenko
static void do_modify_softint(const char* operation, uint32_t value)
3371 4dc28134 Igor V. Kovalenko
{
3372 4dc28134 Igor V. Kovalenko
    if (env->softint != value) {
3373 4dc28134 Igor V. Kovalenko
        env->softint = value;
3374 4dc28134 Igor V. Kovalenko
        DPRINTF_PSTATE(": %s new %08x\n", operation, env->softint);
3375 4dc28134 Igor V. Kovalenko
#if !defined(CONFIG_USER_ONLY)
3376 4dc28134 Igor V. Kovalenko
        if (cpu_interrupts_enabled(env)) {
3377 4dc28134 Igor V. Kovalenko
            cpu_check_irqs(env);
3378 4dc28134 Igor V. Kovalenko
        }
3379 4dc28134 Igor V. Kovalenko
#endif
3380 4dc28134 Igor V. Kovalenko
    }
3381 83469015 bellard
}
3382 9d926598 blueswir1
3383 9d926598 blueswir1
void helper_set_softint(uint64_t value)
3384 9d926598 blueswir1
{
3385 4dc28134 Igor V. Kovalenko
    do_modify_softint("helper_set_softint", env->softint | (uint32_t)value);
3386 9d926598 blueswir1
}
3387 9d926598 blueswir1
3388 9d926598 blueswir1
void helper_clear_softint(uint64_t value)
3389 9d926598 blueswir1
{
3390 4dc28134 Igor V. Kovalenko
    do_modify_softint("helper_clear_softint", env->softint & (uint32_t)~value);
3391 9d926598 blueswir1
}
3392 9d926598 blueswir1
3393 9d926598 blueswir1
void helper_write_softint(uint64_t value)
3394 9d926598 blueswir1
{
3395 4dc28134 Igor V. Kovalenko
    do_modify_softint("helper_write_softint", (uint32_t)value);
3396 9d926598 blueswir1
}
3397 3475187d bellard
#endif
3398 ee5bbe38 bellard
3399 91736d37 blueswir1
void helper_flush(target_ulong addr)
3400 ee5bbe38 bellard
{
3401 91736d37 blueswir1
    addr &= ~7;
3402 91736d37 blueswir1
    tb_invalidate_page_range(addr, addr + 8);
3403 ee5bbe38 bellard
}
3404 ee5bbe38 bellard
3405 91736d37 blueswir1
#ifdef TARGET_SPARC64
3406 91736d37 blueswir1
#ifdef DEBUG_PCALL
3407 91736d37 blueswir1
static const char * const excp_names[0x80] = {
3408 91736d37 blueswir1
    [TT_TFAULT] = "Instruction Access Fault",
3409 91736d37 blueswir1
    [TT_TMISS] = "Instruction Access MMU Miss",
3410 91736d37 blueswir1
    [TT_CODE_ACCESS] = "Instruction Access Error",
3411 91736d37 blueswir1
    [TT_ILL_INSN] = "Illegal Instruction",
3412 91736d37 blueswir1
    [TT_PRIV_INSN] = "Privileged Instruction",
3413 91736d37 blueswir1
    [TT_NFPU_INSN] = "FPU Disabled",
3414 91736d37 blueswir1
    [TT_FP_EXCP] = "FPU Exception",
3415 91736d37 blueswir1
    [TT_TOVF] = "Tag Overflow",
3416 91736d37 blueswir1
    [TT_CLRWIN] = "Clean Windows",
3417 91736d37 blueswir1
    [TT_DIV_ZERO] = "Division By Zero",
3418 91736d37 blueswir1
    [TT_DFAULT] = "Data Access Fault",
3419 91736d37 blueswir1
    [TT_DMISS] = "Data Access MMU Miss",
3420 91736d37 blueswir1
    [TT_DATA_ACCESS] = "Data Access Error",
3421 91736d37 blueswir1
    [TT_DPROT] = "Data Protection Error",
3422 91736d37 blueswir1
    [TT_UNALIGNED] = "Unaligned Memory Access",
3423 91736d37 blueswir1
    [TT_PRIV_ACT] = "Privileged Action",
3424 91736d37 blueswir1
    [TT_EXTINT | 0x1] = "External Interrupt 1",
3425 91736d37 blueswir1
    [TT_EXTINT | 0x2] = "External Interrupt 2",
3426 91736d37 blueswir1
    [TT_EXTINT | 0x3] = "External Interrupt 3",
3427 91736d37 blueswir1
    [TT_EXTINT | 0x4] = "External Interrupt 4",
3428 91736d37 blueswir1
    [TT_EXTINT | 0x5] = "External Interrupt 5",
3429 91736d37 blueswir1
    [TT_EXTINT | 0x6] = "External Interrupt 6",
3430 91736d37 blueswir1
    [TT_EXTINT | 0x7] = "External Interrupt 7",
3431 91736d37 blueswir1
    [TT_EXTINT | 0x8] = "External Interrupt 8",
3432 91736d37 blueswir1
    [TT_EXTINT | 0x9] = "External Interrupt 9",
3433 91736d37 blueswir1
    [TT_EXTINT | 0xa] = "External Interrupt 10",
3434 91736d37 blueswir1
    [TT_EXTINT | 0xb] = "External Interrupt 11",
3435 91736d37 blueswir1
    [TT_EXTINT | 0xc] = "External Interrupt 12",
3436 91736d37 blueswir1
    [TT_EXTINT | 0xd] = "External Interrupt 13",
3437 91736d37 blueswir1
    [TT_EXTINT | 0xe] = "External Interrupt 14",
3438 91736d37 blueswir1
    [TT_EXTINT | 0xf] = "External Interrupt 15",
3439 91736d37 blueswir1
};
3440 91736d37 blueswir1
#endif
3441 91736d37 blueswir1
3442 8194f35a Igor Kovalenko
trap_state* cpu_tsptr(CPUState* env)
3443 8194f35a Igor Kovalenko
{
3444 8194f35a Igor Kovalenko
    return &env->ts[env->tl & MAXTL_MASK];
3445 8194f35a Igor Kovalenko
}
3446 8194f35a Igor Kovalenko
3447 91736d37 blueswir1
void do_interrupt(CPUState *env)
3448 91736d37 blueswir1
{
3449 91736d37 blueswir1
    int intno = env->exception_index;
3450 8194f35a Igor Kovalenko
    trap_state* tsptr;
3451 91736d37 blueswir1
3452 91736d37 blueswir1
#ifdef DEBUG_PCALL
3453 8fec2b8c aliguori
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3454 91736d37 blueswir1
        static int count;
3455 91736d37 blueswir1
        const char *name;
3456 91736d37 blueswir1
3457 91736d37 blueswir1
        if (intno < 0 || intno >= 0x180)
3458 91736d37 blueswir1
            name = "Unknown";
3459 91736d37 blueswir1
        else if (intno >= 0x100)
3460 91736d37 blueswir1
            name = "Trap Instruction";
3461 91736d37 blueswir1
        else if (intno >= 0xc0)
3462 91736d37 blueswir1
            name = "Window Fill";
3463 91736d37 blueswir1
        else if (intno >= 0x80)
3464 91736d37 blueswir1
            name = "Window Spill";
3465 91736d37 blueswir1
        else {
3466 91736d37 blueswir1
            name = excp_names[intno];
3467 91736d37 blueswir1
            if (!name)
3468 91736d37 blueswir1
                name = "Unknown";
3469 91736d37 blueswir1
        }
3470 91736d37 blueswir1
3471 93fcfe39 aliguori
        qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
3472 91736d37 blueswir1
                " SP=%016" PRIx64 "\n",
3473 91736d37 blueswir1
                count, name, intno,
3474 91736d37 blueswir1
                env->pc,
3475 91736d37 blueswir1
                env->npc, env->regwptr[6]);
3476 93fcfe39 aliguori
        log_cpu_state(env, 0);
3477 91736d37 blueswir1
#if 0
3478 91736d37 blueswir1
        {
3479 91736d37 blueswir1
            int i;
3480 91736d37 blueswir1
            uint8_t *ptr;
3481 91736d37 blueswir1

3482 93fcfe39 aliguori
            qemu_log("       code=");
3483 91736d37 blueswir1
            ptr = (uint8_t *)env->pc;
3484 91736d37 blueswir1
            for(i = 0; i < 16; i++) {
3485 93fcfe39 aliguori
                qemu_log(" %02x", ldub(ptr + i));
3486 91736d37 blueswir1
            }
3487 93fcfe39 aliguori
            qemu_log("\n");
3488 91736d37 blueswir1
        }
3489 91736d37 blueswir1
#endif
3490 91736d37 blueswir1
        count++;
3491 91736d37 blueswir1
    }
3492 91736d37 blueswir1
#endif
3493 91736d37 blueswir1
#if !defined(CONFIG_USER_ONLY)
3494 91736d37 blueswir1
    if (env->tl >= env->maxtl) {
3495 91736d37 blueswir1
        cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
3496 91736d37 blueswir1
                  " Error state", env->exception_index, env->tl, env->maxtl);
3497 91736d37 blueswir1
        return;
3498 91736d37 blueswir1
    }
3499 91736d37 blueswir1
#endif
3500 91736d37 blueswir1
    if (env->tl < env->maxtl - 1) {
3501 91736d37 blueswir1
        env->tl++;
3502 91736d37 blueswir1
    } else {
3503 91736d37 blueswir1
        env->pstate |= PS_RED;
3504 91736d37 blueswir1
        if (env->tl < env->maxtl)
3505 91736d37 blueswir1
            env->tl++;
3506 91736d37 blueswir1
    }
3507 8194f35a Igor Kovalenko
    tsptr = cpu_tsptr(env);
3508 8194f35a Igor Kovalenko
3509 8194f35a Igor Kovalenko
    tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
3510 91736d37 blueswir1
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
3511 91736d37 blueswir1
        GET_CWP64(env);
3512 8194f35a Igor Kovalenko
    tsptr->tpc = env->pc;
3513 8194f35a Igor Kovalenko
    tsptr->tnpc = env->npc;
3514 8194f35a Igor Kovalenko
    tsptr->tt = intno;
3515 5210977a Igor Kovalenko
3516 5210977a Igor Kovalenko
    switch (intno) {
3517 5210977a Igor Kovalenko
    case TT_IVEC:
3518 5210977a Igor Kovalenko
        change_pstate(PS_PEF | PS_PRIV | PS_IG);
3519 5210977a Igor Kovalenko
        break;
3520 5210977a Igor Kovalenko
    case TT_TFAULT:
3521 5210977a Igor Kovalenko
    case TT_DFAULT:
3522 87f6d3f6 Igor V. Kovalenko
    case TT_TMISS ... TT_TMISS + 3:
3523 87f6d3f6 Igor V. Kovalenko
    case TT_DMISS ... TT_DMISS + 3:
3524 87f6d3f6 Igor V. Kovalenko
    case TT_DPROT ... TT_DPROT + 3:
3525 5210977a Igor Kovalenko
        change_pstate(PS_PEF | PS_PRIV | PS_MG);
3526 5210977a Igor Kovalenko
        break;
3527 5210977a Igor Kovalenko
    default:
3528 5210977a Igor Kovalenko
        change_pstate(PS_PEF | PS_PRIV | PS_AG);
3529 5210977a Igor Kovalenko
        break;
3530 91736d37 blueswir1
    }
3531 5210977a Igor Kovalenko
3532 91736d37 blueswir1
    if (intno == TT_CLRWIN)
3533 91736d37 blueswir1
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
3534 91736d37 blueswir1
    else if ((intno & 0x1c0) == TT_SPILL)
3535 91736d37 blueswir1
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
3536 91736d37 blueswir1
    else if ((intno & 0x1c0) == TT_FILL)
3537 91736d37 blueswir1
        cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
3538 91736d37 blueswir1
    env->tbr &= ~0x7fffULL;
3539 91736d37 blueswir1
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
3540 91736d37 blueswir1
    env->pc = env->tbr;
3541 91736d37 blueswir1
    env->npc = env->pc + 4;
3542 821b19fe Igor V. Kovalenko
    env->exception_index = -1;
3543 ee5bbe38 bellard
}
3544 91736d37 blueswir1
#else
3545 91736d37 blueswir1
#ifdef DEBUG_PCALL
3546 91736d37 blueswir1
static const char * const excp_names[0x80] = {
3547 91736d37 blueswir1
    [TT_TFAULT] = "Instruction Access Fault",
3548 91736d37 blueswir1
    [TT_ILL_INSN] = "Illegal Instruction",
3549 91736d37 blueswir1
    [TT_PRIV_INSN] = "Privileged Instruction",
3550 91736d37 blueswir1
    [TT_NFPU_INSN] = "FPU Disabled",
3551 91736d37 blueswir1
    [TT_WIN_OVF] = "Window Overflow",
3552 91736d37 blueswir1
    [TT_WIN_UNF] = "Window Underflow",
3553 91736d37 blueswir1
    [TT_UNALIGNED] = "Unaligned Memory Access",
3554 91736d37 blueswir1
    [TT_FP_EXCP] = "FPU Exception",
3555 91736d37 blueswir1
    [TT_DFAULT] = "Data Access Fault",
3556 91736d37 blueswir1
    [TT_TOVF] = "Tag Overflow",
3557 91736d37 blueswir1
    [TT_EXTINT | 0x1] = "External Interrupt 1",
3558 91736d37 blueswir1
    [TT_EXTINT | 0x2] = "External Interrupt 2",
3559 91736d37 blueswir1
    [TT_EXTINT | 0x3] = "External Interrupt 3",
3560 91736d37 blueswir1
    [TT_EXTINT | 0x4] = "External Interrupt 4",
3561 91736d37 blueswir1
    [TT_EXTINT | 0x5] = "External Interrupt 5",
3562 91736d37 blueswir1
    [TT_EXTINT | 0x6] = "External Interrupt 6",
3563 91736d37 blueswir1
    [TT_EXTINT | 0x7] = "External Interrupt 7",
3564 91736d37 blueswir1
    [TT_EXTINT | 0x8] = "External Interrupt 8",
3565 91736d37 blueswir1
    [TT_EXTINT | 0x9] = "External Interrupt 9",
3566 91736d37 blueswir1
    [TT_EXTINT | 0xa] = "External Interrupt 10",
3567 91736d37 blueswir1
    [TT_EXTINT | 0xb] = "External Interrupt 11",
3568 91736d37 blueswir1
    [TT_EXTINT | 0xc] = "External Interrupt 12",
3569 91736d37 blueswir1
    [TT_EXTINT | 0xd] = "External Interrupt 13",
3570 91736d37 blueswir1
    [TT_EXTINT | 0xe] = "External Interrupt 14",
3571 91736d37 blueswir1
    [TT_EXTINT | 0xf] = "External Interrupt 15",
3572 91736d37 blueswir1
    [TT_TOVF] = "Tag Overflow",
3573 91736d37 blueswir1
    [TT_CODE_ACCESS] = "Instruction Access Error",
3574 91736d37 blueswir1
    [TT_DATA_ACCESS] = "Data Access Error",
3575 91736d37 blueswir1
    [TT_DIV_ZERO] = "Division By Zero",
3576 91736d37 blueswir1
    [TT_NCP_INSN] = "Coprocessor Disabled",
3577 91736d37 blueswir1
};
3578 91736d37 blueswir1
#endif
3579 ee5bbe38 bellard
3580 91736d37 blueswir1
void do_interrupt(CPUState *env)
3581 ee5bbe38 bellard
{
3582 91736d37 blueswir1
    int cwp, intno = env->exception_index;
3583 91736d37 blueswir1
3584 91736d37 blueswir1
#ifdef DEBUG_PCALL
3585 8fec2b8c aliguori
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3586 91736d37 blueswir1
        static int count;
3587 91736d37 blueswir1
        const char *name;
3588 91736d37 blueswir1
3589 91736d37 blueswir1
        if (intno < 0 || intno >= 0x100)
3590 91736d37 blueswir1
            name = "Unknown";
3591 91736d37 blueswir1
        else if (intno >= 0x80)
3592 91736d37 blueswir1
            name = "Trap Instruction";
3593 91736d37 blueswir1
        else {
3594 91736d37 blueswir1
            name = excp_names[intno];
3595 91736d37 blueswir1
            if (!name)
3596 91736d37 blueswir1
                name = "Unknown";
3597 91736d37 blueswir1
        }
3598 91736d37 blueswir1
3599 93fcfe39 aliguori
        qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
3600 91736d37 blueswir1
                count, name, intno,
3601 91736d37 blueswir1
                env->pc,
3602 91736d37 blueswir1
                env->npc, env->regwptr[6]);
3603 93fcfe39 aliguori
        log_cpu_state(env, 0);
3604 91736d37 blueswir1
#if 0
3605 91736d37 blueswir1
        {
3606 91736d37 blueswir1
            int i;
3607 91736d37 blueswir1
            uint8_t *ptr;
3608 91736d37 blueswir1

3609 93fcfe39 aliguori
            qemu_log("       code=");
3610 91736d37 blueswir1
            ptr = (uint8_t *)env->pc;
3611 91736d37 blueswir1
            for(i = 0; i < 16; i++) {
3612 93fcfe39 aliguori
                qemu_log(" %02x", ldub(ptr + i));
3613 91736d37 blueswir1
            }
3614 93fcfe39 aliguori
            qemu_log("\n");
3615 91736d37 blueswir1
        }
3616 91736d37 blueswir1
#endif
3617 91736d37 blueswir1
        count++;
3618 91736d37 blueswir1
    }
3619 91736d37 blueswir1
#endif
3620 91736d37 blueswir1
#if !defined(CONFIG_USER_ONLY)
3621 91736d37 blueswir1
    if (env->psret == 0) {
3622 91736d37 blueswir1
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
3623 91736d37 blueswir1
                  env->exception_index);
3624 91736d37 blueswir1
        return;
3625 91736d37 blueswir1
    }
3626 91736d37 blueswir1
#endif
3627 91736d37 blueswir1
    env->psret = 0;
3628 91736d37 blueswir1
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3629 91736d37 blueswir1
    cpu_set_cwp(env, cwp);
3630 91736d37 blueswir1
    env->regwptr[9] = env->pc;
3631 91736d37 blueswir1
    env->regwptr[10] = env->npc;
3632 91736d37 blueswir1
    env->psrps = env->psrs;
3633 91736d37 blueswir1
    env->psrs = 1;
3634 91736d37 blueswir1
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
3635 91736d37 blueswir1
    env->pc = env->tbr;
3636 91736d37 blueswir1
    env->npc = env->pc + 4;
3637 95372a39 Blue Swirl
    env->exception_index = -1;
3638 ee5bbe38 bellard
}
3639 91736d37 blueswir1
#endif
3640 ee5bbe38 bellard
3641 5fafdf24 ths
#if !defined(CONFIG_USER_ONLY)
3642 ee5bbe38 bellard
3643 d2889a3e blueswir1
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3644 d2889a3e blueswir1
                                void *retaddr);
3645 d2889a3e blueswir1
3646 ee5bbe38 bellard
#define MMUSUFFIX _mmu
3647 d2889a3e blueswir1
#define ALIGNED_ONLY
3648 ee5bbe38 bellard
3649 ee5bbe38 bellard
#define SHIFT 0
3650 ee5bbe38 bellard
#include "softmmu_template.h"
3651 ee5bbe38 bellard
3652 ee5bbe38 bellard
#define SHIFT 1
3653 ee5bbe38 bellard
#include "softmmu_template.h"
3654 ee5bbe38 bellard
3655 ee5bbe38 bellard
#define SHIFT 2
3656 ee5bbe38 bellard
#include "softmmu_template.h"
3657 ee5bbe38 bellard
3658 ee5bbe38 bellard
#define SHIFT 3
3659 ee5bbe38 bellard
#include "softmmu_template.h"
3660 ee5bbe38 bellard
3661 c2bc0e38 blueswir1
/* XXX: make it generic ? */
3662 c2bc0e38 blueswir1
static void cpu_restore_state2(void *retaddr)
3663 c2bc0e38 blueswir1
{
3664 c2bc0e38 blueswir1
    TranslationBlock *tb;
3665 c2bc0e38 blueswir1
    unsigned long pc;
3666 c2bc0e38 blueswir1
3667 c2bc0e38 blueswir1
    if (retaddr) {
3668 c2bc0e38 blueswir1
        /* now we have a real cpu fault */
3669 c2bc0e38 blueswir1
        pc = (unsigned long)retaddr;
3670 c2bc0e38 blueswir1
        tb = tb_find_pc(pc);
3671 c2bc0e38 blueswir1
        if (tb) {
3672 c2bc0e38 blueswir1
            /* the PC is inside the translated code. It means that we have
3673 c2bc0e38 blueswir1
               a virtual CPU fault */
3674 c2bc0e38 blueswir1
            cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
3675 c2bc0e38 blueswir1
        }
3676 c2bc0e38 blueswir1
    }
3677 c2bc0e38 blueswir1
}
3678 c2bc0e38 blueswir1
3679 d2889a3e blueswir1
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3680 d2889a3e blueswir1
                                void *retaddr)
3681 d2889a3e blueswir1
{
3682 94554550 blueswir1
#ifdef DEBUG_UNALIGNED
3683 c2bc0e38 blueswir1
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
3684 c2bc0e38 blueswir1
           "\n", addr, env->pc);
3685 94554550 blueswir1
#endif
3686 c2bc0e38 blueswir1
    cpu_restore_state2(retaddr);
3687 94554550 blueswir1
    raise_exception(TT_UNALIGNED);
3688 d2889a3e blueswir1
}
3689 ee5bbe38 bellard
3690 ee5bbe38 bellard
/* try to fill the TLB and return an exception if error. If retaddr is
3691 ee5bbe38 bellard
   NULL, it means that the function was called in C code (i.e. not
3692 ee5bbe38 bellard
   from generated code or from helper.c) */
3693 ee5bbe38 bellard
/* XXX: fix it to restore all registers */
3694 6ebbf390 j_mayer
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3695 ee5bbe38 bellard
{
3696 ee5bbe38 bellard
    int ret;
3697 ee5bbe38 bellard
    CPUState *saved_env;
3698 ee5bbe38 bellard
3699 ee5bbe38 bellard
    /* XXX: hack to restore env in all cases, even if not called from
3700 ee5bbe38 bellard
       generated code */
3701 ee5bbe38 bellard
    saved_env = env;
3702 ee5bbe38 bellard
    env = cpu_single_env;
3703 ee5bbe38 bellard
3704 6ebbf390 j_mayer
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3705 ee5bbe38 bellard
    if (ret) {
3706 c2bc0e38 blueswir1
        cpu_restore_state2(retaddr);
3707 ee5bbe38 bellard
        cpu_loop_exit();
3708 ee5bbe38 bellard
    }
3709 ee5bbe38 bellard
    env = saved_env;
3710 ee5bbe38 bellard
}
3711 ee5bbe38 bellard
3712 3c7b48b7 Paul Brook
#endif /* !CONFIG_USER_ONLY */
3713 6c36d3fa blueswir1
3714 6c36d3fa blueswir1
#ifndef TARGET_SPARC64
3715 3c7b48b7 Paul Brook
#if !defined(CONFIG_USER_ONLY)
3716 c227f099 Anthony Liguori
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3717 e18231a3 blueswir1
                          int is_asi, int size)
3718 6c36d3fa blueswir1
{
3719 6c36d3fa blueswir1
    CPUState *saved_env;
3720 576c2cdc Artyom Tarasenko
    int fault_type;
3721 6c36d3fa blueswir1
3722 6c36d3fa blueswir1
    /* XXX: hack to restore env in all cases, even if not called from
3723 6c36d3fa blueswir1
       generated code */
3724 6c36d3fa blueswir1
    saved_env = env;
3725 6c36d3fa blueswir1
    env = cpu_single_env;
3726 8543e2cf blueswir1
#ifdef DEBUG_UNASSIGNED
3727 8543e2cf blueswir1
    if (is_asi)
3728 e18231a3 blueswir1
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3729 77f193da blueswir1
               " asi 0x%02x from " TARGET_FMT_lx "\n",
3730 e18231a3 blueswir1
               is_exec ? "exec" : is_write ? "write" : "read", size,
3731 e18231a3 blueswir1
               size == 1 ? "" : "s", addr, is_asi, env->pc);
3732 8543e2cf blueswir1
    else
3733 e18231a3 blueswir1
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3734 e18231a3 blueswir1
               " from " TARGET_FMT_lx "\n",
3735 e18231a3 blueswir1
               is_exec ? "exec" : is_write ? "write" : "read", size,
3736 e18231a3 blueswir1
               size == 1 ? "" : "s", addr, env->pc);
3737 8543e2cf blueswir1
#endif
3738 576c2cdc Artyom Tarasenko
    /* Don't overwrite translation and access faults */
3739 576c2cdc Artyom Tarasenko
    fault_type = (env->mmuregs[3] & 0x1c) >> 2;
3740 576c2cdc Artyom Tarasenko
    if ((fault_type > 4) || (fault_type == 0)) {
3741 576c2cdc Artyom Tarasenko
        env->mmuregs[3] = 0; /* Fault status register */
3742 576c2cdc Artyom Tarasenko
        if (is_asi)
3743 576c2cdc Artyom Tarasenko
            env->mmuregs[3] |= 1 << 16;
3744 576c2cdc Artyom Tarasenko
        if (env->psrs)
3745 576c2cdc Artyom Tarasenko
            env->mmuregs[3] |= 1 << 5;
3746 576c2cdc Artyom Tarasenko
        if (is_exec)
3747 576c2cdc Artyom Tarasenko
            env->mmuregs[3] |= 1 << 6;
3748 576c2cdc Artyom Tarasenko
        if (is_write)
3749 576c2cdc Artyom Tarasenko
            env->mmuregs[3] |= 1 << 7;
3750 576c2cdc Artyom Tarasenko
        env->mmuregs[3] |= (5 << 2) | 2;
3751 576c2cdc Artyom Tarasenko
        /* SuperSPARC will never place instruction fault addresses in the FAR */
3752 576c2cdc Artyom Tarasenko
        if (!is_exec) {
3753 576c2cdc Artyom Tarasenko
            env->mmuregs[4] = addr; /* Fault address register */
3754 576c2cdc Artyom Tarasenko
        }
3755 576c2cdc Artyom Tarasenko
    }
3756 576c2cdc Artyom Tarasenko
    /* overflow (same type fault was not read before another fault) */
3757 576c2cdc Artyom Tarasenko
    if (fault_type == ((env->mmuregs[3] & 0x1c)) >> 2) {
3758 576c2cdc Artyom Tarasenko
        env->mmuregs[3] |= 1;
3759 576c2cdc Artyom Tarasenko
    }
3760 576c2cdc Artyom Tarasenko
3761 6c36d3fa blueswir1
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
3762 1b2e93c1 blueswir1
        if (is_exec)
3763 1b2e93c1 blueswir1
            raise_exception(TT_CODE_ACCESS);
3764 1b2e93c1 blueswir1
        else
3765 1b2e93c1 blueswir1
            raise_exception(TT_DATA_ACCESS);
3766 6c36d3fa blueswir1
    }
3767 576c2cdc Artyom Tarasenko
3768 576c2cdc Artyom Tarasenko
    /* flush neverland mappings created during no-fault mode,
3769 576c2cdc Artyom Tarasenko
       so the sequential MMU faults report proper fault types */
3770 576c2cdc Artyom Tarasenko
    if (env->mmuregs[0] & MMU_NF) {
3771 576c2cdc Artyom Tarasenko
        tlb_flush(env, 1);
3772 576c2cdc Artyom Tarasenko
    }
3773 15e7c451 Artyom Tarasenko
3774 15e7c451 Artyom Tarasenko
    env = saved_env;
3775 6c36d3fa blueswir1
}
3776 3c7b48b7 Paul Brook
#endif
3777 3c7b48b7 Paul Brook
#else
3778 3c7b48b7 Paul Brook
#if defined(CONFIG_USER_ONLY)
3779 3c7b48b7 Paul Brook
static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
3780 3c7b48b7 Paul Brook
                          int is_asi, int size)
3781 6c36d3fa blueswir1
#else
3782 c227f099 Anthony Liguori
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3783 e18231a3 blueswir1
                          int is_asi, int size)
3784 3c7b48b7 Paul Brook
#endif
3785 6c36d3fa blueswir1
{
3786 6c36d3fa blueswir1
    CPUState *saved_env;
3787 6c36d3fa blueswir1
3788 6c36d3fa blueswir1
    /* XXX: hack to restore env in all cases, even if not called from
3789 6c36d3fa blueswir1
       generated code */
3790 6c36d3fa blueswir1
    saved_env = env;
3791 6c36d3fa blueswir1
    env = cpu_single_env;
3792 dffbe217 Igor V. Kovalenko
3793 dffbe217 Igor V. Kovalenko
#ifdef DEBUG_UNASSIGNED
3794 77f193da blueswir1
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
3795 77f193da blueswir1
           "\n", addr, env->pc);
3796 6c36d3fa blueswir1
#endif
3797 dffbe217 Igor V. Kovalenko
3798 1b2e93c1 blueswir1
    if (is_exec)
3799 1b2e93c1 blueswir1
        raise_exception(TT_CODE_ACCESS);
3800 1b2e93c1 blueswir1
    else
3801 1b2e93c1 blueswir1
        raise_exception(TT_DATA_ACCESS);
3802 dffbe217 Igor V. Kovalenko
3803 dffbe217 Igor V. Kovalenko
    env = saved_env;
3804 6c36d3fa blueswir1
}
3805 6c36d3fa blueswir1
#endif
3806 20c9f095 blueswir1
3807 3c7b48b7 Paul Brook
3808 f4b1a842 blueswir1
#ifdef TARGET_SPARC64
3809 f4b1a842 blueswir1
void helper_tick_set_count(void *opaque, uint64_t count)
3810 f4b1a842 blueswir1
{
3811 f4b1a842 blueswir1
#if !defined(CONFIG_USER_ONLY)
3812 f4b1a842 blueswir1
    cpu_tick_set_count(opaque, count);
3813 f4b1a842 blueswir1
#endif
3814 f4b1a842 blueswir1
}
3815 f4b1a842 blueswir1
3816 f4b1a842 blueswir1
uint64_t helper_tick_get_count(void *opaque)
3817 f4b1a842 blueswir1
{
3818 f4b1a842 blueswir1
#if !defined(CONFIG_USER_ONLY)
3819 f4b1a842 blueswir1
    return cpu_tick_get_count(opaque);
3820 f4b1a842 blueswir1
#else
3821 f4b1a842 blueswir1
    return 0;
3822 f4b1a842 blueswir1
#endif
3823 f4b1a842 blueswir1
}
3824 f4b1a842 blueswir1
3825 f4b1a842 blueswir1
void helper_tick_set_limit(void *opaque, uint64_t limit)
3826 f4b1a842 blueswir1
{
3827 f4b1a842 blueswir1
#if !defined(CONFIG_USER_ONLY)
3828 f4b1a842 blueswir1
    cpu_tick_set_limit(opaque, limit);
3829 f4b1a842 blueswir1
#endif
3830 f4b1a842 blueswir1
}
3831 f4b1a842 blueswir1
#endif