Statistics
| Branch: | Revision:

root / target-mips / op_helper.c @ 41db4607

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