Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 4f690853

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

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

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