Statistics
| Branch: | Revision:

root / target-mips / op_helper.c @ da80682b

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