Statistics
| Branch: | Revision:

root / target-mips / op_helper.c @ 211315fb

History | View | Annotate | Download (95.8 kB)

1 6af0bf9c bellard
/*
2 6af0bf9c bellard
 *  MIPS emulation helpers for qemu.
3 5fafdf24 ths
 *
4 6af0bf9c bellard
 *  Copyright (c) 2004-2005 Jocelyn Mayer
5 6af0bf9c bellard
 *
6 6af0bf9c bellard
 * This library is free software; you can redistribute it and/or
7 6af0bf9c bellard
 * modify it under the terms of the GNU Lesser General Public
8 6af0bf9c bellard
 * License as published by the Free Software Foundation; either
9 6af0bf9c bellard
 * version 2 of the License, or (at your option) any later version.
10 6af0bf9c bellard
 *
11 6af0bf9c bellard
 * This library is distributed in the hope that it will be useful,
12 6af0bf9c bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 6af0bf9c bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 6af0bf9c bellard
 * Lesser General Public License for more details.
15 6af0bf9c bellard
 *
16 6af0bf9c bellard
 * You should have received a copy of the GNU Lesser General Public
17 8167ee88 Blue Swirl
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 6af0bf9c bellard
 */
19 2d0e944d ths
#include <stdlib.h>
20 6af0bf9c bellard
#include "exec.h"
21 6af0bf9c bellard
22 05f778c8 ths
#include "host-utils.h"
23 05f778c8 ths
24 a7812ae4 pbrook
#include "helper.h"
25 83dae095 Paolo Bonzini
26 83dae095 Paolo Bonzini
#ifndef CONFIG_USER_ONLY
27 83dae095 Paolo Bonzini
static inline void cpu_mips_tlb_flush (CPUState *env, int flush_global);
28 83dae095 Paolo Bonzini
#endif
29 83dae095 Paolo Bonzini
30 6af0bf9c bellard
/*****************************************************************************/
31 6af0bf9c bellard
/* Exceptions processing helpers */
32 6af0bf9c bellard
33 c01fccd2 aurel32
void helper_raise_exception_err (uint32_t exception, int error_code)
34 6af0bf9c bellard
{
35 6af0bf9c bellard
#if 1
36 93fcfe39 aliguori
    if (exception < 0x100)
37 93fcfe39 aliguori
        qemu_log("%s: %d %d\n", __func__, exception, error_code);
38 6af0bf9c bellard
#endif
39 6af0bf9c bellard
    env->exception_index = exception;
40 6af0bf9c bellard
    env->error_code = error_code;
41 6af0bf9c bellard
    cpu_loop_exit();
42 6af0bf9c bellard
}
43 6af0bf9c bellard
44 c01fccd2 aurel32
void helper_raise_exception (uint32_t exception)
45 6af0bf9c bellard
{
46 c01fccd2 aurel32
    helper_raise_exception_err(exception, 0);
47 6af0bf9c bellard
}
48 6af0bf9c bellard
49 f9480ffc ths
#if !defined(CONFIG_USER_ONLY)
50 f9480ffc ths
static void do_restore_state (void *pc_ptr)
51 4ad40f36 bellard
{
52 a607922c bellard
    TranslationBlock *tb;
53 a607922c bellard
    unsigned long pc = (unsigned long) pc_ptr;
54 a607922c bellard
    
55 a607922c bellard
    tb = tb_find_pc (pc);
56 a607922c bellard
    if (tb) {
57 a607922c bellard
        cpu_restore_state (tb, env, pc, NULL);
58 a607922c bellard
    }
59 4ad40f36 bellard
}
60 f9480ffc ths
#endif
61 4ad40f36 bellard
62 0ae43045 Aurelien Jarno
#if defined(CONFIG_USER_ONLY)
63 0ae43045 Aurelien Jarno
#define HELPER_LD(name, insn, type)                                     \
64 0ae43045 Aurelien Jarno
static inline type do_##name(target_ulong addr, int mem_idx)            \
65 0ae43045 Aurelien Jarno
{                                                                       \
66 0ae43045 Aurelien Jarno
    return (type) insn##_raw(addr);                                     \
67 0ae43045 Aurelien Jarno
}
68 0ae43045 Aurelien Jarno
#else
69 0ae43045 Aurelien Jarno
#define HELPER_LD(name, insn, type)                                     \
70 0ae43045 Aurelien Jarno
static inline type do_##name(target_ulong addr, int mem_idx)            \
71 0ae43045 Aurelien Jarno
{                                                                       \
72 0ae43045 Aurelien Jarno
    switch (mem_idx)                                                    \
73 0ae43045 Aurelien Jarno
    {                                                                   \
74 0ae43045 Aurelien Jarno
    case 0: return (type) insn##_kernel(addr); break;                   \
75 0ae43045 Aurelien Jarno
    case 1: return (type) insn##_super(addr); break;                    \
76 0ae43045 Aurelien Jarno
    default:                                                            \
77 0ae43045 Aurelien Jarno
    case 2: return (type) insn##_user(addr); break;                     \
78 0ae43045 Aurelien Jarno
    }                                                                   \
79 0ae43045 Aurelien Jarno
}
80 0ae43045 Aurelien Jarno
#endif
81 0ae43045 Aurelien Jarno
HELPER_LD(lbu, ldub, uint8_t)
82 0ae43045 Aurelien Jarno
HELPER_LD(lw, ldl, int32_t)
83 0ae43045 Aurelien Jarno
#ifdef TARGET_MIPS64
84 0ae43045 Aurelien Jarno
HELPER_LD(ld, ldq, int64_t)
85 0ae43045 Aurelien Jarno
#endif
86 0ae43045 Aurelien Jarno
#undef HELPER_LD
87 0ae43045 Aurelien Jarno
88 0ae43045 Aurelien Jarno
#if defined(CONFIG_USER_ONLY)
89 0ae43045 Aurelien Jarno
#define HELPER_ST(name, insn, type)                                     \
90 0ae43045 Aurelien Jarno
static inline void do_##name(target_ulong addr, type val, int mem_idx)  \
91 0ae43045 Aurelien Jarno
{                                                                       \
92 0ae43045 Aurelien Jarno
    insn##_raw(addr, val);                                              \
93 0ae43045 Aurelien Jarno
}
94 0ae43045 Aurelien Jarno
#else
95 0ae43045 Aurelien Jarno
#define HELPER_ST(name, insn, type)                                     \
96 0ae43045 Aurelien Jarno
static inline void do_##name(target_ulong addr, type val, int mem_idx)  \
97 0ae43045 Aurelien Jarno
{                                                                       \
98 0ae43045 Aurelien Jarno
    switch (mem_idx)                                                    \
99 0ae43045 Aurelien Jarno
    {                                                                   \
100 0ae43045 Aurelien Jarno
    case 0: insn##_kernel(addr, val); break;                            \
101 0ae43045 Aurelien Jarno
    case 1: insn##_super(addr, val); break;                             \
102 0ae43045 Aurelien Jarno
    default:                                                            \
103 0ae43045 Aurelien Jarno
    case 2: insn##_user(addr, val); break;                              \
104 0ae43045 Aurelien Jarno
    }                                                                   \
105 0ae43045 Aurelien Jarno
}
106 0ae43045 Aurelien Jarno
#endif
107 0ae43045 Aurelien Jarno
HELPER_ST(sb, stb, uint8_t)
108 0ae43045 Aurelien Jarno
HELPER_ST(sw, stl, uint32_t)
109 0ae43045 Aurelien Jarno
#ifdef TARGET_MIPS64
110 0ae43045 Aurelien Jarno
HELPER_ST(sd, stq, uint64_t)
111 0ae43045 Aurelien Jarno
#endif
112 0ae43045 Aurelien Jarno
#undef HELPER_ST
113 0ae43045 Aurelien Jarno
114 d9bea114 aurel32
target_ulong helper_clo (target_ulong arg1)
115 30898801 ths
{
116 d9bea114 aurel32
    return clo32(arg1);
117 30898801 ths
}
118 30898801 ths
119 d9bea114 aurel32
target_ulong helper_clz (target_ulong arg1)
120 30898801 ths
{
121 d9bea114 aurel32
    return clz32(arg1);
122 30898801 ths
}
123 30898801 ths
124 d26bc211 ths
#if defined(TARGET_MIPS64)
125 d9bea114 aurel32
target_ulong helper_dclo (target_ulong arg1)
126 05f778c8 ths
{
127 d9bea114 aurel32
    return clo64(arg1);
128 05f778c8 ths
}
129 05f778c8 ths
130 d9bea114 aurel32
target_ulong helper_dclz (target_ulong arg1)
131 05f778c8 ths
{
132 d9bea114 aurel32
    return clz64(arg1);
133 05f778c8 ths
}
134 d26bc211 ths
#endif /* TARGET_MIPS64 */
135 c570fd16 ths
136 6af0bf9c bellard
/* 64 bits arithmetic for 32 bits hosts */
137 c904ef0e ths
static inline uint64_t get_HILO (void)
138 6af0bf9c bellard
{
139 b5dc7732 ths
    return ((uint64_t)(env->active_tc.HI[0]) << 32) | (uint32_t)env->active_tc.LO[0];
140 6af0bf9c bellard
}
141 6af0bf9c bellard
142 c904ef0e ths
static inline void set_HILO (uint64_t HILO)
143 6af0bf9c bellard
{
144 b5dc7732 ths
    env->active_tc.LO[0] = (int32_t)HILO;
145 b5dc7732 ths
    env->active_tc.HI[0] = (int32_t)(HILO >> 32);
146 6af0bf9c bellard
}
147 6af0bf9c bellard
148 d9bea114 aurel32
static inline void set_HIT0_LO (target_ulong arg1, uint64_t HILO)
149 e9c71dd1 ths
{
150 b5dc7732 ths
    env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
151 d9bea114 aurel32
    arg1 = env->active_tc.HI[0] = (int32_t)(HILO >> 32);
152 e9c71dd1 ths
}
153 e9c71dd1 ths
154 d9bea114 aurel32
static inline void set_HI_LOT0 (target_ulong arg1, uint64_t HILO)
155 e9c71dd1 ths
{
156 d9bea114 aurel32
    arg1 = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
157 b5dc7732 ths
    env->active_tc.HI[0] = (int32_t)(HILO >> 32);
158 e9c71dd1 ths
}
159 e9c71dd1 ths
160 e9c71dd1 ths
/* Multiplication variants of the vr54xx. */
161 d9bea114 aurel32
target_ulong helper_muls (target_ulong arg1, target_ulong arg2)
162 e9c71dd1 ths
{
163 d9bea114 aurel32
    set_HI_LOT0(arg1, 0 - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
164 be24bb4f ths
165 d9bea114 aurel32
    return arg1;
166 e9c71dd1 ths
}
167 e9c71dd1 ths
168 d9bea114 aurel32
target_ulong helper_mulsu (target_ulong arg1, target_ulong arg2)
169 e9c71dd1 ths
{
170 d9bea114 aurel32
    set_HI_LOT0(arg1, 0 - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
171 be24bb4f ths
172 d9bea114 aurel32
    return arg1;
173 e9c71dd1 ths
}
174 e9c71dd1 ths
175 d9bea114 aurel32
target_ulong helper_macc (target_ulong arg1, target_ulong arg2)
176 e9c71dd1 ths
{
177 d9bea114 aurel32
    set_HI_LOT0(arg1, ((int64_t)get_HILO()) + ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
178 be24bb4f ths
179 d9bea114 aurel32
    return arg1;
180 e9c71dd1 ths
}
181 e9c71dd1 ths
182 d9bea114 aurel32
target_ulong helper_macchi (target_ulong arg1, target_ulong arg2)
183 e9c71dd1 ths
{
184 d9bea114 aurel32
    set_HIT0_LO(arg1, ((int64_t)get_HILO()) + ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
185 be24bb4f ths
186 d9bea114 aurel32
    return arg1;
187 e9c71dd1 ths
}
188 e9c71dd1 ths
189 d9bea114 aurel32
target_ulong helper_maccu (target_ulong arg1, target_ulong arg2)
190 e9c71dd1 ths
{
191 d9bea114 aurel32
    set_HI_LOT0(arg1, ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
192 be24bb4f ths
193 d9bea114 aurel32
    return arg1;
194 e9c71dd1 ths
}
195 e9c71dd1 ths
196 d9bea114 aurel32
target_ulong helper_macchiu (target_ulong arg1, target_ulong arg2)
197 e9c71dd1 ths
{
198 d9bea114 aurel32
    set_HIT0_LO(arg1, ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
199 be24bb4f ths
200 d9bea114 aurel32
    return arg1;
201 e9c71dd1 ths
}
202 e9c71dd1 ths
203 d9bea114 aurel32
target_ulong helper_msac (target_ulong arg1, target_ulong arg2)
204 e9c71dd1 ths
{
205 d9bea114 aurel32
    set_HI_LOT0(arg1, ((int64_t)get_HILO()) - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
206 be24bb4f ths
207 d9bea114 aurel32
    return arg1;
208 e9c71dd1 ths
}
209 e9c71dd1 ths
210 d9bea114 aurel32
target_ulong helper_msachi (target_ulong arg1, target_ulong arg2)
211 e9c71dd1 ths
{
212 d9bea114 aurel32
    set_HIT0_LO(arg1, ((int64_t)get_HILO()) - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
213 be24bb4f ths
214 d9bea114 aurel32
    return arg1;
215 e9c71dd1 ths
}
216 e9c71dd1 ths
217 d9bea114 aurel32
target_ulong helper_msacu (target_ulong arg1, target_ulong arg2)
218 e9c71dd1 ths
{
219 d9bea114 aurel32
    set_HI_LOT0(arg1, ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
220 be24bb4f ths
221 d9bea114 aurel32
    return arg1;
222 e9c71dd1 ths
}
223 e9c71dd1 ths
224 d9bea114 aurel32
target_ulong helper_msachiu (target_ulong arg1, target_ulong arg2)
225 e9c71dd1 ths
{
226 d9bea114 aurel32
    set_HIT0_LO(arg1, ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
227 be24bb4f ths
228 d9bea114 aurel32
    return arg1;
229 e9c71dd1 ths
}
230 e9c71dd1 ths
231 d9bea114 aurel32
target_ulong helper_mulhi (target_ulong arg1, target_ulong arg2)
232 e9c71dd1 ths
{
233 d9bea114 aurel32
    set_HIT0_LO(arg1, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2);
234 be24bb4f ths
235 d9bea114 aurel32
    return arg1;
236 e9c71dd1 ths
}
237 e9c71dd1 ths
238 d9bea114 aurel32
target_ulong helper_mulhiu (target_ulong arg1, target_ulong arg2)
239 e9c71dd1 ths
{
240 d9bea114 aurel32
    set_HIT0_LO(arg1, (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
241 be24bb4f ths
242 d9bea114 aurel32
    return arg1;
243 e9c71dd1 ths
}
244 e9c71dd1 ths
245 d9bea114 aurel32
target_ulong helper_mulshi (target_ulong arg1, target_ulong arg2)
246 e9c71dd1 ths
{
247 d9bea114 aurel32
    set_HIT0_LO(arg1, 0 - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
248 be24bb4f ths
249 d9bea114 aurel32
    return arg1;
250 e9c71dd1 ths
}
251 e9c71dd1 ths
252 d9bea114 aurel32
target_ulong helper_mulshiu (target_ulong arg1, target_ulong arg2)
253 e9c71dd1 ths
{
254 d9bea114 aurel32
    set_HIT0_LO(arg1, 0 - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
255 be24bb4f ths
256 d9bea114 aurel32
    return arg1;
257 e9c71dd1 ths
}
258 6af0bf9c bellard
259 214c465f ths
#ifdef TARGET_MIPS64
260 d9bea114 aurel32
void helper_dmult (target_ulong arg1, target_ulong arg2)
261 214c465f ths
{
262 d9bea114 aurel32
    muls64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
263 214c465f ths
}
264 214c465f ths
265 d9bea114 aurel32
void helper_dmultu (target_ulong arg1, target_ulong arg2)
266 214c465f ths
{
267 d9bea114 aurel32
    mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
268 214c465f ths
}
269 214c465f ths
#endif
270 214c465f ths
271 e7139c44 Aurelien Jarno
#ifndef CONFIG_USER_ONLY
272 c36bbb28 Aurelien Jarno
273 c36bbb28 Aurelien Jarno
static inline target_phys_addr_t do_translate_address(target_ulong address, int rw)
274 c36bbb28 Aurelien Jarno
{
275 c36bbb28 Aurelien Jarno
    target_phys_addr_t lladdr;
276 c36bbb28 Aurelien Jarno
277 c36bbb28 Aurelien Jarno
    lladdr = cpu_mips_translate_address(env, address, rw);
278 c36bbb28 Aurelien Jarno
279 c36bbb28 Aurelien Jarno
    if (lladdr == -1LL) {
280 c36bbb28 Aurelien Jarno
        cpu_loop_exit();
281 c36bbb28 Aurelien Jarno
    } else {
282 c36bbb28 Aurelien Jarno
        return lladdr;
283 c36bbb28 Aurelien Jarno
    }
284 c36bbb28 Aurelien Jarno
}
285 c36bbb28 Aurelien Jarno
286 e7139c44 Aurelien Jarno
#define HELPER_LD_ATOMIC(name, insn)                                          \
287 e7139c44 Aurelien Jarno
target_ulong helper_##name(target_ulong arg, int mem_idx)                     \
288 e7139c44 Aurelien Jarno
{                                                                             \
289 c36bbb28 Aurelien Jarno
    env->lladdr = do_translate_address(arg, 0);                               \
290 e7139c44 Aurelien Jarno
    env->llval = do_##insn(arg, mem_idx);                                     \
291 e7139c44 Aurelien Jarno
    return env->llval;                                                        \
292 e7139c44 Aurelien Jarno
}
293 e7139c44 Aurelien Jarno
HELPER_LD_ATOMIC(ll, lw)
294 e7139c44 Aurelien Jarno
#ifdef TARGET_MIPS64
295 e7139c44 Aurelien Jarno
HELPER_LD_ATOMIC(lld, ld)
296 e7139c44 Aurelien Jarno
#endif
297 e7139c44 Aurelien Jarno
#undef HELPER_LD_ATOMIC
298 e7139c44 Aurelien Jarno
299 e7139c44 Aurelien Jarno
#define HELPER_ST_ATOMIC(name, ld_insn, st_insn, almask)                      \
300 e7139c44 Aurelien Jarno
target_ulong helper_##name(target_ulong arg1, target_ulong arg2, int mem_idx) \
301 e7139c44 Aurelien Jarno
{                                                                             \
302 e7139c44 Aurelien Jarno
    target_long tmp;                                                          \
303 e7139c44 Aurelien Jarno
                                                                              \
304 e7139c44 Aurelien Jarno
    if (arg2 & almask) {                                                      \
305 e7139c44 Aurelien Jarno
        env->CP0_BadVAddr = arg2;                                             \
306 e7139c44 Aurelien Jarno
        helper_raise_exception(EXCP_AdES);                                    \
307 e7139c44 Aurelien Jarno
    }                                                                         \
308 c36bbb28 Aurelien Jarno
    if (do_translate_address(arg2, 1) == env->lladdr) {                       \
309 e7139c44 Aurelien Jarno
        tmp = do_##ld_insn(arg2, mem_idx);                                    \
310 e7139c44 Aurelien Jarno
        if (tmp == env->llval) {                                              \
311 e7139c44 Aurelien Jarno
            do_##st_insn(arg2, arg1, mem_idx);                                \
312 e7139c44 Aurelien Jarno
            return 1;                                                         \
313 e7139c44 Aurelien Jarno
        }                                                                     \
314 e7139c44 Aurelien Jarno
    }                                                                         \
315 e7139c44 Aurelien Jarno
    return 0;                                                                 \
316 e7139c44 Aurelien Jarno
}
317 e7139c44 Aurelien Jarno
HELPER_ST_ATOMIC(sc, lw, sw, 0x3)
318 e7139c44 Aurelien Jarno
#ifdef TARGET_MIPS64
319 e7139c44 Aurelien Jarno
HELPER_ST_ATOMIC(scd, ld, sd, 0x7)
320 e7139c44 Aurelien Jarno
#endif
321 e7139c44 Aurelien Jarno
#undef HELPER_ST_ATOMIC
322 e7139c44 Aurelien Jarno
#endif
323 e7139c44 Aurelien Jarno
324 c8c2227e ths
#ifdef TARGET_WORDS_BIGENDIAN
325 c8c2227e ths
#define GET_LMASK(v) ((v) & 3)
326 c8c2227e ths
#define GET_OFFSET(addr, offset) (addr + (offset))
327 c8c2227e ths
#else
328 c8c2227e ths
#define GET_LMASK(v) (((v) & 3) ^ 3)
329 c8c2227e ths
#define GET_OFFSET(addr, offset) (addr - (offset))
330 c8c2227e ths
#endif
331 c8c2227e ths
332 d9bea114 aurel32
target_ulong helper_lwl(target_ulong arg1, target_ulong arg2, int mem_idx)
333 c8c2227e ths
{
334 c8c2227e ths
    target_ulong tmp;
335 c8c2227e ths
336 0ae43045 Aurelien Jarno
    tmp = do_lbu(arg2, mem_idx);
337 d9bea114 aurel32
    arg1 = (arg1 & 0x00FFFFFF) | (tmp << 24);
338 c8c2227e ths
339 d9bea114 aurel32
    if (GET_LMASK(arg2) <= 2) {
340 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, 1), mem_idx);
341 d9bea114 aurel32
        arg1 = (arg1 & 0xFF00FFFF) | (tmp << 16);
342 c8c2227e ths
    }
343 c8c2227e ths
344 d9bea114 aurel32
    if (GET_LMASK(arg2) <= 1) {
345 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, 2), mem_idx);
346 d9bea114 aurel32
        arg1 = (arg1 & 0xFFFF00FF) | (tmp << 8);
347 c8c2227e ths
    }
348 c8c2227e ths
349 d9bea114 aurel32
    if (GET_LMASK(arg2) == 0) {
350 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, 3), mem_idx);
351 d9bea114 aurel32
        arg1 = (arg1 & 0xFFFFFF00) | tmp;
352 c8c2227e ths
    }
353 d9bea114 aurel32
    return (int32_t)arg1;
354 c8c2227e ths
}
355 c8c2227e ths
356 d9bea114 aurel32
target_ulong helper_lwr(target_ulong arg1, target_ulong arg2, int mem_idx)
357 c8c2227e ths
{
358 c8c2227e ths
    target_ulong tmp;
359 c8c2227e ths
360 0ae43045 Aurelien Jarno
    tmp = do_lbu(arg2, mem_idx);
361 d9bea114 aurel32
    arg1 = (arg1 & 0xFFFFFF00) | tmp;
362 c8c2227e ths
363 d9bea114 aurel32
    if (GET_LMASK(arg2) >= 1) {
364 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, -1), mem_idx);
365 d9bea114 aurel32
        arg1 = (arg1 & 0xFFFF00FF) | (tmp << 8);
366 c8c2227e ths
    }
367 c8c2227e ths
368 d9bea114 aurel32
    if (GET_LMASK(arg2) >= 2) {
369 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, -2), mem_idx);
370 d9bea114 aurel32
        arg1 = (arg1 & 0xFF00FFFF) | (tmp << 16);
371 c8c2227e ths
    }
372 c8c2227e ths
373 d9bea114 aurel32
    if (GET_LMASK(arg2) == 3) {
374 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, -3), mem_idx);
375 d9bea114 aurel32
        arg1 = (arg1 & 0x00FFFFFF) | (tmp << 24);
376 c8c2227e ths
    }
377 d9bea114 aurel32
    return (int32_t)arg1;
378 c8c2227e ths
}
379 c8c2227e ths
380 d9bea114 aurel32
void helper_swl(target_ulong arg1, target_ulong arg2, int mem_idx)
381 c8c2227e ths
{
382 0ae43045 Aurelien Jarno
    do_sb(arg2, (uint8_t)(arg1 >> 24), mem_idx);
383 c8c2227e ths
384 d9bea114 aurel32
    if (GET_LMASK(arg2) <= 2)
385 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16), mem_idx);
386 c8c2227e ths
387 d9bea114 aurel32
    if (GET_LMASK(arg2) <= 1)
388 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8), mem_idx);
389 c8c2227e ths
390 d9bea114 aurel32
    if (GET_LMASK(arg2) == 0)
391 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, 3), (uint8_t)arg1, mem_idx);
392 c8c2227e ths
}
393 c8c2227e ths
394 d9bea114 aurel32
void helper_swr(target_ulong arg1, target_ulong arg2, int mem_idx)
395 c8c2227e ths
{
396 0ae43045 Aurelien Jarno
    do_sb(arg2, (uint8_t)arg1, mem_idx);
397 c8c2227e ths
398 d9bea114 aurel32
    if (GET_LMASK(arg2) >= 1)
399 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx);
400 c8c2227e ths
401 d9bea114 aurel32
    if (GET_LMASK(arg2) >= 2)
402 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx);
403 c8c2227e ths
404 d9bea114 aurel32
    if (GET_LMASK(arg2) == 3)
405 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx);
406 c8c2227e ths
}
407 c8c2227e ths
408 c8c2227e ths
#if defined(TARGET_MIPS64)
409 c8c2227e ths
/* "half" load and stores.  We must do the memory access inline,
410 c8c2227e ths
   or fault handling won't work.  */
411 c8c2227e ths
412 c8c2227e ths
#ifdef TARGET_WORDS_BIGENDIAN
413 c8c2227e ths
#define GET_LMASK64(v) ((v) & 7)
414 c8c2227e ths
#else
415 c8c2227e ths
#define GET_LMASK64(v) (((v) & 7) ^ 7)
416 c8c2227e ths
#endif
417 c8c2227e ths
418 d9bea114 aurel32
target_ulong helper_ldl(target_ulong arg1, target_ulong arg2, int mem_idx)
419 c8c2227e ths
{
420 c8c2227e ths
    uint64_t tmp;
421 c8c2227e ths
422 0ae43045 Aurelien Jarno
    tmp = do_lbu(arg2, mem_idx);
423 d9bea114 aurel32
    arg1 = (arg1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
424 c8c2227e ths
425 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 6) {
426 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, 1), mem_idx);
427 d9bea114 aurel32
        arg1 = (arg1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
428 c8c2227e ths
    }
429 c8c2227e ths
430 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 5) {
431 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, 2), mem_idx);
432 d9bea114 aurel32
        arg1 = (arg1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
433 c8c2227e ths
    }
434 c8c2227e ths
435 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 4) {
436 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, 3), mem_idx);
437 d9bea114 aurel32
        arg1 = (arg1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
438 c8c2227e ths
    }
439 c8c2227e ths
440 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 3) {
441 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, 4), mem_idx);
442 d9bea114 aurel32
        arg1 = (arg1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
443 c8c2227e ths
    }
444 c8c2227e ths
445 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 2) {
446 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, 5), mem_idx);
447 d9bea114 aurel32
        arg1 = (arg1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
448 c8c2227e ths
    }
449 c8c2227e ths
450 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 1) {
451 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, 6), mem_idx);
452 d9bea114 aurel32
        arg1 = (arg1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
453 c8c2227e ths
    }
454 c8c2227e ths
455 d9bea114 aurel32
    if (GET_LMASK64(arg2) == 0) {
456 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, 7), mem_idx);
457 d9bea114 aurel32
        arg1 = (arg1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
458 c8c2227e ths
    }
459 be24bb4f ths
460 d9bea114 aurel32
    return arg1;
461 c8c2227e ths
}
462 c8c2227e ths
463 d9bea114 aurel32
target_ulong helper_ldr(target_ulong arg1, target_ulong arg2, int mem_idx)
464 c8c2227e ths
{
465 c8c2227e ths
    uint64_t tmp;
466 c8c2227e ths
467 0ae43045 Aurelien Jarno
    tmp = do_lbu(arg2, mem_idx);
468 d9bea114 aurel32
    arg1 = (arg1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
469 c8c2227e ths
470 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 1) {
471 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, -1), mem_idx);
472 d9bea114 aurel32
        arg1 = (arg1 & 0xFFFFFFFFFFFF00FFULL) | (tmp  << 8);
473 c8c2227e ths
    }
474 c8c2227e ths
475 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 2) {
476 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, -2), mem_idx);
477 d9bea114 aurel32
        arg1 = (arg1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
478 c8c2227e ths
    }
479 c8c2227e ths
480 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 3) {
481 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, -3), mem_idx);
482 d9bea114 aurel32
        arg1 = (arg1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
483 c8c2227e ths
    }
484 c8c2227e ths
485 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 4) {
486 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, -4), mem_idx);
487 d9bea114 aurel32
        arg1 = (arg1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
488 c8c2227e ths
    }
489 c8c2227e ths
490 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 5) {
491 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, -5), mem_idx);
492 d9bea114 aurel32
        arg1 = (arg1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
493 c8c2227e ths
    }
494 c8c2227e ths
495 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 6) {
496 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, -6), mem_idx);
497 d9bea114 aurel32
        arg1 = (arg1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
498 c8c2227e ths
    }
499 c8c2227e ths
500 d9bea114 aurel32
    if (GET_LMASK64(arg2) == 7) {
501 0ae43045 Aurelien Jarno
        tmp = do_lbu(GET_OFFSET(arg2, -7), mem_idx);
502 d9bea114 aurel32
        arg1 = (arg1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
503 c8c2227e ths
    }
504 be24bb4f ths
505 d9bea114 aurel32
    return arg1;
506 c8c2227e ths
}
507 c8c2227e ths
508 d9bea114 aurel32
void helper_sdl(target_ulong arg1, target_ulong arg2, int mem_idx)
509 c8c2227e ths
{
510 0ae43045 Aurelien Jarno
    do_sb(arg2, (uint8_t)(arg1 >> 56), mem_idx);
511 c8c2227e ths
512 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 6)
513 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48), mem_idx);
514 c8c2227e ths
515 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 5)
516 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40), mem_idx);
517 c8c2227e ths
518 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 4)
519 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32), mem_idx);
520 c8c2227e ths
521 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 3)
522 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24), mem_idx);
523 c8c2227e ths
524 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 2)
525 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16), mem_idx);
526 c8c2227e ths
527 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 1)
528 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8), mem_idx);
529 c8c2227e ths
530 d9bea114 aurel32
    if (GET_LMASK64(arg2) <= 0)
531 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, 7), (uint8_t)arg1, mem_idx);
532 c8c2227e ths
}
533 c8c2227e ths
534 d9bea114 aurel32
void helper_sdr(target_ulong arg1, target_ulong arg2, int mem_idx)
535 c8c2227e ths
{
536 0ae43045 Aurelien Jarno
    do_sb(arg2, (uint8_t)arg1, mem_idx);
537 c8c2227e ths
538 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 1)
539 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx);
540 c8c2227e ths
541 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 2)
542 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx);
543 c8c2227e ths
544 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 3)
545 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx);
546 c8c2227e ths
547 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 4)
548 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32), mem_idx);
549 c8c2227e ths
550 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 5)
551 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40), mem_idx);
552 c8c2227e ths
553 d9bea114 aurel32
    if (GET_LMASK64(arg2) >= 6)
554 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48), mem_idx);
555 c8c2227e ths
556 d9bea114 aurel32
    if (GET_LMASK64(arg2) == 7)
557 0ae43045 Aurelien Jarno
        do_sb(GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56), mem_idx);
558 c8c2227e ths
}
559 c8c2227e ths
#endif /* TARGET_MIPS64 */
560 c8c2227e ths
561 3c824109 Nathan Froyd
static const int multiple_regs[] = { 16, 17, 18, 19, 20, 21, 22, 23, 30 };
562 3c824109 Nathan Froyd
563 3c824109 Nathan Froyd
void helper_lwm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
564 3c824109 Nathan Froyd
{
565 3c824109 Nathan Froyd
    target_ulong base_reglist = reglist & 0xf;
566 3c824109 Nathan Froyd
    target_ulong do_r31 = reglist & 0x10;
567 3c824109 Nathan Froyd
#ifdef CONFIG_USER_ONLY
568 3c824109 Nathan Froyd
#undef ldfun
569 3c824109 Nathan Froyd
#define ldfun ldl_raw
570 3c824109 Nathan Froyd
#else
571 3c824109 Nathan Froyd
    uint32_t (*ldfun)(target_ulong);
572 3c824109 Nathan Froyd
573 3c824109 Nathan Froyd
    switch (mem_idx)
574 3c824109 Nathan Froyd
    {
575 3c824109 Nathan Froyd
    case 0: ldfun = ldl_kernel; break;
576 3c824109 Nathan Froyd
    case 1: ldfun = ldl_super; break;
577 3c824109 Nathan Froyd
    default:
578 3c824109 Nathan Froyd
    case 2: ldfun = ldl_user; break;
579 3c824109 Nathan Froyd
    }
580 3c824109 Nathan Froyd
#endif
581 3c824109 Nathan Froyd
582 3c824109 Nathan Froyd
    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
583 3c824109 Nathan Froyd
        target_ulong i;
584 3c824109 Nathan Froyd
585 3c824109 Nathan Froyd
        for (i = 0; i < base_reglist; i++) {
586 3c824109 Nathan Froyd
            env->active_tc.gpr[multiple_regs[i]] = (target_long) ldfun(addr);
587 3c824109 Nathan Froyd
            addr += 4;
588 3c824109 Nathan Froyd
        }
589 3c824109 Nathan Froyd
    }
590 3c824109 Nathan Froyd
591 3c824109 Nathan Froyd
    if (do_r31) {
592 3c824109 Nathan Froyd
        env->active_tc.gpr[31] = (target_long) ldfun(addr);
593 3c824109 Nathan Froyd
    }
594 3c824109 Nathan Froyd
}
595 3c824109 Nathan Froyd
596 3c824109 Nathan Froyd
void helper_swm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
597 3c824109 Nathan Froyd
{
598 3c824109 Nathan Froyd
    target_ulong base_reglist = reglist & 0xf;
599 3c824109 Nathan Froyd
    target_ulong do_r31 = reglist & 0x10;
600 3c824109 Nathan Froyd
#ifdef CONFIG_USER_ONLY
601 3c824109 Nathan Froyd
#undef stfun
602 3c824109 Nathan Froyd
#define stfun stl_raw
603 3c824109 Nathan Froyd
#else
604 3c824109 Nathan Froyd
    void (*stfun)(target_ulong, uint32_t);
605 3c824109 Nathan Froyd
606 3c824109 Nathan Froyd
    switch (mem_idx)
607 3c824109 Nathan Froyd
    {
608 3c824109 Nathan Froyd
    case 0: stfun = stl_kernel; break;
609 3c824109 Nathan Froyd
    case 1: stfun = stl_super; break;
610 3c824109 Nathan Froyd
     default:
611 3c824109 Nathan Froyd
    case 2: stfun = stl_user; break;
612 3c824109 Nathan Froyd
    }
613 3c824109 Nathan Froyd
#endif
614 3c824109 Nathan Froyd
615 3c824109 Nathan Froyd
    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
616 3c824109 Nathan Froyd
        target_ulong i;
617 3c824109 Nathan Froyd
618 3c824109 Nathan Froyd
        for (i = 0; i < base_reglist; i++) {
619 3c824109 Nathan Froyd
            stfun(addr, env->active_tc.gpr[multiple_regs[i]]);
620 3c824109 Nathan Froyd
            addr += 4;
621 3c824109 Nathan Froyd
        }
622 3c824109 Nathan Froyd
    }
623 3c824109 Nathan Froyd
624 3c824109 Nathan Froyd
    if (do_r31) {
625 3c824109 Nathan Froyd
        stfun(addr, env->active_tc.gpr[31]);
626 3c824109 Nathan Froyd
    }
627 3c824109 Nathan Froyd
}
628 3c824109 Nathan Froyd
629 3c824109 Nathan Froyd
#if defined(TARGET_MIPS64)
630 3c824109 Nathan Froyd
void helper_ldm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
631 3c824109 Nathan Froyd
{
632 3c824109 Nathan Froyd
    target_ulong base_reglist = reglist & 0xf;
633 3c824109 Nathan Froyd
    target_ulong do_r31 = reglist & 0x10;
634 3c824109 Nathan Froyd
#ifdef CONFIG_USER_ONLY
635 3c824109 Nathan Froyd
#undef ldfun
636 3c824109 Nathan Froyd
#define ldfun ldq_raw
637 3c824109 Nathan Froyd
#else
638 3c824109 Nathan Froyd
    uint64_t (*ldfun)(target_ulong);
639 3c824109 Nathan Froyd
640 3c824109 Nathan Froyd
    switch (mem_idx)
641 3c824109 Nathan Froyd
    {
642 3c824109 Nathan Froyd
    case 0: ldfun = ldq_kernel; break;
643 3c824109 Nathan Froyd
    case 1: ldfun = ldq_super; break;
644 3c824109 Nathan Froyd
    default:
645 3c824109 Nathan Froyd
    case 2: ldfun = ldq_user; break;
646 3c824109 Nathan Froyd
    }
647 3c824109 Nathan Froyd
#endif
648 3c824109 Nathan Froyd
649 3c824109 Nathan Froyd
    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
650 3c824109 Nathan Froyd
        target_ulong i;
651 3c824109 Nathan Froyd
652 3c824109 Nathan Froyd
        for (i = 0; i < base_reglist; i++) {
653 3c824109 Nathan Froyd
            env->active_tc.gpr[multiple_regs[i]] = ldfun(addr);
654 3c824109 Nathan Froyd
            addr += 8;
655 3c824109 Nathan Froyd
        }
656 3c824109 Nathan Froyd
    }
657 3c824109 Nathan Froyd
658 3c824109 Nathan Froyd
    if (do_r31) {
659 3c824109 Nathan Froyd
        env->active_tc.gpr[31] = ldfun(addr);
660 3c824109 Nathan Froyd
    }
661 3c824109 Nathan Froyd
}
662 3c824109 Nathan Froyd
663 3c824109 Nathan Froyd
void helper_sdm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
664 3c824109 Nathan Froyd
{
665 3c824109 Nathan Froyd
    target_ulong base_reglist = reglist & 0xf;
666 3c824109 Nathan Froyd
    target_ulong do_r31 = reglist & 0x10;
667 3c824109 Nathan Froyd
#ifdef CONFIG_USER_ONLY
668 3c824109 Nathan Froyd
#undef stfun
669 3c824109 Nathan Froyd
#define stfun stq_raw
670 3c824109 Nathan Froyd
#else
671 3c824109 Nathan Froyd
    void (*stfun)(target_ulong, uint64_t);
672 3c824109 Nathan Froyd
673 3c824109 Nathan Froyd
    switch (mem_idx)
674 3c824109 Nathan Froyd
    {
675 3c824109 Nathan Froyd
    case 0: stfun = stq_kernel; break;
676 3c824109 Nathan Froyd
    case 1: stfun = stq_super; break;
677 3c824109 Nathan Froyd
     default:
678 3c824109 Nathan Froyd
    case 2: stfun = stq_user; break;
679 3c824109 Nathan Froyd
    }
680 3c824109 Nathan Froyd
#endif
681 3c824109 Nathan Froyd
682 3c824109 Nathan Froyd
    if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
683 3c824109 Nathan Froyd
        target_ulong i;
684 3c824109 Nathan Froyd
685 3c824109 Nathan Froyd
        for (i = 0; i < base_reglist; i++) {
686 3c824109 Nathan Froyd
            stfun(addr, env->active_tc.gpr[multiple_regs[i]]);
687 3c824109 Nathan Froyd
            addr += 8;
688 3c824109 Nathan Froyd
        }
689 3c824109 Nathan Froyd
    }
690 3c824109 Nathan Froyd
691 3c824109 Nathan Froyd
    if (do_r31) {
692 3c824109 Nathan Froyd
        stfun(addr, env->active_tc.gpr[31]);
693 3c824109 Nathan Froyd
    }
694 3c824109 Nathan Froyd
}
695 3c824109 Nathan Froyd
#endif
696 3c824109 Nathan Froyd
697 0eaef5aa ths
#ifndef CONFIG_USER_ONLY
698 6af0bf9c bellard
/* CP0 helpers */
699 c01fccd2 aurel32
target_ulong helper_mfc0_mvpcontrol (void)
700 f1aa6320 ths
{
701 be24bb4f ths
    return env->mvp->CP0_MVPControl;
702 f1aa6320 ths
}
703 f1aa6320 ths
704 c01fccd2 aurel32
target_ulong helper_mfc0_mvpconf0 (void)
705 f1aa6320 ths
{
706 be24bb4f ths
    return env->mvp->CP0_MVPConf0;
707 f1aa6320 ths
}
708 f1aa6320 ths
709 c01fccd2 aurel32
target_ulong helper_mfc0_mvpconf1 (void)
710 f1aa6320 ths
{
711 be24bb4f ths
    return env->mvp->CP0_MVPConf1;
712 f1aa6320 ths
}
713 f1aa6320 ths
714 c01fccd2 aurel32
target_ulong helper_mfc0_random (void)
715 6af0bf9c bellard
{
716 be24bb4f ths
    return (int32_t)cpu_mips_get_random(env);
717 873eb012 ths
}
718 6af0bf9c bellard
719 c01fccd2 aurel32
target_ulong helper_mfc0_tcstatus (void)
720 f1aa6320 ths
{
721 b5dc7732 ths
    return env->active_tc.CP0_TCStatus;
722 f1aa6320 ths
}
723 f1aa6320 ths
724 c01fccd2 aurel32
target_ulong helper_mftc0_tcstatus(void)
725 f1aa6320 ths
{
726 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
727 f1aa6320 ths
728 b5dc7732 ths
    if (other_tc == env->current_tc)
729 b5dc7732 ths
        return env->active_tc.CP0_TCStatus;
730 b5dc7732 ths
    else
731 b5dc7732 ths
        return env->tcs[other_tc].CP0_TCStatus;
732 f1aa6320 ths
}
733 f1aa6320 ths
734 c01fccd2 aurel32
target_ulong helper_mfc0_tcbind (void)
735 f1aa6320 ths
{
736 b5dc7732 ths
    return env->active_tc.CP0_TCBind;
737 f1aa6320 ths
}
738 f1aa6320 ths
739 c01fccd2 aurel32
target_ulong helper_mftc0_tcbind(void)
740 f1aa6320 ths
{
741 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
742 f1aa6320 ths
743 b5dc7732 ths
    if (other_tc == env->current_tc)
744 b5dc7732 ths
        return env->active_tc.CP0_TCBind;
745 b5dc7732 ths
    else
746 b5dc7732 ths
        return env->tcs[other_tc].CP0_TCBind;
747 f1aa6320 ths
}
748 f1aa6320 ths
749 c01fccd2 aurel32
target_ulong helper_mfc0_tcrestart (void)
750 f1aa6320 ths
{
751 b5dc7732 ths
    return env->active_tc.PC;
752 f1aa6320 ths
}
753 f1aa6320 ths
754 c01fccd2 aurel32
target_ulong helper_mftc0_tcrestart(void)
755 f1aa6320 ths
{
756 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
757 f1aa6320 ths
758 b5dc7732 ths
    if (other_tc == env->current_tc)
759 b5dc7732 ths
        return env->active_tc.PC;
760 b5dc7732 ths
    else
761 b5dc7732 ths
        return env->tcs[other_tc].PC;
762 f1aa6320 ths
}
763 f1aa6320 ths
764 c01fccd2 aurel32
target_ulong helper_mfc0_tchalt (void)
765 f1aa6320 ths
{
766 b5dc7732 ths
    return env->active_tc.CP0_TCHalt;
767 f1aa6320 ths
}
768 f1aa6320 ths
769 c01fccd2 aurel32
target_ulong helper_mftc0_tchalt(void)
770 f1aa6320 ths
{
771 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
772 f1aa6320 ths
773 b5dc7732 ths
    if (other_tc == env->current_tc)
774 b5dc7732 ths
        return env->active_tc.CP0_TCHalt;
775 b5dc7732 ths
    else
776 b5dc7732 ths
        return env->tcs[other_tc].CP0_TCHalt;
777 f1aa6320 ths
}
778 f1aa6320 ths
779 c01fccd2 aurel32
target_ulong helper_mfc0_tccontext (void)
780 f1aa6320 ths
{
781 b5dc7732 ths
    return env->active_tc.CP0_TCContext;
782 f1aa6320 ths
}
783 f1aa6320 ths
784 c01fccd2 aurel32
target_ulong helper_mftc0_tccontext(void)
785 f1aa6320 ths
{
786 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
787 f1aa6320 ths
788 b5dc7732 ths
    if (other_tc == env->current_tc)
789 b5dc7732 ths
        return env->active_tc.CP0_TCContext;
790 b5dc7732 ths
    else
791 b5dc7732 ths
        return env->tcs[other_tc].CP0_TCContext;
792 f1aa6320 ths
}
793 f1aa6320 ths
794 c01fccd2 aurel32
target_ulong helper_mfc0_tcschedule (void)
795 f1aa6320 ths
{
796 b5dc7732 ths
    return env->active_tc.CP0_TCSchedule;
797 f1aa6320 ths
}
798 f1aa6320 ths
799 c01fccd2 aurel32
target_ulong helper_mftc0_tcschedule(void)
800 f1aa6320 ths
{
801 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
802 f1aa6320 ths
803 b5dc7732 ths
    if (other_tc == env->current_tc)
804 b5dc7732 ths
        return env->active_tc.CP0_TCSchedule;
805 b5dc7732 ths
    else
806 b5dc7732 ths
        return env->tcs[other_tc].CP0_TCSchedule;
807 f1aa6320 ths
}
808 f1aa6320 ths
809 c01fccd2 aurel32
target_ulong helper_mfc0_tcschefback (void)
810 f1aa6320 ths
{
811 b5dc7732 ths
    return env->active_tc.CP0_TCScheFBack;
812 f1aa6320 ths
}
813 f1aa6320 ths
814 c01fccd2 aurel32
target_ulong helper_mftc0_tcschefback(void)
815 f1aa6320 ths
{
816 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
817 f1aa6320 ths
818 b5dc7732 ths
    if (other_tc == env->current_tc)
819 b5dc7732 ths
        return env->active_tc.CP0_TCScheFBack;
820 b5dc7732 ths
    else
821 b5dc7732 ths
        return env->tcs[other_tc].CP0_TCScheFBack;
822 f1aa6320 ths
}
823 f1aa6320 ths
824 c01fccd2 aurel32
target_ulong helper_mfc0_count (void)
825 873eb012 ths
{
826 be24bb4f ths
    return (int32_t)cpu_mips_get_count(env);
827 6af0bf9c bellard
}
828 6af0bf9c bellard
829 c01fccd2 aurel32
target_ulong helper_mftc0_entryhi(void)
830 f1aa6320 ths
{
831 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
832 b5dc7732 ths
    int32_t tcstatus;
833 f1aa6320 ths
834 b5dc7732 ths
    if (other_tc == env->current_tc)
835 b5dc7732 ths
        tcstatus = env->active_tc.CP0_TCStatus;
836 b5dc7732 ths
    else
837 b5dc7732 ths
        tcstatus = env->tcs[other_tc].CP0_TCStatus;
838 b5dc7732 ths
839 b5dc7732 ths
    return (env->CP0_EntryHi & ~0xff) | (tcstatus & 0xff);
840 f1aa6320 ths
}
841 f1aa6320 ths
842 c01fccd2 aurel32
target_ulong helper_mftc0_status(void)
843 f1aa6320 ths
{
844 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
845 1a3fd9c3 ths
    target_ulong t0;
846 b5dc7732 ths
    int32_t tcstatus;
847 b5dc7732 ths
848 b5dc7732 ths
    if (other_tc == env->current_tc)
849 b5dc7732 ths
        tcstatus = env->active_tc.CP0_TCStatus;
850 b5dc7732 ths
    else
851 b5dc7732 ths
        tcstatus = env->tcs[other_tc].CP0_TCStatus;
852 f1aa6320 ths
853 be24bb4f ths
    t0 = env->CP0_Status & ~0xf1000018;
854 be24bb4f ths
    t0 |= tcstatus & (0xf << CP0TCSt_TCU0);
855 be24bb4f ths
    t0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
856 be24bb4f ths
    t0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
857 be24bb4f ths
858 be24bb4f ths
    return t0;
859 f1aa6320 ths
}
860 f1aa6320 ths
861 c01fccd2 aurel32
target_ulong helper_mfc0_lladdr (void)
862 f1aa6320 ths
{
863 2a6e32dd Aurelien Jarno
    return (int32_t)(env->lladdr >> env->CP0_LLAddr_shift);
864 f1aa6320 ths
}
865 f1aa6320 ths
866 c01fccd2 aurel32
target_ulong helper_mfc0_watchlo (uint32_t sel)
867 f1aa6320 ths
{
868 be24bb4f ths
    return (int32_t)env->CP0_WatchLo[sel];
869 f1aa6320 ths
}
870 f1aa6320 ths
871 c01fccd2 aurel32
target_ulong helper_mfc0_watchhi (uint32_t sel)
872 f1aa6320 ths
{
873 be24bb4f ths
    return env->CP0_WatchHi[sel];
874 f1aa6320 ths
}
875 f1aa6320 ths
876 c01fccd2 aurel32
target_ulong helper_mfc0_debug (void)
877 f1aa6320 ths
{
878 1a3fd9c3 ths
    target_ulong t0 = env->CP0_Debug;
879 f1aa6320 ths
    if (env->hflags & MIPS_HFLAG_DM)
880 be24bb4f ths
        t0 |= 1 << CP0DB_DM;
881 be24bb4f ths
882 be24bb4f ths
    return t0;
883 f1aa6320 ths
}
884 f1aa6320 ths
885 c01fccd2 aurel32
target_ulong helper_mftc0_debug(void)
886 f1aa6320 ths
{
887 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
888 b5dc7732 ths
    int32_t tcstatus;
889 b5dc7732 ths
890 b5dc7732 ths
    if (other_tc == env->current_tc)
891 b5dc7732 ths
        tcstatus = env->active_tc.CP0_Debug_tcstatus;
892 b5dc7732 ths
    else
893 b5dc7732 ths
        tcstatus = env->tcs[other_tc].CP0_Debug_tcstatus;
894 f1aa6320 ths
895 f1aa6320 ths
    /* XXX: Might be wrong, check with EJTAG spec. */
896 be24bb4f ths
    return (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
897 b5dc7732 ths
            (tcstatus & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
898 f1aa6320 ths
}
899 f1aa6320 ths
900 f1aa6320 ths
#if defined(TARGET_MIPS64)
901 c01fccd2 aurel32
target_ulong helper_dmfc0_tcrestart (void)
902 f1aa6320 ths
{
903 b5dc7732 ths
    return env->active_tc.PC;
904 f1aa6320 ths
}
905 f1aa6320 ths
906 c01fccd2 aurel32
target_ulong helper_dmfc0_tchalt (void)
907 f1aa6320 ths
{
908 b5dc7732 ths
    return env->active_tc.CP0_TCHalt;
909 f1aa6320 ths
}
910 f1aa6320 ths
911 c01fccd2 aurel32
target_ulong helper_dmfc0_tccontext (void)
912 f1aa6320 ths
{
913 b5dc7732 ths
    return env->active_tc.CP0_TCContext;
914 f1aa6320 ths
}
915 f1aa6320 ths
916 c01fccd2 aurel32
target_ulong helper_dmfc0_tcschedule (void)
917 f1aa6320 ths
{
918 b5dc7732 ths
    return env->active_tc.CP0_TCSchedule;
919 f1aa6320 ths
}
920 f1aa6320 ths
921 c01fccd2 aurel32
target_ulong helper_dmfc0_tcschefback (void)
922 f1aa6320 ths
{
923 b5dc7732 ths
    return env->active_tc.CP0_TCScheFBack;
924 f1aa6320 ths
}
925 f1aa6320 ths
926 c01fccd2 aurel32
target_ulong helper_dmfc0_lladdr (void)
927 f1aa6320 ths
{
928 2a6e32dd Aurelien Jarno
    return env->lladdr >> env->CP0_LLAddr_shift;
929 f1aa6320 ths
}
930 f1aa6320 ths
931 c01fccd2 aurel32
target_ulong helper_dmfc0_watchlo (uint32_t sel)
932 f1aa6320 ths
{
933 be24bb4f ths
    return env->CP0_WatchLo[sel];
934 f1aa6320 ths
}
935 f1aa6320 ths
#endif /* TARGET_MIPS64 */
936 f1aa6320 ths
937 d9bea114 aurel32
void helper_mtc0_index (target_ulong arg1)
938 f1aa6320 ths
{
939 f1aa6320 ths
    int num = 1;
940 f1aa6320 ths
    unsigned int tmp = env->tlb->nb_tlb;
941 f1aa6320 ths
942 f1aa6320 ths
    do {
943 f1aa6320 ths
        tmp >>= 1;
944 f1aa6320 ths
        num <<= 1;
945 f1aa6320 ths
    } while (tmp);
946 d9bea114 aurel32
    env->CP0_Index = (env->CP0_Index & 0x80000000) | (arg1 & (num - 1));
947 f1aa6320 ths
}
948 f1aa6320 ths
949 d9bea114 aurel32
void helper_mtc0_mvpcontrol (target_ulong arg1)
950 f1aa6320 ths
{
951 f1aa6320 ths
    uint32_t mask = 0;
952 f1aa6320 ths
    uint32_t newval;
953 f1aa6320 ths
954 f1aa6320 ths
    if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
955 f1aa6320 ths
        mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
956 f1aa6320 ths
                (1 << CP0MVPCo_EVP);
957 f1aa6320 ths
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
958 f1aa6320 ths
        mask |= (1 << CP0MVPCo_STLB);
959 d9bea114 aurel32
    newval = (env->mvp->CP0_MVPControl & ~mask) | (arg1 & mask);
960 f1aa6320 ths
961 f1aa6320 ths
    // TODO: Enable/disable shared TLB, enable/disable VPEs.
962 f1aa6320 ths
963 f1aa6320 ths
    env->mvp->CP0_MVPControl = newval;
964 f1aa6320 ths
}
965 f1aa6320 ths
966 d9bea114 aurel32
void helper_mtc0_vpecontrol (target_ulong arg1)
967 f1aa6320 ths
{
968 f1aa6320 ths
    uint32_t mask;
969 f1aa6320 ths
    uint32_t newval;
970 f1aa6320 ths
971 f1aa6320 ths
    mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
972 f1aa6320 ths
           (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
973 d9bea114 aurel32
    newval = (env->CP0_VPEControl & ~mask) | (arg1 & mask);
974 f1aa6320 ths
975 f1aa6320 ths
    /* Yield scheduler intercept not implemented. */
976 f1aa6320 ths
    /* Gating storage scheduler intercept not implemented. */
977 f1aa6320 ths
978 f1aa6320 ths
    // TODO: Enable/disable TCs.
979 f1aa6320 ths
980 f1aa6320 ths
    env->CP0_VPEControl = newval;
981 f1aa6320 ths
}
982 f1aa6320 ths
983 d9bea114 aurel32
void helper_mtc0_vpeconf0 (target_ulong arg1)
984 f1aa6320 ths
{
985 f1aa6320 ths
    uint32_t mask = 0;
986 f1aa6320 ths
    uint32_t newval;
987 f1aa6320 ths
988 f1aa6320 ths
    if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
989 f1aa6320 ths
        if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
990 f1aa6320 ths
            mask |= (0xff << CP0VPEC0_XTC);
991 f1aa6320 ths
        mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
992 f1aa6320 ths
    }
993 d9bea114 aurel32
    newval = (env->CP0_VPEConf0 & ~mask) | (arg1 & mask);
994 f1aa6320 ths
995 f1aa6320 ths
    // TODO: TC exclusive handling due to ERL/EXL.
996 f1aa6320 ths
997 f1aa6320 ths
    env->CP0_VPEConf0 = newval;
998 f1aa6320 ths
}
999 f1aa6320 ths
1000 d9bea114 aurel32
void helper_mtc0_vpeconf1 (target_ulong arg1)
1001 f1aa6320 ths
{
1002 f1aa6320 ths
    uint32_t mask = 0;
1003 f1aa6320 ths
    uint32_t newval;
1004 f1aa6320 ths
1005 f1aa6320 ths
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1006 f1aa6320 ths
        mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
1007 f1aa6320 ths
                (0xff << CP0VPEC1_NCP1);
1008 d9bea114 aurel32
    newval = (env->CP0_VPEConf1 & ~mask) | (arg1 & mask);
1009 f1aa6320 ths
1010 f1aa6320 ths
    /* UDI not implemented. */
1011 f1aa6320 ths
    /* CP2 not implemented. */
1012 f1aa6320 ths
1013 f1aa6320 ths
    // TODO: Handle FPU (CP1) binding.
1014 f1aa6320 ths
1015 f1aa6320 ths
    env->CP0_VPEConf1 = newval;
1016 f1aa6320 ths
}
1017 f1aa6320 ths
1018 d9bea114 aurel32
void helper_mtc0_yqmask (target_ulong arg1)
1019 f1aa6320 ths
{
1020 f1aa6320 ths
    /* Yield qualifier inputs not implemented. */
1021 f1aa6320 ths
    env->CP0_YQMask = 0x00000000;
1022 f1aa6320 ths
}
1023 f1aa6320 ths
1024 d9bea114 aurel32
void helper_mtc0_vpeopt (target_ulong arg1)
1025 f1aa6320 ths
{
1026 d9bea114 aurel32
    env->CP0_VPEOpt = arg1 & 0x0000ffff;
1027 f1aa6320 ths
}
1028 f1aa6320 ths
1029 d9bea114 aurel32
void helper_mtc0_entrylo0 (target_ulong arg1)
1030 f1aa6320 ths
{
1031 f1aa6320 ths
    /* Large physaddr (PABITS) not implemented */
1032 f1aa6320 ths
    /* 1k pages not implemented */
1033 d9bea114 aurel32
    env->CP0_EntryLo0 = arg1 & 0x3FFFFFFF;
1034 f1aa6320 ths
}
1035 f1aa6320 ths
1036 d9bea114 aurel32
void helper_mtc0_tcstatus (target_ulong arg1)
1037 f1aa6320 ths
{
1038 f1aa6320 ths
    uint32_t mask = env->CP0_TCStatus_rw_bitmask;
1039 f1aa6320 ths
    uint32_t newval;
1040 f1aa6320 ths
1041 d9bea114 aurel32
    newval = (env->active_tc.CP0_TCStatus & ~mask) | (arg1 & mask);
1042 f1aa6320 ths
1043 f1aa6320 ths
    // TODO: Sync with CP0_Status.
1044 f1aa6320 ths
1045 b5dc7732 ths
    env->active_tc.CP0_TCStatus = newval;
1046 f1aa6320 ths
}
1047 f1aa6320 ths
1048 d9bea114 aurel32
void helper_mttc0_tcstatus (target_ulong arg1)
1049 f1aa6320 ths
{
1050 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1051 f1aa6320 ths
1052 f1aa6320 ths
    // TODO: Sync with CP0_Status.
1053 f1aa6320 ths
1054 b5dc7732 ths
    if (other_tc == env->current_tc)
1055 d9bea114 aurel32
        env->active_tc.CP0_TCStatus = arg1;
1056 b5dc7732 ths
    else
1057 d9bea114 aurel32
        env->tcs[other_tc].CP0_TCStatus = arg1;
1058 f1aa6320 ths
}
1059 f1aa6320 ths
1060 d9bea114 aurel32
void helper_mtc0_tcbind (target_ulong arg1)
1061 f1aa6320 ths
{
1062 f1aa6320 ths
    uint32_t mask = (1 << CP0TCBd_TBE);
1063 f1aa6320 ths
    uint32_t newval;
1064 f1aa6320 ths
1065 f1aa6320 ths
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1066 f1aa6320 ths
        mask |= (1 << CP0TCBd_CurVPE);
1067 d9bea114 aurel32
    newval = (env->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
1068 b5dc7732 ths
    env->active_tc.CP0_TCBind = newval;
1069 f1aa6320 ths
}
1070 f1aa6320 ths
1071 d9bea114 aurel32
void helper_mttc0_tcbind (target_ulong arg1)
1072 f1aa6320 ths
{
1073 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1074 f1aa6320 ths
    uint32_t mask = (1 << CP0TCBd_TBE);
1075 f1aa6320 ths
    uint32_t newval;
1076 f1aa6320 ths
1077 f1aa6320 ths
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
1078 f1aa6320 ths
        mask |= (1 << CP0TCBd_CurVPE);
1079 b5dc7732 ths
    if (other_tc == env->current_tc) {
1080 d9bea114 aurel32
        newval = (env->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
1081 b5dc7732 ths
        env->active_tc.CP0_TCBind = newval;
1082 b5dc7732 ths
    } else {
1083 d9bea114 aurel32
        newval = (env->tcs[other_tc].CP0_TCBind & ~mask) | (arg1 & mask);
1084 b5dc7732 ths
        env->tcs[other_tc].CP0_TCBind = newval;
1085 b5dc7732 ths
    }
1086 f1aa6320 ths
}
1087 f1aa6320 ths
1088 d9bea114 aurel32
void helper_mtc0_tcrestart (target_ulong arg1)
1089 f1aa6320 ths
{
1090 d9bea114 aurel32
    env->active_tc.PC = arg1;
1091 b5dc7732 ths
    env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
1092 5499b6ff Aurelien Jarno
    env->lladdr = 0ULL;
1093 f1aa6320 ths
    /* MIPS16 not implemented. */
1094 f1aa6320 ths
}
1095 f1aa6320 ths
1096 d9bea114 aurel32
void helper_mttc0_tcrestart (target_ulong arg1)
1097 f1aa6320 ths
{
1098 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1099 f1aa6320 ths
1100 b5dc7732 ths
    if (other_tc == env->current_tc) {
1101 d9bea114 aurel32
        env->active_tc.PC = arg1;
1102 b5dc7732 ths
        env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
1103 5499b6ff Aurelien Jarno
        env->lladdr = 0ULL;
1104 b5dc7732 ths
        /* MIPS16 not implemented. */
1105 b5dc7732 ths
    } else {
1106 d9bea114 aurel32
        env->tcs[other_tc].PC = arg1;
1107 b5dc7732 ths
        env->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
1108 5499b6ff Aurelien Jarno
        env->lladdr = 0ULL;
1109 b5dc7732 ths
        /* MIPS16 not implemented. */
1110 b5dc7732 ths
    }
1111 f1aa6320 ths
}
1112 f1aa6320 ths
1113 d9bea114 aurel32
void helper_mtc0_tchalt (target_ulong arg1)
1114 f1aa6320 ths
{
1115 d9bea114 aurel32
    env->active_tc.CP0_TCHalt = arg1 & 0x1;
1116 f1aa6320 ths
1117 f1aa6320 ths
    // TODO: Halt TC / Restart (if allocated+active) TC.
1118 f1aa6320 ths
}
1119 f1aa6320 ths
1120 d9bea114 aurel32
void helper_mttc0_tchalt (target_ulong arg1)
1121 f1aa6320 ths
{
1122 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1123 f1aa6320 ths
1124 f1aa6320 ths
    // TODO: Halt TC / Restart (if allocated+active) TC.
1125 f1aa6320 ths
1126 b5dc7732 ths
    if (other_tc == env->current_tc)
1127 d9bea114 aurel32
        env->active_tc.CP0_TCHalt = arg1;
1128 b5dc7732 ths
    else
1129 d9bea114 aurel32
        env->tcs[other_tc].CP0_TCHalt = arg1;
1130 f1aa6320 ths
}
1131 f1aa6320 ths
1132 d9bea114 aurel32
void helper_mtc0_tccontext (target_ulong arg1)
1133 f1aa6320 ths
{
1134 d9bea114 aurel32
    env->active_tc.CP0_TCContext = arg1;
1135 f1aa6320 ths
}
1136 f1aa6320 ths
1137 d9bea114 aurel32
void helper_mttc0_tccontext (target_ulong arg1)
1138 f1aa6320 ths
{
1139 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1140 f1aa6320 ths
1141 b5dc7732 ths
    if (other_tc == env->current_tc)
1142 d9bea114 aurel32
        env->active_tc.CP0_TCContext = arg1;
1143 b5dc7732 ths
    else
1144 d9bea114 aurel32
        env->tcs[other_tc].CP0_TCContext = arg1;
1145 f1aa6320 ths
}
1146 f1aa6320 ths
1147 d9bea114 aurel32
void helper_mtc0_tcschedule (target_ulong arg1)
1148 f1aa6320 ths
{
1149 d9bea114 aurel32
    env->active_tc.CP0_TCSchedule = arg1;
1150 f1aa6320 ths
}
1151 f1aa6320 ths
1152 d9bea114 aurel32
void helper_mttc0_tcschedule (target_ulong arg1)
1153 f1aa6320 ths
{
1154 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1155 f1aa6320 ths
1156 b5dc7732 ths
    if (other_tc == env->current_tc)
1157 d9bea114 aurel32
        env->active_tc.CP0_TCSchedule = arg1;
1158 b5dc7732 ths
    else
1159 d9bea114 aurel32
        env->tcs[other_tc].CP0_TCSchedule = arg1;
1160 f1aa6320 ths
}
1161 f1aa6320 ths
1162 d9bea114 aurel32
void helper_mtc0_tcschefback (target_ulong arg1)
1163 f1aa6320 ths
{
1164 d9bea114 aurel32
    env->active_tc.CP0_TCScheFBack = arg1;
1165 f1aa6320 ths
}
1166 f1aa6320 ths
1167 d9bea114 aurel32
void helper_mttc0_tcschefback (target_ulong arg1)
1168 f1aa6320 ths
{
1169 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1170 f1aa6320 ths
1171 b5dc7732 ths
    if (other_tc == env->current_tc)
1172 d9bea114 aurel32
        env->active_tc.CP0_TCScheFBack = arg1;
1173 b5dc7732 ths
    else
1174 d9bea114 aurel32
        env->tcs[other_tc].CP0_TCScheFBack = arg1;
1175 f1aa6320 ths
}
1176 f1aa6320 ths
1177 d9bea114 aurel32
void helper_mtc0_entrylo1 (target_ulong arg1)
1178 f1aa6320 ths
{
1179 f1aa6320 ths
    /* Large physaddr (PABITS) not implemented */
1180 f1aa6320 ths
    /* 1k pages not implemented */
1181 d9bea114 aurel32
    env->CP0_EntryLo1 = arg1 & 0x3FFFFFFF;
1182 f1aa6320 ths
}
1183 f1aa6320 ths
1184 d9bea114 aurel32
void helper_mtc0_context (target_ulong arg1)
1185 f1aa6320 ths
{
1186 d9bea114 aurel32
    env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
1187 f1aa6320 ths
}
1188 f1aa6320 ths
1189 d9bea114 aurel32
void helper_mtc0_pagemask (target_ulong arg1)
1190 f1aa6320 ths
{
1191 f1aa6320 ths
    /* 1k pages not implemented */
1192 d9bea114 aurel32
    env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1193 f1aa6320 ths
}
1194 f1aa6320 ths
1195 d9bea114 aurel32
void helper_mtc0_pagegrain (target_ulong arg1)
1196 f1aa6320 ths
{
1197 f1aa6320 ths
    /* SmartMIPS not implemented */
1198 f1aa6320 ths
    /* Large physaddr (PABITS) not implemented */
1199 f1aa6320 ths
    /* 1k pages not implemented */
1200 f1aa6320 ths
    env->CP0_PageGrain = 0;
1201 f1aa6320 ths
}
1202 f1aa6320 ths
1203 d9bea114 aurel32
void helper_mtc0_wired (target_ulong arg1)
1204 f1aa6320 ths
{
1205 d9bea114 aurel32
    env->CP0_Wired = arg1 % env->tlb->nb_tlb;
1206 f1aa6320 ths
}
1207 f1aa6320 ths
1208 d9bea114 aurel32
void helper_mtc0_srsconf0 (target_ulong arg1)
1209 f1aa6320 ths
{
1210 d9bea114 aurel32
    env->CP0_SRSConf0 |= arg1 & env->CP0_SRSConf0_rw_bitmask;
1211 f1aa6320 ths
}
1212 f1aa6320 ths
1213 d9bea114 aurel32
void helper_mtc0_srsconf1 (target_ulong arg1)
1214 f1aa6320 ths
{
1215 d9bea114 aurel32
    env->CP0_SRSConf1 |= arg1 & env->CP0_SRSConf1_rw_bitmask;
1216 f1aa6320 ths
}
1217 f1aa6320 ths
1218 d9bea114 aurel32
void helper_mtc0_srsconf2 (target_ulong arg1)
1219 f1aa6320 ths
{
1220 d9bea114 aurel32
    env->CP0_SRSConf2 |= arg1 & env->CP0_SRSConf2_rw_bitmask;
1221 f1aa6320 ths
}
1222 f1aa6320 ths
1223 d9bea114 aurel32
void helper_mtc0_srsconf3 (target_ulong arg1)
1224 f1aa6320 ths
{
1225 d9bea114 aurel32
    env->CP0_SRSConf3 |= arg1 & env->CP0_SRSConf3_rw_bitmask;
1226 f1aa6320 ths
}
1227 f1aa6320 ths
1228 d9bea114 aurel32
void helper_mtc0_srsconf4 (target_ulong arg1)
1229 f1aa6320 ths
{
1230 d9bea114 aurel32
    env->CP0_SRSConf4 |= arg1 & env->CP0_SRSConf4_rw_bitmask;
1231 f1aa6320 ths
}
1232 f1aa6320 ths
1233 d9bea114 aurel32
void helper_mtc0_hwrena (target_ulong arg1)
1234 f1aa6320 ths
{
1235 d9bea114 aurel32
    env->CP0_HWREna = arg1 & 0x0000000F;
1236 f1aa6320 ths
}
1237 f1aa6320 ths
1238 d9bea114 aurel32
void helper_mtc0_count (target_ulong arg1)
1239 f1aa6320 ths
{
1240 d9bea114 aurel32
    cpu_mips_store_count(env, arg1);
1241 f1aa6320 ths
}
1242 f1aa6320 ths
1243 d9bea114 aurel32
void helper_mtc0_entryhi (target_ulong arg1)
1244 f1aa6320 ths
{
1245 f1aa6320 ths
    target_ulong old, val;
1246 f1aa6320 ths
1247 f1aa6320 ths
    /* 1k pages not implemented */
1248 d9bea114 aurel32
    val = arg1 & ((TARGET_PAGE_MASK << 1) | 0xFF);
1249 f1aa6320 ths
#if defined(TARGET_MIPS64)
1250 f1aa6320 ths
    val &= env->SEGMask;
1251 f1aa6320 ths
#endif
1252 f1aa6320 ths
    old = env->CP0_EntryHi;
1253 f1aa6320 ths
    env->CP0_EntryHi = val;
1254 f1aa6320 ths
    if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1255 b5dc7732 ths
        uint32_t tcst = env->active_tc.CP0_TCStatus & ~0xff;
1256 b5dc7732 ths
        env->active_tc.CP0_TCStatus = tcst | (val & 0xff);
1257 f1aa6320 ths
    }
1258 f1aa6320 ths
    /* If the ASID changes, flush qemu's TLB.  */
1259 f1aa6320 ths
    if ((old & 0xFF) != (val & 0xFF))
1260 f1aa6320 ths
        cpu_mips_tlb_flush(env, 1);
1261 f1aa6320 ths
}
1262 f1aa6320 ths
1263 d9bea114 aurel32
void helper_mttc0_entryhi(target_ulong arg1)
1264 f1aa6320 ths
{
1265 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1266 b5dc7732 ths
    int32_t tcstatus;
1267 f1aa6320 ths
1268 d9bea114 aurel32
    env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (arg1 & ~0xff);
1269 b5dc7732 ths
    if (other_tc == env->current_tc) {
1270 d9bea114 aurel32
        tcstatus = (env->active_tc.CP0_TCStatus & ~0xff) | (arg1 & 0xff);
1271 b5dc7732 ths
        env->active_tc.CP0_TCStatus = tcstatus;
1272 b5dc7732 ths
    } else {
1273 d9bea114 aurel32
        tcstatus = (env->tcs[other_tc].CP0_TCStatus & ~0xff) | (arg1 & 0xff);
1274 b5dc7732 ths
        env->tcs[other_tc].CP0_TCStatus = tcstatus;
1275 b5dc7732 ths
    }
1276 f1aa6320 ths
}
1277 f1aa6320 ths
1278 d9bea114 aurel32
void helper_mtc0_compare (target_ulong arg1)
1279 f1aa6320 ths
{
1280 d9bea114 aurel32
    cpu_mips_store_compare(env, arg1);
1281 f1aa6320 ths
}
1282 f1aa6320 ths
1283 d9bea114 aurel32
void helper_mtc0_status (target_ulong arg1)
1284 f1aa6320 ths
{
1285 f1aa6320 ths
    uint32_t val, old;
1286 f1aa6320 ths
    uint32_t mask = env->CP0_Status_rw_bitmask;
1287 f1aa6320 ths
1288 d9bea114 aurel32
    val = arg1 & mask;
1289 f1aa6320 ths
    old = env->CP0_Status;
1290 f1aa6320 ths
    env->CP0_Status = (env->CP0_Status & ~mask) | val;
1291 f1aa6320 ths
    compute_hflags(env);
1292 c01fccd2 aurel32
    if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
1293 c01fccd2 aurel32
        qemu_log("Status %08x (%08x) => %08x (%08x) Cause %08x",
1294 c01fccd2 aurel32
                old, old & env->CP0_Cause & CP0Ca_IP_mask,
1295 c01fccd2 aurel32
                val, val & env->CP0_Cause & CP0Ca_IP_mask,
1296 c01fccd2 aurel32
                env->CP0_Cause);
1297 c01fccd2 aurel32
        switch (env->hflags & MIPS_HFLAG_KSU) {
1298 c01fccd2 aurel32
        case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
1299 c01fccd2 aurel32
        case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
1300 c01fccd2 aurel32
        case MIPS_HFLAG_KM: qemu_log("\n"); break;
1301 c01fccd2 aurel32
        default: cpu_abort(env, "Invalid MMU mode!\n"); break;
1302 31e3104f Aurelien Jarno
        }
1303 c01fccd2 aurel32
    }
1304 f1aa6320 ths
}
1305 f1aa6320 ths
1306 d9bea114 aurel32
void helper_mttc0_status(target_ulong arg1)
1307 f1aa6320 ths
{
1308 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1309 b5dc7732 ths
    int32_t tcstatus = env->tcs[other_tc].CP0_TCStatus;
1310 f1aa6320 ths
1311 d9bea114 aurel32
    env->CP0_Status = arg1 & ~0xf1000018;
1312 d9bea114 aurel32
    tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (arg1 & (0xf << CP0St_CU0));
1313 d9bea114 aurel32
    tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((arg1 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
1314 d9bea114 aurel32
    tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((arg1 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
1315 b5dc7732 ths
    if (other_tc == env->current_tc)
1316 b5dc7732 ths
        env->active_tc.CP0_TCStatus = tcstatus;
1317 b5dc7732 ths
    else
1318 b5dc7732 ths
        env->tcs[other_tc].CP0_TCStatus = tcstatus;
1319 f1aa6320 ths
}
1320 f1aa6320 ths
1321 d9bea114 aurel32
void helper_mtc0_intctl (target_ulong arg1)
1322 f1aa6320 ths
{
1323 f1aa6320 ths
    /* vectored interrupts not implemented, no performance counters. */
1324 d9bea114 aurel32
    env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (arg1 & 0x000002e0);
1325 f1aa6320 ths
}
1326 f1aa6320 ths
1327 d9bea114 aurel32
void helper_mtc0_srsctl (target_ulong arg1)
1328 f1aa6320 ths
{
1329 f1aa6320 ths
    uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1330 d9bea114 aurel32
    env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (arg1 & mask);
1331 f1aa6320 ths
}
1332 f1aa6320 ths
1333 d9bea114 aurel32
void helper_mtc0_cause (target_ulong arg1)
1334 f1aa6320 ths
{
1335 f1aa6320 ths
    uint32_t mask = 0x00C00300;
1336 f1aa6320 ths
    uint32_t old = env->CP0_Cause;
1337 5dc5d9f0 Aurelien Jarno
    int i;
1338 f1aa6320 ths
1339 f1aa6320 ths
    if (env->insn_flags & ISA_MIPS32R2)
1340 f1aa6320 ths
        mask |= 1 << CP0Ca_DC;
1341 f1aa6320 ths
1342 d9bea114 aurel32
    env->CP0_Cause = (env->CP0_Cause & ~mask) | (arg1 & mask);
1343 f1aa6320 ths
1344 f1aa6320 ths
    if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
1345 f1aa6320 ths
        if (env->CP0_Cause & (1 << CP0Ca_DC))
1346 f1aa6320 ths
            cpu_mips_stop_count(env);
1347 f1aa6320 ths
        else
1348 f1aa6320 ths
            cpu_mips_start_count(env);
1349 f1aa6320 ths
    }
1350 5dc5d9f0 Aurelien Jarno
1351 5dc5d9f0 Aurelien Jarno
    /* Set/reset software interrupts */
1352 5dc5d9f0 Aurelien Jarno
    for (i = 0 ; i < 2 ; i++) {
1353 5dc5d9f0 Aurelien Jarno
        if ((old ^ env->CP0_Cause) & (1 << (CP0Ca_IP + i))) {
1354 5dc5d9f0 Aurelien Jarno
            cpu_mips_soft_irq(env, i, env->CP0_Cause & (1 << (CP0Ca_IP + i)));
1355 5dc5d9f0 Aurelien Jarno
        }
1356 5dc5d9f0 Aurelien Jarno
    }
1357 f1aa6320 ths
}
1358 f1aa6320 ths
1359 d9bea114 aurel32
void helper_mtc0_ebase (target_ulong arg1)
1360 f1aa6320 ths
{
1361 f1aa6320 ths
    /* vectored interrupts not implemented */
1362 671b0f36 Hervรฉ Poussineau
    env->CP0_EBase = (env->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000);
1363 f1aa6320 ths
}
1364 f1aa6320 ths
1365 d9bea114 aurel32
void helper_mtc0_config0 (target_ulong arg1)
1366 f1aa6320 ths
{
1367 d9bea114 aurel32
    env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (arg1 & 0x00000007);
1368 f1aa6320 ths
}
1369 f1aa6320 ths
1370 d9bea114 aurel32
void helper_mtc0_config2 (target_ulong arg1)
1371 f1aa6320 ths
{
1372 f1aa6320 ths
    /* tertiary/secondary caches not implemented */
1373 f1aa6320 ths
    env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1374 f1aa6320 ths
}
1375 f1aa6320 ths
1376 2a6e32dd Aurelien Jarno
void helper_mtc0_lladdr (target_ulong arg1)
1377 2a6e32dd Aurelien Jarno
{
1378 2a6e32dd Aurelien Jarno
    target_long mask = env->CP0_LLAddr_rw_bitmask;
1379 2a6e32dd Aurelien Jarno
    arg1 = arg1 << env->CP0_LLAddr_shift;
1380 2a6e32dd Aurelien Jarno
    env->lladdr = (env->lladdr & ~mask) | (arg1 & mask);
1381 2a6e32dd Aurelien Jarno
}
1382 2a6e32dd Aurelien Jarno
1383 d9bea114 aurel32
void helper_mtc0_watchlo (target_ulong arg1, uint32_t sel)
1384 f1aa6320 ths
{
1385 f1aa6320 ths
    /* Watch exceptions for instructions, data loads, data stores
1386 f1aa6320 ths
       not implemented. */
1387 d9bea114 aurel32
    env->CP0_WatchLo[sel] = (arg1 & ~0x7);
1388 f1aa6320 ths
}
1389 f1aa6320 ths
1390 d9bea114 aurel32
void helper_mtc0_watchhi (target_ulong arg1, uint32_t sel)
1391 f1aa6320 ths
{
1392 d9bea114 aurel32
    env->CP0_WatchHi[sel] = (arg1 & 0x40FF0FF8);
1393 d9bea114 aurel32
    env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7);
1394 f1aa6320 ths
}
1395 f1aa6320 ths
1396 d9bea114 aurel32
void helper_mtc0_xcontext (target_ulong arg1)
1397 f1aa6320 ths
{
1398 f1aa6320 ths
    target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1399 d9bea114 aurel32
    env->CP0_XContext = (env->CP0_XContext & mask) | (arg1 & ~mask);
1400 f1aa6320 ths
}
1401 f1aa6320 ths
1402 d9bea114 aurel32
void helper_mtc0_framemask (target_ulong arg1)
1403 f1aa6320 ths
{
1404 d9bea114 aurel32
    env->CP0_Framemask = arg1; /* XXX */
1405 f1aa6320 ths
}
1406 f1aa6320 ths
1407 d9bea114 aurel32
void helper_mtc0_debug (target_ulong arg1)
1408 f1aa6320 ths
{
1409 d9bea114 aurel32
    env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (arg1 & 0x13300120);
1410 d9bea114 aurel32
    if (arg1 & (1 << CP0DB_DM))
1411 f1aa6320 ths
        env->hflags |= MIPS_HFLAG_DM;
1412 f1aa6320 ths
    else
1413 f1aa6320 ths
        env->hflags &= ~MIPS_HFLAG_DM;
1414 f1aa6320 ths
}
1415 f1aa6320 ths
1416 d9bea114 aurel32
void helper_mttc0_debug(target_ulong arg1)
1417 f1aa6320 ths
{
1418 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1419 d9bea114 aurel32
    uint32_t val = arg1 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1420 f1aa6320 ths
1421 f1aa6320 ths
    /* XXX: Might be wrong, check with EJTAG spec. */
1422 b5dc7732 ths
    if (other_tc == env->current_tc)
1423 b5dc7732 ths
        env->active_tc.CP0_Debug_tcstatus = val;
1424 b5dc7732 ths
    else
1425 b5dc7732 ths
        env->tcs[other_tc].CP0_Debug_tcstatus = val;
1426 f1aa6320 ths
    env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1427 d9bea114 aurel32
                     (arg1 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1428 f1aa6320 ths
}
1429 f1aa6320 ths
1430 d9bea114 aurel32
void helper_mtc0_performance0 (target_ulong arg1)
1431 f1aa6320 ths
{
1432 d9bea114 aurel32
    env->CP0_Performance0 = arg1 & 0x000007ff;
1433 f1aa6320 ths
}
1434 f1aa6320 ths
1435 d9bea114 aurel32
void helper_mtc0_taglo (target_ulong arg1)
1436 f1aa6320 ths
{
1437 d9bea114 aurel32
    env->CP0_TagLo = arg1 & 0xFFFFFCF6;
1438 f1aa6320 ths
}
1439 f1aa6320 ths
1440 d9bea114 aurel32
void helper_mtc0_datalo (target_ulong arg1)
1441 f1aa6320 ths
{
1442 d9bea114 aurel32
    env->CP0_DataLo = arg1; /* XXX */
1443 f1aa6320 ths
}
1444 f1aa6320 ths
1445 d9bea114 aurel32
void helper_mtc0_taghi (target_ulong arg1)
1446 f1aa6320 ths
{
1447 d9bea114 aurel32
    env->CP0_TagHi = arg1; /* XXX */
1448 f1aa6320 ths
}
1449 f1aa6320 ths
1450 d9bea114 aurel32
void helper_mtc0_datahi (target_ulong arg1)
1451 f1aa6320 ths
{
1452 d9bea114 aurel32
    env->CP0_DataHi = arg1; /* XXX */
1453 f1aa6320 ths
}
1454 f1aa6320 ths
1455 f1aa6320 ths
/* MIPS MT functions */
1456 c01fccd2 aurel32
target_ulong helper_mftgpr(uint32_t sel)
1457 f1aa6320 ths
{
1458 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1459 f1aa6320 ths
1460 b5dc7732 ths
    if (other_tc == env->current_tc)
1461 b5dc7732 ths
        return env->active_tc.gpr[sel];
1462 b5dc7732 ths
    else
1463 b5dc7732 ths
        return env->tcs[other_tc].gpr[sel];
1464 f1aa6320 ths
}
1465 f1aa6320 ths
1466 c01fccd2 aurel32
target_ulong helper_mftlo(uint32_t sel)
1467 f1aa6320 ths
{
1468 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1469 f1aa6320 ths
1470 b5dc7732 ths
    if (other_tc == env->current_tc)
1471 b5dc7732 ths
        return env->active_tc.LO[sel];
1472 b5dc7732 ths
    else
1473 b5dc7732 ths
        return env->tcs[other_tc].LO[sel];
1474 f1aa6320 ths
}
1475 f1aa6320 ths
1476 c01fccd2 aurel32
target_ulong helper_mfthi(uint32_t sel)
1477 f1aa6320 ths
{
1478 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1479 f1aa6320 ths
1480 b5dc7732 ths
    if (other_tc == env->current_tc)
1481 b5dc7732 ths
        return env->active_tc.HI[sel];
1482 b5dc7732 ths
    else
1483 b5dc7732 ths
        return env->tcs[other_tc].HI[sel];
1484 f1aa6320 ths
}
1485 f1aa6320 ths
1486 c01fccd2 aurel32
target_ulong helper_mftacx(uint32_t sel)
1487 f1aa6320 ths
{
1488 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1489 f1aa6320 ths
1490 b5dc7732 ths
    if (other_tc == env->current_tc)
1491 b5dc7732 ths
        return env->active_tc.ACX[sel];
1492 b5dc7732 ths
    else
1493 b5dc7732 ths
        return env->tcs[other_tc].ACX[sel];
1494 f1aa6320 ths
}
1495 f1aa6320 ths
1496 c01fccd2 aurel32
target_ulong helper_mftdsp(void)
1497 f1aa6320 ths
{
1498 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1499 f1aa6320 ths
1500 b5dc7732 ths
    if (other_tc == env->current_tc)
1501 b5dc7732 ths
        return env->active_tc.DSPControl;
1502 b5dc7732 ths
    else
1503 b5dc7732 ths
        return env->tcs[other_tc].DSPControl;
1504 f1aa6320 ths
}
1505 6af0bf9c bellard
1506 d9bea114 aurel32
void helper_mttgpr(target_ulong arg1, uint32_t sel)
1507 f1aa6320 ths
{
1508 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1509 f1aa6320 ths
1510 b5dc7732 ths
    if (other_tc == env->current_tc)
1511 d9bea114 aurel32
        env->active_tc.gpr[sel] = arg1;
1512 b5dc7732 ths
    else
1513 d9bea114 aurel32
        env->tcs[other_tc].gpr[sel] = arg1;
1514 f1aa6320 ths
}
1515 f1aa6320 ths
1516 d9bea114 aurel32
void helper_mttlo(target_ulong arg1, uint32_t sel)
1517 f1aa6320 ths
{
1518 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1519 f1aa6320 ths
1520 b5dc7732 ths
    if (other_tc == env->current_tc)
1521 d9bea114 aurel32
        env->active_tc.LO[sel] = arg1;
1522 b5dc7732 ths
    else
1523 d9bea114 aurel32
        env->tcs[other_tc].LO[sel] = arg1;
1524 f1aa6320 ths
}
1525 f1aa6320 ths
1526 d9bea114 aurel32
void helper_mtthi(target_ulong arg1, uint32_t sel)
1527 f1aa6320 ths
{
1528 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1529 f1aa6320 ths
1530 b5dc7732 ths
    if (other_tc == env->current_tc)
1531 d9bea114 aurel32
        env->active_tc.HI[sel] = arg1;
1532 b5dc7732 ths
    else
1533 d9bea114 aurel32
        env->tcs[other_tc].HI[sel] = arg1;
1534 f1aa6320 ths
}
1535 f1aa6320 ths
1536 d9bea114 aurel32
void helper_mttacx(target_ulong arg1, uint32_t sel)
1537 f1aa6320 ths
{
1538 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1539 f1aa6320 ths
1540 b5dc7732 ths
    if (other_tc == env->current_tc)
1541 d9bea114 aurel32
        env->active_tc.ACX[sel] = arg1;
1542 b5dc7732 ths
    else
1543 d9bea114 aurel32
        env->tcs[other_tc].ACX[sel] = arg1;
1544 f1aa6320 ths
}
1545 f1aa6320 ths
1546 d9bea114 aurel32
void helper_mttdsp(target_ulong arg1)
1547 f1aa6320 ths
{
1548 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1549 f1aa6320 ths
1550 b5dc7732 ths
    if (other_tc == env->current_tc)
1551 d9bea114 aurel32
        env->active_tc.DSPControl = arg1;
1552 b5dc7732 ths
    else
1553 d9bea114 aurel32
        env->tcs[other_tc].DSPControl = arg1;
1554 f1aa6320 ths
}
1555 f1aa6320 ths
1556 f1aa6320 ths
/* MIPS MT functions */
1557 9ed5726c Nathan Froyd
target_ulong helper_dmt(void)
1558 f1aa6320 ths
{
1559 f1aa6320 ths
    // TODO
1560 9ed5726c Nathan Froyd
     return 0;
1561 f1aa6320 ths
}
1562 f1aa6320 ths
1563 9ed5726c Nathan Froyd
target_ulong helper_emt(void)
1564 f1aa6320 ths
{
1565 f1aa6320 ths
    // TODO
1566 9ed5726c Nathan Froyd
    return 0;
1567 f1aa6320 ths
}
1568 f1aa6320 ths
1569 9ed5726c Nathan Froyd
target_ulong helper_dvpe(void)
1570 f1aa6320 ths
{
1571 f1aa6320 ths
    // TODO
1572 9ed5726c Nathan Froyd
    return 0;
1573 f1aa6320 ths
}
1574 f1aa6320 ths
1575 9ed5726c Nathan Froyd
target_ulong helper_evpe(void)
1576 f1aa6320 ths
{
1577 f1aa6320 ths
    // TODO
1578 9ed5726c Nathan Froyd
    return 0;
1579 f1aa6320 ths
}
1580 f9480ffc ths
#endif /* !CONFIG_USER_ONLY */
1581 f1aa6320 ths
1582 d9bea114 aurel32
void helper_fork(target_ulong arg1, target_ulong arg2)
1583 f1aa6320 ths
{
1584 d9bea114 aurel32
    // arg1 = rt, arg2 = rs
1585 d9bea114 aurel32
    arg1 = 0;
1586 f1aa6320 ths
    // TODO: store to TC register
1587 f1aa6320 ths
}
1588 f1aa6320 ths
1589 1c7242da Blue Swirl
target_ulong helper_yield(target_ulong arg)
1590 f1aa6320 ths
{
1591 1c7242da Blue Swirl
    target_long arg1 = arg;
1592 1c7242da Blue Swirl
1593 d9bea114 aurel32
    if (arg1 < 0) {
1594 f1aa6320 ths
        /* No scheduling policy implemented. */
1595 d9bea114 aurel32
        if (arg1 != -2) {
1596 f1aa6320 ths
            if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
1597 b5dc7732 ths
                env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) {
1598 f1aa6320 ths
                env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1599 f1aa6320 ths
                env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
1600 c01fccd2 aurel32
                helper_raise_exception(EXCP_THREAD);
1601 f1aa6320 ths
            }
1602 f1aa6320 ths
        }
1603 d9bea114 aurel32
    } else if (arg1 == 0) {
1604 6958549d aurel32
        if (0 /* TODO: TC underflow */) {
1605 f1aa6320 ths
            env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1606 c01fccd2 aurel32
            helper_raise_exception(EXCP_THREAD);
1607 f1aa6320 ths
        } else {
1608 f1aa6320 ths
            // TODO: Deallocate TC
1609 f1aa6320 ths
        }
1610 d9bea114 aurel32
    } else if (arg1 > 0) {
1611 f1aa6320 ths
        /* Yield qualifier inputs not implemented. */
1612 f1aa6320 ths
        env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1613 f1aa6320 ths
        env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
1614 c01fccd2 aurel32
        helper_raise_exception(EXCP_THREAD);
1615 f1aa6320 ths
    }
1616 be24bb4f ths
    return env->CP0_YQMask;
1617 f1aa6320 ths
}
1618 f1aa6320 ths
1619 f1aa6320 ths
#ifndef CONFIG_USER_ONLY
1620 6af0bf9c bellard
/* TLB management */
1621 83dae095 Paolo Bonzini
static void cpu_mips_tlb_flush (CPUState *env, int flush_global)
1622 814b9a47 ths
{
1623 814b9a47 ths
    /* Flush qemu's TLB and discard all shadowed entries.  */
1624 814b9a47 ths
    tlb_flush (env, flush_global);
1625 ead9360e ths
    env->tlb->tlb_in_use = env->tlb->nb_tlb;
1626 814b9a47 ths
}
1627 814b9a47 ths
1628 29929e34 ths
static void r4k_mips_tlb_flush_extra (CPUState *env, int first)
1629 814b9a47 ths
{
1630 814b9a47 ths
    /* Discard entries from env->tlb[first] onwards.  */
1631 ead9360e ths
    while (env->tlb->tlb_in_use > first) {
1632 ead9360e ths
        r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0);
1633 814b9a47 ths
    }
1634 814b9a47 ths
}
1635 814b9a47 ths
1636 29929e34 ths
static void r4k_fill_tlb (int idx)
1637 6af0bf9c bellard
{
1638 c227f099 Anthony Liguori
    r4k_tlb_t *tlb;
1639 6af0bf9c bellard
1640 6af0bf9c bellard
    /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
1641 ead9360e ths
    tlb = &env->tlb->mmu.r4k.tlb[idx];
1642 f2e9ebef ths
    tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
1643 d26bc211 ths
#if defined(TARGET_MIPS64)
1644 e034e2c3 ths
    tlb->VPN &= env->SEGMask;
1645 100ce988 ths
#endif
1646 98c1b82b pbrook
    tlb->ASID = env->CP0_EntryHi & 0xFF;
1647 3b1c8be4 ths
    tlb->PageMask = env->CP0_PageMask;
1648 6af0bf9c bellard
    tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
1649 98c1b82b pbrook
    tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
1650 98c1b82b pbrook
    tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
1651 98c1b82b pbrook
    tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
1652 6af0bf9c bellard
    tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
1653 98c1b82b pbrook
    tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
1654 98c1b82b pbrook
    tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
1655 98c1b82b pbrook
    tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
1656 6af0bf9c bellard
    tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
1657 6af0bf9c bellard
}
1658 6af0bf9c bellard
1659 c01fccd2 aurel32
void r4k_helper_tlbwi (void)
1660 6af0bf9c bellard
{
1661 bbc0d79c aurel32
    int idx;
1662 bbc0d79c aurel32
1663 bbc0d79c aurel32
    idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
1664 bbc0d79c aurel32
1665 814b9a47 ths
    /* Discard cached TLB entries.  We could avoid doing this if the
1666 814b9a47 ths
       tlbwi is just upgrading access permissions on the current entry;
1667 814b9a47 ths
       that might be a further win.  */
1668 ead9360e ths
    r4k_mips_tlb_flush_extra (env, env->tlb->nb_tlb);
1669 814b9a47 ths
1670 bbc0d79c aurel32
    r4k_invalidate_tlb(env, idx, 0);
1671 bbc0d79c aurel32
    r4k_fill_tlb(idx);
1672 6af0bf9c bellard
}
1673 6af0bf9c bellard
1674 c01fccd2 aurel32
void r4k_helper_tlbwr (void)
1675 6af0bf9c bellard
{
1676 6af0bf9c bellard
    int r = cpu_mips_get_random(env);
1677 6af0bf9c bellard
1678 29929e34 ths
    r4k_invalidate_tlb(env, r, 1);
1679 29929e34 ths
    r4k_fill_tlb(r);
1680 6af0bf9c bellard
}
1681 6af0bf9c bellard
1682 c01fccd2 aurel32
void r4k_helper_tlbp (void)
1683 6af0bf9c bellard
{
1684 c227f099 Anthony Liguori
    r4k_tlb_t *tlb;
1685 f2e9ebef ths
    target_ulong mask;
1686 6af0bf9c bellard
    target_ulong tag;
1687 f2e9ebef ths
    target_ulong VPN;
1688 6af0bf9c bellard
    uint8_t ASID;
1689 6af0bf9c bellard
    int i;
1690 6af0bf9c bellard
1691 3d9fb9fe bellard
    ASID = env->CP0_EntryHi & 0xFF;
1692 ead9360e ths
    for (i = 0; i < env->tlb->nb_tlb; i++) {
1693 ead9360e ths
        tlb = &env->tlb->mmu.r4k.tlb[i];
1694 f2e9ebef ths
        /* 1k pages are not supported. */
1695 f2e9ebef ths
        mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
1696 f2e9ebef ths
        tag = env->CP0_EntryHi & ~mask;
1697 f2e9ebef ths
        VPN = tlb->VPN & ~mask;
1698 6af0bf9c bellard
        /* Check ASID, virtual page number & size */
1699 f2e9ebef ths
        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1700 6af0bf9c bellard
            /* TLB match */
1701 9c2149c8 ths
            env->CP0_Index = i;
1702 6af0bf9c bellard
            break;
1703 6af0bf9c bellard
        }
1704 6af0bf9c bellard
    }
1705 ead9360e ths
    if (i == env->tlb->nb_tlb) {
1706 814b9a47 ths
        /* No match.  Discard any shadow entries, if any of them match.  */
1707 ead9360e ths
        for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) {
1708 6958549d aurel32
            tlb = &env->tlb->mmu.r4k.tlb[i];
1709 6958549d aurel32
            /* 1k pages are not supported. */
1710 6958549d aurel32
            mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
1711 6958549d aurel32
            tag = env->CP0_EntryHi & ~mask;
1712 6958549d aurel32
            VPN = tlb->VPN & ~mask;
1713 6958549d aurel32
            /* Check ASID, virtual page number & size */
1714 6958549d aurel32
            if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1715 29929e34 ths
                r4k_mips_tlb_flush_extra (env, i);
1716 6958549d aurel32
                break;
1717 6958549d aurel32
            }
1718 6958549d aurel32
        }
1719 814b9a47 ths
1720 9c2149c8 ths
        env->CP0_Index |= 0x80000000;
1721 6af0bf9c bellard
    }
1722 6af0bf9c bellard
}
1723 6af0bf9c bellard
1724 c01fccd2 aurel32
void r4k_helper_tlbr (void)
1725 6af0bf9c bellard
{
1726 c227f099 Anthony Liguori
    r4k_tlb_t *tlb;
1727 09c56b84 pbrook
    uint8_t ASID;
1728 bbc0d79c aurel32
    int idx;
1729 6af0bf9c bellard
1730 09c56b84 pbrook
    ASID = env->CP0_EntryHi & 0xFF;
1731 bbc0d79c aurel32
    idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
1732 bbc0d79c aurel32
    tlb = &env->tlb->mmu.r4k.tlb[idx];
1733 4ad40f36 bellard
1734 4ad40f36 bellard
    /* If this will change the current ASID, flush qemu's TLB.  */
1735 814b9a47 ths
    if (ASID != tlb->ASID)
1736 814b9a47 ths
        cpu_mips_tlb_flush (env, 1);
1737 814b9a47 ths
1738 ead9360e ths
    r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
1739 4ad40f36 bellard
1740 6af0bf9c bellard
    env->CP0_EntryHi = tlb->VPN | tlb->ASID;
1741 3b1c8be4 ths
    env->CP0_PageMask = tlb->PageMask;
1742 7495fd0f ths
    env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
1743 7495fd0f ths
                        (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
1744 7495fd0f ths
    env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
1745 7495fd0f ths
                        (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
1746 6af0bf9c bellard
}
1747 6af0bf9c bellard
1748 c01fccd2 aurel32
void helper_tlbwi(void)
1749 a7812ae4 pbrook
{
1750 c01fccd2 aurel32
    env->tlb->helper_tlbwi();
1751 a7812ae4 pbrook
}
1752 a7812ae4 pbrook
1753 c01fccd2 aurel32
void helper_tlbwr(void)
1754 a7812ae4 pbrook
{
1755 c01fccd2 aurel32
    env->tlb->helper_tlbwr();
1756 a7812ae4 pbrook
}
1757 a7812ae4 pbrook
1758 c01fccd2 aurel32
void helper_tlbp(void)
1759 a7812ae4 pbrook
{
1760 c01fccd2 aurel32
    env->tlb->helper_tlbp();
1761 a7812ae4 pbrook
}
1762 a7812ae4 pbrook
1763 c01fccd2 aurel32
void helper_tlbr(void)
1764 a7812ae4 pbrook
{
1765 c01fccd2 aurel32
    env->tlb->helper_tlbr();
1766 a7812ae4 pbrook
}
1767 a7812ae4 pbrook
1768 2b0233ab ths
/* Specials */
1769 c01fccd2 aurel32
target_ulong helper_di (void)
1770 2b0233ab ths
{
1771 2796188e ths
    target_ulong t0 = env->CP0_Status;
1772 2796188e ths
1773 be24bb4f ths
    env->CP0_Status = t0 & ~(1 << CP0St_IE);
1774 be24bb4f ths
    return t0;
1775 2b0233ab ths
}
1776 2b0233ab ths
1777 c01fccd2 aurel32
target_ulong helper_ei (void)
1778 2b0233ab ths
{
1779 2796188e ths
    target_ulong t0 = env->CP0_Status;
1780 2796188e ths
1781 be24bb4f ths
    env->CP0_Status = t0 | (1 << CP0St_IE);
1782 be24bb4f ths
    return t0;
1783 2b0233ab ths
}
1784 2b0233ab ths
1785 cd5158ea aurel32
static void debug_pre_eret (void)
1786 6af0bf9c bellard
{
1787 8fec2b8c aliguori
    if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
1788 93fcfe39 aliguori
        qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
1789 93fcfe39 aliguori
                env->active_tc.PC, env->CP0_EPC);
1790 93fcfe39 aliguori
        if (env->CP0_Status & (1 << CP0St_ERL))
1791 93fcfe39 aliguori
            qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
1792 93fcfe39 aliguori
        if (env->hflags & MIPS_HFLAG_DM)
1793 93fcfe39 aliguori
            qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
1794 93fcfe39 aliguori
        qemu_log("\n");
1795 93fcfe39 aliguori
    }
1796 f41c52f1 ths
}
1797 f41c52f1 ths
1798 cd5158ea aurel32
static void debug_post_eret (void)
1799 f41c52f1 ths
{
1800 8fec2b8c aliguori
    if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
1801 93fcfe39 aliguori
        qemu_log("  =>  PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
1802 93fcfe39 aliguori
                env->active_tc.PC, env->CP0_EPC);
1803 93fcfe39 aliguori
        if (env->CP0_Status & (1 << CP0St_ERL))
1804 93fcfe39 aliguori
            qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
1805 93fcfe39 aliguori
        if (env->hflags & MIPS_HFLAG_DM)
1806 93fcfe39 aliguori
            qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
1807 93fcfe39 aliguori
        switch (env->hflags & MIPS_HFLAG_KSU) {
1808 93fcfe39 aliguori
        case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
1809 93fcfe39 aliguori
        case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
1810 93fcfe39 aliguori
        case MIPS_HFLAG_KM: qemu_log("\n"); break;
1811 93fcfe39 aliguori
        default: cpu_abort(env, "Invalid MMU mode!\n"); break;
1812 93fcfe39 aliguori
        }
1813 623a930e ths
    }
1814 6af0bf9c bellard
}
1815 6af0bf9c bellard
1816 32188a03 Nathan Froyd
static void set_pc (target_ulong error_pc)
1817 32188a03 Nathan Froyd
{
1818 32188a03 Nathan Froyd
    env->active_tc.PC = error_pc & ~(target_ulong)1;
1819 32188a03 Nathan Froyd
    if (error_pc & 1) {
1820 32188a03 Nathan Froyd
        env->hflags |= MIPS_HFLAG_M16;
1821 32188a03 Nathan Froyd
    } else {
1822 32188a03 Nathan Froyd
        env->hflags &= ~(MIPS_HFLAG_M16);
1823 32188a03 Nathan Froyd
    }
1824 32188a03 Nathan Froyd
}
1825 32188a03 Nathan Froyd
1826 c01fccd2 aurel32
void helper_eret (void)
1827 2b0233ab ths
{
1828 93fcfe39 aliguori
    debug_pre_eret();
1829 2b0233ab ths
    if (env->CP0_Status & (1 << CP0St_ERL)) {
1830 32188a03 Nathan Froyd
        set_pc(env->CP0_ErrorEPC);
1831 2b0233ab ths
        env->CP0_Status &= ~(1 << CP0St_ERL);
1832 2b0233ab ths
    } else {
1833 32188a03 Nathan Froyd
        set_pc(env->CP0_EPC);
1834 2b0233ab ths
        env->CP0_Status &= ~(1 << CP0St_EXL);
1835 2b0233ab ths
    }
1836 2b0233ab ths
    compute_hflags(env);
1837 93fcfe39 aliguori
    debug_post_eret();
1838 5499b6ff Aurelien Jarno
    env->lladdr = 1;
1839 2b0233ab ths
}
1840 2b0233ab ths
1841 c01fccd2 aurel32
void helper_deret (void)
1842 2b0233ab ths
{
1843 93fcfe39 aliguori
    debug_pre_eret();
1844 32188a03 Nathan Froyd
    set_pc(env->CP0_DEPC);
1845 32188a03 Nathan Froyd
1846 2b0233ab ths
    env->hflags &= MIPS_HFLAG_DM;
1847 2b0233ab ths
    compute_hflags(env);
1848 93fcfe39 aliguori
    debug_post_eret();
1849 5499b6ff Aurelien Jarno
    env->lladdr = 1;
1850 2b0233ab ths
}
1851 0eaef5aa ths
#endif /* !CONFIG_USER_ONLY */
1852 2b0233ab ths
1853 c01fccd2 aurel32
target_ulong helper_rdhwr_cpunum(void)
1854 2b0233ab ths
{
1855 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1856 2b0233ab ths
        (env->CP0_HWREna & (1 << 0)))
1857 2796188e ths
        return env->CP0_EBase & 0x3ff;
1858 2b0233ab ths
    else
1859 c01fccd2 aurel32
        helper_raise_exception(EXCP_RI);
1860 be24bb4f ths
1861 2796188e ths
    return 0;
1862 2b0233ab ths
}
1863 2b0233ab ths
1864 c01fccd2 aurel32
target_ulong helper_rdhwr_synci_step(void)
1865 2b0233ab ths
{
1866 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1867 2b0233ab ths
        (env->CP0_HWREna & (1 << 1)))
1868 2796188e ths
        return env->SYNCI_Step;
1869 2b0233ab ths
    else
1870 c01fccd2 aurel32
        helper_raise_exception(EXCP_RI);
1871 be24bb4f ths
1872 2796188e ths
    return 0;
1873 2b0233ab ths
}
1874 2b0233ab ths
1875 c01fccd2 aurel32
target_ulong helper_rdhwr_cc(void)
1876 2b0233ab ths
{
1877 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1878 2b0233ab ths
        (env->CP0_HWREna & (1 << 2)))
1879 2796188e ths
        return env->CP0_Count;
1880 2b0233ab ths
    else
1881 c01fccd2 aurel32
        helper_raise_exception(EXCP_RI);
1882 be24bb4f ths
1883 2796188e ths
    return 0;
1884 2b0233ab ths
}
1885 2b0233ab ths
1886 c01fccd2 aurel32
target_ulong helper_rdhwr_ccres(void)
1887 2b0233ab ths
{
1888 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1889 2b0233ab ths
        (env->CP0_HWREna & (1 << 3)))
1890 2796188e ths
        return env->CCRes;
1891 2b0233ab ths
    else
1892 c01fccd2 aurel32
        helper_raise_exception(EXCP_RI);
1893 be24bb4f ths
1894 2796188e ths
    return 0;
1895 2b0233ab ths
}
1896 2b0233ab ths
1897 c01fccd2 aurel32
void helper_pmon (int function)
1898 6af0bf9c bellard
{
1899 6af0bf9c bellard
    function /= 2;
1900 6af0bf9c bellard
    switch (function) {
1901 6af0bf9c bellard
    case 2: /* TODO: char inbyte(int waitflag); */
1902 b5dc7732 ths
        if (env->active_tc.gpr[4] == 0)
1903 b5dc7732 ths
            env->active_tc.gpr[2] = -1;
1904 6af0bf9c bellard
        /* Fall through */
1905 6af0bf9c bellard
    case 11: /* TODO: char inbyte (void); */
1906 b5dc7732 ths
        env->active_tc.gpr[2] = -1;
1907 6af0bf9c bellard
        break;
1908 6af0bf9c bellard
    case 3:
1909 6af0bf9c bellard
    case 12:
1910 b5dc7732 ths
        printf("%c", (char)(env->active_tc.gpr[4] & 0xFF));
1911 6af0bf9c bellard
        break;
1912 6af0bf9c bellard
    case 17:
1913 6af0bf9c bellard
        break;
1914 6af0bf9c bellard
    case 158:
1915 6af0bf9c bellard
        {
1916 b5dc7732 ths
            unsigned char *fmt = (void *)(unsigned long)env->active_tc.gpr[4];
1917 6af0bf9c bellard
            printf("%s", fmt);
1918 6af0bf9c bellard
        }
1919 6af0bf9c bellard
        break;
1920 6af0bf9c bellard
    }
1921 6af0bf9c bellard
}
1922 e37e863f bellard
1923 c01fccd2 aurel32
void helper_wait (void)
1924 08ba7963 ths
{
1925 08ba7963 ths
    env->halted = 1;
1926 c01fccd2 aurel32
    helper_raise_exception(EXCP_HLT);
1927 08ba7963 ths
}
1928 08ba7963 ths
1929 5fafdf24 ths
#if !defined(CONFIG_USER_ONLY)
1930 e37e863f bellard
1931 4ad40f36 bellard
static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
1932 4ad40f36 bellard
1933 e37e863f bellard
#define MMUSUFFIX _mmu
1934 4ad40f36 bellard
#define ALIGNED_ONLY
1935 e37e863f bellard
1936 e37e863f bellard
#define SHIFT 0
1937 e37e863f bellard
#include "softmmu_template.h"
1938 e37e863f bellard
1939 e37e863f bellard
#define SHIFT 1
1940 e37e863f bellard
#include "softmmu_template.h"
1941 e37e863f bellard
1942 e37e863f bellard
#define SHIFT 2
1943 e37e863f bellard
#include "softmmu_template.h"
1944 e37e863f bellard
1945 e37e863f bellard
#define SHIFT 3
1946 e37e863f bellard
#include "softmmu_template.h"
1947 e37e863f bellard
1948 4ad40f36 bellard
static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
1949 4ad40f36 bellard
{
1950 4ad40f36 bellard
    env->CP0_BadVAddr = addr;
1951 4ad40f36 bellard
    do_restore_state (retaddr);
1952 c01fccd2 aurel32
    helper_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
1953 4ad40f36 bellard
}
1954 4ad40f36 bellard
1955 6ebbf390 j_mayer
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1956 e37e863f bellard
{
1957 e37e863f bellard
    TranslationBlock *tb;
1958 e37e863f bellard
    CPUState *saved_env;
1959 e37e863f bellard
    unsigned long pc;
1960 e37e863f bellard
    int ret;
1961 e37e863f bellard
1962 e37e863f bellard
    /* XXX: hack to restore env in all cases, even if not called from
1963 e37e863f bellard
       generated code */
1964 e37e863f bellard
    saved_env = env;
1965 e37e863f bellard
    env = cpu_single_env;
1966 6ebbf390 j_mayer
    ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1967 e37e863f bellard
    if (ret) {
1968 e37e863f bellard
        if (retaddr) {
1969 e37e863f bellard
            /* now we have a real cpu fault */
1970 e37e863f bellard
            pc = (unsigned long)retaddr;
1971 e37e863f bellard
            tb = tb_find_pc(pc);
1972 e37e863f bellard
            if (tb) {
1973 e37e863f bellard
                /* the PC is inside the translated code. It means that we have
1974 e37e863f bellard
                   a virtual CPU fault */
1975 e37e863f bellard
                cpu_restore_state(tb, env, pc, NULL);
1976 e37e863f bellard
            }
1977 e37e863f bellard
        }
1978 c01fccd2 aurel32
        helper_raise_exception_err(env->exception_index, env->error_code);
1979 e37e863f bellard
    }
1980 e37e863f bellard
    env = saved_env;
1981 e37e863f bellard
}
1982 e37e863f bellard
1983 c227f099 Anthony Liguori
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1984 e18231a3 blueswir1
                          int unused, int size)
1985 647de6ca ths
{
1986 647de6ca ths
    if (is_exec)
1987 c01fccd2 aurel32
        helper_raise_exception(EXCP_IBE);
1988 647de6ca ths
    else
1989 c01fccd2 aurel32
        helper_raise_exception(EXCP_DBE);
1990 647de6ca ths
}
1991 f1aa6320 ths
#endif /* !CONFIG_USER_ONLY */
1992 fd4a04eb ths
1993 fd4a04eb ths
/* Complex FPU operations which may need stack space. */
1994 fd4a04eb ths
1995 f090c9d4 pbrook
#define FLOAT_ONE32 make_float32(0x3f8 << 20)
1996 f090c9d4 pbrook
#define FLOAT_ONE64 make_float64(0x3ffULL << 52)
1997 f090c9d4 pbrook
#define FLOAT_TWO32 make_float32(1 << 30)
1998 f090c9d4 pbrook
#define FLOAT_TWO64 make_float64(1ULL << 62)
1999 54454097 ths
#define FLOAT_QNAN32 0x7fbfffff
2000 54454097 ths
#define FLOAT_QNAN64 0x7ff7ffffffffffffULL
2001 54454097 ths
#define FLOAT_SNAN32 0x7fffffff
2002 54454097 ths
#define FLOAT_SNAN64 0x7fffffffffffffffULL
2003 8dfdb87c ths
2004 fd4a04eb ths
/* convert MIPS rounding mode in FCR31 to IEEE library */
2005 6f4fc367 Blue Swirl
static unsigned int ieee_rm[] = {
2006 fd4a04eb ths
    float_round_nearest_even,
2007 fd4a04eb ths
    float_round_to_zero,
2008 fd4a04eb ths
    float_round_up,
2009 fd4a04eb ths
    float_round_down
2010 fd4a04eb ths
};
2011 fd4a04eb ths
2012 fd4a04eb ths
#define RESTORE_ROUNDING_MODE \
2013 f01be154 ths
    set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], &env->active_fpu.fp_status)
2014 fd4a04eb ths
2015 41e0c701 aurel32
#define RESTORE_FLUSH_MODE \
2016 41e0c701 aurel32
    set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0, &env->active_fpu.fp_status);
2017 41e0c701 aurel32
2018 c01fccd2 aurel32
target_ulong helper_cfc1 (uint32_t reg)
2019 fd4a04eb ths
{
2020 d9bea114 aurel32
    target_ulong arg1;
2021 6c5c1e20 ths
2022 ead9360e ths
    switch (reg) {
2023 ead9360e ths
    case 0:
2024 d9bea114 aurel32
        arg1 = (int32_t)env->active_fpu.fcr0;
2025 ead9360e ths
        break;
2026 ead9360e ths
    case 25:
2027 d9bea114 aurel32
        arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1);
2028 ead9360e ths
        break;
2029 ead9360e ths
    case 26:
2030 d9bea114 aurel32
        arg1 = env->active_fpu.fcr31 & 0x0003f07c;
2031 ead9360e ths
        break;
2032 ead9360e ths
    case 28:
2033 d9bea114 aurel32
        arg1 = (env->active_fpu.fcr31 & 0x00000f83) | ((env->active_fpu.fcr31 >> 22) & 0x4);
2034 ead9360e ths
        break;
2035 ead9360e ths
    default:
2036 d9bea114 aurel32
        arg1 = (int32_t)env->active_fpu.fcr31;
2037 ead9360e ths
        break;
2038 ead9360e ths
    }
2039 be24bb4f ths
2040 d9bea114 aurel32
    return arg1;
2041 ead9360e ths
}
2042 ead9360e ths
2043 d9bea114 aurel32
void helper_ctc1 (target_ulong arg1, uint32_t reg)
2044 ead9360e ths
{
2045 ead9360e ths
    switch(reg) {
2046 fd4a04eb ths
    case 25:
2047 d9bea114 aurel32
        if (arg1 & 0xffffff00)
2048 fd4a04eb ths
            return;
2049 d9bea114 aurel32
        env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | ((arg1 & 0xfe) << 24) |
2050 d9bea114 aurel32
                     ((arg1 & 0x1) << 23);
2051 fd4a04eb ths
        break;
2052 fd4a04eb ths
    case 26:
2053 d9bea114 aurel32
        if (arg1 & 0x007c0000)
2054 fd4a04eb ths
            return;
2055 d9bea114 aurel32
        env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfffc0f83) | (arg1 & 0x0003f07c);
2056 fd4a04eb ths
        break;
2057 fd4a04eb ths
    case 28:
2058 d9bea114 aurel32
        if (arg1 & 0x007c0000)
2059 fd4a04eb ths
            return;
2060 d9bea114 aurel32
        env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfefff07c) | (arg1 & 0x00000f83) |
2061 d9bea114 aurel32
                     ((arg1 & 0x4) << 22);
2062 fd4a04eb ths
        break;
2063 fd4a04eb ths
    case 31:
2064 d9bea114 aurel32
        if (arg1 & 0x007c0000)
2065 fd4a04eb ths
            return;
2066 d9bea114 aurel32
        env->active_fpu.fcr31 = arg1;
2067 fd4a04eb ths
        break;
2068 fd4a04eb ths
    default:
2069 fd4a04eb ths
        return;
2070 fd4a04eb ths
    }
2071 fd4a04eb ths
    /* set rounding mode */
2072 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2073 41e0c701 aurel32
    /* set flush-to-zero mode */
2074 41e0c701 aurel32
    RESTORE_FLUSH_MODE;
2075 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2076 f01be154 ths
    if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31))
2077 c01fccd2 aurel32
        helper_raise_exception(EXCP_FPE);
2078 fd4a04eb ths
}
2079 fd4a04eb ths
2080 c904ef0e ths
static inline char ieee_ex_to_mips(char xcpt)
2081 fd4a04eb ths
{
2082 fd4a04eb ths
    return (xcpt & float_flag_inexact) >> 5 |
2083 fd4a04eb ths
           (xcpt & float_flag_underflow) >> 3 |
2084 fd4a04eb ths
           (xcpt & float_flag_overflow) >> 1 |
2085 fd4a04eb ths
           (xcpt & float_flag_divbyzero) << 1 |
2086 fd4a04eb ths
           (xcpt & float_flag_invalid) << 4;
2087 fd4a04eb ths
}
2088 fd4a04eb ths
2089 c904ef0e ths
static inline char mips_ex_to_ieee(char xcpt)
2090 fd4a04eb ths
{
2091 fd4a04eb ths
    return (xcpt & FP_INEXACT) << 5 |
2092 fd4a04eb ths
           (xcpt & FP_UNDERFLOW) << 3 |
2093 fd4a04eb ths
           (xcpt & FP_OVERFLOW) << 1 |
2094 fd4a04eb ths
           (xcpt & FP_DIV0) >> 1 |
2095 fd4a04eb ths
           (xcpt & FP_INVALID) >> 4;
2096 fd4a04eb ths
}
2097 fd4a04eb ths
2098 c904ef0e ths
static inline void update_fcr31(void)
2099 fd4a04eb ths
{
2100 f01be154 ths
    int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->active_fpu.fp_status));
2101 fd4a04eb ths
2102 f01be154 ths
    SET_FP_CAUSE(env->active_fpu.fcr31, tmp);
2103 f01be154 ths
    if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp)
2104 c01fccd2 aurel32
        helper_raise_exception(EXCP_FPE);
2105 fd4a04eb ths
    else
2106 f01be154 ths
        UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp);
2107 fd4a04eb ths
}
2108 fd4a04eb ths
2109 a16336e4 ths
/* Float support.
2110 a16336e4 ths
   Single precition routines have a "s" suffix, double precision a
2111 a16336e4 ths
   "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps",
2112 a16336e4 ths
   paired single lower "pl", paired single upper "pu".  */
2113 a16336e4 ths
2114 a16336e4 ths
/* unary operations, modifying fp status  */
2115 c01fccd2 aurel32
uint64_t helper_float_sqrt_d(uint64_t fdt0)
2116 b6d96bed ths
{
2117 f01be154 ths
    return float64_sqrt(fdt0, &env->active_fpu.fp_status);
2118 b6d96bed ths
}
2119 b6d96bed ths
2120 c01fccd2 aurel32
uint32_t helper_float_sqrt_s(uint32_t fst0)
2121 b6d96bed ths
{
2122 f01be154 ths
    return float32_sqrt(fst0, &env->active_fpu.fp_status);
2123 b6d96bed ths
}
2124 a16336e4 ths
2125 c01fccd2 aurel32
uint64_t helper_float_cvtd_s(uint32_t fst0)
2126 fd4a04eb ths
{
2127 b6d96bed ths
    uint64_t fdt2;
2128 b6d96bed ths
2129 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2130 f01be154 ths
    fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status);
2131 fd4a04eb ths
    update_fcr31();
2132 b6d96bed ths
    return fdt2;
2133 fd4a04eb ths
}
2134 b6d96bed ths
2135 c01fccd2 aurel32
uint64_t helper_float_cvtd_w(uint32_t wt0)
2136 fd4a04eb ths
{
2137 b6d96bed ths
    uint64_t fdt2;
2138 b6d96bed ths
2139 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2140 f01be154 ths
    fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status);
2141 fd4a04eb ths
    update_fcr31();
2142 b6d96bed ths
    return fdt2;
2143 fd4a04eb ths
}
2144 b6d96bed ths
2145 c01fccd2 aurel32
uint64_t helper_float_cvtd_l(uint64_t dt0)
2146 fd4a04eb ths
{
2147 b6d96bed ths
    uint64_t fdt2;
2148 b6d96bed ths
2149 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2150 f01be154 ths
    fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status);
2151 fd4a04eb ths
    update_fcr31();
2152 b6d96bed ths
    return fdt2;
2153 fd4a04eb ths
}
2154 b6d96bed ths
2155 c01fccd2 aurel32
uint64_t helper_float_cvtl_d(uint64_t fdt0)
2156 fd4a04eb ths
{
2157 b6d96bed ths
    uint64_t dt2;
2158 b6d96bed ths
2159 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2160 f01be154 ths
    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
2161 fd4a04eb ths
    update_fcr31();
2162 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2163 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2164 b6d96bed ths
    return dt2;
2165 fd4a04eb ths
}
2166 b6d96bed ths
2167 c01fccd2 aurel32
uint64_t helper_float_cvtl_s(uint32_t fst0)
2168 fd4a04eb ths
{
2169 b6d96bed ths
    uint64_t dt2;
2170 b6d96bed ths
2171 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2172 f01be154 ths
    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
2173 fd4a04eb ths
    update_fcr31();
2174 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2175 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2176 b6d96bed ths
    return dt2;
2177 fd4a04eb ths
}
2178 fd4a04eb ths
2179 c01fccd2 aurel32
uint64_t helper_float_cvtps_pw(uint64_t dt0)
2180 fd4a04eb ths
{
2181 b6d96bed ths
    uint32_t fst2;
2182 b6d96bed ths
    uint32_t fsth2;
2183 b6d96bed ths
2184 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2185 f01be154 ths
    fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2186 f01be154 ths
    fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status);
2187 fd4a04eb ths
    update_fcr31();
2188 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2189 fd4a04eb ths
}
2190 b6d96bed ths
2191 c01fccd2 aurel32
uint64_t helper_float_cvtpw_ps(uint64_t fdt0)
2192 fd4a04eb ths
{
2193 b6d96bed ths
    uint32_t wt2;
2194 b6d96bed ths
    uint32_t wth2;
2195 b6d96bed ths
2196 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2197 f01be154 ths
    wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2198 f01be154 ths
    wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status);
2199 fd4a04eb ths
    update_fcr31();
2200 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) {
2201 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2202 b6d96bed ths
        wth2 = FLOAT_SNAN32;
2203 b6d96bed ths
    }
2204 b6d96bed ths
    return ((uint64_t)wth2 << 32) | wt2;
2205 fd4a04eb ths
}
2206 b6d96bed ths
2207 c01fccd2 aurel32
uint32_t helper_float_cvts_d(uint64_t fdt0)
2208 fd4a04eb ths
{
2209 b6d96bed ths
    uint32_t fst2;
2210 b6d96bed ths
2211 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2212 f01be154 ths
    fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status);
2213 fd4a04eb ths
    update_fcr31();
2214 b6d96bed ths
    return fst2;
2215 fd4a04eb ths
}
2216 b6d96bed ths
2217 c01fccd2 aurel32
uint32_t helper_float_cvts_w(uint32_t wt0)
2218 fd4a04eb ths
{
2219 b6d96bed ths
    uint32_t fst2;
2220 b6d96bed ths
2221 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2222 f01be154 ths
    fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status);
2223 fd4a04eb ths
    update_fcr31();
2224 b6d96bed ths
    return fst2;
2225 fd4a04eb ths
}
2226 b6d96bed ths
2227 c01fccd2 aurel32
uint32_t helper_float_cvts_l(uint64_t dt0)
2228 fd4a04eb ths
{
2229 b6d96bed ths
    uint32_t fst2;
2230 b6d96bed ths
2231 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2232 f01be154 ths
    fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status);
2233 fd4a04eb ths
    update_fcr31();
2234 b6d96bed ths
    return fst2;
2235 fd4a04eb ths
}
2236 b6d96bed ths
2237 c01fccd2 aurel32
uint32_t helper_float_cvts_pl(uint32_t wt0)
2238 fd4a04eb ths
{
2239 b6d96bed ths
    uint32_t wt2;
2240 b6d96bed ths
2241 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2242 b6d96bed ths
    wt2 = wt0;
2243 fd4a04eb ths
    update_fcr31();
2244 b6d96bed ths
    return wt2;
2245 fd4a04eb ths
}
2246 b6d96bed ths
2247 c01fccd2 aurel32
uint32_t helper_float_cvts_pu(uint32_t wth0)
2248 fd4a04eb ths
{
2249 b6d96bed ths
    uint32_t wt2;
2250 b6d96bed ths
2251 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2252 b6d96bed ths
    wt2 = wth0;
2253 fd4a04eb ths
    update_fcr31();
2254 b6d96bed ths
    return wt2;
2255 fd4a04eb ths
}
2256 b6d96bed ths
2257 c01fccd2 aurel32
uint32_t helper_float_cvtw_s(uint32_t fst0)
2258 fd4a04eb ths
{
2259 b6d96bed ths
    uint32_t wt2;
2260 b6d96bed ths
2261 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2262 f01be154 ths
    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
2263 fd4a04eb ths
    update_fcr31();
2264 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2265 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2266 b6d96bed ths
    return wt2;
2267 fd4a04eb ths
}
2268 b6d96bed ths
2269 c01fccd2 aurel32
uint32_t helper_float_cvtw_d(uint64_t fdt0)
2270 fd4a04eb ths
{
2271 b6d96bed ths
    uint32_t wt2;
2272 b6d96bed ths
2273 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2274 f01be154 ths
    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
2275 fd4a04eb ths
    update_fcr31();
2276 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2277 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2278 b6d96bed ths
    return wt2;
2279 fd4a04eb ths
}
2280 fd4a04eb ths
2281 c01fccd2 aurel32
uint64_t helper_float_roundl_d(uint64_t fdt0)
2282 fd4a04eb ths
{
2283 b6d96bed ths
    uint64_t dt2;
2284 b6d96bed ths
2285 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2286 f01be154 ths
    set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2287 f01be154 ths
    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
2288 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2289 fd4a04eb ths
    update_fcr31();
2290 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2291 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2292 b6d96bed ths
    return dt2;
2293 fd4a04eb ths
}
2294 b6d96bed ths
2295 c01fccd2 aurel32
uint64_t helper_float_roundl_s(uint32_t fst0)
2296 fd4a04eb ths
{
2297 b6d96bed ths
    uint64_t dt2;
2298 b6d96bed ths
2299 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2300 f01be154 ths
    set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2301 f01be154 ths
    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
2302 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2303 fd4a04eb ths
    update_fcr31();
2304 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2305 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2306 b6d96bed ths
    return dt2;
2307 fd4a04eb ths
}
2308 b6d96bed ths
2309 c01fccd2 aurel32
uint32_t helper_float_roundw_d(uint64_t fdt0)
2310 fd4a04eb ths
{
2311 b6d96bed ths
    uint32_t wt2;
2312 b6d96bed ths
2313 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2314 f01be154 ths
    set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2315 f01be154 ths
    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
2316 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2317 fd4a04eb ths
    update_fcr31();
2318 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2319 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2320 b6d96bed ths
    return wt2;
2321 fd4a04eb ths
}
2322 b6d96bed ths
2323 c01fccd2 aurel32
uint32_t helper_float_roundw_s(uint32_t fst0)
2324 fd4a04eb ths
{
2325 b6d96bed ths
    uint32_t wt2;
2326 b6d96bed ths
2327 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2328 f01be154 ths
    set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
2329 f01be154 ths
    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
2330 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2331 fd4a04eb ths
    update_fcr31();
2332 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2333 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2334 b6d96bed ths
    return wt2;
2335 fd4a04eb ths
}
2336 fd4a04eb ths
2337 c01fccd2 aurel32
uint64_t helper_float_truncl_d(uint64_t fdt0)
2338 fd4a04eb ths
{
2339 b6d96bed ths
    uint64_t dt2;
2340 b6d96bed ths
2341 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2342 f01be154 ths
    dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
2343 fd4a04eb ths
    update_fcr31();
2344 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2345 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2346 b6d96bed ths
    return dt2;
2347 fd4a04eb ths
}
2348 b6d96bed ths
2349 c01fccd2 aurel32
uint64_t helper_float_truncl_s(uint32_t fst0)
2350 fd4a04eb ths
{
2351 b6d96bed ths
    uint64_t dt2;
2352 b6d96bed ths
2353 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2354 f01be154 ths
    dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
2355 fd4a04eb ths
    update_fcr31();
2356 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2357 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2358 b6d96bed ths
    return dt2;
2359 fd4a04eb ths
}
2360 b6d96bed ths
2361 c01fccd2 aurel32
uint32_t helper_float_truncw_d(uint64_t fdt0)
2362 fd4a04eb ths
{
2363 b6d96bed ths
    uint32_t wt2;
2364 b6d96bed ths
2365 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2366 f01be154 ths
    wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
2367 fd4a04eb ths
    update_fcr31();
2368 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2369 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2370 b6d96bed ths
    return wt2;
2371 fd4a04eb ths
}
2372 b6d96bed ths
2373 c01fccd2 aurel32
uint32_t helper_float_truncw_s(uint32_t fst0)
2374 fd4a04eb ths
{
2375 b6d96bed ths
    uint32_t wt2;
2376 b6d96bed ths
2377 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2378 f01be154 ths
    wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
2379 fd4a04eb ths
    update_fcr31();
2380 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2381 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2382 b6d96bed ths
    return wt2;
2383 fd4a04eb ths
}
2384 fd4a04eb ths
2385 c01fccd2 aurel32
uint64_t helper_float_ceill_d(uint64_t fdt0)
2386 fd4a04eb ths
{
2387 b6d96bed ths
    uint64_t dt2;
2388 b6d96bed ths
2389 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2390 f01be154 ths
    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2391 f01be154 ths
    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
2392 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2393 fd4a04eb ths
    update_fcr31();
2394 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2395 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2396 b6d96bed ths
    return dt2;
2397 fd4a04eb ths
}
2398 b6d96bed ths
2399 c01fccd2 aurel32
uint64_t helper_float_ceill_s(uint32_t fst0)
2400 fd4a04eb ths
{
2401 b6d96bed ths
    uint64_t dt2;
2402 b6d96bed ths
2403 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2404 f01be154 ths
    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2405 f01be154 ths
    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
2406 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2407 fd4a04eb ths
    update_fcr31();
2408 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2409 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2410 b6d96bed ths
    return dt2;
2411 fd4a04eb ths
}
2412 b6d96bed ths
2413 c01fccd2 aurel32
uint32_t helper_float_ceilw_d(uint64_t fdt0)
2414 fd4a04eb ths
{
2415 b6d96bed ths
    uint32_t wt2;
2416 b6d96bed ths
2417 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2418 f01be154 ths
    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2419 f01be154 ths
    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
2420 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2421 fd4a04eb ths
    update_fcr31();
2422 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2423 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2424 b6d96bed ths
    return wt2;
2425 fd4a04eb ths
}
2426 b6d96bed ths
2427 c01fccd2 aurel32
uint32_t helper_float_ceilw_s(uint32_t fst0)
2428 fd4a04eb ths
{
2429 b6d96bed ths
    uint32_t wt2;
2430 b6d96bed ths
2431 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2432 f01be154 ths
    set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
2433 f01be154 ths
    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
2434 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2435 fd4a04eb ths
    update_fcr31();
2436 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2437 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2438 b6d96bed ths
    return wt2;
2439 fd4a04eb ths
}
2440 fd4a04eb ths
2441 c01fccd2 aurel32
uint64_t helper_float_floorl_d(uint64_t fdt0)
2442 fd4a04eb ths
{
2443 b6d96bed ths
    uint64_t dt2;
2444 b6d96bed ths
2445 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2446 f01be154 ths
    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2447 f01be154 ths
    dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
2448 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2449 fd4a04eb ths
    update_fcr31();
2450 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2451 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2452 b6d96bed ths
    return dt2;
2453 fd4a04eb ths
}
2454 b6d96bed ths
2455 c01fccd2 aurel32
uint64_t helper_float_floorl_s(uint32_t fst0)
2456 fd4a04eb ths
{
2457 b6d96bed ths
    uint64_t dt2;
2458 b6d96bed ths
2459 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2460 f01be154 ths
    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2461 f01be154 ths
    dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
2462 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2463 fd4a04eb ths
    update_fcr31();
2464 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2465 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2466 b6d96bed ths
    return dt2;
2467 fd4a04eb ths
}
2468 b6d96bed ths
2469 c01fccd2 aurel32
uint32_t helper_float_floorw_d(uint64_t fdt0)
2470 fd4a04eb ths
{
2471 b6d96bed ths
    uint32_t wt2;
2472 b6d96bed ths
2473 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2474 f01be154 ths
    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2475 f01be154 ths
    wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
2476 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2477 fd4a04eb ths
    update_fcr31();
2478 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2479 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2480 b6d96bed ths
    return wt2;
2481 fd4a04eb ths
}
2482 b6d96bed ths
2483 c01fccd2 aurel32
uint32_t helper_float_floorw_s(uint32_t fst0)
2484 fd4a04eb ths
{
2485 b6d96bed ths
    uint32_t wt2;
2486 b6d96bed ths
2487 efd41037 Chris Dearman
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2488 f01be154 ths
    set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
2489 f01be154 ths
    wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
2490 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2491 fd4a04eb ths
    update_fcr31();
2492 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
2493 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2494 b6d96bed ths
    return wt2;
2495 fd4a04eb ths
}
2496 fd4a04eb ths
2497 a16336e4 ths
/* unary operations, not modifying fp status  */
2498 b6d96bed ths
#define FLOAT_UNOP(name)                                       \
2499 c01fccd2 aurel32
uint64_t helper_float_ ## name ## _d(uint64_t fdt0)                \
2500 b6d96bed ths
{                                                              \
2501 b6d96bed ths
    return float64_ ## name(fdt0);                             \
2502 b6d96bed ths
}                                                              \
2503 c01fccd2 aurel32
uint32_t helper_float_ ## name ## _s(uint32_t fst0)                \
2504 b6d96bed ths
{                                                              \
2505 b6d96bed ths
    return float32_ ## name(fst0);                             \
2506 b6d96bed ths
}                                                              \
2507 c01fccd2 aurel32
uint64_t helper_float_ ## name ## _ps(uint64_t fdt0)               \
2508 b6d96bed ths
{                                                              \
2509 b6d96bed ths
    uint32_t wt0;                                              \
2510 b6d96bed ths
    uint32_t wth0;                                             \
2511 b6d96bed ths
                                                               \
2512 b6d96bed ths
    wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF);                 \
2513 b6d96bed ths
    wth0 = float32_ ## name(fdt0 >> 32);                       \
2514 b6d96bed ths
    return ((uint64_t)wth0 << 32) | wt0;                       \
2515 a16336e4 ths
}
2516 a16336e4 ths
FLOAT_UNOP(abs)
2517 a16336e4 ths
FLOAT_UNOP(chs)
2518 a16336e4 ths
#undef FLOAT_UNOP
2519 a16336e4 ths
2520 8dfdb87c ths
/* MIPS specific unary operations */
2521 c01fccd2 aurel32
uint64_t helper_float_recip_d(uint64_t fdt0)
2522 8dfdb87c ths
{
2523 b6d96bed ths
    uint64_t fdt2;
2524 b6d96bed ths
2525 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2526 f01be154 ths
    fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status);
2527 8dfdb87c ths
    update_fcr31();
2528 b6d96bed ths
    return fdt2;
2529 8dfdb87c ths
}
2530 b6d96bed ths
2531 c01fccd2 aurel32
uint32_t helper_float_recip_s(uint32_t fst0)
2532 8dfdb87c ths
{
2533 b6d96bed ths
    uint32_t fst2;
2534 b6d96bed ths
2535 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2536 f01be154 ths
    fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status);
2537 8dfdb87c ths
    update_fcr31();
2538 b6d96bed ths
    return fst2;
2539 57fa1fb3 ths
}
2540 57fa1fb3 ths
2541 c01fccd2 aurel32
uint64_t helper_float_rsqrt_d(uint64_t fdt0)
2542 8dfdb87c ths
{
2543 b6d96bed ths
    uint64_t fdt2;
2544 b6d96bed ths
2545 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2546 f01be154 ths
    fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
2547 f01be154 ths
    fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status);
2548 8dfdb87c ths
    update_fcr31();
2549 b6d96bed ths
    return fdt2;
2550 8dfdb87c ths
}
2551 b6d96bed ths
2552 c01fccd2 aurel32
uint32_t helper_float_rsqrt_s(uint32_t fst0)
2553 8dfdb87c ths
{
2554 b6d96bed ths
    uint32_t fst2;
2555 b6d96bed ths
2556 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2557 f01be154 ths
    fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
2558 f01be154 ths
    fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
2559 8dfdb87c ths
    update_fcr31();
2560 b6d96bed ths
    return fst2;
2561 8dfdb87c ths
}
2562 8dfdb87c ths
2563 c01fccd2 aurel32
uint64_t helper_float_recip1_d(uint64_t fdt0)
2564 8dfdb87c ths
{
2565 b6d96bed ths
    uint64_t fdt2;
2566 b6d96bed ths
2567 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2568 f01be154 ths
    fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status);
2569 8dfdb87c ths
    update_fcr31();
2570 b6d96bed ths
    return fdt2;
2571 8dfdb87c ths
}
2572 b6d96bed ths
2573 c01fccd2 aurel32
uint32_t helper_float_recip1_s(uint32_t fst0)
2574 8dfdb87c ths
{
2575 b6d96bed ths
    uint32_t fst2;
2576 b6d96bed ths
2577 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2578 f01be154 ths
    fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status);
2579 8dfdb87c ths
    update_fcr31();
2580 b6d96bed ths
    return fst2;
2581 8dfdb87c ths
}
2582 b6d96bed ths
2583 c01fccd2 aurel32
uint64_t helper_float_recip1_ps(uint64_t fdt0)
2584 8dfdb87c ths
{
2585 b6d96bed ths
    uint32_t fst2;
2586 b6d96bed ths
    uint32_t fsth2;
2587 b6d96bed ths
2588 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2589 f01be154 ths
    fst2 = float32_div(FLOAT_ONE32, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2590 f01be154 ths
    fsth2 = float32_div(FLOAT_ONE32, fdt0 >> 32, &env->active_fpu.fp_status);
2591 8dfdb87c ths
    update_fcr31();
2592 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2593 8dfdb87c ths
}
2594 8dfdb87c ths
2595 c01fccd2 aurel32
uint64_t helper_float_rsqrt1_d(uint64_t fdt0)
2596 8dfdb87c ths
{
2597 b6d96bed ths
    uint64_t fdt2;
2598 b6d96bed ths
2599 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2600 f01be154 ths
    fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
2601 f01be154 ths
    fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status);
2602 8dfdb87c ths
    update_fcr31();
2603 b6d96bed ths
    return fdt2;
2604 8dfdb87c ths
}
2605 b6d96bed ths
2606 c01fccd2 aurel32
uint32_t helper_float_rsqrt1_s(uint32_t fst0)
2607 8dfdb87c ths
{
2608 b6d96bed ths
    uint32_t fst2;
2609 b6d96bed ths
2610 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2611 f01be154 ths
    fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
2612 f01be154 ths
    fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
2613 8dfdb87c ths
    update_fcr31();
2614 b6d96bed ths
    return fst2;
2615 8dfdb87c ths
}
2616 b6d96bed ths
2617 c01fccd2 aurel32
uint64_t helper_float_rsqrt1_ps(uint64_t fdt0)
2618 8dfdb87c ths
{
2619 b6d96bed ths
    uint32_t fst2;
2620 b6d96bed ths
    uint32_t fsth2;
2621 b6d96bed ths
2622 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2623 f01be154 ths
    fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
2624 f01be154 ths
    fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status);
2625 f01be154 ths
    fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
2626 f01be154 ths
    fsth2 = float32_div(FLOAT_ONE32, fsth2, &env->active_fpu.fp_status);
2627 8dfdb87c ths
    update_fcr31();
2628 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2629 57fa1fb3 ths
}
2630 57fa1fb3 ths
2631 c01fccd2 aurel32
#define FLOAT_OP(name, p) void helper_float_##name##_##p(void)
2632 b6d96bed ths
2633 fd4a04eb ths
/* binary operations */
2634 b6d96bed ths
#define FLOAT_BINOP(name)                                          \
2635 c01fccd2 aurel32
uint64_t helper_float_ ## name ## _d(uint64_t fdt0, uint64_t fdt1)     \
2636 b6d96bed ths
{                                                                  \
2637 b6d96bed ths
    uint64_t dt2;                                                  \
2638 b6d96bed ths
                                                                   \
2639 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);            \
2640 f01be154 ths
    dt2 = float64_ ## name (fdt0, fdt1, &env->active_fpu.fp_status);     \
2641 ead9360e ths
    update_fcr31();                                                \
2642 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID)                \
2643 b6d96bed ths
        dt2 = FLOAT_QNAN64;                                        \
2644 b6d96bed ths
    return dt2;                                                    \
2645 b6d96bed ths
}                                                                  \
2646 b6d96bed ths
                                                                   \
2647 c01fccd2 aurel32
uint32_t helper_float_ ## name ## _s(uint32_t fst0, uint32_t fst1)     \
2648 b6d96bed ths
{                                                                  \
2649 b6d96bed ths
    uint32_t wt2;                                                  \
2650 b6d96bed ths
                                                                   \
2651 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);            \
2652 f01be154 ths
    wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status);     \
2653 ead9360e ths
    update_fcr31();                                                \
2654 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID)                \
2655 b6d96bed ths
        wt2 = FLOAT_QNAN32;                                        \
2656 b6d96bed ths
    return wt2;                                                    \
2657 b6d96bed ths
}                                                                  \
2658 b6d96bed ths
                                                                   \
2659 c01fccd2 aurel32
uint64_t helper_float_ ## name ## _ps(uint64_t fdt0, uint64_t fdt1)    \
2660 b6d96bed ths
{                                                                  \
2661 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;                             \
2662 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;                                   \
2663 b6d96bed ths
    uint32_t fst1 = fdt1 & 0XFFFFFFFF;                             \
2664 b6d96bed ths
    uint32_t fsth1 = fdt1 >> 32;                                   \
2665 b6d96bed ths
    uint32_t wt2;                                                  \
2666 b6d96bed ths
    uint32_t wth2;                                                 \
2667 b6d96bed ths
                                                                   \
2668 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);            \
2669 f01be154 ths
    wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status);     \
2670 f01be154 ths
    wth2 = float32_ ## name (fsth0, fsth1, &env->active_fpu.fp_status);  \
2671 b6d96bed ths
    update_fcr31();                                                \
2672 f01be154 ths
    if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) {              \
2673 b6d96bed ths
        wt2 = FLOAT_QNAN32;                                        \
2674 b6d96bed ths
        wth2 = FLOAT_QNAN32;                                       \
2675 b6d96bed ths
    }                                                              \
2676 b6d96bed ths
    return ((uint64_t)wth2 << 32) | wt2;                           \
2677 fd4a04eb ths
}
2678 b6d96bed ths
2679 fd4a04eb ths
FLOAT_BINOP(add)
2680 fd4a04eb ths
FLOAT_BINOP(sub)
2681 fd4a04eb ths
FLOAT_BINOP(mul)
2682 fd4a04eb ths
FLOAT_BINOP(div)
2683 fd4a04eb ths
#undef FLOAT_BINOP
2684 fd4a04eb ths
2685 a16336e4 ths
/* ternary operations */
2686 b6d96bed ths
#define FLOAT_TERNOP(name1, name2)                                        \
2687 c01fccd2 aurel32
uint64_t helper_float_ ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1,  \
2688 b6d96bed ths
                                           uint64_t fdt2)                 \
2689 b6d96bed ths
{                                                                         \
2690 f01be154 ths
    fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status);          \
2691 f01be154 ths
    return float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status);          \
2692 b6d96bed ths
}                                                                         \
2693 b6d96bed ths
                                                                          \
2694 c01fccd2 aurel32
uint32_t helper_float_ ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1,  \
2695 b6d96bed ths
                                           uint32_t fst2)                 \
2696 b6d96bed ths
{                                                                         \
2697 f01be154 ths
    fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
2698 f01be154 ths
    return float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
2699 b6d96bed ths
}                                                                         \
2700 b6d96bed ths
                                                                          \
2701 c01fccd2 aurel32
uint64_t helper_float_ ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1, \
2702 b6d96bed ths
                                            uint64_t fdt2)                \
2703 b6d96bed ths
{                                                                         \
2704 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;                                    \
2705 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;                                          \
2706 b6d96bed ths
    uint32_t fst1 = fdt1 & 0XFFFFFFFF;                                    \
2707 b6d96bed ths
    uint32_t fsth1 = fdt1 >> 32;                                          \
2708 b6d96bed ths
    uint32_t fst2 = fdt2 & 0XFFFFFFFF;                                    \
2709 b6d96bed ths
    uint32_t fsth2 = fdt2 >> 32;                                          \
2710 b6d96bed ths
                                                                          \
2711 f01be154 ths
    fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
2712 f01be154 ths
    fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status);       \
2713 f01be154 ths
    fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
2714 f01be154 ths
    fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status);       \
2715 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;                                \
2716 a16336e4 ths
}
2717 b6d96bed ths
2718 a16336e4 ths
FLOAT_TERNOP(mul, add)
2719 a16336e4 ths
FLOAT_TERNOP(mul, sub)
2720 a16336e4 ths
#undef FLOAT_TERNOP
2721 a16336e4 ths
2722 a16336e4 ths
/* negated ternary operations */
2723 b6d96bed ths
#define FLOAT_NTERNOP(name1, name2)                                       \
2724 c01fccd2 aurel32
uint64_t helper_float_n ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1, \
2725 b6d96bed ths
                                           uint64_t fdt2)                 \
2726 b6d96bed ths
{                                                                         \
2727 f01be154 ths
    fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status);          \
2728 f01be154 ths
    fdt2 = float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status);          \
2729 b6d96bed ths
    return float64_chs(fdt2);                                             \
2730 b6d96bed ths
}                                                                         \
2731 b6d96bed ths
                                                                          \
2732 c01fccd2 aurel32
uint32_t helper_float_n ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1, \
2733 b6d96bed ths
                                           uint32_t fst2)                 \
2734 b6d96bed ths
{                                                                         \
2735 f01be154 ths
    fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
2736 f01be154 ths
    fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
2737 b6d96bed ths
    return float32_chs(fst2);                                             \
2738 b6d96bed ths
}                                                                         \
2739 b6d96bed ths
                                                                          \
2740 c01fccd2 aurel32
uint64_t helper_float_n ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1,\
2741 b6d96bed ths
                                           uint64_t fdt2)                 \
2742 b6d96bed ths
{                                                                         \
2743 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;                                    \
2744 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;                                          \
2745 b6d96bed ths
    uint32_t fst1 = fdt1 & 0XFFFFFFFF;                                    \
2746 b6d96bed ths
    uint32_t fsth1 = fdt1 >> 32;                                          \
2747 b6d96bed ths
    uint32_t fst2 = fdt2 & 0XFFFFFFFF;                                    \
2748 b6d96bed ths
    uint32_t fsth2 = fdt2 >> 32;                                          \
2749 b6d96bed ths
                                                                          \
2750 f01be154 ths
    fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
2751 f01be154 ths
    fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status);       \
2752 f01be154 ths
    fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
2753 f01be154 ths
    fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status);       \
2754 b6d96bed ths
    fst2 = float32_chs(fst2);                                             \
2755 b6d96bed ths
    fsth2 = float32_chs(fsth2);                                           \
2756 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;                                \
2757 a16336e4 ths
}
2758 b6d96bed ths
2759 a16336e4 ths
FLOAT_NTERNOP(mul, add)
2760 a16336e4 ths
FLOAT_NTERNOP(mul, sub)
2761 a16336e4 ths
#undef FLOAT_NTERNOP
2762 a16336e4 ths
2763 8dfdb87c ths
/* MIPS specific binary operations */
2764 c01fccd2 aurel32
uint64_t helper_float_recip2_d(uint64_t fdt0, uint64_t fdt2)
2765 8dfdb87c ths
{
2766 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2767 f01be154 ths
    fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
2768 f01be154 ths
    fdt2 = float64_chs(float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status));
2769 8dfdb87c ths
    update_fcr31();
2770 b6d96bed ths
    return fdt2;
2771 8dfdb87c ths
}
2772 b6d96bed ths
2773 c01fccd2 aurel32
uint32_t helper_float_recip2_s(uint32_t fst0, uint32_t fst2)
2774 8dfdb87c ths
{
2775 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2776 f01be154 ths
    fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2777 f01be154 ths
    fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status));
2778 8dfdb87c ths
    update_fcr31();
2779 b6d96bed ths
    return fst2;
2780 8dfdb87c ths
}
2781 b6d96bed ths
2782 c01fccd2 aurel32
uint64_t helper_float_recip2_ps(uint64_t fdt0, uint64_t fdt2)
2783 8dfdb87c ths
{
2784 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2785 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;
2786 b6d96bed ths
    uint32_t fst2 = fdt2 & 0XFFFFFFFF;
2787 b6d96bed ths
    uint32_t fsth2 = fdt2 >> 32;
2788 b6d96bed ths
2789 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2790 f01be154 ths
    fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2791 f01be154 ths
    fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
2792 f01be154 ths
    fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status));
2793 f01be154 ths
    fsth2 = float32_chs(float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status));
2794 8dfdb87c ths
    update_fcr31();
2795 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2796 8dfdb87c ths
}
2797 8dfdb87c ths
2798 c01fccd2 aurel32
uint64_t helper_float_rsqrt2_d(uint64_t fdt0, uint64_t fdt2)
2799 8dfdb87c ths
{
2800 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2801 f01be154 ths
    fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
2802 f01be154 ths
    fdt2 = float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status);
2803 f01be154 ths
    fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->active_fpu.fp_status));
2804 8dfdb87c ths
    update_fcr31();
2805 b6d96bed ths
    return fdt2;
2806 8dfdb87c ths
}
2807 b6d96bed ths
2808 c01fccd2 aurel32
uint32_t helper_float_rsqrt2_s(uint32_t fst0, uint32_t fst2)
2809 8dfdb87c ths
{
2810 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2811 f01be154 ths
    fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2812 f01be154 ths
    fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status);
2813 f01be154 ths
    fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
2814 8dfdb87c ths
    update_fcr31();
2815 b6d96bed ths
    return fst2;
2816 8dfdb87c ths
}
2817 b6d96bed ths
2818 c01fccd2 aurel32
uint64_t helper_float_rsqrt2_ps(uint64_t fdt0, uint64_t fdt2)
2819 8dfdb87c ths
{
2820 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2821 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;
2822 b6d96bed ths
    uint32_t fst2 = fdt2 & 0XFFFFFFFF;
2823 b6d96bed ths
    uint32_t fsth2 = fdt2 >> 32;
2824 b6d96bed ths
2825 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2826 f01be154 ths
    fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
2827 f01be154 ths
    fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
2828 f01be154 ths
    fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status);
2829 f01be154 ths
    fsth2 = float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status);
2830 f01be154 ths
    fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
2831 f01be154 ths
    fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->active_fpu.fp_status));
2832 8dfdb87c ths
    update_fcr31();
2833 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2834 57fa1fb3 ths
}
2835 57fa1fb3 ths
2836 c01fccd2 aurel32
uint64_t helper_float_addr_ps(uint64_t fdt0, uint64_t fdt1)
2837 fd4a04eb ths
{
2838 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2839 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;
2840 b6d96bed ths
    uint32_t fst1 = fdt1 & 0XFFFFFFFF;
2841 b6d96bed ths
    uint32_t fsth1 = fdt1 >> 32;
2842 b6d96bed ths
    uint32_t fst2;
2843 b6d96bed ths
    uint32_t fsth2;
2844 b6d96bed ths
2845 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2846 f01be154 ths
    fst2 = float32_add (fst0, fsth0, &env->active_fpu.fp_status);
2847 f01be154 ths
    fsth2 = float32_add (fst1, fsth1, &env->active_fpu.fp_status);
2848 fd4a04eb ths
    update_fcr31();
2849 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2850 fd4a04eb ths
}
2851 fd4a04eb ths
2852 c01fccd2 aurel32
uint64_t helper_float_mulr_ps(uint64_t fdt0, uint64_t fdt1)
2853 57fa1fb3 ths
{
2854 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2855 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;
2856 b6d96bed ths
    uint32_t fst1 = fdt1 & 0XFFFFFFFF;
2857 b6d96bed ths
    uint32_t fsth1 = fdt1 >> 32;
2858 b6d96bed ths
    uint32_t fst2;
2859 b6d96bed ths
    uint32_t fsth2;
2860 b6d96bed ths
2861 f01be154 ths
    set_float_exception_flags(0, &env->active_fpu.fp_status);
2862 f01be154 ths
    fst2 = float32_mul (fst0, fsth0, &env->active_fpu.fp_status);
2863 f01be154 ths
    fsth2 = float32_mul (fst1, fsth1, &env->active_fpu.fp_status);
2864 57fa1fb3 ths
    update_fcr31();
2865 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2866 57fa1fb3 ths
}
2867 57fa1fb3 ths
2868 8dfdb87c ths
/* compare operations */
2869 b6d96bed ths
#define FOP_COND_D(op, cond)                                   \
2870 c01fccd2 aurel32
void helper_cmp_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
2871 b6d96bed ths
{                                                              \
2872 b6d96bed ths
    int c = cond;                                              \
2873 b6d96bed ths
    update_fcr31();                                            \
2874 b6d96bed ths
    if (c)                                                     \
2875 f01be154 ths
        SET_FP_COND(cc, env->active_fpu);                      \
2876 b6d96bed ths
    else                                                       \
2877 f01be154 ths
        CLEAR_FP_COND(cc, env->active_fpu);                    \
2878 b6d96bed ths
}                                                              \
2879 c01fccd2 aurel32
void helper_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
2880 b6d96bed ths
{                                                              \
2881 b6d96bed ths
    int c;                                                     \
2882 b6d96bed ths
    fdt0 = float64_abs(fdt0);                                  \
2883 b6d96bed ths
    fdt1 = float64_abs(fdt1);                                  \
2884 b6d96bed ths
    c = cond;                                                  \
2885 b6d96bed ths
    update_fcr31();                                            \
2886 b6d96bed ths
    if (c)                                                     \
2887 f01be154 ths
        SET_FP_COND(cc, env->active_fpu);                      \
2888 b6d96bed ths
    else                                                       \
2889 f01be154 ths
        CLEAR_FP_COND(cc, env->active_fpu);                    \
2890 fd4a04eb ths
}
2891 fd4a04eb ths
2892 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2893 3a599383 Aurelien Jarno
 * but float64_unordered_quiet() is still called. */
2894 3a599383 Aurelien Jarno
FOP_COND_D(f,   (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status), 0))
2895 3a599383 Aurelien Jarno
FOP_COND_D(un,  float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status))
2896 211315fb Aurelien Jarno
FOP_COND_D(eq,  !float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
2897 211315fb Aurelien Jarno
FOP_COND_D(ueq, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
2898 3a599383 Aurelien Jarno
FOP_COND_D(olt, !float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
2899 3a599383 Aurelien Jarno
FOP_COND_D(ult, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
2900 3a599383 Aurelien Jarno
FOP_COND_D(ole, !float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
2901 3a599383 Aurelien Jarno
FOP_COND_D(ule, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
2902 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2903 3a599383 Aurelien Jarno
 * but float64_unordered() is still called. */
2904 3a599383 Aurelien Jarno
FOP_COND_D(sf,  (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status), 0))
2905 3a599383 Aurelien Jarno
FOP_COND_D(ngle,float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status))
2906 211315fb Aurelien Jarno
FOP_COND_D(seq, !float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
2907 211315fb Aurelien Jarno
FOP_COND_D(ngl, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
2908 3a599383 Aurelien Jarno
FOP_COND_D(lt,  !float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
2909 3a599383 Aurelien Jarno
FOP_COND_D(nge, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
2910 3a599383 Aurelien Jarno
FOP_COND_D(le,  !float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
2911 3a599383 Aurelien Jarno
FOP_COND_D(ngt, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
2912 b6d96bed ths
2913 b6d96bed ths
#define FOP_COND_S(op, cond)                                   \
2914 c01fccd2 aurel32
void helper_cmp_s_ ## op (uint32_t fst0, uint32_t fst1, int cc)    \
2915 b6d96bed ths
{                                                              \
2916 b6d96bed ths
    int c = cond;                                              \
2917 b6d96bed ths
    update_fcr31();                                            \
2918 b6d96bed ths
    if (c)                                                     \
2919 f01be154 ths
        SET_FP_COND(cc, env->active_fpu);                      \
2920 b6d96bed ths
    else                                                       \
2921 f01be154 ths
        CLEAR_FP_COND(cc, env->active_fpu);                    \
2922 b6d96bed ths
}                                                              \
2923 c01fccd2 aurel32
void helper_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
2924 b6d96bed ths
{                                                              \
2925 b6d96bed ths
    int c;                                                     \
2926 b6d96bed ths
    fst0 = float32_abs(fst0);                                  \
2927 b6d96bed ths
    fst1 = float32_abs(fst1);                                  \
2928 b6d96bed ths
    c = cond;                                                  \
2929 b6d96bed ths
    update_fcr31();                                            \
2930 b6d96bed ths
    if (c)                                                     \
2931 f01be154 ths
        SET_FP_COND(cc, env->active_fpu);                      \
2932 b6d96bed ths
    else                                                       \
2933 f01be154 ths
        CLEAR_FP_COND(cc, env->active_fpu);                    \
2934 fd4a04eb ths
}
2935 fd4a04eb ths
2936 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2937 3a599383 Aurelien Jarno
 * but float32_unordered_quiet() is still called. */
2938 3a599383 Aurelien Jarno
FOP_COND_S(f,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0))
2939 3a599383 Aurelien Jarno
FOP_COND_S(un,  float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status))
2940 211315fb Aurelien Jarno
FOP_COND_S(eq,  !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) && float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
2941 211315fb Aurelien Jarno
FOP_COND_S(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
2942 3a599383 Aurelien Jarno
FOP_COND_S(olt, !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
2943 3a599383 Aurelien Jarno
FOP_COND_S(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
2944 3a599383 Aurelien Jarno
FOP_COND_S(ole, !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
2945 3a599383 Aurelien Jarno
FOP_COND_S(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_le(fst0, fst1, &env->active_fpu.fp_status))
2946 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2947 3a599383 Aurelien Jarno
 * but float32_unordered() is still called. */
2948 3a599383 Aurelien Jarno
FOP_COND_S(sf,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0))
2949 3a599383 Aurelien Jarno
FOP_COND_S(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status))
2950 211315fb Aurelien Jarno
FOP_COND_S(seq, !float32_unordered(fst1, fst0, &env->active_fpu.fp_status) && float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
2951 211315fb Aurelien Jarno
FOP_COND_S(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
2952 3a599383 Aurelien Jarno
FOP_COND_S(lt,  !float32_unordered(fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
2953 3a599383 Aurelien Jarno
FOP_COND_S(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
2954 3a599383 Aurelien Jarno
FOP_COND_S(le,  !float32_unordered(fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
2955 3a599383 Aurelien Jarno
FOP_COND_S(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_le(fst0, fst1, &env->active_fpu.fp_status))
2956 b6d96bed ths
2957 b6d96bed ths
#define FOP_COND_PS(op, condl, condh)                           \
2958 c01fccd2 aurel32
void helper_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
2959 b6d96bed ths
{                                                               \
2960 b6d96bed ths
    uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF);             \
2961 b6d96bed ths
    uint32_t fsth0 = float32_abs(fdt0 >> 32);                   \
2962 b6d96bed ths
    uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF);             \
2963 b6d96bed ths
    uint32_t fsth1 = float32_abs(fdt1 >> 32);                   \
2964 b6d96bed ths
    int cl = condl;                                             \
2965 b6d96bed ths
    int ch = condh;                                             \
2966 b6d96bed ths
                                                                \
2967 b6d96bed ths
    update_fcr31();                                             \
2968 b6d96bed ths
    if (cl)                                                     \
2969 f01be154 ths
        SET_FP_COND(cc, env->active_fpu);                       \
2970 b6d96bed ths
    else                                                        \
2971 f01be154 ths
        CLEAR_FP_COND(cc, env->active_fpu);                     \
2972 b6d96bed ths
    if (ch)                                                     \
2973 f01be154 ths
        SET_FP_COND(cc + 1, env->active_fpu);                   \
2974 b6d96bed ths
    else                                                        \
2975 f01be154 ths
        CLEAR_FP_COND(cc + 1, env->active_fpu);                 \
2976 b6d96bed ths
}                                                               \
2977 c01fccd2 aurel32
void helper_cmpabs_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
2978 b6d96bed ths
{                                                               \
2979 b6d96bed ths
    uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF);             \
2980 b6d96bed ths
    uint32_t fsth0 = float32_abs(fdt0 >> 32);                   \
2981 b6d96bed ths
    uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF);             \
2982 b6d96bed ths
    uint32_t fsth1 = float32_abs(fdt1 >> 32);                   \
2983 b6d96bed ths
    int cl = condl;                                             \
2984 b6d96bed ths
    int ch = condh;                                             \
2985 b6d96bed ths
                                                                \
2986 b6d96bed ths
    update_fcr31();                                             \
2987 b6d96bed ths
    if (cl)                                                     \
2988 f01be154 ths
        SET_FP_COND(cc, env->active_fpu);                       \
2989 b6d96bed ths
    else                                                        \
2990 f01be154 ths
        CLEAR_FP_COND(cc, env->active_fpu);                     \
2991 b6d96bed ths
    if (ch)                                                     \
2992 f01be154 ths
        SET_FP_COND(cc + 1, env->active_fpu);                   \
2993 b6d96bed ths
    else                                                        \
2994 f01be154 ths
        CLEAR_FP_COND(cc + 1, env->active_fpu);                 \
2995 fd4a04eb ths
}
2996 fd4a04eb ths
2997 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2998 3a599383 Aurelien Jarno
 * but float32_unordered_quiet() is still called. */
2999 3a599383 Aurelien Jarno
FOP_COND_PS(f,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0),
3000 3a599383 Aurelien Jarno
                 (float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status), 0))
3001 3a599383 Aurelien Jarno
FOP_COND_PS(un,  float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status),
3002 3a599383 Aurelien Jarno
                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status))
3003 211315fb Aurelien Jarno
FOP_COND_PS(eq,  !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)   && float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
3004 211315fb Aurelien Jarno
                 !float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3005 211315fb Aurelien Jarno
FOP_COND_PS(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
3006 211315fb Aurelien Jarno
                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3007 3a599383 Aurelien Jarno
FOP_COND_PS(olt, !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)   && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
3008 3a599383 Aurelien Jarno
                 !float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
3009 3a599383 Aurelien Jarno
FOP_COND_PS(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
3010 3a599383 Aurelien Jarno
                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
3011 3a599383 Aurelien Jarno
FOP_COND_PS(ole, !float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)   && float32_le(fst0, fst1, &env->active_fpu.fp_status),
3012 3a599383 Aurelien Jarno
                 !float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
3013 3a599383 Aurelien Jarno
FOP_COND_PS(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_le(fst0, fst1, &env->active_fpu.fp_status),
3014 3a599383 Aurelien Jarno
                 float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
3015 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
3016 3a599383 Aurelien Jarno
 * but float32_unordered() is still called. */
3017 3a599383 Aurelien Jarno
FOP_COND_PS(sf,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0),
3018 3a599383 Aurelien Jarno
                 (float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status), 0))
3019 3a599383 Aurelien Jarno
FOP_COND_PS(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status),
3020 3a599383 Aurelien Jarno
                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status))
3021 211315fb Aurelien Jarno
FOP_COND_PS(seq, !float32_unordered(fst1, fst0, &env->active_fpu.fp_status)   && float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
3022 211315fb Aurelien Jarno
                 !float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3023 211315fb Aurelien Jarno
FOP_COND_PS(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
3024 211315fb Aurelien Jarno
                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
3025 3a599383 Aurelien Jarno
FOP_COND_PS(lt,  !float32_unordered(fst1, fst0, &env->active_fpu.fp_status)   && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
3026 3a599383 Aurelien Jarno
                 !float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
3027 3a599383 Aurelien Jarno
FOP_COND_PS(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
3028 3a599383 Aurelien Jarno
                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
3029 3a599383 Aurelien Jarno
FOP_COND_PS(le,  !float32_unordered(fst1, fst0, &env->active_fpu.fp_status)   && float32_le(fst0, fst1, &env->active_fpu.fp_status),
3030 3a599383 Aurelien Jarno
                 !float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
3031 3a599383 Aurelien Jarno
FOP_COND_PS(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_le(fst0, fst1, &env->active_fpu.fp_status),
3032 3a599383 Aurelien Jarno
                 float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))