Statistics
| Branch: | Revision:

root / target-mips / op_helper.c @ c227f099

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