Statistics
| Branch: | Revision:

root / target-mips / op_helper.c @ ed23fbd9

History | View | Annotate | Download (87.6 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 be24bb4f ths
target_ulong do_mftgpr(target_ulong t0, 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 be24bb4f ths
target_ulong do_mftlo(target_ulong t0, 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 be24bb4f ths
target_ulong do_mfthi(target_ulong t0, 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 be24bb4f ths
target_ulong do_mftacx(target_ulong t0, 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 be24bb4f ths
target_ulong do_mftdsp(target_ulong t0)
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 814b9a47 ths
    /* Discard cached TLB entries.  We could avoid doing this if the
1576 814b9a47 ths
       tlbwi is just upgrading access permissions on the current entry;
1577 814b9a47 ths
       that might be a further win.  */
1578 ead9360e ths
    r4k_mips_tlb_flush_extra (env, env->tlb->nb_tlb);
1579 814b9a47 ths
1580 ead9360e ths
    r4k_invalidate_tlb(env, env->CP0_Index % env->tlb->nb_tlb, 0);
1581 ead9360e ths
    r4k_fill_tlb(env->CP0_Index % env->tlb->nb_tlb);
1582 6af0bf9c bellard
}
1583 6af0bf9c bellard
1584 29929e34 ths
void r4k_do_tlbwr (void)
1585 6af0bf9c bellard
{
1586 6af0bf9c bellard
    int r = cpu_mips_get_random(env);
1587 6af0bf9c bellard
1588 29929e34 ths
    r4k_invalidate_tlb(env, r, 1);
1589 29929e34 ths
    r4k_fill_tlb(r);
1590 6af0bf9c bellard
}
1591 6af0bf9c bellard
1592 29929e34 ths
void r4k_do_tlbp (void)
1593 6af0bf9c bellard
{
1594 29929e34 ths
    r4k_tlb_t *tlb;
1595 f2e9ebef ths
    target_ulong mask;
1596 6af0bf9c bellard
    target_ulong tag;
1597 f2e9ebef ths
    target_ulong VPN;
1598 6af0bf9c bellard
    uint8_t ASID;
1599 6af0bf9c bellard
    int i;
1600 6af0bf9c bellard
1601 3d9fb9fe bellard
    ASID = env->CP0_EntryHi & 0xFF;
1602 ead9360e ths
    for (i = 0; i < env->tlb->nb_tlb; i++) {
1603 ead9360e ths
        tlb = &env->tlb->mmu.r4k.tlb[i];
1604 f2e9ebef ths
        /* 1k pages are not supported. */
1605 f2e9ebef ths
        mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
1606 f2e9ebef ths
        tag = env->CP0_EntryHi & ~mask;
1607 f2e9ebef ths
        VPN = tlb->VPN & ~mask;
1608 6af0bf9c bellard
        /* Check ASID, virtual page number & size */
1609 f2e9ebef ths
        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1610 6af0bf9c bellard
            /* TLB match */
1611 9c2149c8 ths
            env->CP0_Index = i;
1612 6af0bf9c bellard
            break;
1613 6af0bf9c bellard
        }
1614 6af0bf9c bellard
    }
1615 ead9360e ths
    if (i == env->tlb->nb_tlb) {
1616 814b9a47 ths
        /* No match.  Discard any shadow entries, if any of them match.  */
1617 ead9360e ths
        for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) {
1618 ead9360e ths
            tlb = &env->tlb->mmu.r4k.tlb[i];
1619 f2e9ebef ths
            /* 1k pages are not supported. */
1620 f2e9ebef ths
            mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
1621 f2e9ebef ths
            tag = env->CP0_EntryHi & ~mask;
1622 f2e9ebef ths
            VPN = tlb->VPN & ~mask;
1623 814b9a47 ths
            /* Check ASID, virtual page number & size */
1624 f2e9ebef ths
            if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1625 29929e34 ths
                r4k_mips_tlb_flush_extra (env, i);
1626 814b9a47 ths
                break;
1627 814b9a47 ths
            }
1628 814b9a47 ths
        }
1629 814b9a47 ths
1630 9c2149c8 ths
        env->CP0_Index |= 0x80000000;
1631 6af0bf9c bellard
    }
1632 6af0bf9c bellard
}
1633 6af0bf9c bellard
1634 29929e34 ths
void r4k_do_tlbr (void)
1635 6af0bf9c bellard
{
1636 29929e34 ths
    r4k_tlb_t *tlb;
1637 09c56b84 pbrook
    uint8_t ASID;
1638 6af0bf9c bellard
1639 09c56b84 pbrook
    ASID = env->CP0_EntryHi & 0xFF;
1640 ead9360e ths
    tlb = &env->tlb->mmu.r4k.tlb[env->CP0_Index % env->tlb->nb_tlb];
1641 4ad40f36 bellard
1642 4ad40f36 bellard
    /* If this will change the current ASID, flush qemu's TLB.  */
1643 814b9a47 ths
    if (ASID != tlb->ASID)
1644 814b9a47 ths
        cpu_mips_tlb_flush (env, 1);
1645 814b9a47 ths
1646 ead9360e ths
    r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
1647 4ad40f36 bellard
1648 6af0bf9c bellard
    env->CP0_EntryHi = tlb->VPN | tlb->ASID;
1649 3b1c8be4 ths
    env->CP0_PageMask = tlb->PageMask;
1650 7495fd0f ths
    env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
1651 7495fd0f ths
                        (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
1652 7495fd0f ths
    env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
1653 7495fd0f ths
                        (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
1654 6af0bf9c bellard
}
1655 6af0bf9c bellard
1656 2b0233ab ths
/* Specials */
1657 2796188e ths
target_ulong do_di (void)
1658 2b0233ab ths
{
1659 2796188e ths
    target_ulong t0 = env->CP0_Status;
1660 2796188e ths
1661 be24bb4f ths
    env->CP0_Status = t0 & ~(1 << CP0St_IE);
1662 2b0233ab ths
    cpu_mips_update_irq(env);
1663 be24bb4f ths
1664 be24bb4f ths
    return t0;
1665 2b0233ab ths
}
1666 2b0233ab ths
1667 2796188e ths
target_ulong do_ei (void)
1668 2b0233ab ths
{
1669 2796188e ths
    target_ulong t0 = env->CP0_Status;
1670 2796188e ths
1671 be24bb4f ths
    env->CP0_Status = t0 | (1 << CP0St_IE);
1672 2b0233ab ths
    cpu_mips_update_irq(env);
1673 be24bb4f ths
1674 be24bb4f ths
    return t0;
1675 2b0233ab ths
}
1676 2b0233ab ths
1677 f41c52f1 ths
void debug_pre_eret (void)
1678 6af0bf9c bellard
{
1679 f41c52f1 ths
    fprintf(logfile, "ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
1680 b5dc7732 ths
            env->active_tc.PC, env->CP0_EPC);
1681 f41c52f1 ths
    if (env->CP0_Status & (1 << CP0St_ERL))
1682 f41c52f1 ths
        fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
1683 f41c52f1 ths
    if (env->hflags & MIPS_HFLAG_DM)
1684 f41c52f1 ths
        fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC);
1685 f41c52f1 ths
    fputs("\n", logfile);
1686 f41c52f1 ths
}
1687 f41c52f1 ths
1688 f41c52f1 ths
void debug_post_eret (void)
1689 f41c52f1 ths
{
1690 744e0915 ths
    fprintf(logfile, "  =>  PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
1691 b5dc7732 ths
            env->active_tc.PC, env->CP0_EPC);
1692 f41c52f1 ths
    if (env->CP0_Status & (1 << CP0St_ERL))
1693 f41c52f1 ths
        fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
1694 f41c52f1 ths
    if (env->hflags & MIPS_HFLAG_DM)
1695 f41c52f1 ths
        fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC);
1696 623a930e ths
    switch (env->hflags & MIPS_HFLAG_KSU) {
1697 623a930e ths
    case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break;
1698 623a930e ths
    case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break;
1699 623a930e ths
    case MIPS_HFLAG_KM: fputs("\n", logfile); break;
1700 623a930e ths
    default: cpu_abort(env, "Invalid MMU mode!\n"); break;
1701 623a930e ths
    }
1702 6af0bf9c bellard
}
1703 6af0bf9c bellard
1704 6c5c1e20 ths
void do_eret (void)
1705 2b0233ab ths
{
1706 2b0233ab ths
    if (loglevel & CPU_LOG_EXEC)
1707 2b0233ab ths
        debug_pre_eret();
1708 2b0233ab ths
    if (env->CP0_Status & (1 << CP0St_ERL)) {
1709 b5dc7732 ths
        env->active_tc.PC = env->CP0_ErrorEPC;
1710 2b0233ab ths
        env->CP0_Status &= ~(1 << CP0St_ERL);
1711 2b0233ab ths
    } else {
1712 b5dc7732 ths
        env->active_tc.PC = env->CP0_EPC;
1713 2b0233ab ths
        env->CP0_Status &= ~(1 << CP0St_EXL);
1714 2b0233ab ths
    }
1715 2b0233ab ths
    compute_hflags(env);
1716 2b0233ab ths
    if (loglevel & CPU_LOG_EXEC)
1717 2b0233ab ths
        debug_post_eret();
1718 2b0233ab ths
    env->CP0_LLAddr = 1;
1719 2b0233ab ths
}
1720 2b0233ab ths
1721 6c5c1e20 ths
void do_deret (void)
1722 2b0233ab ths
{
1723 2b0233ab ths
    if (loglevel & CPU_LOG_EXEC)
1724 2b0233ab ths
        debug_pre_eret();
1725 b5dc7732 ths
    env->active_tc.PC = env->CP0_DEPC;
1726 2b0233ab ths
    env->hflags &= MIPS_HFLAG_DM;
1727 2b0233ab ths
    compute_hflags(env);
1728 2b0233ab ths
    if (loglevel & CPU_LOG_EXEC)
1729 2b0233ab ths
        debug_post_eret();
1730 2b0233ab ths
    env->CP0_LLAddr = 1;
1731 2b0233ab ths
}
1732 0eaef5aa ths
#endif /* !CONFIG_USER_ONLY */
1733 2b0233ab ths
1734 2796188e ths
target_ulong do_rdhwr_cpunum(void)
1735 2b0233ab ths
{
1736 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1737 2b0233ab ths
        (env->CP0_HWREna & (1 << 0)))
1738 2796188e ths
        return env->CP0_EBase & 0x3ff;
1739 2b0233ab ths
    else
1740 2b0233ab ths
        do_raise_exception(EXCP_RI);
1741 be24bb4f ths
1742 2796188e ths
    return 0;
1743 2b0233ab ths
}
1744 2b0233ab ths
1745 2796188e ths
target_ulong do_rdhwr_synci_step(void)
1746 2b0233ab ths
{
1747 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1748 2b0233ab ths
        (env->CP0_HWREna & (1 << 1)))
1749 2796188e ths
        return env->SYNCI_Step;
1750 2b0233ab ths
    else
1751 2b0233ab ths
        do_raise_exception(EXCP_RI);
1752 be24bb4f ths
1753 2796188e ths
    return 0;
1754 2b0233ab ths
}
1755 2b0233ab ths
1756 2796188e ths
target_ulong do_rdhwr_cc(void)
1757 2b0233ab ths
{
1758 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1759 2b0233ab ths
        (env->CP0_HWREna & (1 << 2)))
1760 2796188e ths
        return env->CP0_Count;
1761 2b0233ab ths
    else
1762 2b0233ab ths
        do_raise_exception(EXCP_RI);
1763 be24bb4f ths
1764 2796188e ths
    return 0;
1765 2b0233ab ths
}
1766 2b0233ab ths
1767 2796188e ths
target_ulong do_rdhwr_ccres(void)
1768 2b0233ab ths
{
1769 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1770 2b0233ab ths
        (env->CP0_HWREna & (1 << 3)))
1771 2796188e ths
        return env->CCRes;
1772 2b0233ab ths
    else
1773 2b0233ab ths
        do_raise_exception(EXCP_RI);
1774 be24bb4f ths
1775 2796188e ths
    return 0;
1776 2b0233ab ths
}
1777 2b0233ab ths
1778 2b0233ab ths
/* Bitfield operations. */
1779 d26968ec ths
target_ulong do_ext(target_ulong t1, uint32_t pos, uint32_t size)
1780 2b0233ab ths
{
1781 be24bb4f ths
    return (int32_t)((t1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0));
1782 2b0233ab ths
}
1783 2b0233ab ths
1784 be24bb4f ths
target_ulong do_ins(target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size)
1785 2b0233ab ths
{
1786 2b0233ab ths
    target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
1787 2b0233ab ths
1788 be24bb4f ths
    return (int32_t)((t0 & ~mask) | ((t1 << pos) & mask));
1789 2b0233ab ths
}
1790 2b0233ab ths
1791 d26968ec ths
target_ulong do_wsbh(target_ulong t1)
1792 2b0233ab ths
{
1793 be24bb4f ths
    return (int32_t)(((t1 << 8) & ~0x00FF00FF) | ((t1 >> 8) & 0x00FF00FF));
1794 2b0233ab ths
}
1795 2b0233ab ths
1796 2b0233ab ths
#if defined(TARGET_MIPS64)
1797 d26968ec ths
target_ulong do_dext(target_ulong t1, uint32_t pos, uint32_t size)
1798 2b0233ab ths
{
1799 be24bb4f ths
    return (t1 >> pos) & ((size < 64) ? ((1ULL << size) - 1) : ~0ULL);
1800 2b0233ab ths
}
1801 2b0233ab ths
1802 be24bb4f ths
target_ulong do_dins(target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size)
1803 2b0233ab ths
{
1804 2b0233ab ths
    target_ulong mask = ((size < 64) ? ((1ULL << size) - 1) : ~0ULL) << pos;
1805 2b0233ab ths
1806 be24bb4f ths
    return (t0 & ~mask) | ((t1 << pos) & mask);
1807 2b0233ab ths
}
1808 2b0233ab ths
1809 d26968ec ths
target_ulong do_dsbh(target_ulong t1)
1810 2b0233ab ths
{
1811 be24bb4f ths
    return ((t1 << 8) & ~0x00FF00FF00FF00FFULL) | ((t1 >> 8) & 0x00FF00FF00FF00FFULL);
1812 2b0233ab ths
}
1813 2b0233ab ths
1814 d26968ec ths
target_ulong do_dshd(target_ulong t1)
1815 2b0233ab ths
{
1816 be24bb4f ths
    t1 = ((t1 << 16) & ~0x0000FFFF0000FFFFULL) | ((t1 >> 16) & 0x0000FFFF0000FFFFULL);
1817 be24bb4f ths
    return (t1 << 32) | (t1 >> 32);
1818 2b0233ab ths
}
1819 2b0233ab ths
#endif
1820 2b0233ab ths
1821 6af0bf9c bellard
void do_pmon (int function)
1822 6af0bf9c bellard
{
1823 6af0bf9c bellard
    function /= 2;
1824 6af0bf9c bellard
    switch (function) {
1825 6af0bf9c bellard
    case 2: /* TODO: char inbyte(int waitflag); */
1826 b5dc7732 ths
        if (env->active_tc.gpr[4] == 0)
1827 b5dc7732 ths
            env->active_tc.gpr[2] = -1;
1828 6af0bf9c bellard
        /* Fall through */
1829 6af0bf9c bellard
    case 11: /* TODO: char inbyte (void); */
1830 b5dc7732 ths
        env->active_tc.gpr[2] = -1;
1831 6af0bf9c bellard
        break;
1832 6af0bf9c bellard
    case 3:
1833 6af0bf9c bellard
    case 12:
1834 b5dc7732 ths
        printf("%c", (char)(env->active_tc.gpr[4] & 0xFF));
1835 6af0bf9c bellard
        break;
1836 6af0bf9c bellard
    case 17:
1837 6af0bf9c bellard
        break;
1838 6af0bf9c bellard
    case 158:
1839 6af0bf9c bellard
        {
1840 b5dc7732 ths
            unsigned char *fmt = (void *)(unsigned long)env->active_tc.gpr[4];
1841 6af0bf9c bellard
            printf("%s", fmt);
1842 6af0bf9c bellard
        }
1843 6af0bf9c bellard
        break;
1844 6af0bf9c bellard
    }
1845 6af0bf9c bellard
}
1846 e37e863f bellard
1847 08ba7963 ths
void do_wait (void)
1848 08ba7963 ths
{
1849 08ba7963 ths
    env->halted = 1;
1850 08ba7963 ths
    do_raise_exception(EXCP_HLT);
1851 08ba7963 ths
}
1852 08ba7963 ths
1853 5fafdf24 ths
#if !defined(CONFIG_USER_ONLY)
1854 e37e863f bellard
1855 4ad40f36 bellard
static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
1856 4ad40f36 bellard
1857 e37e863f bellard
#define MMUSUFFIX _mmu
1858 4ad40f36 bellard
#define ALIGNED_ONLY
1859 e37e863f bellard
1860 e37e863f bellard
#define SHIFT 0
1861 e37e863f bellard
#include "softmmu_template.h"
1862 e37e863f bellard
1863 e37e863f bellard
#define SHIFT 1
1864 e37e863f bellard
#include "softmmu_template.h"
1865 e37e863f bellard
1866 e37e863f bellard
#define SHIFT 2
1867 e37e863f bellard
#include "softmmu_template.h"
1868 e37e863f bellard
1869 e37e863f bellard
#define SHIFT 3
1870 e37e863f bellard
#include "softmmu_template.h"
1871 e37e863f bellard
1872 4ad40f36 bellard
static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
1873 4ad40f36 bellard
{
1874 4ad40f36 bellard
    env->CP0_BadVAddr = addr;
1875 4ad40f36 bellard
    do_restore_state (retaddr);
1876 4ad40f36 bellard
    do_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
1877 4ad40f36 bellard
}
1878 4ad40f36 bellard
1879 6ebbf390 j_mayer
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1880 e37e863f bellard
{
1881 e37e863f bellard
    TranslationBlock *tb;
1882 e37e863f bellard
    CPUState *saved_env;
1883 e37e863f bellard
    unsigned long pc;
1884 e37e863f bellard
    int ret;
1885 e37e863f bellard
1886 e37e863f bellard
    /* XXX: hack to restore env in all cases, even if not called from
1887 e37e863f bellard
       generated code */
1888 e37e863f bellard
    saved_env = env;
1889 e37e863f bellard
    env = cpu_single_env;
1890 6ebbf390 j_mayer
    ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1891 e37e863f bellard
    if (ret) {
1892 e37e863f bellard
        if (retaddr) {
1893 e37e863f bellard
            /* now we have a real cpu fault */
1894 e37e863f bellard
            pc = (unsigned long)retaddr;
1895 e37e863f bellard
            tb = tb_find_pc(pc);
1896 e37e863f bellard
            if (tb) {
1897 e37e863f bellard
                /* the PC is inside the translated code. It means that we have
1898 e37e863f bellard
                   a virtual CPU fault */
1899 e37e863f bellard
                cpu_restore_state(tb, env, pc, NULL);
1900 e37e863f bellard
            }
1901 e37e863f bellard
        }
1902 e37e863f bellard
        do_raise_exception_err(env->exception_index, env->error_code);
1903 e37e863f bellard
    }
1904 e37e863f bellard
    env = saved_env;
1905 e37e863f bellard
}
1906 e37e863f bellard
1907 647de6ca ths
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1908 647de6ca ths
                          int unused)
1909 647de6ca ths
{
1910 647de6ca ths
    if (is_exec)
1911 647de6ca ths
        do_raise_exception(EXCP_IBE);
1912 647de6ca ths
    else
1913 647de6ca ths
        do_raise_exception(EXCP_DBE);
1914 647de6ca ths
}
1915 f1aa6320 ths
#endif /* !CONFIG_USER_ONLY */
1916 fd4a04eb ths
1917 fd4a04eb ths
/* Complex FPU operations which may need stack space. */
1918 fd4a04eb ths
1919 f090c9d4 pbrook
#define FLOAT_ONE32 make_float32(0x3f8 << 20)
1920 f090c9d4 pbrook
#define FLOAT_ONE64 make_float64(0x3ffULL << 52)
1921 f090c9d4 pbrook
#define FLOAT_TWO32 make_float32(1 << 30)
1922 f090c9d4 pbrook
#define FLOAT_TWO64 make_float64(1ULL << 62)
1923 54454097 ths
#define FLOAT_QNAN32 0x7fbfffff
1924 54454097 ths
#define FLOAT_QNAN64 0x7ff7ffffffffffffULL
1925 54454097 ths
#define FLOAT_SNAN32 0x7fffffff
1926 54454097 ths
#define FLOAT_SNAN64 0x7fffffffffffffffULL
1927 8dfdb87c ths
1928 fd4a04eb ths
/* convert MIPS rounding mode in FCR31 to IEEE library */
1929 fd4a04eb ths
unsigned int ieee_rm[] = {
1930 fd4a04eb ths
    float_round_nearest_even,
1931 fd4a04eb ths
    float_round_to_zero,
1932 fd4a04eb ths
    float_round_up,
1933 fd4a04eb ths
    float_round_down
1934 fd4a04eb ths
};
1935 fd4a04eb ths
1936 fd4a04eb ths
#define RESTORE_ROUNDING_MODE \
1937 ead9360e ths
    set_float_rounding_mode(ieee_rm[env->fpu->fcr31 & 3], &env->fpu->fp_status)
1938 fd4a04eb ths
1939 6c5c1e20 ths
target_ulong do_cfc1 (uint32_t reg)
1940 fd4a04eb ths
{
1941 6c5c1e20 ths
    target_ulong t0;
1942 6c5c1e20 ths
1943 ead9360e ths
    switch (reg) {
1944 ead9360e ths
    case 0:
1945 be24bb4f ths
        t0 = (int32_t)env->fpu->fcr0;
1946 ead9360e ths
        break;
1947 ead9360e ths
    case 25:
1948 be24bb4f ths
        t0 = ((env->fpu->fcr31 >> 24) & 0xfe) | ((env->fpu->fcr31 >> 23) & 0x1);
1949 ead9360e ths
        break;
1950 ead9360e ths
    case 26:
1951 be24bb4f ths
        t0 = env->fpu->fcr31 & 0x0003f07c;
1952 ead9360e ths
        break;
1953 ead9360e ths
    case 28:
1954 be24bb4f ths
        t0 = (env->fpu->fcr31 & 0x00000f83) | ((env->fpu->fcr31 >> 22) & 0x4);
1955 ead9360e ths
        break;
1956 ead9360e ths
    default:
1957 be24bb4f ths
        t0 = (int32_t)env->fpu->fcr31;
1958 ead9360e ths
        break;
1959 ead9360e ths
    }
1960 be24bb4f ths
1961 be24bb4f ths
    return t0;
1962 ead9360e ths
}
1963 ead9360e ths
1964 be24bb4f ths
void do_ctc1 (target_ulong t0, uint32_t reg)
1965 ead9360e ths
{
1966 ead9360e ths
    switch(reg) {
1967 fd4a04eb ths
    case 25:
1968 be24bb4f ths
        if (t0 & 0xffffff00)
1969 fd4a04eb ths
            return;
1970 be24bb4f ths
        env->fpu->fcr31 = (env->fpu->fcr31 & 0x017fffff) | ((t0 & 0xfe) << 24) |
1971 be24bb4f ths
                     ((t0 & 0x1) << 23);
1972 fd4a04eb ths
        break;
1973 fd4a04eb ths
    case 26:
1974 be24bb4f ths
        if (t0 & 0x007c0000)
1975 fd4a04eb ths
            return;
1976 be24bb4f ths
        env->fpu->fcr31 = (env->fpu->fcr31 & 0xfffc0f83) | (t0 & 0x0003f07c);
1977 fd4a04eb ths
        break;
1978 fd4a04eb ths
    case 28:
1979 be24bb4f ths
        if (t0 & 0x007c0000)
1980 fd4a04eb ths
            return;
1981 be24bb4f ths
        env->fpu->fcr31 = (env->fpu->fcr31 & 0xfefff07c) | (t0 & 0x00000f83) |
1982 be24bb4f ths
                     ((t0 & 0x4) << 22);
1983 fd4a04eb ths
        break;
1984 fd4a04eb ths
    case 31:
1985 be24bb4f ths
        if (t0 & 0x007c0000)
1986 fd4a04eb ths
            return;
1987 be24bb4f ths
        env->fpu->fcr31 = t0;
1988 fd4a04eb ths
        break;
1989 fd4a04eb ths
    default:
1990 fd4a04eb ths
        return;
1991 fd4a04eb ths
    }
1992 fd4a04eb ths
    /* set rounding mode */
1993 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
1994 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
1995 ead9360e ths
    if ((GET_FP_ENABLE(env->fpu->fcr31) | 0x20) & GET_FP_CAUSE(env->fpu->fcr31))
1996 fd4a04eb ths
        do_raise_exception(EXCP_FPE);
1997 fd4a04eb ths
}
1998 fd4a04eb ths
1999 c904ef0e ths
static inline char ieee_ex_to_mips(char xcpt)
2000 fd4a04eb ths
{
2001 fd4a04eb ths
    return (xcpt & float_flag_inexact) >> 5 |
2002 fd4a04eb ths
           (xcpt & float_flag_underflow) >> 3 |
2003 fd4a04eb ths
           (xcpt & float_flag_overflow) >> 1 |
2004 fd4a04eb ths
           (xcpt & float_flag_divbyzero) << 1 |
2005 fd4a04eb ths
           (xcpt & float_flag_invalid) << 4;
2006 fd4a04eb ths
}
2007 fd4a04eb ths
2008 c904ef0e ths
static inline char mips_ex_to_ieee(char xcpt)
2009 fd4a04eb ths
{
2010 fd4a04eb ths
    return (xcpt & FP_INEXACT) << 5 |
2011 fd4a04eb ths
           (xcpt & FP_UNDERFLOW) << 3 |
2012 fd4a04eb ths
           (xcpt & FP_OVERFLOW) << 1 |
2013 fd4a04eb ths
           (xcpt & FP_DIV0) >> 1 |
2014 fd4a04eb ths
           (xcpt & FP_INVALID) >> 4;
2015 fd4a04eb ths
}
2016 fd4a04eb ths
2017 c904ef0e ths
static inline void update_fcr31(void)
2018 fd4a04eb ths
{
2019 ead9360e ths
    int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fpu->fp_status));
2020 fd4a04eb ths
2021 ead9360e ths
    SET_FP_CAUSE(env->fpu->fcr31, tmp);
2022 ead9360e ths
    if (GET_FP_ENABLE(env->fpu->fcr31) & tmp)
2023 fd4a04eb ths
        do_raise_exception(EXCP_FPE);
2024 fd4a04eb ths
    else
2025 ead9360e ths
        UPDATE_FP_FLAGS(env->fpu->fcr31, tmp);
2026 fd4a04eb ths
}
2027 fd4a04eb ths
2028 a16336e4 ths
/* Float support.
2029 a16336e4 ths
   Single precition routines have a "s" suffix, double precision a
2030 a16336e4 ths
   "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps",
2031 a16336e4 ths
   paired single lower "pl", paired single upper "pu".  */
2032 a16336e4 ths
2033 a16336e4 ths
/* unary operations, modifying fp status  */
2034 b6d96bed ths
uint64_t do_float_sqrt_d(uint64_t fdt0)
2035 b6d96bed ths
{
2036 b6d96bed ths
    return float64_sqrt(fdt0, &env->fpu->fp_status);
2037 b6d96bed ths
}
2038 b6d96bed ths
2039 b6d96bed ths
uint32_t do_float_sqrt_s(uint32_t fst0)
2040 b6d96bed ths
{
2041 b6d96bed ths
    return float32_sqrt(fst0, &env->fpu->fp_status);
2042 b6d96bed ths
}
2043 a16336e4 ths
2044 b6d96bed ths
uint64_t do_float_cvtd_s(uint32_t fst0)
2045 fd4a04eb ths
{
2046 b6d96bed ths
    uint64_t fdt2;
2047 b6d96bed ths
2048 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2049 b6d96bed ths
    fdt2 = float32_to_float64(fst0, &env->fpu->fp_status);
2050 fd4a04eb ths
    update_fcr31();
2051 b6d96bed ths
    return fdt2;
2052 fd4a04eb ths
}
2053 b6d96bed ths
2054 b6d96bed ths
uint64_t do_float_cvtd_w(uint32_t wt0)
2055 fd4a04eb ths
{
2056 b6d96bed ths
    uint64_t fdt2;
2057 b6d96bed ths
2058 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2059 b6d96bed ths
    fdt2 = int32_to_float64(wt0, &env->fpu->fp_status);
2060 fd4a04eb ths
    update_fcr31();
2061 b6d96bed ths
    return fdt2;
2062 fd4a04eb ths
}
2063 b6d96bed ths
2064 b6d96bed ths
uint64_t do_float_cvtd_l(uint64_t dt0)
2065 fd4a04eb ths
{
2066 b6d96bed ths
    uint64_t fdt2;
2067 b6d96bed ths
2068 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2069 b6d96bed ths
    fdt2 = int64_to_float64(dt0, &env->fpu->fp_status);
2070 fd4a04eb ths
    update_fcr31();
2071 b6d96bed ths
    return fdt2;
2072 fd4a04eb ths
}
2073 b6d96bed ths
2074 b6d96bed ths
uint64_t do_float_cvtl_d(uint64_t fdt0)
2075 fd4a04eb ths
{
2076 b6d96bed ths
    uint64_t dt2;
2077 b6d96bed ths
2078 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2079 b6d96bed ths
    dt2 = float64_to_int64(fdt0, &env->fpu->fp_status);
2080 fd4a04eb ths
    update_fcr31();
2081 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2082 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2083 b6d96bed ths
    return dt2;
2084 fd4a04eb ths
}
2085 b6d96bed ths
2086 b6d96bed ths
uint64_t do_float_cvtl_s(uint32_t fst0)
2087 fd4a04eb ths
{
2088 b6d96bed ths
    uint64_t dt2;
2089 b6d96bed ths
2090 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2091 b6d96bed ths
    dt2 = float32_to_int64(fst0, &env->fpu->fp_status);
2092 fd4a04eb ths
    update_fcr31();
2093 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2094 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2095 b6d96bed ths
    return dt2;
2096 fd4a04eb ths
}
2097 fd4a04eb ths
2098 b6d96bed ths
uint64_t do_float_cvtps_pw(uint64_t dt0)
2099 fd4a04eb ths
{
2100 b6d96bed ths
    uint32_t fst2;
2101 b6d96bed ths
    uint32_t fsth2;
2102 b6d96bed ths
2103 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2104 b6d96bed ths
    fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->fpu->fp_status);
2105 b6d96bed ths
    fsth2 = int32_to_float32(dt0 >> 32, &env->fpu->fp_status);
2106 fd4a04eb ths
    update_fcr31();
2107 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2108 fd4a04eb ths
}
2109 b6d96bed ths
2110 b6d96bed ths
uint64_t do_float_cvtpw_ps(uint64_t fdt0)
2111 fd4a04eb ths
{
2112 b6d96bed ths
    uint32_t wt2;
2113 b6d96bed ths
    uint32_t wth2;
2114 b6d96bed ths
2115 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2116 b6d96bed ths
    wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->fpu->fp_status);
2117 b6d96bed ths
    wth2 = float32_to_int32(fdt0 >> 32, &env->fpu->fp_status);
2118 fd4a04eb ths
    update_fcr31();
2119 b6d96bed ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID)) {
2120 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2121 b6d96bed ths
        wth2 = FLOAT_SNAN32;
2122 b6d96bed ths
    }
2123 b6d96bed ths
    return ((uint64_t)wth2 << 32) | wt2;
2124 fd4a04eb ths
}
2125 b6d96bed ths
2126 b6d96bed ths
uint32_t do_float_cvts_d(uint64_t fdt0)
2127 fd4a04eb ths
{
2128 b6d96bed ths
    uint32_t fst2;
2129 b6d96bed ths
2130 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2131 b6d96bed ths
    fst2 = float64_to_float32(fdt0, &env->fpu->fp_status);
2132 fd4a04eb ths
    update_fcr31();
2133 b6d96bed ths
    return fst2;
2134 fd4a04eb ths
}
2135 b6d96bed ths
2136 b6d96bed ths
uint32_t do_float_cvts_w(uint32_t wt0)
2137 fd4a04eb ths
{
2138 b6d96bed ths
    uint32_t fst2;
2139 b6d96bed ths
2140 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2141 b6d96bed ths
    fst2 = int32_to_float32(wt0, &env->fpu->fp_status);
2142 fd4a04eb ths
    update_fcr31();
2143 b6d96bed ths
    return fst2;
2144 fd4a04eb ths
}
2145 b6d96bed ths
2146 b6d96bed ths
uint32_t do_float_cvts_l(uint64_t dt0)
2147 fd4a04eb ths
{
2148 b6d96bed ths
    uint32_t fst2;
2149 b6d96bed ths
2150 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2151 b6d96bed ths
    fst2 = int64_to_float32(dt0, &env->fpu->fp_status);
2152 fd4a04eb ths
    update_fcr31();
2153 b6d96bed ths
    return fst2;
2154 fd4a04eb ths
}
2155 b6d96bed ths
2156 b6d96bed ths
uint32_t do_float_cvts_pl(uint32_t wt0)
2157 fd4a04eb ths
{
2158 b6d96bed ths
    uint32_t wt2;
2159 b6d96bed ths
2160 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2161 b6d96bed ths
    wt2 = wt0;
2162 fd4a04eb ths
    update_fcr31();
2163 b6d96bed ths
    return wt2;
2164 fd4a04eb ths
}
2165 b6d96bed ths
2166 b6d96bed ths
uint32_t do_float_cvts_pu(uint32_t wth0)
2167 fd4a04eb ths
{
2168 b6d96bed ths
    uint32_t wt2;
2169 b6d96bed ths
2170 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2171 b6d96bed ths
    wt2 = wth0;
2172 fd4a04eb ths
    update_fcr31();
2173 b6d96bed ths
    return wt2;
2174 fd4a04eb ths
}
2175 b6d96bed ths
2176 b6d96bed ths
uint32_t do_float_cvtw_s(uint32_t fst0)
2177 fd4a04eb ths
{
2178 b6d96bed ths
    uint32_t wt2;
2179 b6d96bed ths
2180 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2181 b6d96bed ths
    wt2 = float32_to_int32(fst0, &env->fpu->fp_status);
2182 fd4a04eb ths
    update_fcr31();
2183 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2184 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2185 b6d96bed ths
    return wt2;
2186 fd4a04eb ths
}
2187 b6d96bed ths
2188 b6d96bed ths
uint32_t do_float_cvtw_d(uint64_t fdt0)
2189 fd4a04eb ths
{
2190 b6d96bed ths
    uint32_t wt2;
2191 b6d96bed ths
2192 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2193 b6d96bed ths
    wt2 = float64_to_int32(fdt0, &env->fpu->fp_status);
2194 fd4a04eb ths
    update_fcr31();
2195 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2196 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2197 b6d96bed ths
    return wt2;
2198 fd4a04eb ths
}
2199 fd4a04eb ths
2200 b6d96bed ths
uint64_t do_float_roundl_d(uint64_t fdt0)
2201 fd4a04eb ths
{
2202 b6d96bed ths
    uint64_t dt2;
2203 b6d96bed ths
2204 ead9360e ths
    set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
2205 b6d96bed ths
    dt2 = float64_to_int64(fdt0, &env->fpu->fp_status);
2206 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2207 fd4a04eb ths
    update_fcr31();
2208 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2209 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2210 b6d96bed ths
    return dt2;
2211 fd4a04eb ths
}
2212 b6d96bed ths
2213 b6d96bed ths
uint64_t do_float_roundl_s(uint32_t fst0)
2214 fd4a04eb ths
{
2215 b6d96bed ths
    uint64_t dt2;
2216 b6d96bed ths
2217 ead9360e ths
    set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
2218 b6d96bed ths
    dt2 = float32_to_int64(fst0, &env->fpu->fp_status);
2219 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2220 fd4a04eb ths
    update_fcr31();
2221 ead9360e ths
    if (GET_FP_CAUSE(env->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
uint32_t do_float_roundw_d(uint64_t fdt0)
2227 fd4a04eb ths
{
2228 b6d96bed ths
    uint32_t wt2;
2229 b6d96bed ths
2230 ead9360e ths
    set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
2231 b6d96bed ths
    wt2 = float64_to_int32(fdt0, &env->fpu->fp_status);
2232 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2233 fd4a04eb ths
    update_fcr31();
2234 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2235 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2236 b6d96bed ths
    return wt2;
2237 fd4a04eb ths
}
2238 b6d96bed ths
2239 b6d96bed ths
uint32_t do_float_roundw_s(uint32_t fst0)
2240 fd4a04eb ths
{
2241 b6d96bed ths
    uint32_t wt2;
2242 b6d96bed ths
2243 ead9360e ths
    set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
2244 b6d96bed ths
    wt2 = float32_to_int32(fst0, &env->fpu->fp_status);
2245 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2246 fd4a04eb ths
    update_fcr31();
2247 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2248 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2249 b6d96bed ths
    return wt2;
2250 fd4a04eb ths
}
2251 fd4a04eb ths
2252 b6d96bed ths
uint64_t do_float_truncl_d(uint64_t fdt0)
2253 fd4a04eb ths
{
2254 b6d96bed ths
    uint64_t dt2;
2255 b6d96bed ths
2256 b6d96bed ths
    dt2 = float64_to_int64_round_to_zero(fdt0, &env->fpu->fp_status);
2257 fd4a04eb ths
    update_fcr31();
2258 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2259 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2260 b6d96bed ths
    return dt2;
2261 fd4a04eb ths
}
2262 b6d96bed ths
2263 b6d96bed ths
uint64_t do_float_truncl_s(uint32_t fst0)
2264 fd4a04eb ths
{
2265 b6d96bed ths
    uint64_t dt2;
2266 b6d96bed ths
2267 b6d96bed ths
    dt2 = float32_to_int64_round_to_zero(fst0, &env->fpu->fp_status);
2268 fd4a04eb ths
    update_fcr31();
2269 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2270 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2271 b6d96bed ths
    return dt2;
2272 fd4a04eb ths
}
2273 b6d96bed ths
2274 b6d96bed ths
uint32_t do_float_truncw_d(uint64_t fdt0)
2275 fd4a04eb ths
{
2276 b6d96bed ths
    uint32_t wt2;
2277 b6d96bed ths
2278 b6d96bed ths
    wt2 = float64_to_int32_round_to_zero(fdt0, &env->fpu->fp_status);
2279 fd4a04eb ths
    update_fcr31();
2280 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2281 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2282 b6d96bed ths
    return wt2;
2283 fd4a04eb ths
}
2284 b6d96bed ths
2285 b6d96bed ths
uint32_t do_float_truncw_s(uint32_t fst0)
2286 fd4a04eb ths
{
2287 b6d96bed ths
    uint32_t wt2;
2288 b6d96bed ths
2289 b6d96bed ths
    wt2 = float32_to_int32_round_to_zero(fst0, &env->fpu->fp_status);
2290 fd4a04eb ths
    update_fcr31();
2291 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2292 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2293 b6d96bed ths
    return wt2;
2294 fd4a04eb ths
}
2295 fd4a04eb ths
2296 b6d96bed ths
uint64_t do_float_ceill_d(uint64_t fdt0)
2297 fd4a04eb ths
{
2298 b6d96bed ths
    uint64_t dt2;
2299 b6d96bed ths
2300 ead9360e ths
    set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
2301 b6d96bed ths
    dt2 = float64_to_int64(fdt0, &env->fpu->fp_status);
2302 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2303 fd4a04eb ths
    update_fcr31();
2304 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2305 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2306 b6d96bed ths
    return dt2;
2307 fd4a04eb ths
}
2308 b6d96bed ths
2309 b6d96bed ths
uint64_t do_float_ceill_s(uint32_t fst0)
2310 fd4a04eb ths
{
2311 b6d96bed ths
    uint64_t dt2;
2312 b6d96bed ths
2313 ead9360e ths
    set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
2314 b6d96bed ths
    dt2 = float32_to_int64(fst0, &env->fpu->fp_status);
2315 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2316 fd4a04eb ths
    update_fcr31();
2317 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2318 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2319 b6d96bed ths
    return dt2;
2320 fd4a04eb ths
}
2321 b6d96bed ths
2322 b6d96bed ths
uint32_t do_float_ceilw_d(uint64_t fdt0)
2323 fd4a04eb ths
{
2324 b6d96bed ths
    uint32_t wt2;
2325 b6d96bed ths
2326 ead9360e ths
    set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
2327 b6d96bed ths
    wt2 = float64_to_int32(fdt0, &env->fpu->fp_status);
2328 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2329 fd4a04eb ths
    update_fcr31();
2330 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2331 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2332 b6d96bed ths
    return wt2;
2333 fd4a04eb ths
}
2334 b6d96bed ths
2335 b6d96bed ths
uint32_t do_float_ceilw_s(uint32_t fst0)
2336 fd4a04eb ths
{
2337 b6d96bed ths
    uint32_t wt2;
2338 b6d96bed ths
2339 ead9360e ths
    set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
2340 b6d96bed ths
    wt2 = float32_to_int32(fst0, &env->fpu->fp_status);
2341 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2342 fd4a04eb ths
    update_fcr31();
2343 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2344 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2345 b6d96bed ths
    return wt2;
2346 fd4a04eb ths
}
2347 fd4a04eb ths
2348 b6d96bed ths
uint64_t do_float_floorl_d(uint64_t fdt0)
2349 fd4a04eb ths
{
2350 b6d96bed ths
    uint64_t dt2;
2351 b6d96bed ths
2352 ead9360e ths
    set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
2353 b6d96bed ths
    dt2 = float64_to_int64(fdt0, &env->fpu->fp_status);
2354 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2355 fd4a04eb ths
    update_fcr31();
2356 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2357 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2358 b6d96bed ths
    return dt2;
2359 fd4a04eb ths
}
2360 b6d96bed ths
2361 b6d96bed ths
uint64_t do_float_floorl_s(uint32_t fst0)
2362 fd4a04eb ths
{
2363 b6d96bed ths
    uint64_t dt2;
2364 b6d96bed ths
2365 ead9360e ths
    set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
2366 b6d96bed ths
    dt2 = float32_to_int64(fst0, &env->fpu->fp_status);
2367 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2368 fd4a04eb ths
    update_fcr31();
2369 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2370 b6d96bed ths
        dt2 = FLOAT_SNAN64;
2371 b6d96bed ths
    return dt2;
2372 fd4a04eb ths
}
2373 b6d96bed ths
2374 b6d96bed ths
uint32_t do_float_floorw_d(uint64_t fdt0)
2375 fd4a04eb ths
{
2376 b6d96bed ths
    uint32_t wt2;
2377 b6d96bed ths
2378 ead9360e ths
    set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
2379 b6d96bed ths
    wt2 = float64_to_int32(fdt0, &env->fpu->fp_status);
2380 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2381 fd4a04eb ths
    update_fcr31();
2382 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2383 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2384 b6d96bed ths
    return wt2;
2385 fd4a04eb ths
}
2386 b6d96bed ths
2387 b6d96bed ths
uint32_t do_float_floorw_s(uint32_t fst0)
2388 fd4a04eb ths
{
2389 b6d96bed ths
    uint32_t wt2;
2390 b6d96bed ths
2391 ead9360e ths
    set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
2392 b6d96bed ths
    wt2 = float32_to_int32(fst0, &env->fpu->fp_status);
2393 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2394 fd4a04eb ths
    update_fcr31();
2395 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2396 b6d96bed ths
        wt2 = FLOAT_SNAN32;
2397 b6d96bed ths
    return wt2;
2398 fd4a04eb ths
}
2399 fd4a04eb ths
2400 a16336e4 ths
/* unary operations, not modifying fp status  */
2401 b6d96bed ths
#define FLOAT_UNOP(name)                                       \
2402 b6d96bed ths
uint64_t do_float_ ## name ## _d(uint64_t fdt0)                \
2403 b6d96bed ths
{                                                              \
2404 b6d96bed ths
    return float64_ ## name(fdt0);                             \
2405 b6d96bed ths
}                                                              \
2406 b6d96bed ths
uint32_t do_float_ ## name ## _s(uint32_t fst0)                \
2407 b6d96bed ths
{                                                              \
2408 b6d96bed ths
    return float32_ ## name(fst0);                             \
2409 b6d96bed ths
}                                                              \
2410 b6d96bed ths
uint64_t do_float_ ## name ## _ps(uint64_t fdt0)               \
2411 b6d96bed ths
{                                                              \
2412 b6d96bed ths
    uint32_t wt0;                                              \
2413 b6d96bed ths
    uint32_t wth0;                                             \
2414 b6d96bed ths
                                                               \
2415 b6d96bed ths
    wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF);                 \
2416 b6d96bed ths
    wth0 = float32_ ## name(fdt0 >> 32);                       \
2417 b6d96bed ths
    return ((uint64_t)wth0 << 32) | wt0;                       \
2418 a16336e4 ths
}
2419 a16336e4 ths
FLOAT_UNOP(abs)
2420 a16336e4 ths
FLOAT_UNOP(chs)
2421 a16336e4 ths
#undef FLOAT_UNOP
2422 a16336e4 ths
2423 8dfdb87c ths
/* MIPS specific unary operations */
2424 b6d96bed ths
uint64_t do_float_recip_d(uint64_t fdt0)
2425 8dfdb87c ths
{
2426 b6d96bed ths
    uint64_t fdt2;
2427 b6d96bed ths
2428 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2429 b6d96bed ths
    fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->fpu->fp_status);
2430 8dfdb87c ths
    update_fcr31();
2431 b6d96bed ths
    return fdt2;
2432 8dfdb87c ths
}
2433 b6d96bed ths
2434 b6d96bed ths
uint32_t do_float_recip_s(uint32_t fst0)
2435 8dfdb87c ths
{
2436 b6d96bed ths
    uint32_t fst2;
2437 b6d96bed ths
2438 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2439 b6d96bed ths
    fst2 = float32_div(FLOAT_ONE32, fst0, &env->fpu->fp_status);
2440 8dfdb87c ths
    update_fcr31();
2441 b6d96bed ths
    return fst2;
2442 57fa1fb3 ths
}
2443 57fa1fb3 ths
2444 b6d96bed ths
uint64_t do_float_rsqrt_d(uint64_t fdt0)
2445 8dfdb87c ths
{
2446 b6d96bed ths
    uint64_t fdt2;
2447 b6d96bed ths
2448 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2449 b6d96bed ths
    fdt2 = float64_sqrt(fdt0, &env->fpu->fp_status);
2450 b6d96bed ths
    fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->fpu->fp_status);
2451 8dfdb87c ths
    update_fcr31();
2452 b6d96bed ths
    return fdt2;
2453 8dfdb87c ths
}
2454 b6d96bed ths
2455 b6d96bed ths
uint32_t do_float_rsqrt_s(uint32_t fst0)
2456 8dfdb87c ths
{
2457 b6d96bed ths
    uint32_t fst2;
2458 b6d96bed ths
2459 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2460 b6d96bed ths
    fst2 = float32_sqrt(fst0, &env->fpu->fp_status);
2461 b6d96bed ths
    fst2 = float32_div(FLOAT_ONE32, fst2, &env->fpu->fp_status);
2462 8dfdb87c ths
    update_fcr31();
2463 b6d96bed ths
    return fst2;
2464 8dfdb87c ths
}
2465 8dfdb87c ths
2466 b6d96bed ths
uint64_t do_float_recip1_d(uint64_t fdt0)
2467 8dfdb87c ths
{
2468 b6d96bed ths
    uint64_t fdt2;
2469 b6d96bed ths
2470 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2471 b6d96bed ths
    fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->fpu->fp_status);
2472 8dfdb87c ths
    update_fcr31();
2473 b6d96bed ths
    return fdt2;
2474 8dfdb87c ths
}
2475 b6d96bed ths
2476 b6d96bed ths
uint32_t do_float_recip1_s(uint32_t fst0)
2477 8dfdb87c ths
{
2478 b6d96bed ths
    uint32_t fst2;
2479 b6d96bed ths
2480 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2481 b6d96bed ths
    fst2 = float32_div(FLOAT_ONE32, fst0, &env->fpu->fp_status);
2482 8dfdb87c ths
    update_fcr31();
2483 b6d96bed ths
    return fst2;
2484 8dfdb87c ths
}
2485 b6d96bed ths
2486 b6d96bed ths
uint64_t do_float_recip1_ps(uint64_t fdt0)
2487 8dfdb87c ths
{
2488 b6d96bed ths
    uint32_t fst2;
2489 b6d96bed ths
    uint32_t fsth2;
2490 b6d96bed ths
2491 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2492 b6d96bed ths
    fst2 = float32_div(FLOAT_ONE32, fdt0 & 0XFFFFFFFF, &env->fpu->fp_status);
2493 b6d96bed ths
    fsth2 = float32_div(FLOAT_ONE32, fdt0 >> 32, &env->fpu->fp_status);
2494 8dfdb87c ths
    update_fcr31();
2495 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2496 8dfdb87c ths
}
2497 8dfdb87c ths
2498 b6d96bed ths
uint64_t do_float_rsqrt1_d(uint64_t fdt0)
2499 8dfdb87c ths
{
2500 b6d96bed ths
    uint64_t fdt2;
2501 b6d96bed ths
2502 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2503 b6d96bed ths
    fdt2 = float64_sqrt(fdt0, &env->fpu->fp_status);
2504 b6d96bed ths
    fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->fpu->fp_status);
2505 8dfdb87c ths
    update_fcr31();
2506 b6d96bed ths
    return fdt2;
2507 8dfdb87c ths
}
2508 b6d96bed ths
2509 b6d96bed ths
uint32_t do_float_rsqrt1_s(uint32_t fst0)
2510 8dfdb87c ths
{
2511 b6d96bed ths
    uint32_t fst2;
2512 b6d96bed ths
2513 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2514 b6d96bed ths
    fst2 = float32_sqrt(fst0, &env->fpu->fp_status);
2515 b6d96bed ths
    fst2 = float32_div(FLOAT_ONE32, fst2, &env->fpu->fp_status);
2516 8dfdb87c ths
    update_fcr31();
2517 b6d96bed ths
    return fst2;
2518 8dfdb87c ths
}
2519 b6d96bed ths
2520 b6d96bed ths
uint64_t do_float_rsqrt1_ps(uint64_t fdt0)
2521 8dfdb87c ths
{
2522 b6d96bed ths
    uint32_t fst2;
2523 b6d96bed ths
    uint32_t fsth2;
2524 b6d96bed ths
2525 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2526 b6d96bed ths
    fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->fpu->fp_status);
2527 b6d96bed ths
    fsth2 = float32_sqrt(fdt0 >> 32, &env->fpu->fp_status);
2528 b6d96bed ths
    fst2 = float32_div(FLOAT_ONE32, fst2, &env->fpu->fp_status);
2529 b6d96bed ths
    fsth2 = float32_div(FLOAT_ONE32, fsth2, &env->fpu->fp_status);
2530 8dfdb87c ths
    update_fcr31();
2531 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2532 57fa1fb3 ths
}
2533 57fa1fb3 ths
2534 b6d96bed ths
#define FLOAT_OP(name, p) void do_float_##name##_##p(void)
2535 b6d96bed ths
2536 fd4a04eb ths
/* binary operations */
2537 b6d96bed ths
#define FLOAT_BINOP(name)                                          \
2538 b6d96bed ths
uint64_t do_float_ ## name ## _d(uint64_t fdt0, uint64_t fdt1)     \
2539 b6d96bed ths
{                                                                  \
2540 b6d96bed ths
    uint64_t dt2;                                                  \
2541 b6d96bed ths
                                                                   \
2542 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);            \
2543 b6d96bed ths
    dt2 = float64_ ## name (fdt0, fdt1, &env->fpu->fp_status);     \
2544 ead9360e ths
    update_fcr31();                                                \
2545 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID)                \
2546 b6d96bed ths
        dt2 = FLOAT_QNAN64;                                        \
2547 b6d96bed ths
    return dt2;                                                    \
2548 b6d96bed ths
}                                                                  \
2549 b6d96bed ths
                                                                   \
2550 b6d96bed ths
uint32_t do_float_ ## name ## _s(uint32_t fst0, uint32_t fst1)     \
2551 b6d96bed ths
{                                                                  \
2552 b6d96bed ths
    uint32_t wt2;                                                  \
2553 b6d96bed ths
                                                                   \
2554 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);            \
2555 b6d96bed ths
    wt2 = float32_ ## name (fst0, fst1, &env->fpu->fp_status);     \
2556 ead9360e ths
    update_fcr31();                                                \
2557 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID)                \
2558 b6d96bed ths
        wt2 = FLOAT_QNAN32;                                        \
2559 b6d96bed ths
    return wt2;                                                    \
2560 b6d96bed ths
}                                                                  \
2561 b6d96bed ths
                                                                   \
2562 b6d96bed ths
uint64_t do_float_ ## name ## _ps(uint64_t fdt0, uint64_t fdt1)    \
2563 b6d96bed ths
{                                                                  \
2564 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;                             \
2565 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;                                   \
2566 b6d96bed ths
    uint32_t fst1 = fdt1 & 0XFFFFFFFF;                             \
2567 b6d96bed ths
    uint32_t fsth1 = fdt1 >> 32;                                   \
2568 b6d96bed ths
    uint32_t wt2;                                                  \
2569 b6d96bed ths
    uint32_t wth2;                                                 \
2570 b6d96bed ths
                                                                   \
2571 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);            \
2572 b6d96bed ths
    wt2 = float32_ ## name (fst0, fst1, &env->fpu->fp_status);     \
2573 b6d96bed ths
    wth2 = float32_ ## name (fsth0, fsth1, &env->fpu->fp_status);  \
2574 b6d96bed ths
    update_fcr31();                                                \
2575 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) {              \
2576 b6d96bed ths
        wt2 = FLOAT_QNAN32;                                        \
2577 b6d96bed ths
        wth2 = FLOAT_QNAN32;                                       \
2578 b6d96bed ths
    }                                                              \
2579 b6d96bed ths
    return ((uint64_t)wth2 << 32) | wt2;                           \
2580 fd4a04eb ths
}
2581 b6d96bed ths
2582 fd4a04eb ths
FLOAT_BINOP(add)
2583 fd4a04eb ths
FLOAT_BINOP(sub)
2584 fd4a04eb ths
FLOAT_BINOP(mul)
2585 fd4a04eb ths
FLOAT_BINOP(div)
2586 fd4a04eb ths
#undef FLOAT_BINOP
2587 fd4a04eb ths
2588 a16336e4 ths
/* ternary operations */
2589 b6d96bed ths
#define FLOAT_TERNOP(name1, name2)                                        \
2590 b6d96bed ths
uint64_t do_float_ ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1,  \
2591 b6d96bed ths
                                           uint64_t fdt2)                 \
2592 b6d96bed ths
{                                                                         \
2593 b6d96bed ths
    fdt0 = float64_ ## name1 (fdt0, fdt1, &env->fpu->fp_status);          \
2594 b6d96bed ths
    return float64_ ## name2 (fdt0, fdt2, &env->fpu->fp_status);          \
2595 b6d96bed ths
}                                                                         \
2596 b6d96bed ths
                                                                          \
2597 b6d96bed ths
uint32_t do_float_ ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1,  \
2598 b6d96bed ths
                                           uint32_t fst2)                 \
2599 b6d96bed ths
{                                                                         \
2600 b6d96bed ths
    fst0 = float32_ ## name1 (fst0, fst1, &env->fpu->fp_status);          \
2601 b6d96bed ths
    return float32_ ## name2 (fst0, fst2, &env->fpu->fp_status);          \
2602 b6d96bed ths
}                                                                         \
2603 b6d96bed ths
                                                                          \
2604 b6d96bed ths
uint64_t do_float_ ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1, \
2605 b6d96bed ths
                                            uint64_t fdt2)                \
2606 b6d96bed ths
{                                                                         \
2607 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;                                    \
2608 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;                                          \
2609 b6d96bed ths
    uint32_t fst1 = fdt1 & 0XFFFFFFFF;                                    \
2610 b6d96bed ths
    uint32_t fsth1 = fdt1 >> 32;                                          \
2611 b6d96bed ths
    uint32_t fst2 = fdt2 & 0XFFFFFFFF;                                    \
2612 b6d96bed ths
    uint32_t fsth2 = fdt2 >> 32;                                          \
2613 b6d96bed ths
                                                                          \
2614 b6d96bed ths
    fst0 = float32_ ## name1 (fst0, fst1, &env->fpu->fp_status);          \
2615 b6d96bed ths
    fsth0 = float32_ ## name1 (fsth0, fsth1, &env->fpu->fp_status);       \
2616 b6d96bed ths
    fst2 = float32_ ## name2 (fst0, fst2, &env->fpu->fp_status);          \
2617 b6d96bed ths
    fsth2 = float32_ ## name2 (fsth0, fsth2, &env->fpu->fp_status);       \
2618 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;                                \
2619 a16336e4 ths
}
2620 b6d96bed ths
2621 a16336e4 ths
FLOAT_TERNOP(mul, add)
2622 a16336e4 ths
FLOAT_TERNOP(mul, sub)
2623 a16336e4 ths
#undef FLOAT_TERNOP
2624 a16336e4 ths
2625 a16336e4 ths
/* negated ternary operations */
2626 b6d96bed ths
#define FLOAT_NTERNOP(name1, name2)                                       \
2627 b6d96bed ths
uint64_t do_float_n ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1, \
2628 b6d96bed ths
                                           uint64_t fdt2)                 \
2629 b6d96bed ths
{                                                                         \
2630 b6d96bed ths
    fdt0 = float64_ ## name1 (fdt0, fdt1, &env->fpu->fp_status);          \
2631 b6d96bed ths
    fdt2 = float64_ ## name2 (fdt0, fdt2, &env->fpu->fp_status);          \
2632 b6d96bed ths
    return float64_chs(fdt2);                                             \
2633 b6d96bed ths
}                                                                         \
2634 b6d96bed ths
                                                                          \
2635 b6d96bed ths
uint32_t do_float_n ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1, \
2636 b6d96bed ths
                                           uint32_t fst2)                 \
2637 b6d96bed ths
{                                                                         \
2638 b6d96bed ths
    fst0 = float32_ ## name1 (fst0, fst1, &env->fpu->fp_status);          \
2639 b6d96bed ths
    fst2 = float32_ ## name2 (fst0, fst2, &env->fpu->fp_status);          \
2640 b6d96bed ths
    return float32_chs(fst2);                                             \
2641 b6d96bed ths
}                                                                         \
2642 b6d96bed ths
                                                                          \
2643 b6d96bed ths
uint64_t do_float_n ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1,\
2644 b6d96bed ths
                                           uint64_t fdt2)                 \
2645 b6d96bed ths
{                                                                         \
2646 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;                                    \
2647 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;                                          \
2648 b6d96bed ths
    uint32_t fst1 = fdt1 & 0XFFFFFFFF;                                    \
2649 b6d96bed ths
    uint32_t fsth1 = fdt1 >> 32;                                          \
2650 b6d96bed ths
    uint32_t fst2 = fdt2 & 0XFFFFFFFF;                                    \
2651 b6d96bed ths
    uint32_t fsth2 = fdt2 >> 32;                                          \
2652 b6d96bed ths
                                                                          \
2653 b6d96bed ths
    fst0 = float32_ ## name1 (fst0, fst1, &env->fpu->fp_status);          \
2654 b6d96bed ths
    fsth0 = float32_ ## name1 (fsth0, fsth1, &env->fpu->fp_status);       \
2655 b6d96bed ths
    fst2 = float32_ ## name2 (fst0, fst2, &env->fpu->fp_status);          \
2656 b6d96bed ths
    fsth2 = float32_ ## name2 (fsth0, fsth2, &env->fpu->fp_status);       \
2657 b6d96bed ths
    fst2 = float32_chs(fst2);                                             \
2658 b6d96bed ths
    fsth2 = float32_chs(fsth2);                                           \
2659 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;                                \
2660 a16336e4 ths
}
2661 b6d96bed ths
2662 a16336e4 ths
FLOAT_NTERNOP(mul, add)
2663 a16336e4 ths
FLOAT_NTERNOP(mul, sub)
2664 a16336e4 ths
#undef FLOAT_NTERNOP
2665 a16336e4 ths
2666 8dfdb87c ths
/* MIPS specific binary operations */
2667 b6d96bed ths
uint64_t do_float_recip2_d(uint64_t fdt0, uint64_t fdt2)
2668 8dfdb87c ths
{
2669 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2670 b6d96bed ths
    fdt2 = float64_mul(fdt0, fdt2, &env->fpu->fp_status);
2671 b6d96bed ths
    fdt2 = float64_chs(float64_sub(fdt2, FLOAT_ONE64, &env->fpu->fp_status));
2672 8dfdb87c ths
    update_fcr31();
2673 b6d96bed ths
    return fdt2;
2674 8dfdb87c ths
}
2675 b6d96bed ths
2676 b6d96bed ths
uint32_t do_float_recip2_s(uint32_t fst0, uint32_t fst2)
2677 8dfdb87c ths
{
2678 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2679 b6d96bed ths
    fst2 = float32_mul(fst0, fst2, &env->fpu->fp_status);
2680 b6d96bed ths
    fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->fpu->fp_status));
2681 8dfdb87c ths
    update_fcr31();
2682 b6d96bed ths
    return fst2;
2683 8dfdb87c ths
}
2684 b6d96bed ths
2685 b6d96bed ths
uint64_t do_float_recip2_ps(uint64_t fdt0, uint64_t fdt2)
2686 8dfdb87c ths
{
2687 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2688 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;
2689 b6d96bed ths
    uint32_t fst2 = fdt2 & 0XFFFFFFFF;
2690 b6d96bed ths
    uint32_t fsth2 = fdt2 >> 32;
2691 b6d96bed ths
2692 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2693 b6d96bed ths
    fst2 = float32_mul(fst0, fst2, &env->fpu->fp_status);
2694 b6d96bed ths
    fsth2 = float32_mul(fsth0, fsth2, &env->fpu->fp_status);
2695 b6d96bed ths
    fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->fpu->fp_status));
2696 b6d96bed ths
    fsth2 = float32_chs(float32_sub(fsth2, FLOAT_ONE32, &env->fpu->fp_status));
2697 8dfdb87c ths
    update_fcr31();
2698 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2699 8dfdb87c ths
}
2700 8dfdb87c ths
2701 b6d96bed ths
uint64_t do_float_rsqrt2_d(uint64_t fdt0, uint64_t fdt2)
2702 8dfdb87c ths
{
2703 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2704 b6d96bed ths
    fdt2 = float64_mul(fdt0, fdt2, &env->fpu->fp_status);
2705 b6d96bed ths
    fdt2 = float64_sub(fdt2, FLOAT_ONE64, &env->fpu->fp_status);
2706 b6d96bed ths
    fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->fpu->fp_status));
2707 8dfdb87c ths
    update_fcr31();
2708 b6d96bed ths
    return fdt2;
2709 8dfdb87c ths
}
2710 b6d96bed ths
2711 b6d96bed ths
uint32_t do_float_rsqrt2_s(uint32_t fst0, uint32_t fst2)
2712 8dfdb87c ths
{
2713 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2714 b6d96bed ths
    fst2 = float32_mul(fst0, fst2, &env->fpu->fp_status);
2715 b6d96bed ths
    fst2 = float32_sub(fst2, FLOAT_ONE32, &env->fpu->fp_status);
2716 b6d96bed ths
    fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->fpu->fp_status));
2717 8dfdb87c ths
    update_fcr31();
2718 b6d96bed ths
    return fst2;
2719 8dfdb87c ths
}
2720 b6d96bed ths
2721 b6d96bed ths
uint64_t do_float_rsqrt2_ps(uint64_t fdt0, uint64_t fdt2)
2722 8dfdb87c ths
{
2723 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2724 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;
2725 b6d96bed ths
    uint32_t fst2 = fdt2 & 0XFFFFFFFF;
2726 b6d96bed ths
    uint32_t fsth2 = fdt2 >> 32;
2727 b6d96bed ths
2728 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2729 b6d96bed ths
    fst2 = float32_mul(fst0, fst2, &env->fpu->fp_status);
2730 b6d96bed ths
    fsth2 = float32_mul(fsth0, fsth2, &env->fpu->fp_status);
2731 b6d96bed ths
    fst2 = float32_sub(fst2, FLOAT_ONE32, &env->fpu->fp_status);
2732 b6d96bed ths
    fsth2 = float32_sub(fsth2, FLOAT_ONE32, &env->fpu->fp_status);
2733 b6d96bed ths
    fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->fpu->fp_status));
2734 b6d96bed ths
    fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->fpu->fp_status));
2735 8dfdb87c ths
    update_fcr31();
2736 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2737 57fa1fb3 ths
}
2738 57fa1fb3 ths
2739 b6d96bed ths
uint64_t do_float_addr_ps(uint64_t fdt0, uint64_t fdt1)
2740 fd4a04eb ths
{
2741 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2742 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;
2743 b6d96bed ths
    uint32_t fst1 = fdt1 & 0XFFFFFFFF;
2744 b6d96bed ths
    uint32_t fsth1 = fdt1 >> 32;
2745 b6d96bed ths
    uint32_t fst2;
2746 b6d96bed ths
    uint32_t fsth2;
2747 b6d96bed ths
2748 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2749 b6d96bed ths
    fst2 = float32_add (fst0, fsth0, &env->fpu->fp_status);
2750 b6d96bed ths
    fsth2 = float32_add (fst1, fsth1, &env->fpu->fp_status);
2751 fd4a04eb ths
    update_fcr31();
2752 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2753 fd4a04eb ths
}
2754 fd4a04eb ths
2755 b6d96bed ths
uint64_t do_float_mulr_ps(uint64_t fdt0, uint64_t fdt1)
2756 57fa1fb3 ths
{
2757 b6d96bed ths
    uint32_t fst0 = fdt0 & 0XFFFFFFFF;
2758 b6d96bed ths
    uint32_t fsth0 = fdt0 >> 32;
2759 b6d96bed ths
    uint32_t fst1 = fdt1 & 0XFFFFFFFF;
2760 b6d96bed ths
    uint32_t fsth1 = fdt1 >> 32;
2761 b6d96bed ths
    uint32_t fst2;
2762 b6d96bed ths
    uint32_t fsth2;
2763 b6d96bed ths
2764 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2765 b6d96bed ths
    fst2 = float32_mul (fst0, fsth0, &env->fpu->fp_status);
2766 b6d96bed ths
    fsth2 = float32_mul (fst1, fsth1, &env->fpu->fp_status);
2767 57fa1fb3 ths
    update_fcr31();
2768 b6d96bed ths
    return ((uint64_t)fsth2 << 32) | fst2;
2769 57fa1fb3 ths
}
2770 57fa1fb3 ths
2771 8dfdb87c ths
/* compare operations */
2772 b6d96bed ths
#define FOP_COND_D(op, cond)                                   \
2773 b6d96bed ths
void do_cmp_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
2774 b6d96bed ths
{                                                              \
2775 b6d96bed ths
    int c = cond;                                              \
2776 b6d96bed ths
    update_fcr31();                                            \
2777 b6d96bed ths
    if (c)                                                     \
2778 b6d96bed ths
        SET_FP_COND(cc, env->fpu);                             \
2779 b6d96bed ths
    else                                                       \
2780 b6d96bed ths
        CLEAR_FP_COND(cc, env->fpu);                           \
2781 b6d96bed ths
}                                                              \
2782 b6d96bed ths
void do_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
2783 b6d96bed ths
{                                                              \
2784 b6d96bed ths
    int c;                                                     \
2785 b6d96bed ths
    fdt0 = float64_abs(fdt0);                                  \
2786 b6d96bed ths
    fdt1 = float64_abs(fdt1);                                  \
2787 b6d96bed ths
    c = cond;                                                  \
2788 b6d96bed ths
    update_fcr31();                                            \
2789 b6d96bed ths
    if (c)                                                     \
2790 b6d96bed ths
        SET_FP_COND(cc, env->fpu);                             \
2791 b6d96bed ths
    else                                                       \
2792 b6d96bed ths
        CLEAR_FP_COND(cc, env->fpu);                           \
2793 fd4a04eb ths
}
2794 fd4a04eb ths
2795 fd4a04eb ths
int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
2796 fd4a04eb ths
{
2797 fd4a04eb ths
    if (float64_is_signaling_nan(a) ||
2798 fd4a04eb ths
        float64_is_signaling_nan(b) ||
2799 fd4a04eb ths
        (sig && (float64_is_nan(a) || float64_is_nan(b)))) {
2800 fd4a04eb ths
        float_raise(float_flag_invalid, status);
2801 fd4a04eb ths
        return 1;
2802 fd4a04eb ths
    } else if (float64_is_nan(a) || float64_is_nan(b)) {
2803 fd4a04eb ths
        return 1;
2804 fd4a04eb ths
    } else {
2805 fd4a04eb ths
        return 0;
2806 fd4a04eb ths
    }
2807 fd4a04eb ths
}
2808 fd4a04eb ths
2809 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2810 fd4a04eb ths
 * but float*_is_unordered() is still called. */
2811 b6d96bed ths
FOP_COND_D(f,   (float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status), 0))
2812 b6d96bed ths
FOP_COND_D(un,  float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status))
2813 b6d96bed ths
FOP_COND_D(eq,  !float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status) && float64_eq(fdt0, fdt1, &env->fpu->fp_status))
2814 b6d96bed ths
FOP_COND_D(ueq, float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status)  || float64_eq(fdt0, fdt1, &env->fpu->fp_status))
2815 b6d96bed ths
FOP_COND_D(olt, !float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status) && float64_lt(fdt0, fdt1, &env->fpu->fp_status))
2816 b6d96bed ths
FOP_COND_D(ult, float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status)  || float64_lt(fdt0, fdt1, &env->fpu->fp_status))
2817 b6d96bed ths
FOP_COND_D(ole, !float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status) && float64_le(fdt0, fdt1, &env->fpu->fp_status))
2818 b6d96bed ths
FOP_COND_D(ule, float64_is_unordered(0, fdt1, fdt0, &env->fpu->fp_status)  || float64_le(fdt0, fdt1, &env->fpu->fp_status))
2819 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2820 fd4a04eb ths
 * but float*_is_unordered() is still called. */
2821 b6d96bed ths
FOP_COND_D(sf,  (float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status), 0))
2822 b6d96bed ths
FOP_COND_D(ngle,float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status))
2823 b6d96bed ths
FOP_COND_D(seq, !float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status) && float64_eq(fdt0, fdt1, &env->fpu->fp_status))
2824 b6d96bed ths
FOP_COND_D(ngl, float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status)  || float64_eq(fdt0, fdt1, &env->fpu->fp_status))
2825 b6d96bed ths
FOP_COND_D(lt,  !float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status) && float64_lt(fdt0, fdt1, &env->fpu->fp_status))
2826 b6d96bed ths
FOP_COND_D(nge, float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status)  || float64_lt(fdt0, fdt1, &env->fpu->fp_status))
2827 b6d96bed ths
FOP_COND_D(le,  !float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status) && float64_le(fdt0, fdt1, &env->fpu->fp_status))
2828 b6d96bed ths
FOP_COND_D(ngt, float64_is_unordered(1, fdt1, fdt0, &env->fpu->fp_status)  || float64_le(fdt0, fdt1, &env->fpu->fp_status))
2829 b6d96bed ths
2830 b6d96bed ths
#define FOP_COND_S(op, cond)                                   \
2831 b6d96bed ths
void do_cmp_s_ ## op (uint32_t fst0, uint32_t fst1, int cc)    \
2832 b6d96bed ths
{                                                              \
2833 b6d96bed ths
    int c = cond;                                              \
2834 b6d96bed ths
    update_fcr31();                                            \
2835 b6d96bed ths
    if (c)                                                     \
2836 b6d96bed ths
        SET_FP_COND(cc, env->fpu);                             \
2837 b6d96bed ths
    else                                                       \
2838 b6d96bed ths
        CLEAR_FP_COND(cc, env->fpu);                           \
2839 b6d96bed ths
}                                                              \
2840 b6d96bed ths
void do_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
2841 b6d96bed ths
{                                                              \
2842 b6d96bed ths
    int c;                                                     \
2843 b6d96bed ths
    fst0 = float32_abs(fst0);                                  \
2844 b6d96bed ths
    fst1 = float32_abs(fst1);                                  \
2845 b6d96bed ths
    c = cond;                                                  \
2846 b6d96bed ths
    update_fcr31();                                            \
2847 b6d96bed ths
    if (c)                                                     \
2848 b6d96bed ths
        SET_FP_COND(cc, env->fpu);                             \
2849 b6d96bed ths
    else                                                       \
2850 b6d96bed ths
        CLEAR_FP_COND(cc, env->fpu);                           \
2851 fd4a04eb ths
}
2852 fd4a04eb ths
2853 fd4a04eb ths
flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
2854 fd4a04eb ths
{
2855 fd4a04eb ths
    if (float32_is_signaling_nan(a) ||
2856 fd4a04eb ths
        float32_is_signaling_nan(b) ||
2857 fd4a04eb ths
        (sig && (float32_is_nan(a) || float32_is_nan(b)))) {
2858 fd4a04eb ths
        float_raise(float_flag_invalid, status);
2859 fd4a04eb ths
        return 1;
2860 fd4a04eb ths
    } else if (float32_is_nan(a) || float32_is_nan(b)) {
2861 fd4a04eb ths
        return 1;
2862 fd4a04eb ths
    } else {
2863 fd4a04eb ths
        return 0;
2864 fd4a04eb ths
    }
2865 fd4a04eb ths
}
2866 fd4a04eb ths
2867 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2868 fd4a04eb ths
 * but float*_is_unordered() is still called. */
2869 b6d96bed ths
FOP_COND_S(f,   (float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status), 0))
2870 b6d96bed ths
FOP_COND_S(un,  float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status))
2871 b6d96bed ths
FOP_COND_S(eq,  !float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status) && float32_eq(fst0, fst1, &env->fpu->fp_status))
2872 b6d96bed ths
FOP_COND_S(ueq, float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status)  || float32_eq(fst0, fst1, &env->fpu->fp_status))
2873 b6d96bed ths
FOP_COND_S(olt, !float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status) && float32_lt(fst0, fst1, &env->fpu->fp_status))
2874 b6d96bed ths
FOP_COND_S(ult, float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status)  || float32_lt(fst0, fst1, &env->fpu->fp_status))
2875 b6d96bed ths
FOP_COND_S(ole, !float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status) && float32_le(fst0, fst1, &env->fpu->fp_status))
2876 b6d96bed ths
FOP_COND_S(ule, float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status)  || float32_le(fst0, fst1, &env->fpu->fp_status))
2877 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2878 fd4a04eb ths
 * but float*_is_unordered() is still called. */
2879 b6d96bed ths
FOP_COND_S(sf,  (float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status), 0))
2880 b6d96bed ths
FOP_COND_S(ngle,float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status))
2881 b6d96bed ths
FOP_COND_S(seq, !float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status) && float32_eq(fst0, fst1, &env->fpu->fp_status))
2882 b6d96bed ths
FOP_COND_S(ngl, float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status)  || float32_eq(fst0, fst1, &env->fpu->fp_status))
2883 b6d96bed ths
FOP_COND_S(lt,  !float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status) && float32_lt(fst0, fst1, &env->fpu->fp_status))
2884 b6d96bed ths
FOP_COND_S(nge, float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status)  || float32_lt(fst0, fst1, &env->fpu->fp_status))
2885 b6d96bed ths
FOP_COND_S(le,  !float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status) && float32_le(fst0, fst1, &env->fpu->fp_status))
2886 b6d96bed ths
FOP_COND_S(ngt, float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status)  || float32_le(fst0, fst1, &env->fpu->fp_status))
2887 b6d96bed ths
2888 b6d96bed ths
#define FOP_COND_PS(op, condl, condh)                           \
2889 b6d96bed ths
void do_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
2890 b6d96bed ths
{                                                               \
2891 b6d96bed ths
    uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF);             \
2892 b6d96bed ths
    uint32_t fsth0 = float32_abs(fdt0 >> 32);                   \
2893 b6d96bed ths
    uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF);             \
2894 b6d96bed ths
    uint32_t fsth1 = float32_abs(fdt1 >> 32);                   \
2895 b6d96bed ths
    int cl = condl;                                             \
2896 b6d96bed ths
    int ch = condh;                                             \
2897 b6d96bed ths
                                                                \
2898 b6d96bed ths
    update_fcr31();                                             \
2899 b6d96bed ths
    if (cl)                                                     \
2900 b6d96bed ths
        SET_FP_COND(cc, env->fpu);                              \
2901 b6d96bed ths
    else                                                        \
2902 b6d96bed ths
        CLEAR_FP_COND(cc, env->fpu);                            \
2903 b6d96bed ths
    if (ch)                                                     \
2904 b6d96bed ths
        SET_FP_COND(cc + 1, env->fpu);                          \
2905 b6d96bed ths
    else                                                        \
2906 b6d96bed ths
        CLEAR_FP_COND(cc + 1, env->fpu);                        \
2907 b6d96bed ths
}                                                               \
2908 b6d96bed ths
void do_cmpabs_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
2909 b6d96bed ths
{                                                               \
2910 b6d96bed ths
    uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF);             \
2911 b6d96bed ths
    uint32_t fsth0 = float32_abs(fdt0 >> 32);                   \
2912 b6d96bed ths
    uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF);             \
2913 b6d96bed ths
    uint32_t fsth1 = float32_abs(fdt1 >> 32);                   \
2914 b6d96bed ths
    int cl = condl;                                             \
2915 b6d96bed ths
    int ch = condh;                                             \
2916 b6d96bed ths
                                                                \
2917 b6d96bed ths
    update_fcr31();                                             \
2918 b6d96bed ths
    if (cl)                                                     \
2919 b6d96bed ths
        SET_FP_COND(cc, env->fpu);                              \
2920 b6d96bed ths
    else                                                        \
2921 b6d96bed ths
        CLEAR_FP_COND(cc, env->fpu);                            \
2922 b6d96bed ths
    if (ch)                                                     \
2923 b6d96bed ths
        SET_FP_COND(cc + 1, env->fpu);                          \
2924 b6d96bed ths
    else                                                        \
2925 b6d96bed ths
        CLEAR_FP_COND(cc + 1, env->fpu);                        \
2926 fd4a04eb ths
}
2927 fd4a04eb ths
2928 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2929 fd4a04eb ths
 * but float*_is_unordered() is still called. */
2930 b6d96bed ths
FOP_COND_PS(f,   (float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status), 0),
2931 b6d96bed ths
                 (float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status), 0))
2932 b6d96bed ths
FOP_COND_PS(un,  float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status),
2933 b6d96bed ths
                 float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status))
2934 b6d96bed ths
FOP_COND_PS(eq,  !float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status)   && float32_eq(fst0, fst1, &env->fpu->fp_status),
2935 b6d96bed ths
                 !float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status) && float32_eq(fsth0, fsth1, &env->fpu->fp_status))
2936 b6d96bed ths
FOP_COND_PS(ueq, float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status)    || float32_eq(fst0, fst1, &env->fpu->fp_status),
2937 b6d96bed ths
                 float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status)  || float32_eq(fsth0, fsth1, &env->fpu->fp_status))
2938 b6d96bed ths
FOP_COND_PS(olt, !float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status)   && float32_lt(fst0, fst1, &env->fpu->fp_status),
2939 b6d96bed ths
                 !float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status) && float32_lt(fsth0, fsth1, &env->fpu->fp_status))
2940 b6d96bed ths
FOP_COND_PS(ult, float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status)    || float32_lt(fst0, fst1, &env->fpu->fp_status),
2941 b6d96bed ths
                 float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status)  || float32_lt(fsth0, fsth1, &env->fpu->fp_status))
2942 b6d96bed ths
FOP_COND_PS(ole, !float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status)   && float32_le(fst0, fst1, &env->fpu->fp_status),
2943 b6d96bed ths
                 !float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status) && float32_le(fsth0, fsth1, &env->fpu->fp_status))
2944 b6d96bed ths
FOP_COND_PS(ule, float32_is_unordered(0, fst1, fst0, &env->fpu->fp_status)    || float32_le(fst0, fst1, &env->fpu->fp_status),
2945 b6d96bed ths
                 float32_is_unordered(0, fsth1, fsth0, &env->fpu->fp_status)  || float32_le(fsth0, fsth1, &env->fpu->fp_status))
2946 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2947 fd4a04eb ths
 * but float*_is_unordered() is still called. */
2948 b6d96bed ths
FOP_COND_PS(sf,  (float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status), 0),
2949 b6d96bed ths
                 (float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status), 0))
2950 b6d96bed ths
FOP_COND_PS(ngle,float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status),
2951 b6d96bed ths
                 float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status))
2952 b6d96bed ths
FOP_COND_PS(seq, !float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status)   && float32_eq(fst0, fst1, &env->fpu->fp_status),
2953 b6d96bed ths
                 !float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status) && float32_eq(fsth0, fsth1, &env->fpu->fp_status))
2954 b6d96bed ths
FOP_COND_PS(ngl, float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status)    || float32_eq(fst0, fst1, &env->fpu->fp_status),
2955 b6d96bed ths
                 float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status)  || float32_eq(fsth0, fsth1, &env->fpu->fp_status))
2956 b6d96bed ths
FOP_COND_PS(lt,  !float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status)   && float32_lt(fst0, fst1, &env->fpu->fp_status),
2957 b6d96bed ths
                 !float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status) && float32_lt(fsth0, fsth1, &env->fpu->fp_status))
2958 b6d96bed ths
FOP_COND_PS(nge, float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status)    || float32_lt(fst0, fst1, &env->fpu->fp_status),
2959 b6d96bed ths
                 float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status)  || float32_lt(fsth0, fsth1, &env->fpu->fp_status))
2960 b6d96bed ths
FOP_COND_PS(le,  !float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status)   && float32_le(fst0, fst1, &env->fpu->fp_status),
2961 b6d96bed ths
                 !float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status) && float32_le(fsth0, fsth1, &env->fpu->fp_status))
2962 b6d96bed ths
FOP_COND_PS(ngt, float32_is_unordered(1, fst1, fst0, &env->fpu->fp_status)    || float32_le(fst0, fst1, &env->fpu->fp_status),
2963 b6d96bed ths
                 float32_is_unordered(1, fsth1, fsth0, &env->fpu->fp_status)  || float32_le(fsth0, fsth1, &env->fpu->fp_status))