Statistics
| Branch: | Revision:

root / target-mips / op_helper.c @ be24bb4f

History | View | Annotate | Download (76.8 kB)

1 6af0bf9c bellard
/*
2 6af0bf9c bellard
 *  MIPS emulation helpers for qemu.
3 5fafdf24 ths
 *
4 6af0bf9c bellard
 *  Copyright (c) 2004-2005 Jocelyn Mayer
5 6af0bf9c bellard
 *
6 6af0bf9c bellard
 * This library is free software; you can redistribute it and/or
7 6af0bf9c bellard
 * modify it under the terms of the GNU Lesser General Public
8 6af0bf9c bellard
 * License as published by the Free Software Foundation; either
9 6af0bf9c bellard
 * version 2 of the License, or (at your option) any later version.
10 6af0bf9c bellard
 *
11 6af0bf9c bellard
 * This library is distributed in the hope that it will be useful,
12 6af0bf9c bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 6af0bf9c bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 6af0bf9c bellard
 * Lesser General Public License for more details.
15 6af0bf9c bellard
 *
16 6af0bf9c bellard
 * You should have received a copy of the GNU Lesser General Public
17 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 aa343735 ths
static always_inline uint64_t get_HILO (void)
91 6af0bf9c bellard
{
92 92af06d2 ths
    return ((uint64_t)(env->HI[env->current_tc][0]) << 32) | (uint32_t)env->LO[env->current_tc][0];
93 6af0bf9c bellard
}
94 6af0bf9c bellard
95 aa343735 ths
static always_inline void set_HILO (uint64_t HILO)
96 6af0bf9c bellard
{
97 d0dc7dc3 ths
    env->LO[env->current_tc][0] = (int32_t)HILO;
98 d0dc7dc3 ths
    env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
99 6af0bf9c bellard
}
100 6af0bf9c bellard
101 be24bb4f ths
static always_inline void set_HIT0_LO (target_ulong t0, uint64_t HILO)
102 e9c71dd1 ths
{
103 d0dc7dc3 ths
    env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
104 be24bb4f ths
    t0 = env->HI[env->current_tc][0] = (int32_t)(HILO >> 32);
105 e9c71dd1 ths
}
106 e9c71dd1 ths
107 be24bb4f ths
static always_inline void set_HI_LOT0 (target_ulong t0, uint64_t HILO)
108 e9c71dd1 ths
{
109 be24bb4f ths
    t0 = env->LO[env->current_tc][0] = (int32_t)(HILO & 0xFFFFFFFF);
110 d0dc7dc3 ths
    env->HI[env->current_tc][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 be24bb4f ths
    muls64(&(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][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 be24bb4f ths
    mulu64(&(env->LO[env->current_tc][0]), &(env->HI[env->current_tc][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 f1aa6320 ths
#ifdef CONFIG_USER_ONLY
600 873eb012 ths
void do_mfc0_random (void)
601 048f6b4d bellard
{
602 873eb012 ths
    cpu_abort(env, "mfc0 random\n");
603 048f6b4d bellard
}
604 873eb012 ths
605 873eb012 ths
void do_mfc0_count (void)
606 873eb012 ths
{
607 873eb012 ths
    cpu_abort(env, "mfc0 count\n");
608 873eb012 ths
}
609 873eb012 ths
610 8c0fdd85 ths
void cpu_mips_store_count(CPUState *env, uint32_t value)
611 048f6b4d bellard
{
612 8c0fdd85 ths
    cpu_abort(env, "mtc0 count\n");
613 8c0fdd85 ths
}
614 8c0fdd85 ths
615 8c0fdd85 ths
void cpu_mips_store_compare(CPUState *env, uint32_t value)
616 8c0fdd85 ths
{
617 8c0fdd85 ths
    cpu_abort(env, "mtc0 compare\n");
618 8c0fdd85 ths
}
619 8c0fdd85 ths
620 42532189 ths
void cpu_mips_start_count(CPUState *env)
621 42532189 ths
{
622 42532189 ths
    cpu_abort(env, "start count\n");
623 42532189 ths
}
624 42532189 ths
625 42532189 ths
void cpu_mips_stop_count(CPUState *env)
626 42532189 ths
{
627 42532189 ths
    cpu_abort(env, "stop count\n");
628 42532189 ths
}
629 42532189 ths
630 4de9b249 ths
void cpu_mips_update_irq(CPUState *env)
631 4de9b249 ths
{
632 4de9b249 ths
    cpu_abort(env, "mtc0 status / mtc0 cause\n");
633 4de9b249 ths
}
634 4de9b249 ths
635 8c0fdd85 ths
void do_mtc0_status_debug(uint32_t old, uint32_t val)
636 8c0fdd85 ths
{
637 7a387fff ths
    cpu_abort(env, "mtc0 status debug\n");
638 8c0fdd85 ths
}
639 8c0fdd85 ths
640 7a387fff ths
void do_mtc0_status_irqraise_debug (void)
641 8c0fdd85 ths
{
642 7a387fff ths
    cpu_abort(env, "mtc0 status irqraise debug\n");
643 048f6b4d bellard
}
644 048f6b4d bellard
645 8c0fdd85 ths
void cpu_mips_tlb_flush (CPUState *env, int flush_global)
646 8c0fdd85 ths
{
647 8c0fdd85 ths
    cpu_abort(env, "mips_tlb_flush\n");
648 8c0fdd85 ths
}
649 8c0fdd85 ths
650 048f6b4d bellard
#else
651 048f6b4d bellard
652 6af0bf9c bellard
/* CP0 helpers */
653 be24bb4f ths
target_ulong do_mfc0_mvpcontrol (target_ulong t0)
654 f1aa6320 ths
{
655 be24bb4f ths
    return env->mvp->CP0_MVPControl;
656 f1aa6320 ths
}
657 f1aa6320 ths
658 be24bb4f ths
target_ulong do_mfc0_mvpconf0 (target_ulong t0)
659 f1aa6320 ths
{
660 be24bb4f ths
    return env->mvp->CP0_MVPConf0;
661 f1aa6320 ths
}
662 f1aa6320 ths
663 be24bb4f ths
target_ulong do_mfc0_mvpconf1 (target_ulong t0)
664 f1aa6320 ths
{
665 be24bb4f ths
    return env->mvp->CP0_MVPConf1;
666 f1aa6320 ths
}
667 f1aa6320 ths
668 be24bb4f ths
target_ulong do_mfc0_random (target_ulong t0)
669 6af0bf9c bellard
{
670 be24bb4f ths
    return (int32_t)cpu_mips_get_random(env);
671 873eb012 ths
}
672 6af0bf9c bellard
673 be24bb4f ths
target_ulong do_mfc0_tcstatus (target_ulong t0)
674 f1aa6320 ths
{
675 be24bb4f ths
    return env->CP0_TCStatus[env->current_tc];
676 f1aa6320 ths
}
677 f1aa6320 ths
678 be24bb4f ths
target_ulong do_mftc0_tcstatus(target_ulong t0)
679 f1aa6320 ths
{
680 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
681 f1aa6320 ths
682 be24bb4f ths
    return env->CP0_TCStatus[other_tc];
683 f1aa6320 ths
}
684 f1aa6320 ths
685 be24bb4f ths
target_ulong do_mfc0_tcbind (target_ulong t0)
686 f1aa6320 ths
{
687 be24bb4f ths
    return env->CP0_TCBind[env->current_tc];
688 f1aa6320 ths
}
689 f1aa6320 ths
690 be24bb4f ths
target_ulong do_mftc0_tcbind(target_ulong t0)
691 f1aa6320 ths
{
692 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
693 f1aa6320 ths
694 be24bb4f ths
    return env->CP0_TCBind[other_tc];
695 f1aa6320 ths
}
696 f1aa6320 ths
697 be24bb4f ths
target_ulong do_mfc0_tcrestart (target_ulong t0)
698 f1aa6320 ths
{
699 be24bb4f ths
    return env->PC[env->current_tc];
700 f1aa6320 ths
}
701 f1aa6320 ths
702 be24bb4f ths
target_ulong do_mftc0_tcrestart(target_ulong t0)
703 f1aa6320 ths
{
704 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
705 f1aa6320 ths
706 be24bb4f ths
    return env->PC[other_tc];
707 f1aa6320 ths
}
708 f1aa6320 ths
709 be24bb4f ths
target_ulong do_mfc0_tchalt (target_ulong t0)
710 f1aa6320 ths
{
711 be24bb4f ths
    return env->CP0_TCHalt[env->current_tc];
712 f1aa6320 ths
}
713 f1aa6320 ths
714 be24bb4f ths
target_ulong do_mftc0_tchalt(target_ulong t0)
715 f1aa6320 ths
{
716 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
717 f1aa6320 ths
718 be24bb4f ths
    return env->CP0_TCHalt[other_tc];
719 f1aa6320 ths
}
720 f1aa6320 ths
721 be24bb4f ths
target_ulong do_mfc0_tccontext (target_ulong t0)
722 f1aa6320 ths
{
723 be24bb4f ths
    return env->CP0_TCContext[env->current_tc];
724 f1aa6320 ths
}
725 f1aa6320 ths
726 be24bb4f ths
target_ulong do_mftc0_tccontext(target_ulong t0)
727 f1aa6320 ths
{
728 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
729 f1aa6320 ths
730 be24bb4f ths
    return env->CP0_TCContext[other_tc];
731 f1aa6320 ths
}
732 f1aa6320 ths
733 be24bb4f ths
target_ulong do_mfc0_tcschedule (target_ulong t0)
734 f1aa6320 ths
{
735 be24bb4f ths
    return env->CP0_TCSchedule[env->current_tc];
736 f1aa6320 ths
}
737 f1aa6320 ths
738 be24bb4f ths
target_ulong do_mftc0_tcschedule(target_ulong t0)
739 f1aa6320 ths
{
740 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
741 f1aa6320 ths
742 be24bb4f ths
    return env->CP0_TCSchedule[other_tc];
743 f1aa6320 ths
}
744 f1aa6320 ths
745 be24bb4f ths
target_ulong do_mfc0_tcschefback (target_ulong t0)
746 f1aa6320 ths
{
747 be24bb4f ths
    return env->CP0_TCScheFBack[env->current_tc];
748 f1aa6320 ths
}
749 f1aa6320 ths
750 be24bb4f ths
target_ulong do_mftc0_tcschefback(target_ulong t0)
751 f1aa6320 ths
{
752 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
753 f1aa6320 ths
754 be24bb4f ths
    return env->CP0_TCScheFBack[other_tc];
755 f1aa6320 ths
}
756 f1aa6320 ths
757 be24bb4f ths
target_ulong do_mfc0_count (target_ulong t0)
758 873eb012 ths
{
759 be24bb4f ths
    return (int32_t)cpu_mips_get_count(env);
760 6af0bf9c bellard
}
761 6af0bf9c bellard
762 be24bb4f ths
target_ulong do_mftc0_entryhi(target_ulong t0)
763 f1aa6320 ths
{
764 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
765 f1aa6320 ths
766 be24bb4f ths
    return (env->CP0_EntryHi & ~0xff) | (env->CP0_TCStatus[other_tc] & 0xff);
767 f1aa6320 ths
}
768 f1aa6320 ths
769 be24bb4f ths
target_ulong do_mftc0_status(target_ulong t0)
770 f1aa6320 ths
{
771 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
772 f1aa6320 ths
    uint32_t tcstatus = env->CP0_TCStatus[other_tc];
773 f1aa6320 ths
774 be24bb4f ths
    t0 = env->CP0_Status & ~0xf1000018;
775 be24bb4f ths
    t0 |= tcstatus & (0xf << CP0TCSt_TCU0);
776 be24bb4f ths
    t0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
777 be24bb4f ths
    t0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
778 be24bb4f ths
779 be24bb4f ths
    return t0;
780 f1aa6320 ths
}
781 f1aa6320 ths
782 be24bb4f ths
target_ulong do_mfc0_lladdr (target_ulong t0)
783 f1aa6320 ths
{
784 be24bb4f ths
    return (int32_t)env->CP0_LLAddr >> 4;
785 f1aa6320 ths
}
786 f1aa6320 ths
787 be24bb4f ths
target_ulong do_mfc0_watchlo (target_ulong t0, uint32_t sel)
788 f1aa6320 ths
{
789 be24bb4f ths
    return (int32_t)env->CP0_WatchLo[sel];
790 f1aa6320 ths
}
791 f1aa6320 ths
792 be24bb4f ths
target_ulong do_mfc0_watchhi (target_ulong t0, uint32_t sel)
793 f1aa6320 ths
{
794 be24bb4f ths
    return env->CP0_WatchHi[sel];
795 f1aa6320 ths
}
796 f1aa6320 ths
797 be24bb4f ths
target_ulong do_mfc0_debug (target_ulong t0)
798 f1aa6320 ths
{
799 be24bb4f ths
    t0 = env->CP0_Debug;
800 f1aa6320 ths
    if (env->hflags & MIPS_HFLAG_DM)
801 be24bb4f ths
        t0 |= 1 << CP0DB_DM;
802 be24bb4f ths
803 be24bb4f ths
    return t0;
804 f1aa6320 ths
}
805 f1aa6320 ths
806 be24bb4f ths
target_ulong do_mftc0_debug(target_ulong t0)
807 f1aa6320 ths
{
808 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
809 f1aa6320 ths
810 f1aa6320 ths
    /* XXX: Might be wrong, check with EJTAG spec. */
811 be24bb4f ths
    return (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
812 be24bb4f ths
            (env->CP0_Debug_tcstatus[other_tc] &
813 be24bb4f ths
             ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
814 f1aa6320 ths
}
815 f1aa6320 ths
816 f1aa6320 ths
#if defined(TARGET_MIPS64)
817 be24bb4f ths
target_ulong do_dmfc0_tcrestart (target_ulong t0)
818 f1aa6320 ths
{
819 be24bb4f ths
    return env->PC[env->current_tc];
820 f1aa6320 ths
}
821 f1aa6320 ths
822 be24bb4f ths
target_ulong do_dmfc0_tchalt (target_ulong t0)
823 f1aa6320 ths
{
824 be24bb4f ths
    return env->CP0_TCHalt[env->current_tc];
825 f1aa6320 ths
}
826 f1aa6320 ths
827 be24bb4f ths
target_ulong do_dmfc0_tccontext (target_ulong t0)
828 f1aa6320 ths
{
829 be24bb4f ths
    return env->CP0_TCContext[env->current_tc];
830 f1aa6320 ths
}
831 f1aa6320 ths
832 be24bb4f ths
target_ulong do_dmfc0_tcschedule (target_ulong t0)
833 f1aa6320 ths
{
834 be24bb4f ths
    return env->CP0_TCSchedule[env->current_tc];
835 f1aa6320 ths
}
836 f1aa6320 ths
837 be24bb4f ths
target_ulong do_dmfc0_tcschefback (target_ulong t0)
838 f1aa6320 ths
{
839 be24bb4f ths
    return env->CP0_TCScheFBack[env->current_tc];
840 f1aa6320 ths
}
841 f1aa6320 ths
842 be24bb4f ths
target_ulong do_dmfc0_lladdr (target_ulong t0)
843 f1aa6320 ths
{
844 be24bb4f ths
    return env->CP0_LLAddr >> 4;
845 f1aa6320 ths
}
846 f1aa6320 ths
847 be24bb4f ths
target_ulong do_dmfc0_watchlo (target_ulong t0, uint32_t sel)
848 f1aa6320 ths
{
849 be24bb4f ths
    return env->CP0_WatchLo[sel];
850 f1aa6320 ths
}
851 f1aa6320 ths
#endif /* TARGET_MIPS64 */
852 f1aa6320 ths
853 be24bb4f ths
void do_mtc0_index (target_ulong t0)
854 f1aa6320 ths
{
855 f1aa6320 ths
    int num = 1;
856 f1aa6320 ths
    unsigned int tmp = env->tlb->nb_tlb;
857 f1aa6320 ths
858 f1aa6320 ths
    do {
859 f1aa6320 ths
        tmp >>= 1;
860 f1aa6320 ths
        num <<= 1;
861 f1aa6320 ths
    } while (tmp);
862 be24bb4f ths
    env->CP0_Index = (env->CP0_Index & 0x80000000) | (t0 & (num - 1));
863 f1aa6320 ths
}
864 f1aa6320 ths
865 be24bb4f ths
void do_mtc0_mvpcontrol (target_ulong t0)
866 f1aa6320 ths
{
867 f1aa6320 ths
    uint32_t mask = 0;
868 f1aa6320 ths
    uint32_t newval;
869 f1aa6320 ths
870 f1aa6320 ths
    if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
871 f1aa6320 ths
        mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
872 f1aa6320 ths
                (1 << CP0MVPCo_EVP);
873 f1aa6320 ths
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
874 f1aa6320 ths
        mask |= (1 << CP0MVPCo_STLB);
875 be24bb4f ths
    newval = (env->mvp->CP0_MVPControl & ~mask) | (t0 & mask);
876 f1aa6320 ths
877 f1aa6320 ths
    // TODO: Enable/disable shared TLB, enable/disable VPEs.
878 f1aa6320 ths
879 f1aa6320 ths
    env->mvp->CP0_MVPControl = newval;
880 f1aa6320 ths
}
881 f1aa6320 ths
882 be24bb4f ths
void do_mtc0_vpecontrol (target_ulong t0)
883 f1aa6320 ths
{
884 f1aa6320 ths
    uint32_t mask;
885 f1aa6320 ths
    uint32_t newval;
886 f1aa6320 ths
887 f1aa6320 ths
    mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
888 f1aa6320 ths
           (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
889 be24bb4f ths
    newval = (env->CP0_VPEControl & ~mask) | (t0 & mask);
890 f1aa6320 ths
891 f1aa6320 ths
    /* Yield scheduler intercept not implemented. */
892 f1aa6320 ths
    /* Gating storage scheduler intercept not implemented. */
893 f1aa6320 ths
894 f1aa6320 ths
    // TODO: Enable/disable TCs.
895 f1aa6320 ths
896 f1aa6320 ths
    env->CP0_VPEControl = newval;
897 f1aa6320 ths
}
898 f1aa6320 ths
899 be24bb4f ths
void do_mtc0_vpeconf0 (target_ulong t0)
900 f1aa6320 ths
{
901 f1aa6320 ths
    uint32_t mask = 0;
902 f1aa6320 ths
    uint32_t newval;
903 f1aa6320 ths
904 f1aa6320 ths
    if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
905 f1aa6320 ths
        if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
906 f1aa6320 ths
            mask |= (0xff << CP0VPEC0_XTC);
907 f1aa6320 ths
        mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
908 f1aa6320 ths
    }
909 be24bb4f ths
    newval = (env->CP0_VPEConf0 & ~mask) | (t0 & mask);
910 f1aa6320 ths
911 f1aa6320 ths
    // TODO: TC exclusive handling due to ERL/EXL.
912 f1aa6320 ths
913 f1aa6320 ths
    env->CP0_VPEConf0 = newval;
914 f1aa6320 ths
}
915 f1aa6320 ths
916 be24bb4f ths
void do_mtc0_vpeconf1 (target_ulong t0)
917 f1aa6320 ths
{
918 f1aa6320 ths
    uint32_t mask = 0;
919 f1aa6320 ths
    uint32_t newval;
920 f1aa6320 ths
921 f1aa6320 ths
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
922 f1aa6320 ths
        mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
923 f1aa6320 ths
                (0xff << CP0VPEC1_NCP1);
924 be24bb4f ths
    newval = (env->CP0_VPEConf1 & ~mask) | (t0 & mask);
925 f1aa6320 ths
926 f1aa6320 ths
    /* UDI not implemented. */
927 f1aa6320 ths
    /* CP2 not implemented. */
928 f1aa6320 ths
929 f1aa6320 ths
    // TODO: Handle FPU (CP1) binding.
930 f1aa6320 ths
931 f1aa6320 ths
    env->CP0_VPEConf1 = newval;
932 f1aa6320 ths
}
933 f1aa6320 ths
934 be24bb4f ths
void do_mtc0_yqmask (target_ulong t0)
935 f1aa6320 ths
{
936 f1aa6320 ths
    /* Yield qualifier inputs not implemented. */
937 f1aa6320 ths
    env->CP0_YQMask = 0x00000000;
938 f1aa6320 ths
}
939 f1aa6320 ths
940 be24bb4f ths
void do_mtc0_vpeopt (target_ulong t0)
941 f1aa6320 ths
{
942 be24bb4f ths
    env->CP0_VPEOpt = t0 & 0x0000ffff;
943 f1aa6320 ths
}
944 f1aa6320 ths
945 be24bb4f ths
void do_mtc0_entrylo0 (target_ulong t0)
946 f1aa6320 ths
{
947 f1aa6320 ths
    /* Large physaddr (PABITS) not implemented */
948 f1aa6320 ths
    /* 1k pages not implemented */
949 be24bb4f ths
    env->CP0_EntryLo0 = t0 & 0x3FFFFFFF;
950 f1aa6320 ths
}
951 f1aa6320 ths
952 be24bb4f ths
void do_mtc0_tcstatus (target_ulong t0)
953 f1aa6320 ths
{
954 f1aa6320 ths
    uint32_t mask = env->CP0_TCStatus_rw_bitmask;
955 f1aa6320 ths
    uint32_t newval;
956 f1aa6320 ths
957 be24bb4f ths
    newval = (env->CP0_TCStatus[env->current_tc] & ~mask) | (t0 & mask);
958 f1aa6320 ths
959 f1aa6320 ths
    // TODO: Sync with CP0_Status.
960 f1aa6320 ths
961 f1aa6320 ths
    env->CP0_TCStatus[env->current_tc] = newval;
962 f1aa6320 ths
}
963 f1aa6320 ths
964 be24bb4f ths
void do_mttc0_tcstatus (target_ulong t0)
965 f1aa6320 ths
{
966 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
967 f1aa6320 ths
968 f1aa6320 ths
    // TODO: Sync with CP0_Status.
969 f1aa6320 ths
970 be24bb4f ths
    env->CP0_TCStatus[other_tc] = t0;
971 f1aa6320 ths
}
972 f1aa6320 ths
973 be24bb4f ths
void do_mtc0_tcbind (target_ulong t0)
974 f1aa6320 ths
{
975 f1aa6320 ths
    uint32_t mask = (1 << CP0TCBd_TBE);
976 f1aa6320 ths
    uint32_t newval;
977 f1aa6320 ths
978 f1aa6320 ths
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
979 f1aa6320 ths
        mask |= (1 << CP0TCBd_CurVPE);
980 be24bb4f ths
    newval = (env->CP0_TCBind[env->current_tc] & ~mask) | (t0 & mask);
981 f1aa6320 ths
    env->CP0_TCBind[env->current_tc] = newval;
982 f1aa6320 ths
}
983 f1aa6320 ths
984 be24bb4f ths
void do_mttc0_tcbind (target_ulong t0)
985 f1aa6320 ths
{
986 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
987 f1aa6320 ths
    uint32_t mask = (1 << CP0TCBd_TBE);
988 f1aa6320 ths
    uint32_t newval;
989 f1aa6320 ths
990 f1aa6320 ths
    if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
991 f1aa6320 ths
        mask |= (1 << CP0TCBd_CurVPE);
992 be24bb4f ths
    newval = (env->CP0_TCBind[other_tc] & ~mask) | (t0 & mask);
993 f1aa6320 ths
    env->CP0_TCBind[other_tc] = newval;
994 f1aa6320 ths
}
995 f1aa6320 ths
996 be24bb4f ths
void do_mtc0_tcrestart (target_ulong t0)
997 f1aa6320 ths
{
998 be24bb4f ths
    env->PC[env->current_tc] = t0;
999 f1aa6320 ths
    env->CP0_TCStatus[env->current_tc] &= ~(1 << CP0TCSt_TDS);
1000 f1aa6320 ths
    env->CP0_LLAddr = 0ULL;
1001 f1aa6320 ths
    /* MIPS16 not implemented. */
1002 f1aa6320 ths
}
1003 f1aa6320 ths
1004 be24bb4f ths
void do_mttc0_tcrestart (target_ulong t0)
1005 f1aa6320 ths
{
1006 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1007 f1aa6320 ths
1008 be24bb4f ths
    env->PC[other_tc] = t0;
1009 f1aa6320 ths
    env->CP0_TCStatus[other_tc] &= ~(1 << CP0TCSt_TDS);
1010 f1aa6320 ths
    env->CP0_LLAddr = 0ULL;
1011 f1aa6320 ths
    /* MIPS16 not implemented. */
1012 f1aa6320 ths
}
1013 f1aa6320 ths
1014 be24bb4f ths
void do_mtc0_tchalt (target_ulong t0)
1015 f1aa6320 ths
{
1016 be24bb4f ths
    env->CP0_TCHalt[env->current_tc] = t0 & 0x1;
1017 f1aa6320 ths
1018 f1aa6320 ths
    // TODO: Halt TC / Restart (if allocated+active) TC.
1019 f1aa6320 ths
}
1020 f1aa6320 ths
1021 be24bb4f ths
void do_mttc0_tchalt (target_ulong t0)
1022 f1aa6320 ths
{
1023 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1024 f1aa6320 ths
1025 f1aa6320 ths
    // TODO: Halt TC / Restart (if allocated+active) TC.
1026 f1aa6320 ths
1027 be24bb4f ths
    env->CP0_TCHalt[other_tc] = t0;
1028 f1aa6320 ths
}
1029 f1aa6320 ths
1030 be24bb4f ths
void do_mtc0_tccontext (target_ulong t0)
1031 f1aa6320 ths
{
1032 be24bb4f ths
    env->CP0_TCContext[env->current_tc] = t0;
1033 f1aa6320 ths
}
1034 f1aa6320 ths
1035 be24bb4f ths
void do_mttc0_tccontext (target_ulong t0)
1036 f1aa6320 ths
{
1037 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1038 f1aa6320 ths
1039 be24bb4f ths
    env->CP0_TCContext[other_tc] = t0;
1040 f1aa6320 ths
}
1041 f1aa6320 ths
1042 be24bb4f ths
void do_mtc0_tcschedule (target_ulong t0)
1043 f1aa6320 ths
{
1044 be24bb4f ths
    env->CP0_TCSchedule[env->current_tc] = t0;
1045 f1aa6320 ths
}
1046 f1aa6320 ths
1047 be24bb4f ths
void do_mttc0_tcschedule (target_ulong t0)
1048 f1aa6320 ths
{
1049 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1050 f1aa6320 ths
1051 be24bb4f ths
    env->CP0_TCSchedule[other_tc] = t0;
1052 f1aa6320 ths
}
1053 f1aa6320 ths
1054 be24bb4f ths
void do_mtc0_tcschefback (target_ulong t0)
1055 f1aa6320 ths
{
1056 be24bb4f ths
    env->CP0_TCScheFBack[env->current_tc] = t0;
1057 f1aa6320 ths
}
1058 f1aa6320 ths
1059 be24bb4f ths
void do_mttc0_tcschefback (target_ulong t0)
1060 f1aa6320 ths
{
1061 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1062 f1aa6320 ths
1063 be24bb4f ths
    env->CP0_TCScheFBack[other_tc] = t0;
1064 f1aa6320 ths
}
1065 f1aa6320 ths
1066 be24bb4f ths
void do_mtc0_entrylo1 (target_ulong t0)
1067 f1aa6320 ths
{
1068 f1aa6320 ths
    /* Large physaddr (PABITS) not implemented */
1069 f1aa6320 ths
    /* 1k pages not implemented */
1070 be24bb4f ths
    env->CP0_EntryLo1 = t0 & 0x3FFFFFFF;
1071 f1aa6320 ths
}
1072 f1aa6320 ths
1073 be24bb4f ths
void do_mtc0_context (target_ulong t0)
1074 f1aa6320 ths
{
1075 be24bb4f ths
    env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (t0 & ~0x007FFFFF);
1076 f1aa6320 ths
}
1077 f1aa6320 ths
1078 be24bb4f ths
void do_mtc0_pagemask (target_ulong t0)
1079 f1aa6320 ths
{
1080 f1aa6320 ths
    /* 1k pages not implemented */
1081 be24bb4f ths
    env->CP0_PageMask = t0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1082 f1aa6320 ths
}
1083 f1aa6320 ths
1084 be24bb4f ths
void do_mtc0_pagegrain (target_ulong t0)
1085 f1aa6320 ths
{
1086 f1aa6320 ths
    /* SmartMIPS not implemented */
1087 f1aa6320 ths
    /* Large physaddr (PABITS) not implemented */
1088 f1aa6320 ths
    /* 1k pages not implemented */
1089 f1aa6320 ths
    env->CP0_PageGrain = 0;
1090 f1aa6320 ths
}
1091 f1aa6320 ths
1092 be24bb4f ths
void do_mtc0_wired (target_ulong t0)
1093 f1aa6320 ths
{
1094 be24bb4f ths
    env->CP0_Wired = t0 % env->tlb->nb_tlb;
1095 f1aa6320 ths
}
1096 f1aa6320 ths
1097 be24bb4f ths
void do_mtc0_srsconf0 (target_ulong t0)
1098 f1aa6320 ths
{
1099 be24bb4f ths
    env->CP0_SRSConf0 |= t0 & env->CP0_SRSConf0_rw_bitmask;
1100 f1aa6320 ths
}
1101 f1aa6320 ths
1102 be24bb4f ths
void do_mtc0_srsconf1 (target_ulong t0)
1103 f1aa6320 ths
{
1104 be24bb4f ths
    env->CP0_SRSConf1 |= t0 & env->CP0_SRSConf1_rw_bitmask;
1105 f1aa6320 ths
}
1106 f1aa6320 ths
1107 be24bb4f ths
void do_mtc0_srsconf2 (target_ulong t0)
1108 f1aa6320 ths
{
1109 be24bb4f ths
    env->CP0_SRSConf2 |= t0 & env->CP0_SRSConf2_rw_bitmask;
1110 f1aa6320 ths
}
1111 f1aa6320 ths
1112 be24bb4f ths
void do_mtc0_srsconf3 (target_ulong t0)
1113 f1aa6320 ths
{
1114 be24bb4f ths
    env->CP0_SRSConf3 |= t0 & env->CP0_SRSConf3_rw_bitmask;
1115 f1aa6320 ths
}
1116 f1aa6320 ths
1117 be24bb4f ths
void do_mtc0_srsconf4 (target_ulong t0)
1118 f1aa6320 ths
{
1119 be24bb4f ths
    env->CP0_SRSConf4 |= t0 & env->CP0_SRSConf4_rw_bitmask;
1120 f1aa6320 ths
}
1121 f1aa6320 ths
1122 be24bb4f ths
void do_mtc0_hwrena (target_ulong t0)
1123 f1aa6320 ths
{
1124 be24bb4f ths
    env->CP0_HWREna = t0 & 0x0000000F;
1125 f1aa6320 ths
}
1126 f1aa6320 ths
1127 be24bb4f ths
void do_mtc0_count (target_ulong t0)
1128 f1aa6320 ths
{
1129 be24bb4f ths
    cpu_mips_store_count(env, t0);
1130 f1aa6320 ths
}
1131 f1aa6320 ths
1132 be24bb4f ths
void do_mtc0_entryhi (target_ulong t0)
1133 f1aa6320 ths
{
1134 f1aa6320 ths
    target_ulong old, val;
1135 f1aa6320 ths
1136 f1aa6320 ths
    /* 1k pages not implemented */
1137 be24bb4f ths
    val = t0 & ((TARGET_PAGE_MASK << 1) | 0xFF);
1138 f1aa6320 ths
#if defined(TARGET_MIPS64)
1139 f1aa6320 ths
    val &= env->SEGMask;
1140 f1aa6320 ths
#endif
1141 f1aa6320 ths
    old = env->CP0_EntryHi;
1142 f1aa6320 ths
    env->CP0_EntryHi = val;
1143 f1aa6320 ths
    if (env->CP0_Config3 & (1 << CP0C3_MT)) {
1144 f1aa6320 ths
        uint32_t tcst = env->CP0_TCStatus[env->current_tc] & ~0xff;
1145 f1aa6320 ths
        env->CP0_TCStatus[env->current_tc] = tcst | (val & 0xff);
1146 f1aa6320 ths
    }
1147 f1aa6320 ths
    /* If the ASID changes, flush qemu's TLB.  */
1148 f1aa6320 ths
    if ((old & 0xFF) != (val & 0xFF))
1149 f1aa6320 ths
        cpu_mips_tlb_flush(env, 1);
1150 f1aa6320 ths
}
1151 f1aa6320 ths
1152 be24bb4f ths
void do_mttc0_entryhi(target_ulong t0)
1153 f1aa6320 ths
{
1154 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1155 f1aa6320 ths
1156 be24bb4f ths
    env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (t0 & ~0xff);
1157 be24bb4f ths
    env->CP0_TCStatus[other_tc] = (env->CP0_TCStatus[other_tc] & ~0xff) | (t0 & 0xff);
1158 f1aa6320 ths
}
1159 f1aa6320 ths
1160 be24bb4f ths
void do_mtc0_compare (target_ulong t0)
1161 f1aa6320 ths
{
1162 be24bb4f ths
    cpu_mips_store_compare(env, t0);
1163 f1aa6320 ths
}
1164 f1aa6320 ths
1165 be24bb4f ths
void do_mtc0_status (target_ulong t0)
1166 f1aa6320 ths
{
1167 f1aa6320 ths
    uint32_t val, old;
1168 f1aa6320 ths
    uint32_t mask = env->CP0_Status_rw_bitmask;
1169 f1aa6320 ths
1170 be24bb4f ths
    val = t0 & mask;
1171 f1aa6320 ths
    old = env->CP0_Status;
1172 f1aa6320 ths
    env->CP0_Status = (env->CP0_Status & ~mask) | val;
1173 f1aa6320 ths
    compute_hflags(env);
1174 f1aa6320 ths
    if (loglevel & CPU_LOG_EXEC)
1175 f1aa6320 ths
        do_mtc0_status_debug(old, val);
1176 f1aa6320 ths
    cpu_mips_update_irq(env);
1177 f1aa6320 ths
}
1178 f1aa6320 ths
1179 be24bb4f ths
void do_mttc0_status(target_ulong t0)
1180 f1aa6320 ths
{
1181 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1182 f1aa6320 ths
    uint32_t tcstatus = env->CP0_TCStatus[other_tc];
1183 f1aa6320 ths
1184 be24bb4f ths
    env->CP0_Status = t0 & ~0xf1000018;
1185 be24bb4f ths
    tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (t0 & (0xf << CP0St_CU0));
1186 be24bb4f ths
    tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((t0 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
1187 be24bb4f ths
    tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((t0 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
1188 f1aa6320 ths
    env->CP0_TCStatus[other_tc] = tcstatus;
1189 f1aa6320 ths
}
1190 f1aa6320 ths
1191 be24bb4f ths
void do_mtc0_intctl (target_ulong t0)
1192 f1aa6320 ths
{
1193 f1aa6320 ths
    /* vectored interrupts not implemented, no performance counters. */
1194 be24bb4f ths
    env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (t0 & 0x000002e0);
1195 f1aa6320 ths
}
1196 f1aa6320 ths
1197 be24bb4f ths
void do_mtc0_srsctl (target_ulong t0)
1198 f1aa6320 ths
{
1199 f1aa6320 ths
    uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1200 be24bb4f ths
    env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (t0 & mask);
1201 f1aa6320 ths
}
1202 f1aa6320 ths
1203 be24bb4f ths
void do_mtc0_cause (target_ulong t0)
1204 f1aa6320 ths
{
1205 f1aa6320 ths
    uint32_t mask = 0x00C00300;
1206 f1aa6320 ths
    uint32_t old = env->CP0_Cause;
1207 f1aa6320 ths
1208 f1aa6320 ths
    if (env->insn_flags & ISA_MIPS32R2)
1209 f1aa6320 ths
        mask |= 1 << CP0Ca_DC;
1210 f1aa6320 ths
1211 be24bb4f ths
    env->CP0_Cause = (env->CP0_Cause & ~mask) | (t0 & mask);
1212 f1aa6320 ths
1213 f1aa6320 ths
    if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
1214 f1aa6320 ths
        if (env->CP0_Cause & (1 << CP0Ca_DC))
1215 f1aa6320 ths
            cpu_mips_stop_count(env);
1216 f1aa6320 ths
        else
1217 f1aa6320 ths
            cpu_mips_start_count(env);
1218 f1aa6320 ths
    }
1219 f1aa6320 ths
1220 f1aa6320 ths
    /* Handle the software interrupt as an hardware one, as they
1221 f1aa6320 ths
       are very similar */
1222 be24bb4f ths
    if (t0 & CP0Ca_IP_mask) {
1223 f1aa6320 ths
        cpu_mips_update_irq(env);
1224 f1aa6320 ths
    }
1225 f1aa6320 ths
}
1226 f1aa6320 ths
1227 be24bb4f ths
void do_mtc0_ebase (target_ulong t0)
1228 f1aa6320 ths
{
1229 f1aa6320 ths
    /* vectored interrupts not implemented */
1230 f1aa6320 ths
    /* Multi-CPU not implemented */
1231 be24bb4f ths
    env->CP0_EBase = 0x80000000 | (t0 & 0x3FFFF000);
1232 f1aa6320 ths
}
1233 f1aa6320 ths
1234 be24bb4f ths
void do_mtc0_config0 (target_ulong t0)
1235 f1aa6320 ths
{
1236 be24bb4f ths
    env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (t0 & 0x00000007);
1237 f1aa6320 ths
}
1238 f1aa6320 ths
1239 be24bb4f ths
void do_mtc0_config2 (target_ulong t0)
1240 f1aa6320 ths
{
1241 f1aa6320 ths
    /* tertiary/secondary caches not implemented */
1242 f1aa6320 ths
    env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1243 f1aa6320 ths
}
1244 f1aa6320 ths
1245 be24bb4f ths
void do_mtc0_watchlo (target_ulong t0, uint32_t sel)
1246 f1aa6320 ths
{
1247 f1aa6320 ths
    /* Watch exceptions for instructions, data loads, data stores
1248 f1aa6320 ths
       not implemented. */
1249 be24bb4f ths
    env->CP0_WatchLo[sel] = (t0 & ~0x7);
1250 f1aa6320 ths
}
1251 f1aa6320 ths
1252 be24bb4f ths
void do_mtc0_watchhi (target_ulong t0, uint32_t sel)
1253 f1aa6320 ths
{
1254 be24bb4f ths
    env->CP0_WatchHi[sel] = (t0 & 0x40FF0FF8);
1255 be24bb4f ths
    env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & t0 & 0x7);
1256 f1aa6320 ths
}
1257 f1aa6320 ths
1258 be24bb4f ths
void do_mtc0_xcontext (target_ulong t0)
1259 f1aa6320 ths
{
1260 f1aa6320 ths
    target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1261 be24bb4f ths
    env->CP0_XContext = (env->CP0_XContext & mask) | (t0 & ~mask);
1262 f1aa6320 ths
}
1263 f1aa6320 ths
1264 be24bb4f ths
void do_mtc0_framemask (target_ulong t0)
1265 f1aa6320 ths
{
1266 be24bb4f ths
    env->CP0_Framemask = t0; /* XXX */
1267 f1aa6320 ths
}
1268 f1aa6320 ths
1269 be24bb4f ths
void do_mtc0_debug (target_ulong t0)
1270 f1aa6320 ths
{
1271 be24bb4f ths
    env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (t0 & 0x13300120);
1272 be24bb4f ths
    if (t0 & (1 << CP0DB_DM))
1273 f1aa6320 ths
        env->hflags |= MIPS_HFLAG_DM;
1274 f1aa6320 ths
    else
1275 f1aa6320 ths
        env->hflags &= ~MIPS_HFLAG_DM;
1276 f1aa6320 ths
}
1277 f1aa6320 ths
1278 be24bb4f ths
void do_mttc0_debug(target_ulong t0)
1279 f1aa6320 ths
{
1280 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1281 f1aa6320 ths
1282 f1aa6320 ths
    /* XXX: Might be wrong, check with EJTAG spec. */
1283 be24bb4f ths
    env->CP0_Debug_tcstatus[other_tc] = t0 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1284 f1aa6320 ths
    env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1285 be24bb4f ths
                     (t0 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1286 f1aa6320 ths
}
1287 f1aa6320 ths
1288 be24bb4f ths
void do_mtc0_performance0 (target_ulong t0)
1289 f1aa6320 ths
{
1290 be24bb4f ths
    env->CP0_Performance0 = t0 & 0x000007ff;
1291 f1aa6320 ths
}
1292 f1aa6320 ths
1293 be24bb4f ths
void do_mtc0_taglo (target_ulong t0)
1294 f1aa6320 ths
{
1295 be24bb4f ths
    env->CP0_TagLo = t0 & 0xFFFFFCF6;
1296 f1aa6320 ths
}
1297 f1aa6320 ths
1298 be24bb4f ths
void do_mtc0_datalo (target_ulong t0)
1299 f1aa6320 ths
{
1300 be24bb4f ths
    env->CP0_DataLo = t0; /* XXX */
1301 f1aa6320 ths
}
1302 f1aa6320 ths
1303 be24bb4f ths
void do_mtc0_taghi (target_ulong t0)
1304 f1aa6320 ths
{
1305 be24bb4f ths
    env->CP0_TagHi = t0; /* XXX */
1306 f1aa6320 ths
}
1307 f1aa6320 ths
1308 be24bb4f ths
void do_mtc0_datahi (target_ulong t0)
1309 f1aa6320 ths
{
1310 be24bb4f ths
    env->CP0_DataHi = t0; /* XXX */
1311 f1aa6320 ths
}
1312 f1aa6320 ths
1313 8c0fdd85 ths
void do_mtc0_status_debug(uint32_t old, uint32_t val)
1314 6af0bf9c bellard
{
1315 f41c52f1 ths
    fprintf(logfile, "Status %08x (%08x) => %08x (%08x) Cause %08x",
1316 f41c52f1 ths
            old, old & env->CP0_Cause & CP0Ca_IP_mask,
1317 f41c52f1 ths
            val, val & env->CP0_Cause & CP0Ca_IP_mask,
1318 f41c52f1 ths
            env->CP0_Cause);
1319 623a930e ths
    switch (env->hflags & MIPS_HFLAG_KSU) {
1320 623a930e ths
    case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break;
1321 623a930e ths
    case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break;
1322 623a930e ths
    case MIPS_HFLAG_KM: fputs("\n", logfile); break;
1323 623a930e ths
    default: cpu_abort(env, "Invalid MMU mode!\n"); break;
1324 623a930e ths
    }
1325 8c0fdd85 ths
}
1326 8c0fdd85 ths
1327 8c0fdd85 ths
void do_mtc0_status_irqraise_debug(void)
1328 8c0fdd85 ths
{
1329 8c0fdd85 ths
    fprintf(logfile, "Raise pending IRQs\n");
1330 6af0bf9c bellard
}
1331 f1aa6320 ths
#endif /* !CONFIG_USER_ONLY */
1332 f1aa6320 ths
1333 f1aa6320 ths
/* MIPS MT functions */
1334 be24bb4f ths
target_ulong do_mftgpr(target_ulong t0, uint32_t sel)
1335 f1aa6320 ths
{
1336 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1337 f1aa6320 ths
1338 be24bb4f ths
    return env->gpr[other_tc][sel];
1339 f1aa6320 ths
}
1340 f1aa6320 ths
1341 be24bb4f ths
target_ulong do_mftlo(target_ulong t0, uint32_t sel)
1342 f1aa6320 ths
{
1343 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1344 f1aa6320 ths
1345 be24bb4f ths
    return env->LO[other_tc][sel];
1346 f1aa6320 ths
}
1347 f1aa6320 ths
1348 be24bb4f ths
target_ulong do_mfthi(target_ulong t0, uint32_t sel)
1349 f1aa6320 ths
{
1350 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1351 f1aa6320 ths
1352 be24bb4f ths
    return env->HI[other_tc][sel];
1353 f1aa6320 ths
}
1354 f1aa6320 ths
1355 be24bb4f ths
target_ulong do_mftacx(target_ulong t0, uint32_t sel)
1356 f1aa6320 ths
{
1357 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1358 f1aa6320 ths
1359 be24bb4f ths
    return env->ACX[other_tc][sel];
1360 f1aa6320 ths
}
1361 f1aa6320 ths
1362 be24bb4f ths
target_ulong do_mftdsp(target_ulong t0)
1363 f1aa6320 ths
{
1364 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1365 f1aa6320 ths
1366 be24bb4f ths
    return env->DSPControl[other_tc];
1367 f1aa6320 ths
}
1368 6af0bf9c bellard
1369 be24bb4f ths
void do_mttgpr(target_ulong t0, uint32_t sel)
1370 f1aa6320 ths
{
1371 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1372 f1aa6320 ths
1373 be24bb4f ths
    env->gpr[other_tc][sel] = t0;
1374 f1aa6320 ths
}
1375 f1aa6320 ths
1376 be24bb4f ths
void do_mttlo(target_ulong t0, uint32_t sel)
1377 f1aa6320 ths
{
1378 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1379 f1aa6320 ths
1380 be24bb4f ths
    env->LO[other_tc][sel] = t0;
1381 f1aa6320 ths
}
1382 f1aa6320 ths
1383 be24bb4f ths
void do_mtthi(target_ulong t0, uint32_t sel)
1384 f1aa6320 ths
{
1385 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1386 f1aa6320 ths
1387 be24bb4f ths
    env->HI[other_tc][sel] = t0;
1388 f1aa6320 ths
}
1389 f1aa6320 ths
1390 be24bb4f ths
void do_mttacx(target_ulong t0, uint32_t sel)
1391 f1aa6320 ths
{
1392 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1393 f1aa6320 ths
1394 be24bb4f ths
    env->ACX[other_tc][sel] = t0;
1395 f1aa6320 ths
}
1396 f1aa6320 ths
1397 be24bb4f ths
void do_mttdsp(target_ulong t0)
1398 f1aa6320 ths
{
1399 f1aa6320 ths
    int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1400 f1aa6320 ths
1401 be24bb4f ths
    env->DSPControl[other_tc] = t0;
1402 f1aa6320 ths
}
1403 f1aa6320 ths
1404 f1aa6320 ths
/* MIPS MT functions */
1405 be24bb4f ths
target_ulong do_dmt(target_ulong t0)
1406 f1aa6320 ths
{
1407 f1aa6320 ths
    // TODO
1408 be24bb4f ths
    t0 = 0;
1409 be24bb4f ths
    // rt = t0
1410 be24bb4f ths
1411 be24bb4f ths
    return t0;
1412 f1aa6320 ths
}
1413 f1aa6320 ths
1414 be24bb4f ths
target_ulong do_emt(target_ulong t0)
1415 f1aa6320 ths
{
1416 f1aa6320 ths
    // TODO
1417 be24bb4f ths
    t0 = 0;
1418 be24bb4f ths
    // rt = t0
1419 be24bb4f ths
1420 be24bb4f ths
    return t0;
1421 f1aa6320 ths
}
1422 f1aa6320 ths
1423 be24bb4f ths
target_ulong do_dvpe(target_ulong t0)
1424 f1aa6320 ths
{
1425 f1aa6320 ths
    // TODO
1426 be24bb4f ths
    t0 = 0;
1427 be24bb4f ths
    // rt = t0
1428 be24bb4f ths
1429 be24bb4f ths
    return t0;
1430 f1aa6320 ths
}
1431 f1aa6320 ths
1432 be24bb4f ths
target_ulong do_evpe(target_ulong t0)
1433 f1aa6320 ths
{
1434 f1aa6320 ths
    // TODO
1435 be24bb4f ths
    t0 = 0;
1436 be24bb4f ths
    // rt = t0
1437 be24bb4f ths
1438 be24bb4f ths
    return t0;
1439 f1aa6320 ths
}
1440 f1aa6320 ths
1441 be24bb4f ths
target_ulong do_fork(target_ulong t0, target_ulong t1)
1442 f1aa6320 ths
{
1443 be24bb4f ths
    // t0 = rt, t1 = rs
1444 be24bb4f ths
    t0 = 0;
1445 f1aa6320 ths
    // TODO: store to TC register
1446 be24bb4f ths
1447 be24bb4f ths
    return t0;
1448 f1aa6320 ths
}
1449 f1aa6320 ths
1450 be24bb4f ths
target_ulong do_yield(target_ulong t0)
1451 f1aa6320 ths
{
1452 be24bb4f ths
    if (t0 < 0) {
1453 f1aa6320 ths
        /* No scheduling policy implemented. */
1454 be24bb4f ths
        if (t0 != -2) {
1455 f1aa6320 ths
            if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
1456 f1aa6320 ths
                env->CP0_TCStatus[env->current_tc] & (1 << CP0TCSt_DT)) {
1457 f1aa6320 ths
                env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1458 f1aa6320 ths
                env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
1459 f1aa6320 ths
                do_raise_exception(EXCP_THREAD);
1460 f1aa6320 ths
            }
1461 f1aa6320 ths
        }
1462 be24bb4f ths
    } else if (t0 == 0) {
1463 f1aa6320 ths
        if (0 /* TODO: TC underflow */) {
1464 f1aa6320 ths
            env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1465 f1aa6320 ths
            do_raise_exception(EXCP_THREAD);
1466 f1aa6320 ths
        } else {
1467 f1aa6320 ths
            // TODO: Deallocate TC
1468 f1aa6320 ths
        }
1469 be24bb4f ths
    } else if (t0 > 0) {
1470 f1aa6320 ths
        /* Yield qualifier inputs not implemented. */
1471 f1aa6320 ths
        env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1472 f1aa6320 ths
        env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
1473 f1aa6320 ths
        do_raise_exception(EXCP_THREAD);
1474 f1aa6320 ths
    }
1475 be24bb4f ths
    return env->CP0_YQMask;
1476 f1aa6320 ths
}
1477 f1aa6320 ths
1478 f1aa6320 ths
/* CP1 functions */
1479 6ea83fed bellard
void fpu_handle_exception(void)
1480 6ea83fed bellard
{
1481 6ea83fed bellard
#ifdef CONFIG_SOFTFLOAT
1482 ead9360e ths
    int flags = get_float_exception_flags(&env->fpu->fp_status);
1483 6ea83fed bellard
    unsigned int cpuflags = 0, enable, cause = 0;
1484 6ea83fed bellard
1485 ead9360e ths
    enable = GET_FP_ENABLE(env->fpu->fcr31);
1486 6ea83fed bellard
1487 3b46e624 ths
    /* determine current flags */
1488 6ea83fed bellard
    if (flags & float_flag_invalid) {
1489 6ea83fed bellard
        cpuflags |= FP_INVALID;
1490 6ea83fed bellard
        cause |= FP_INVALID & enable;
1491 6ea83fed bellard
    }
1492 6ea83fed bellard
    if (flags & float_flag_divbyzero) {
1493 3b46e624 ths
        cpuflags |= FP_DIV0;
1494 6ea83fed bellard
        cause |= FP_DIV0 & enable;
1495 6ea83fed bellard
    }
1496 6ea83fed bellard
    if (flags & float_flag_overflow) {
1497 3b46e624 ths
        cpuflags |= FP_OVERFLOW;
1498 6ea83fed bellard
        cause |= FP_OVERFLOW & enable;
1499 6ea83fed bellard
    }
1500 6ea83fed bellard
    if (flags & float_flag_underflow) {
1501 3b46e624 ths
        cpuflags |= FP_UNDERFLOW;
1502 6ea83fed bellard
        cause |= FP_UNDERFLOW & enable;
1503 6ea83fed bellard
    }
1504 6ea83fed bellard
    if (flags & float_flag_inexact) {
1505 5fafdf24 ths
        cpuflags |= FP_INEXACT;
1506 6ea83fed bellard
        cause |= FP_INEXACT & enable;
1507 6ea83fed bellard
    }
1508 ead9360e ths
    SET_FP_FLAGS(env->fpu->fcr31, cpuflags);
1509 ead9360e ths
    SET_FP_CAUSE(env->fpu->fcr31, cause);
1510 6ea83fed bellard
#else
1511 ead9360e ths
    SET_FP_FLAGS(env->fpu->fcr31, 0);
1512 ead9360e ths
    SET_FP_CAUSE(env->fpu->fcr31, 0);
1513 6ea83fed bellard
#endif
1514 6ea83fed bellard
}
1515 6ea83fed bellard
1516 f1aa6320 ths
#ifndef CONFIG_USER_ONLY
1517 6af0bf9c bellard
/* TLB management */
1518 814b9a47 ths
void cpu_mips_tlb_flush (CPUState *env, int flush_global)
1519 814b9a47 ths
{
1520 814b9a47 ths
    /* Flush qemu's TLB and discard all shadowed entries.  */
1521 814b9a47 ths
    tlb_flush (env, flush_global);
1522 ead9360e ths
    env->tlb->tlb_in_use = env->tlb->nb_tlb;
1523 814b9a47 ths
}
1524 814b9a47 ths
1525 29929e34 ths
static void r4k_mips_tlb_flush_extra (CPUState *env, int first)
1526 814b9a47 ths
{
1527 814b9a47 ths
    /* Discard entries from env->tlb[first] onwards.  */
1528 ead9360e ths
    while (env->tlb->tlb_in_use > first) {
1529 ead9360e ths
        r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0);
1530 814b9a47 ths
    }
1531 814b9a47 ths
}
1532 814b9a47 ths
1533 29929e34 ths
static void r4k_fill_tlb (int idx)
1534 6af0bf9c bellard
{
1535 29929e34 ths
    r4k_tlb_t *tlb;
1536 6af0bf9c bellard
1537 6af0bf9c bellard
    /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
1538 ead9360e ths
    tlb = &env->tlb->mmu.r4k.tlb[idx];
1539 f2e9ebef ths
    tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
1540 d26bc211 ths
#if defined(TARGET_MIPS64)
1541 e034e2c3 ths
    tlb->VPN &= env->SEGMask;
1542 100ce988 ths
#endif
1543 98c1b82b pbrook
    tlb->ASID = env->CP0_EntryHi & 0xFF;
1544 3b1c8be4 ths
    tlb->PageMask = env->CP0_PageMask;
1545 6af0bf9c bellard
    tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
1546 98c1b82b pbrook
    tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
1547 98c1b82b pbrook
    tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
1548 98c1b82b pbrook
    tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
1549 6af0bf9c bellard
    tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
1550 98c1b82b pbrook
    tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
1551 98c1b82b pbrook
    tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
1552 98c1b82b pbrook
    tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
1553 6af0bf9c bellard
    tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
1554 6af0bf9c bellard
}
1555 6af0bf9c bellard
1556 29929e34 ths
void r4k_do_tlbwi (void)
1557 6af0bf9c bellard
{
1558 814b9a47 ths
    /* Discard cached TLB entries.  We could avoid doing this if the
1559 814b9a47 ths
       tlbwi is just upgrading access permissions on the current entry;
1560 814b9a47 ths
       that might be a further win.  */
1561 ead9360e ths
    r4k_mips_tlb_flush_extra (env, env->tlb->nb_tlb);
1562 814b9a47 ths
1563 ead9360e ths
    r4k_invalidate_tlb(env, env->CP0_Index % env->tlb->nb_tlb, 0);
1564 ead9360e ths
    r4k_fill_tlb(env->CP0_Index % env->tlb->nb_tlb);
1565 6af0bf9c bellard
}
1566 6af0bf9c bellard
1567 29929e34 ths
void r4k_do_tlbwr (void)
1568 6af0bf9c bellard
{
1569 6af0bf9c bellard
    int r = cpu_mips_get_random(env);
1570 6af0bf9c bellard
1571 29929e34 ths
    r4k_invalidate_tlb(env, r, 1);
1572 29929e34 ths
    r4k_fill_tlb(r);
1573 6af0bf9c bellard
}
1574 6af0bf9c bellard
1575 29929e34 ths
void r4k_do_tlbp (void)
1576 6af0bf9c bellard
{
1577 29929e34 ths
    r4k_tlb_t *tlb;
1578 f2e9ebef ths
    target_ulong mask;
1579 6af0bf9c bellard
    target_ulong tag;
1580 f2e9ebef ths
    target_ulong VPN;
1581 6af0bf9c bellard
    uint8_t ASID;
1582 6af0bf9c bellard
    int i;
1583 6af0bf9c bellard
1584 3d9fb9fe bellard
    ASID = env->CP0_EntryHi & 0xFF;
1585 ead9360e ths
    for (i = 0; i < env->tlb->nb_tlb; i++) {
1586 ead9360e ths
        tlb = &env->tlb->mmu.r4k.tlb[i];
1587 f2e9ebef ths
        /* 1k pages are not supported. */
1588 f2e9ebef ths
        mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
1589 f2e9ebef ths
        tag = env->CP0_EntryHi & ~mask;
1590 f2e9ebef ths
        VPN = tlb->VPN & ~mask;
1591 6af0bf9c bellard
        /* Check ASID, virtual page number & size */
1592 f2e9ebef ths
        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1593 6af0bf9c bellard
            /* TLB match */
1594 9c2149c8 ths
            env->CP0_Index = i;
1595 6af0bf9c bellard
            break;
1596 6af0bf9c bellard
        }
1597 6af0bf9c bellard
    }
1598 ead9360e ths
    if (i == env->tlb->nb_tlb) {
1599 814b9a47 ths
        /* No match.  Discard any shadow entries, if any of them match.  */
1600 ead9360e ths
        for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) {
1601 ead9360e ths
            tlb = &env->tlb->mmu.r4k.tlb[i];
1602 f2e9ebef ths
            /* 1k pages are not supported. */
1603 f2e9ebef ths
            mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
1604 f2e9ebef ths
            tag = env->CP0_EntryHi & ~mask;
1605 f2e9ebef ths
            VPN = tlb->VPN & ~mask;
1606 814b9a47 ths
            /* Check ASID, virtual page number & size */
1607 f2e9ebef ths
            if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1608 29929e34 ths
                r4k_mips_tlb_flush_extra (env, i);
1609 814b9a47 ths
                break;
1610 814b9a47 ths
            }
1611 814b9a47 ths
        }
1612 814b9a47 ths
1613 9c2149c8 ths
        env->CP0_Index |= 0x80000000;
1614 6af0bf9c bellard
    }
1615 6af0bf9c bellard
}
1616 6af0bf9c bellard
1617 29929e34 ths
void r4k_do_tlbr (void)
1618 6af0bf9c bellard
{
1619 29929e34 ths
    r4k_tlb_t *tlb;
1620 09c56b84 pbrook
    uint8_t ASID;
1621 6af0bf9c bellard
1622 09c56b84 pbrook
    ASID = env->CP0_EntryHi & 0xFF;
1623 ead9360e ths
    tlb = &env->tlb->mmu.r4k.tlb[env->CP0_Index % env->tlb->nb_tlb];
1624 4ad40f36 bellard
1625 4ad40f36 bellard
    /* If this will change the current ASID, flush qemu's TLB.  */
1626 814b9a47 ths
    if (ASID != tlb->ASID)
1627 814b9a47 ths
        cpu_mips_tlb_flush (env, 1);
1628 814b9a47 ths
1629 ead9360e ths
    r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
1630 4ad40f36 bellard
1631 6af0bf9c bellard
    env->CP0_EntryHi = tlb->VPN | tlb->ASID;
1632 3b1c8be4 ths
    env->CP0_PageMask = tlb->PageMask;
1633 7495fd0f ths
    env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
1634 7495fd0f ths
                        (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
1635 7495fd0f ths
    env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
1636 7495fd0f ths
                        (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
1637 6af0bf9c bellard
}
1638 6af0bf9c bellard
1639 048f6b4d bellard
#endif /* !CONFIG_USER_ONLY */
1640 048f6b4d bellard
1641 2b0233ab ths
/* Specials */
1642 be24bb4f ths
target_ulong do_di (target_ulong t0)
1643 2b0233ab ths
{
1644 be24bb4f ths
    t0 = env->CP0_Status;
1645 be24bb4f ths
    env->CP0_Status = t0 & ~(1 << CP0St_IE);
1646 2b0233ab ths
    cpu_mips_update_irq(env);
1647 be24bb4f ths
1648 be24bb4f ths
    return t0;
1649 2b0233ab ths
}
1650 2b0233ab ths
1651 be24bb4f ths
target_ulong do_ei (target_ulong t0)
1652 2b0233ab ths
{
1653 be24bb4f ths
    t0 = env->CP0_Status;
1654 be24bb4f ths
    env->CP0_Status = t0 | (1 << CP0St_IE);
1655 2b0233ab ths
    cpu_mips_update_irq(env);
1656 be24bb4f ths
1657 be24bb4f ths
    return t0;
1658 2b0233ab ths
}
1659 2b0233ab ths
1660 f41c52f1 ths
void debug_pre_eret (void)
1661 6af0bf9c bellard
{
1662 f41c52f1 ths
    fprintf(logfile, "ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
1663 ead9360e ths
            env->PC[env->current_tc], env->CP0_EPC);
1664 f41c52f1 ths
    if (env->CP0_Status & (1 << CP0St_ERL))
1665 f41c52f1 ths
        fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
1666 f41c52f1 ths
    if (env->hflags & MIPS_HFLAG_DM)
1667 f41c52f1 ths
        fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC);
1668 f41c52f1 ths
    fputs("\n", logfile);
1669 f41c52f1 ths
}
1670 f41c52f1 ths
1671 f41c52f1 ths
void debug_post_eret (void)
1672 f41c52f1 ths
{
1673 744e0915 ths
    fprintf(logfile, "  =>  PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
1674 ead9360e ths
            env->PC[env->current_tc], env->CP0_EPC);
1675 f41c52f1 ths
    if (env->CP0_Status & (1 << CP0St_ERL))
1676 f41c52f1 ths
        fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
1677 f41c52f1 ths
    if (env->hflags & MIPS_HFLAG_DM)
1678 f41c52f1 ths
        fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC);
1679 623a930e ths
    switch (env->hflags & MIPS_HFLAG_KSU) {
1680 623a930e ths
    case MIPS_HFLAG_UM: fputs(", UM\n", logfile); break;
1681 623a930e ths
    case MIPS_HFLAG_SM: fputs(", SM\n", logfile); break;
1682 623a930e ths
    case MIPS_HFLAG_KM: fputs("\n", logfile); break;
1683 623a930e ths
    default: cpu_abort(env, "Invalid MMU mode!\n"); break;
1684 623a930e ths
    }
1685 6af0bf9c bellard
}
1686 6af0bf9c bellard
1687 be24bb4f ths
void do_eret (target_ulong t0)
1688 2b0233ab ths
{
1689 2b0233ab ths
    if (loglevel & CPU_LOG_EXEC)
1690 2b0233ab ths
        debug_pre_eret();
1691 2b0233ab ths
    if (env->CP0_Status & (1 << CP0St_ERL)) {
1692 2b0233ab ths
        env->PC[env->current_tc] = env->CP0_ErrorEPC;
1693 2b0233ab ths
        env->CP0_Status &= ~(1 << CP0St_ERL);
1694 2b0233ab ths
    } else {
1695 2b0233ab ths
        env->PC[env->current_tc] = env->CP0_EPC;
1696 2b0233ab ths
        env->CP0_Status &= ~(1 << CP0St_EXL);
1697 2b0233ab ths
    }
1698 2b0233ab ths
    compute_hflags(env);
1699 2b0233ab ths
    if (loglevel & CPU_LOG_EXEC)
1700 2b0233ab ths
        debug_post_eret();
1701 2b0233ab ths
    env->CP0_LLAddr = 1;
1702 2b0233ab ths
}
1703 2b0233ab ths
1704 be24bb4f ths
void do_deret (target_ulong t0)
1705 2b0233ab ths
{
1706 2b0233ab ths
    if (loglevel & CPU_LOG_EXEC)
1707 2b0233ab ths
        debug_pre_eret();
1708 2b0233ab ths
    env->PC[env->current_tc] = env->CP0_DEPC;
1709 2b0233ab ths
    env->hflags &= MIPS_HFLAG_DM;
1710 2b0233ab ths
    compute_hflags(env);
1711 2b0233ab ths
    if (loglevel & CPU_LOG_EXEC)
1712 2b0233ab ths
        debug_post_eret();
1713 2b0233ab ths
    env->CP0_LLAddr = 1;
1714 2b0233ab ths
}
1715 2b0233ab ths
1716 be24bb4f ths
target_ulong do_rdhwr_cpunum(target_ulong t0)
1717 2b0233ab ths
{
1718 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1719 2b0233ab ths
        (env->CP0_HWREna & (1 << 0)))
1720 be24bb4f ths
        t0 = env->CP0_EBase & 0x3ff;
1721 2b0233ab ths
    else
1722 2b0233ab ths
        do_raise_exception(EXCP_RI);
1723 be24bb4f ths
1724 be24bb4f ths
    return t0;
1725 2b0233ab ths
}
1726 2b0233ab ths
1727 be24bb4f ths
target_ulong do_rdhwr_synci_step(target_ulong t0)
1728 2b0233ab ths
{
1729 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1730 2b0233ab ths
        (env->CP0_HWREna & (1 << 1)))
1731 be24bb4f ths
        t0 = env->SYNCI_Step;
1732 2b0233ab ths
    else
1733 2b0233ab ths
        do_raise_exception(EXCP_RI);
1734 be24bb4f ths
1735 be24bb4f ths
    return t0;
1736 2b0233ab ths
}
1737 2b0233ab ths
1738 be24bb4f ths
target_ulong do_rdhwr_cc(target_ulong t0)
1739 2b0233ab ths
{
1740 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1741 2b0233ab ths
        (env->CP0_HWREna & (1 << 2)))
1742 be24bb4f ths
        t0 = env->CP0_Count;
1743 2b0233ab ths
    else
1744 2b0233ab ths
        do_raise_exception(EXCP_RI);
1745 be24bb4f ths
1746 be24bb4f ths
    return t0;
1747 2b0233ab ths
}
1748 2b0233ab ths
1749 be24bb4f ths
target_ulong do_rdhwr_ccres(target_ulong t0)
1750 2b0233ab ths
{
1751 2b0233ab ths
    if ((env->hflags & MIPS_HFLAG_CP0) ||
1752 2b0233ab ths
        (env->CP0_HWREna & (1 << 3)))
1753 be24bb4f ths
        t0 = env->CCRes;
1754 2b0233ab ths
    else
1755 2b0233ab ths
        do_raise_exception(EXCP_RI);
1756 be24bb4f ths
1757 be24bb4f ths
    return t0;
1758 2b0233ab ths
}
1759 2b0233ab ths
1760 2b0233ab ths
/* Bitfield operations. */
1761 be24bb4f ths
target_ulong do_ext(target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size)
1762 2b0233ab ths
{
1763 be24bb4f ths
    return (int32_t)((t1 >> pos) & ((size < 32) ? ((1 << size) - 1) : ~0));
1764 2b0233ab ths
}
1765 2b0233ab ths
1766 be24bb4f ths
target_ulong do_ins(target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size)
1767 2b0233ab ths
{
1768 2b0233ab ths
    target_ulong mask = ((size < 32) ? ((1 << size) - 1) : ~0) << pos;
1769 2b0233ab ths
1770 be24bb4f ths
    return (int32_t)((t0 & ~mask) | ((t1 << pos) & mask));
1771 2b0233ab ths
}
1772 2b0233ab ths
1773 be24bb4f ths
target_ulong do_wsbh(target_ulong t0, target_ulong t1)
1774 2b0233ab ths
{
1775 be24bb4f ths
    return (int32_t)(((t1 << 8) & ~0x00FF00FF) | ((t1 >> 8) & 0x00FF00FF));
1776 2b0233ab ths
}
1777 2b0233ab ths
1778 2b0233ab ths
#if defined(TARGET_MIPS64)
1779 be24bb4f ths
target_ulong do_dext(target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size)
1780 2b0233ab ths
{
1781 be24bb4f ths
    return (t1 >> pos) & ((size < 64) ? ((1ULL << size) - 1) : ~0ULL);
1782 2b0233ab ths
}
1783 2b0233ab ths
1784 be24bb4f ths
target_ulong do_dins(target_ulong t0, target_ulong t1, uint32_t pos, uint32_t size)
1785 2b0233ab ths
{
1786 2b0233ab ths
    target_ulong mask = ((size < 64) ? ((1ULL << size) - 1) : ~0ULL) << pos;
1787 2b0233ab ths
1788 be24bb4f ths
    return (t0 & ~mask) | ((t1 << pos) & mask);
1789 2b0233ab ths
}
1790 2b0233ab ths
1791 be24bb4f ths
target_ulong do_dsbh(target_ulong t0, target_ulong t1)
1792 2b0233ab ths
{
1793 be24bb4f ths
    return ((t1 << 8) & ~0x00FF00FF00FF00FFULL) | ((t1 >> 8) & 0x00FF00FF00FF00FFULL);
1794 2b0233ab ths
}
1795 2b0233ab ths
1796 be24bb4f ths
target_ulong do_dshd(target_ulong t0, target_ulong t1)
1797 2b0233ab ths
{
1798 be24bb4f ths
    t1 = ((t1 << 16) & ~0x0000FFFF0000FFFFULL) | ((t1 >> 16) & 0x0000FFFF0000FFFFULL);
1799 be24bb4f ths
    return (t1 << 32) | (t1 >> 32);
1800 2b0233ab ths
}
1801 2b0233ab ths
#endif
1802 2b0233ab ths
1803 6af0bf9c bellard
void do_pmon (int function)
1804 6af0bf9c bellard
{
1805 6af0bf9c bellard
    function /= 2;
1806 6af0bf9c bellard
    switch (function) {
1807 6af0bf9c bellard
    case 2: /* TODO: char inbyte(int waitflag); */
1808 d0dc7dc3 ths
        if (env->gpr[env->current_tc][4] == 0)
1809 d0dc7dc3 ths
            env->gpr[env->current_tc][2] = -1;
1810 6af0bf9c bellard
        /* Fall through */
1811 6af0bf9c bellard
    case 11: /* TODO: char inbyte (void); */
1812 d0dc7dc3 ths
        env->gpr[env->current_tc][2] = -1;
1813 6af0bf9c bellard
        break;
1814 6af0bf9c bellard
    case 3:
1815 6af0bf9c bellard
    case 12:
1816 d0dc7dc3 ths
        printf("%c", (char)(env->gpr[env->current_tc][4] & 0xFF));
1817 6af0bf9c bellard
        break;
1818 6af0bf9c bellard
    case 17:
1819 6af0bf9c bellard
        break;
1820 6af0bf9c bellard
    case 158:
1821 6af0bf9c bellard
        {
1822 d0dc7dc3 ths
            unsigned char *fmt = (void *)(unsigned long)env->gpr[env->current_tc][4];
1823 6af0bf9c bellard
            printf("%s", fmt);
1824 6af0bf9c bellard
        }
1825 6af0bf9c bellard
        break;
1826 6af0bf9c bellard
    }
1827 6af0bf9c bellard
}
1828 e37e863f bellard
1829 08ba7963 ths
void do_wait (void)
1830 08ba7963 ths
{
1831 08ba7963 ths
    env->halted = 1;
1832 08ba7963 ths
    do_raise_exception(EXCP_HLT);
1833 08ba7963 ths
}
1834 08ba7963 ths
1835 5fafdf24 ths
#if !defined(CONFIG_USER_ONLY)
1836 e37e863f bellard
1837 4ad40f36 bellard
static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
1838 4ad40f36 bellard
1839 e37e863f bellard
#define MMUSUFFIX _mmu
1840 4ad40f36 bellard
#define ALIGNED_ONLY
1841 e37e863f bellard
1842 e37e863f bellard
#define SHIFT 0
1843 e37e863f bellard
#include "softmmu_template.h"
1844 e37e863f bellard
1845 e37e863f bellard
#define SHIFT 1
1846 e37e863f bellard
#include "softmmu_template.h"
1847 e37e863f bellard
1848 e37e863f bellard
#define SHIFT 2
1849 e37e863f bellard
#include "softmmu_template.h"
1850 e37e863f bellard
1851 e37e863f bellard
#define SHIFT 3
1852 e37e863f bellard
#include "softmmu_template.h"
1853 e37e863f bellard
1854 4ad40f36 bellard
static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
1855 4ad40f36 bellard
{
1856 4ad40f36 bellard
    env->CP0_BadVAddr = addr;
1857 4ad40f36 bellard
    do_restore_state (retaddr);
1858 4ad40f36 bellard
    do_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
1859 4ad40f36 bellard
}
1860 4ad40f36 bellard
1861 6ebbf390 j_mayer
void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1862 e37e863f bellard
{
1863 e37e863f bellard
    TranslationBlock *tb;
1864 e37e863f bellard
    CPUState *saved_env;
1865 e37e863f bellard
    unsigned long pc;
1866 e37e863f bellard
    int ret;
1867 e37e863f bellard
1868 e37e863f bellard
    /* XXX: hack to restore env in all cases, even if not called from
1869 e37e863f bellard
       generated code */
1870 e37e863f bellard
    saved_env = env;
1871 e37e863f bellard
    env = cpu_single_env;
1872 6ebbf390 j_mayer
    ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1873 e37e863f bellard
    if (ret) {
1874 e37e863f bellard
        if (retaddr) {
1875 e37e863f bellard
            /* now we have a real cpu fault */
1876 e37e863f bellard
            pc = (unsigned long)retaddr;
1877 e37e863f bellard
            tb = tb_find_pc(pc);
1878 e37e863f bellard
            if (tb) {
1879 e37e863f bellard
                /* the PC is inside the translated code. It means that we have
1880 e37e863f bellard
                   a virtual CPU fault */
1881 e37e863f bellard
                cpu_restore_state(tb, env, pc, NULL);
1882 e37e863f bellard
            }
1883 e37e863f bellard
        }
1884 e37e863f bellard
        do_raise_exception_err(env->exception_index, env->error_code);
1885 e37e863f bellard
    }
1886 e37e863f bellard
    env = saved_env;
1887 e37e863f bellard
}
1888 e37e863f bellard
1889 647de6ca ths
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1890 647de6ca ths
                          int unused)
1891 647de6ca ths
{
1892 647de6ca ths
    if (is_exec)
1893 647de6ca ths
        do_raise_exception(EXCP_IBE);
1894 647de6ca ths
    else
1895 647de6ca ths
        do_raise_exception(EXCP_DBE);
1896 647de6ca ths
}
1897 f1aa6320 ths
#endif /* !CONFIG_USER_ONLY */
1898 fd4a04eb ths
1899 fd4a04eb ths
/* Complex FPU operations which may need stack space. */
1900 fd4a04eb ths
1901 f090c9d4 pbrook
#define FLOAT_ONE32 make_float32(0x3f8 << 20)
1902 f090c9d4 pbrook
#define FLOAT_ONE64 make_float64(0x3ffULL << 52)
1903 f090c9d4 pbrook
#define FLOAT_TWO32 make_float32(1 << 30)
1904 f090c9d4 pbrook
#define FLOAT_TWO64 make_float64(1ULL << 62)
1905 54454097 ths
#define FLOAT_QNAN32 0x7fbfffff
1906 54454097 ths
#define FLOAT_QNAN64 0x7ff7ffffffffffffULL
1907 54454097 ths
#define FLOAT_SNAN32 0x7fffffff
1908 54454097 ths
#define FLOAT_SNAN64 0x7fffffffffffffffULL
1909 8dfdb87c ths
1910 fd4a04eb ths
/* convert MIPS rounding mode in FCR31 to IEEE library */
1911 fd4a04eb ths
unsigned int ieee_rm[] = {
1912 fd4a04eb ths
    float_round_nearest_even,
1913 fd4a04eb ths
    float_round_to_zero,
1914 fd4a04eb ths
    float_round_up,
1915 fd4a04eb ths
    float_round_down
1916 fd4a04eb ths
};
1917 fd4a04eb ths
1918 fd4a04eb ths
#define RESTORE_ROUNDING_MODE \
1919 ead9360e ths
    set_float_rounding_mode(ieee_rm[env->fpu->fcr31 & 3], &env->fpu->fp_status)
1920 fd4a04eb ths
1921 be24bb4f ths
target_ulong do_cfc1 (target_ulong t0, uint32_t reg)
1922 fd4a04eb ths
{
1923 ead9360e ths
    switch (reg) {
1924 ead9360e ths
    case 0:
1925 be24bb4f ths
        t0 = (int32_t)env->fpu->fcr0;
1926 ead9360e ths
        break;
1927 ead9360e ths
    case 25:
1928 be24bb4f ths
        t0 = ((env->fpu->fcr31 >> 24) & 0xfe) | ((env->fpu->fcr31 >> 23) & 0x1);
1929 ead9360e ths
        break;
1930 ead9360e ths
    case 26:
1931 be24bb4f ths
        t0 = env->fpu->fcr31 & 0x0003f07c;
1932 ead9360e ths
        break;
1933 ead9360e ths
    case 28:
1934 be24bb4f ths
        t0 = (env->fpu->fcr31 & 0x00000f83) | ((env->fpu->fcr31 >> 22) & 0x4);
1935 ead9360e ths
        break;
1936 ead9360e ths
    default:
1937 be24bb4f ths
        t0 = (int32_t)env->fpu->fcr31;
1938 ead9360e ths
        break;
1939 ead9360e ths
    }
1940 be24bb4f ths
1941 be24bb4f ths
    return t0;
1942 ead9360e ths
}
1943 ead9360e ths
1944 be24bb4f ths
void do_ctc1 (target_ulong t0, uint32_t reg)
1945 ead9360e ths
{
1946 ead9360e ths
    switch(reg) {
1947 fd4a04eb ths
    case 25:
1948 be24bb4f ths
        if (t0 & 0xffffff00)
1949 fd4a04eb ths
            return;
1950 be24bb4f ths
        env->fpu->fcr31 = (env->fpu->fcr31 & 0x017fffff) | ((t0 & 0xfe) << 24) |
1951 be24bb4f ths
                     ((t0 & 0x1) << 23);
1952 fd4a04eb ths
        break;
1953 fd4a04eb ths
    case 26:
1954 be24bb4f ths
        if (t0 & 0x007c0000)
1955 fd4a04eb ths
            return;
1956 be24bb4f ths
        env->fpu->fcr31 = (env->fpu->fcr31 & 0xfffc0f83) | (t0 & 0x0003f07c);
1957 fd4a04eb ths
        break;
1958 fd4a04eb ths
    case 28:
1959 be24bb4f ths
        if (t0 & 0x007c0000)
1960 fd4a04eb ths
            return;
1961 be24bb4f ths
        env->fpu->fcr31 = (env->fpu->fcr31 & 0xfefff07c) | (t0 & 0x00000f83) |
1962 be24bb4f ths
                     ((t0 & 0x4) << 22);
1963 fd4a04eb ths
        break;
1964 fd4a04eb ths
    case 31:
1965 be24bb4f ths
        if (t0 & 0x007c0000)
1966 fd4a04eb ths
            return;
1967 be24bb4f ths
        env->fpu->fcr31 = t0;
1968 fd4a04eb ths
        break;
1969 fd4a04eb ths
    default:
1970 fd4a04eb ths
        return;
1971 fd4a04eb ths
    }
1972 fd4a04eb ths
    /* set rounding mode */
1973 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
1974 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
1975 ead9360e ths
    if ((GET_FP_ENABLE(env->fpu->fcr31) | 0x20) & GET_FP_CAUSE(env->fpu->fcr31))
1976 fd4a04eb ths
        do_raise_exception(EXCP_FPE);
1977 fd4a04eb ths
}
1978 fd4a04eb ths
1979 aa343735 ths
static always_inline char ieee_ex_to_mips(char xcpt)
1980 fd4a04eb ths
{
1981 fd4a04eb ths
    return (xcpt & float_flag_inexact) >> 5 |
1982 fd4a04eb ths
           (xcpt & float_flag_underflow) >> 3 |
1983 fd4a04eb ths
           (xcpt & float_flag_overflow) >> 1 |
1984 fd4a04eb ths
           (xcpt & float_flag_divbyzero) << 1 |
1985 fd4a04eb ths
           (xcpt & float_flag_invalid) << 4;
1986 fd4a04eb ths
}
1987 fd4a04eb ths
1988 aa343735 ths
static always_inline char mips_ex_to_ieee(char xcpt)
1989 fd4a04eb ths
{
1990 fd4a04eb ths
    return (xcpt & FP_INEXACT) << 5 |
1991 fd4a04eb ths
           (xcpt & FP_UNDERFLOW) << 3 |
1992 fd4a04eb ths
           (xcpt & FP_OVERFLOW) << 1 |
1993 fd4a04eb ths
           (xcpt & FP_DIV0) >> 1 |
1994 fd4a04eb ths
           (xcpt & FP_INVALID) >> 4;
1995 fd4a04eb ths
}
1996 fd4a04eb ths
1997 aa343735 ths
static always_inline void update_fcr31(void)
1998 fd4a04eb ths
{
1999 ead9360e ths
    int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fpu->fp_status));
2000 fd4a04eb ths
2001 ead9360e ths
    SET_FP_CAUSE(env->fpu->fcr31, tmp);
2002 ead9360e ths
    if (GET_FP_ENABLE(env->fpu->fcr31) & tmp)
2003 fd4a04eb ths
        do_raise_exception(EXCP_FPE);
2004 fd4a04eb ths
    else
2005 ead9360e ths
        UPDATE_FP_FLAGS(env->fpu->fcr31, tmp);
2006 fd4a04eb ths
}
2007 fd4a04eb ths
2008 a16336e4 ths
/* Float support.
2009 a16336e4 ths
   Single precition routines have a "s" suffix, double precision a
2010 a16336e4 ths
   "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps",
2011 a16336e4 ths
   paired single lower "pl", paired single upper "pu".  */
2012 a16336e4 ths
2013 fd4a04eb ths
#define FLOAT_OP(name, p) void do_float_##name##_##p(void)
2014 fd4a04eb ths
2015 a16336e4 ths
/* unary operations, modifying fp status  */
2016 a16336e4 ths
#define FLOAT_UNOP(name)  \
2017 a16336e4 ths
FLOAT_OP(name, d)         \
2018 a16336e4 ths
{                         \
2019 a16336e4 ths
    FDT2 = float64_ ## name(FDT0, &env->fpu->fp_status); \
2020 a16336e4 ths
}                         \
2021 a16336e4 ths
FLOAT_OP(name, s)         \
2022 a16336e4 ths
{                         \
2023 a16336e4 ths
    FST2 = float32_ ## name(FST0, &env->fpu->fp_status); \
2024 a16336e4 ths
}
2025 a16336e4 ths
FLOAT_UNOP(sqrt)
2026 a16336e4 ths
#undef FLOAT_UNOP
2027 a16336e4 ths
2028 fd4a04eb ths
FLOAT_OP(cvtd, s)
2029 fd4a04eb ths
{
2030 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2031 ead9360e ths
    FDT2 = float32_to_float64(FST0, &env->fpu->fp_status);
2032 fd4a04eb ths
    update_fcr31();
2033 fd4a04eb ths
}
2034 fd4a04eb ths
FLOAT_OP(cvtd, w)
2035 fd4a04eb ths
{
2036 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2037 ead9360e ths
    FDT2 = int32_to_float64(WT0, &env->fpu->fp_status);
2038 fd4a04eb ths
    update_fcr31();
2039 fd4a04eb ths
}
2040 fd4a04eb ths
FLOAT_OP(cvtd, l)
2041 fd4a04eb ths
{
2042 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2043 ead9360e ths
    FDT2 = int64_to_float64(DT0, &env->fpu->fp_status);
2044 fd4a04eb ths
    update_fcr31();
2045 fd4a04eb ths
}
2046 fd4a04eb ths
FLOAT_OP(cvtl, d)
2047 fd4a04eb ths
{
2048 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2049 ead9360e ths
    DT2 = float64_to_int64(FDT0, &env->fpu->fp_status);
2050 fd4a04eb ths
    update_fcr31();
2051 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2052 54454097 ths
        DT2 = FLOAT_SNAN64;
2053 fd4a04eb ths
}
2054 fd4a04eb ths
FLOAT_OP(cvtl, s)
2055 fd4a04eb ths
{
2056 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2057 ead9360e ths
    DT2 = float32_to_int64(FST0, &env->fpu->fp_status);
2058 fd4a04eb ths
    update_fcr31();
2059 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2060 54454097 ths
        DT2 = FLOAT_SNAN64;
2061 fd4a04eb ths
}
2062 fd4a04eb ths
2063 fd4a04eb ths
FLOAT_OP(cvtps, pw)
2064 fd4a04eb ths
{
2065 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2066 ead9360e ths
    FST2 = int32_to_float32(WT0, &env->fpu->fp_status);
2067 ead9360e ths
    FSTH2 = int32_to_float32(WTH0, &env->fpu->fp_status);
2068 fd4a04eb ths
    update_fcr31();
2069 fd4a04eb ths
}
2070 fd4a04eb ths
FLOAT_OP(cvtpw, ps)
2071 fd4a04eb ths
{
2072 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2073 ead9360e ths
    WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
2074 ead9360e ths
    WTH2 = float32_to_int32(FSTH0, &env->fpu->fp_status);
2075 fd4a04eb ths
    update_fcr31();
2076 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2077 54454097 ths
        WT2 = FLOAT_SNAN32;
2078 fd4a04eb ths
}
2079 fd4a04eb ths
FLOAT_OP(cvts, d)
2080 fd4a04eb ths
{
2081 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2082 ead9360e ths
    FST2 = float64_to_float32(FDT0, &env->fpu->fp_status);
2083 fd4a04eb ths
    update_fcr31();
2084 fd4a04eb ths
}
2085 fd4a04eb ths
FLOAT_OP(cvts, w)
2086 fd4a04eb ths
{
2087 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2088 ead9360e ths
    FST2 = int32_to_float32(WT0, &env->fpu->fp_status);
2089 fd4a04eb ths
    update_fcr31();
2090 fd4a04eb ths
}
2091 fd4a04eb ths
FLOAT_OP(cvts, l)
2092 fd4a04eb ths
{
2093 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2094 ead9360e ths
    FST2 = int64_to_float32(DT0, &env->fpu->fp_status);
2095 fd4a04eb ths
    update_fcr31();
2096 fd4a04eb ths
}
2097 fd4a04eb ths
FLOAT_OP(cvts, pl)
2098 fd4a04eb ths
{
2099 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2100 fd4a04eb ths
    WT2 = WT0;
2101 fd4a04eb ths
    update_fcr31();
2102 fd4a04eb ths
}
2103 fd4a04eb ths
FLOAT_OP(cvts, pu)
2104 fd4a04eb ths
{
2105 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2106 fd4a04eb ths
    WT2 = WTH0;
2107 fd4a04eb ths
    update_fcr31();
2108 fd4a04eb ths
}
2109 fd4a04eb ths
FLOAT_OP(cvtw, s)
2110 fd4a04eb ths
{
2111 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2112 ead9360e ths
    WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
2113 fd4a04eb ths
    update_fcr31();
2114 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2115 54454097 ths
        WT2 = FLOAT_SNAN32;
2116 fd4a04eb ths
}
2117 fd4a04eb ths
FLOAT_OP(cvtw, d)
2118 fd4a04eb ths
{
2119 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2120 ead9360e ths
    WT2 = float64_to_int32(FDT0, &env->fpu->fp_status);
2121 fd4a04eb ths
    update_fcr31();
2122 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2123 54454097 ths
        WT2 = FLOAT_SNAN32;
2124 fd4a04eb ths
}
2125 fd4a04eb ths
2126 fd4a04eb ths
FLOAT_OP(roundl, d)
2127 fd4a04eb ths
{
2128 ead9360e ths
    set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
2129 ead9360e ths
    DT2 = float64_to_int64(FDT0, &env->fpu->fp_status);
2130 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2131 fd4a04eb ths
    update_fcr31();
2132 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2133 54454097 ths
        DT2 = FLOAT_SNAN64;
2134 fd4a04eb ths
}
2135 fd4a04eb ths
FLOAT_OP(roundl, s)
2136 fd4a04eb ths
{
2137 ead9360e ths
    set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
2138 ead9360e ths
    DT2 = float32_to_int64(FST0, &env->fpu->fp_status);
2139 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2140 fd4a04eb ths
    update_fcr31();
2141 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2142 54454097 ths
        DT2 = FLOAT_SNAN64;
2143 fd4a04eb ths
}
2144 fd4a04eb ths
FLOAT_OP(roundw, d)
2145 fd4a04eb ths
{
2146 ead9360e ths
    set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
2147 ead9360e ths
    WT2 = float64_to_int32(FDT0, &env->fpu->fp_status);
2148 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2149 fd4a04eb ths
    update_fcr31();
2150 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2151 54454097 ths
        WT2 = FLOAT_SNAN32;
2152 fd4a04eb ths
}
2153 fd4a04eb ths
FLOAT_OP(roundw, s)
2154 fd4a04eb ths
{
2155 ead9360e ths
    set_float_rounding_mode(float_round_nearest_even, &env->fpu->fp_status);
2156 ead9360e ths
    WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
2157 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2158 fd4a04eb ths
    update_fcr31();
2159 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2160 54454097 ths
        WT2 = FLOAT_SNAN32;
2161 fd4a04eb ths
}
2162 fd4a04eb ths
2163 fd4a04eb ths
FLOAT_OP(truncl, d)
2164 fd4a04eb ths
{
2165 ead9360e ths
    DT2 = float64_to_int64_round_to_zero(FDT0, &env->fpu->fp_status);
2166 fd4a04eb ths
    update_fcr31();
2167 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2168 54454097 ths
        DT2 = FLOAT_SNAN64;
2169 fd4a04eb ths
}
2170 fd4a04eb ths
FLOAT_OP(truncl, s)
2171 fd4a04eb ths
{
2172 ead9360e ths
    DT2 = float32_to_int64_round_to_zero(FST0, &env->fpu->fp_status);
2173 fd4a04eb ths
    update_fcr31();
2174 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2175 54454097 ths
        DT2 = FLOAT_SNAN64;
2176 fd4a04eb ths
}
2177 fd4a04eb ths
FLOAT_OP(truncw, d)
2178 fd4a04eb ths
{
2179 ead9360e ths
    WT2 = float64_to_int32_round_to_zero(FDT0, &env->fpu->fp_status);
2180 fd4a04eb ths
    update_fcr31();
2181 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2182 54454097 ths
        WT2 = FLOAT_SNAN32;
2183 fd4a04eb ths
}
2184 fd4a04eb ths
FLOAT_OP(truncw, s)
2185 fd4a04eb ths
{
2186 ead9360e ths
    WT2 = float32_to_int32_round_to_zero(FST0, &env->fpu->fp_status);
2187 fd4a04eb ths
    update_fcr31();
2188 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2189 54454097 ths
        WT2 = FLOAT_SNAN32;
2190 fd4a04eb ths
}
2191 fd4a04eb ths
2192 fd4a04eb ths
FLOAT_OP(ceill, d)
2193 fd4a04eb ths
{
2194 ead9360e ths
    set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
2195 ead9360e ths
    DT2 = float64_to_int64(FDT0, &env->fpu->fp_status);
2196 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2197 fd4a04eb ths
    update_fcr31();
2198 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2199 54454097 ths
        DT2 = FLOAT_SNAN64;
2200 fd4a04eb ths
}
2201 fd4a04eb ths
FLOAT_OP(ceill, s)
2202 fd4a04eb ths
{
2203 ead9360e ths
    set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
2204 ead9360e ths
    DT2 = float32_to_int64(FST0, &env->fpu->fp_status);
2205 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2206 fd4a04eb ths
    update_fcr31();
2207 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2208 54454097 ths
        DT2 = FLOAT_SNAN64;
2209 fd4a04eb ths
}
2210 fd4a04eb ths
FLOAT_OP(ceilw, d)
2211 fd4a04eb ths
{
2212 ead9360e ths
    set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
2213 ead9360e ths
    WT2 = float64_to_int32(FDT0, &env->fpu->fp_status);
2214 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2215 fd4a04eb ths
    update_fcr31();
2216 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2217 54454097 ths
        WT2 = FLOAT_SNAN32;
2218 fd4a04eb ths
}
2219 fd4a04eb ths
FLOAT_OP(ceilw, s)
2220 fd4a04eb ths
{
2221 ead9360e ths
    set_float_rounding_mode(float_round_up, &env->fpu->fp_status);
2222 ead9360e ths
    WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
2223 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2224 fd4a04eb ths
    update_fcr31();
2225 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2226 54454097 ths
        WT2 = FLOAT_SNAN32;
2227 fd4a04eb ths
}
2228 fd4a04eb ths
2229 fd4a04eb ths
FLOAT_OP(floorl, d)
2230 fd4a04eb ths
{
2231 ead9360e ths
    set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
2232 ead9360e ths
    DT2 = float64_to_int64(FDT0, &env->fpu->fp_status);
2233 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2234 fd4a04eb ths
    update_fcr31();
2235 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2236 54454097 ths
        DT2 = FLOAT_SNAN64;
2237 fd4a04eb ths
}
2238 fd4a04eb ths
FLOAT_OP(floorl, s)
2239 fd4a04eb ths
{
2240 ead9360e ths
    set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
2241 ead9360e ths
    DT2 = float32_to_int64(FST0, &env->fpu->fp_status);
2242 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2243 fd4a04eb ths
    update_fcr31();
2244 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2245 54454097 ths
        DT2 = FLOAT_SNAN64;
2246 fd4a04eb ths
}
2247 fd4a04eb ths
FLOAT_OP(floorw, d)
2248 fd4a04eb ths
{
2249 ead9360e ths
    set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
2250 ead9360e ths
    WT2 = float64_to_int32(FDT0, &env->fpu->fp_status);
2251 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2252 fd4a04eb ths
    update_fcr31();
2253 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2254 54454097 ths
        WT2 = FLOAT_SNAN32;
2255 fd4a04eb ths
}
2256 fd4a04eb ths
FLOAT_OP(floorw, s)
2257 fd4a04eb ths
{
2258 ead9360e ths
    set_float_rounding_mode(float_round_down, &env->fpu->fp_status);
2259 ead9360e ths
    WT2 = float32_to_int32(FST0, &env->fpu->fp_status);
2260 fd4a04eb ths
    RESTORE_ROUNDING_MODE;
2261 fd4a04eb ths
    update_fcr31();
2262 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & (FP_OVERFLOW | FP_INVALID))
2263 54454097 ths
        WT2 = FLOAT_SNAN32;
2264 fd4a04eb ths
}
2265 fd4a04eb ths
2266 a16336e4 ths
/* unary operations, not modifying fp status  */
2267 a16336e4 ths
#define FLOAT_UNOP(name)  \
2268 a16336e4 ths
FLOAT_OP(name, d)         \
2269 a16336e4 ths
{                         \
2270 a16336e4 ths
    FDT2 = float64_ ## name(FDT0);   \
2271 a16336e4 ths
}                         \
2272 a16336e4 ths
FLOAT_OP(name, s)         \
2273 a16336e4 ths
{                         \
2274 a16336e4 ths
    FST2 = float32_ ## name(FST0);   \
2275 a16336e4 ths
}                         \
2276 a16336e4 ths
FLOAT_OP(name, ps)        \
2277 a16336e4 ths
{                         \
2278 a16336e4 ths
    FST2 = float32_ ## name(FST0);   \
2279 a16336e4 ths
    FSTH2 = float32_ ## name(FSTH0); \
2280 a16336e4 ths
}
2281 a16336e4 ths
FLOAT_UNOP(abs)
2282 a16336e4 ths
FLOAT_UNOP(chs)
2283 a16336e4 ths
#undef FLOAT_UNOP
2284 a16336e4 ths
2285 8dfdb87c ths
/* MIPS specific unary operations */
2286 8dfdb87c ths
FLOAT_OP(recip, d)
2287 8dfdb87c ths
{
2288 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2289 ead9360e ths
    FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fpu->fp_status);
2290 8dfdb87c ths
    update_fcr31();
2291 8dfdb87c ths
}
2292 8dfdb87c ths
FLOAT_OP(recip, s)
2293 8dfdb87c ths
{
2294 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2295 ead9360e ths
    FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status);
2296 8dfdb87c ths
    update_fcr31();
2297 57fa1fb3 ths
}
2298 57fa1fb3 ths
2299 8dfdb87c ths
FLOAT_OP(rsqrt, d)
2300 8dfdb87c ths
{
2301 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2302 ead9360e ths
    FDT2 = float64_sqrt(FDT0, &env->fpu->fp_status);
2303 ead9360e ths
    FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fpu->fp_status);
2304 8dfdb87c ths
    update_fcr31();
2305 8dfdb87c ths
}
2306 8dfdb87c ths
FLOAT_OP(rsqrt, s)
2307 8dfdb87c ths
{
2308 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2309 ead9360e ths
    FST2 = float32_sqrt(FST0, &env->fpu->fp_status);
2310 ead9360e ths
    FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status);
2311 8dfdb87c ths
    update_fcr31();
2312 8dfdb87c ths
}
2313 8dfdb87c ths
2314 8dfdb87c ths
FLOAT_OP(recip1, d)
2315 8dfdb87c ths
{
2316 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2317 ead9360e ths
    FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fpu->fp_status);
2318 8dfdb87c ths
    update_fcr31();
2319 8dfdb87c ths
}
2320 8dfdb87c ths
FLOAT_OP(recip1, s)
2321 8dfdb87c ths
{
2322 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2323 ead9360e ths
    FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status);
2324 8dfdb87c ths
    update_fcr31();
2325 8dfdb87c ths
}
2326 8dfdb87c ths
FLOAT_OP(recip1, ps)
2327 8dfdb87c ths
{
2328 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2329 ead9360e ths
    FST2 = float32_div(FLOAT_ONE32, FST0, &env->fpu->fp_status);
2330 ead9360e ths
    FSTH2 = float32_div(FLOAT_ONE32, FSTH0, &env->fpu->fp_status);
2331 8dfdb87c ths
    update_fcr31();
2332 8dfdb87c ths
}
2333 8dfdb87c ths
2334 8dfdb87c ths
FLOAT_OP(rsqrt1, d)
2335 8dfdb87c ths
{
2336 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2337 ead9360e ths
    FDT2 = float64_sqrt(FDT0, &env->fpu->fp_status);
2338 ead9360e ths
    FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fpu->fp_status);
2339 8dfdb87c ths
    update_fcr31();
2340 8dfdb87c ths
}
2341 8dfdb87c ths
FLOAT_OP(rsqrt1, s)
2342 8dfdb87c ths
{
2343 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2344 ead9360e ths
    FST2 = float32_sqrt(FST0, &env->fpu->fp_status);
2345 ead9360e ths
    FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status);
2346 8dfdb87c ths
    update_fcr31();
2347 8dfdb87c ths
}
2348 8dfdb87c ths
FLOAT_OP(rsqrt1, ps)
2349 8dfdb87c ths
{
2350 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2351 ead9360e ths
    FST2 = float32_sqrt(FST0, &env->fpu->fp_status);
2352 ead9360e ths
    FSTH2 = float32_sqrt(FSTH0, &env->fpu->fp_status);
2353 ead9360e ths
    FST2 = float32_div(FLOAT_ONE32, FST2, &env->fpu->fp_status);
2354 ead9360e ths
    FSTH2 = float32_div(FLOAT_ONE32, FSTH2, &env->fpu->fp_status);
2355 8dfdb87c ths
    update_fcr31();
2356 57fa1fb3 ths
}
2357 57fa1fb3 ths
2358 fd4a04eb ths
/* binary operations */
2359 fd4a04eb ths
#define FLOAT_BINOP(name) \
2360 fd4a04eb ths
FLOAT_OP(name, d)         \
2361 fd4a04eb ths
{                         \
2362 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);            \
2363 ead9360e ths
    FDT2 = float64_ ## name (FDT0, FDT1, &env->fpu->fp_status);    \
2364 ead9360e ths
    update_fcr31();                                                \
2365 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID)                \
2366 5747c073 pbrook
        DT2 = FLOAT_QNAN64;                                        \
2367 fd4a04eb ths
}                         \
2368 fd4a04eb ths
FLOAT_OP(name, s)         \
2369 fd4a04eb ths
{                         \
2370 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);            \
2371 ead9360e ths
    FST2 = float32_ ## name (FST0, FST1, &env->fpu->fp_status);    \
2372 ead9360e ths
    update_fcr31();                                                \
2373 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID)                \
2374 5747c073 pbrook
        WT2 = FLOAT_QNAN32;                                        \
2375 fd4a04eb ths
}                         \
2376 fd4a04eb ths
FLOAT_OP(name, ps)        \
2377 fd4a04eb ths
{                         \
2378 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);            \
2379 ead9360e ths
    FST2 = float32_ ## name (FST0, FST1, &env->fpu->fp_status);    \
2380 ead9360e ths
    FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fpu->fp_status); \
2381 fd4a04eb ths
    update_fcr31();       \
2382 ead9360e ths
    if (GET_FP_CAUSE(env->fpu->fcr31) & FP_INVALID) {              \
2383 5747c073 pbrook
        WT2 = FLOAT_QNAN32;                                        \
2384 5747c073 pbrook
        WTH2 = FLOAT_QNAN32;                                       \
2385 3a5b360d ths
    }                     \
2386 fd4a04eb ths
}
2387 fd4a04eb ths
FLOAT_BINOP(add)
2388 fd4a04eb ths
FLOAT_BINOP(sub)
2389 fd4a04eb ths
FLOAT_BINOP(mul)
2390 fd4a04eb ths
FLOAT_BINOP(div)
2391 fd4a04eb ths
#undef FLOAT_BINOP
2392 fd4a04eb ths
2393 a16336e4 ths
/* ternary operations */
2394 a16336e4 ths
#define FLOAT_TERNOP(name1, name2) \
2395 a16336e4 ths
FLOAT_OP(name1 ## name2, d)        \
2396 a16336e4 ths
{                                  \
2397 a16336e4 ths
    FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status);    \
2398 a16336e4 ths
    FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status);    \
2399 a16336e4 ths
}                                  \
2400 a16336e4 ths
FLOAT_OP(name1 ## name2, s)        \
2401 a16336e4 ths
{                                  \
2402 a16336e4 ths
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2403 a16336e4 ths
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2404 a16336e4 ths
}                                  \
2405 a16336e4 ths
FLOAT_OP(name1 ## name2, ps)       \
2406 a16336e4 ths
{                                  \
2407 a16336e4 ths
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2408 a16336e4 ths
    FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2409 a16336e4 ths
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2410 a16336e4 ths
    FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2411 a16336e4 ths
}
2412 a16336e4 ths
FLOAT_TERNOP(mul, add)
2413 a16336e4 ths
FLOAT_TERNOP(mul, sub)
2414 a16336e4 ths
#undef FLOAT_TERNOP
2415 a16336e4 ths
2416 a16336e4 ths
/* negated ternary operations */
2417 a16336e4 ths
#define FLOAT_NTERNOP(name1, name2) \
2418 a16336e4 ths
FLOAT_OP(n ## name1 ## name2, d)    \
2419 a16336e4 ths
{                                   \
2420 a16336e4 ths
    FDT0 = float64_ ## name1 (FDT0, FDT1, &env->fpu->fp_status);    \
2421 a16336e4 ths
    FDT2 = float64_ ## name2 (FDT0, FDT2, &env->fpu->fp_status);    \
2422 a16336e4 ths
    FDT2 = float64_chs(FDT2);       \
2423 a16336e4 ths
}                                   \
2424 a16336e4 ths
FLOAT_OP(n ## name1 ## name2, s)    \
2425 a16336e4 ths
{                                   \
2426 a16336e4 ths
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2427 a16336e4 ths
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2428 a16336e4 ths
    FST2 = float32_chs(FST2);       \
2429 a16336e4 ths
}                                   \
2430 a16336e4 ths
FLOAT_OP(n ## name1 ## name2, ps)   \
2431 a16336e4 ths
{                                   \
2432 a16336e4 ths
    FST0 = float32_ ## name1 (FST0, FST1, &env->fpu->fp_status);    \
2433 a16336e4 ths
    FSTH0 = float32_ ## name1 (FSTH0, FSTH1, &env->fpu->fp_status); \
2434 a16336e4 ths
    FST2 = float32_ ## name2 (FST0, FST2, &env->fpu->fp_status);    \
2435 a16336e4 ths
    FSTH2 = float32_ ## name2 (FSTH0, FSTH2, &env->fpu->fp_status); \
2436 a16336e4 ths
    FST2 = float32_chs(FST2);       \
2437 a16336e4 ths
    FSTH2 = float32_chs(FSTH2);     \
2438 a16336e4 ths
}
2439 a16336e4 ths
FLOAT_NTERNOP(mul, add)
2440 a16336e4 ths
FLOAT_NTERNOP(mul, sub)
2441 a16336e4 ths
#undef FLOAT_NTERNOP
2442 a16336e4 ths
2443 8dfdb87c ths
/* MIPS specific binary operations */
2444 8dfdb87c ths
FLOAT_OP(recip2, d)
2445 8dfdb87c ths
{
2446 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2447 ead9360e ths
    FDT2 = float64_mul(FDT0, FDT2, &env->fpu->fp_status);
2448 5747c073 pbrook
    FDT2 = float64_chs(float64_sub(FDT2, FLOAT_ONE64, &env->fpu->fp_status));
2449 8dfdb87c ths
    update_fcr31();
2450 8dfdb87c ths
}
2451 8dfdb87c ths
FLOAT_OP(recip2, s)
2452 8dfdb87c ths
{
2453 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2454 ead9360e ths
    FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status);
2455 5747c073 pbrook
    FST2 = float32_chs(float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status));
2456 8dfdb87c ths
    update_fcr31();
2457 8dfdb87c ths
}
2458 8dfdb87c ths
FLOAT_OP(recip2, ps)
2459 8dfdb87c ths
{
2460 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2461 ead9360e ths
    FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status);
2462 ead9360e ths
    FSTH2 = float32_mul(FSTH0, FSTH2, &env->fpu->fp_status);
2463 5747c073 pbrook
    FST2 = float32_chs(float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status));
2464 5747c073 pbrook
    FSTH2 = float32_chs(float32_sub(FSTH2, FLOAT_ONE32, &env->fpu->fp_status));
2465 8dfdb87c ths
    update_fcr31();
2466 8dfdb87c ths
}
2467 8dfdb87c ths
2468 8dfdb87c ths
FLOAT_OP(rsqrt2, d)
2469 8dfdb87c ths
{
2470 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2471 ead9360e ths
    FDT2 = float64_mul(FDT0, FDT2, &env->fpu->fp_status);
2472 ead9360e ths
    FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fpu->fp_status);
2473 5747c073 pbrook
    FDT2 = float64_chs(float64_div(FDT2, FLOAT_TWO64, &env->fpu->fp_status));
2474 8dfdb87c ths
    update_fcr31();
2475 8dfdb87c ths
}
2476 8dfdb87c ths
FLOAT_OP(rsqrt2, s)
2477 8dfdb87c ths
{
2478 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2479 ead9360e ths
    FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status);
2480 ead9360e ths
    FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status);
2481 5747c073 pbrook
    FST2 = float32_chs(float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status));
2482 8dfdb87c ths
    update_fcr31();
2483 8dfdb87c ths
}
2484 8dfdb87c ths
FLOAT_OP(rsqrt2, ps)
2485 8dfdb87c ths
{
2486 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2487 ead9360e ths
    FST2 = float32_mul(FST0, FST2, &env->fpu->fp_status);
2488 ead9360e ths
    FSTH2 = float32_mul(FSTH0, FSTH2, &env->fpu->fp_status);
2489 ead9360e ths
    FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fpu->fp_status);
2490 ead9360e ths
    FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fpu->fp_status);
2491 5747c073 pbrook
    FST2 = float32_chs(float32_div(FST2, FLOAT_TWO32, &env->fpu->fp_status));
2492 5747c073 pbrook
    FSTH2 = float32_chs(float32_div(FSTH2, FLOAT_TWO32, &env->fpu->fp_status));
2493 8dfdb87c ths
    update_fcr31();
2494 57fa1fb3 ths
}
2495 57fa1fb3 ths
2496 fd4a04eb ths
FLOAT_OP(addr, ps)
2497 fd4a04eb ths
{
2498 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2499 ead9360e ths
    FST2 = float32_add (FST0, FSTH0, &env->fpu->fp_status);
2500 ead9360e ths
    FSTH2 = float32_add (FST1, FSTH1, &env->fpu->fp_status);
2501 fd4a04eb ths
    update_fcr31();
2502 fd4a04eb ths
}
2503 fd4a04eb ths
2504 57fa1fb3 ths
FLOAT_OP(mulr, ps)
2505 57fa1fb3 ths
{
2506 ead9360e ths
    set_float_exception_flags(0, &env->fpu->fp_status);
2507 ead9360e ths
    FST2 = float32_mul (FST0, FSTH0, &env->fpu->fp_status);
2508 ead9360e ths
    FSTH2 = float32_mul (FST1, FSTH1, &env->fpu->fp_status);
2509 57fa1fb3 ths
    update_fcr31();
2510 57fa1fb3 ths
}
2511 57fa1fb3 ths
2512 8dfdb87c ths
/* compare operations */
2513 fd4a04eb ths
#define FOP_COND_D(op, cond)                   \
2514 fd4a04eb ths
void do_cmp_d_ ## op (long cc)                 \
2515 fd4a04eb ths
{                                              \
2516 fd4a04eb ths
    int c = cond;                              \
2517 fd4a04eb ths
    update_fcr31();                            \
2518 fd4a04eb ths
    if (c)                                     \
2519 ead9360e ths
        SET_FP_COND(cc, env->fpu);             \
2520 fd4a04eb ths
    else                                       \
2521 ead9360e ths
        CLEAR_FP_COND(cc, env->fpu);           \
2522 fd4a04eb ths
}                                              \
2523 fd4a04eb ths
void do_cmpabs_d_ ## op (long cc)              \
2524 fd4a04eb ths
{                                              \
2525 fd4a04eb ths
    int c;                                     \
2526 6b5435d7 ths
    FDT0 = float64_abs(FDT0);                  \
2527 6b5435d7 ths
    FDT1 = float64_abs(FDT1);                  \
2528 fd4a04eb ths
    c = cond;                                  \
2529 fd4a04eb ths
    update_fcr31();                            \
2530 fd4a04eb ths
    if (c)                                     \
2531 ead9360e ths
        SET_FP_COND(cc, env->fpu);             \
2532 fd4a04eb ths
    else                                       \
2533 ead9360e ths
        CLEAR_FP_COND(cc, env->fpu);           \
2534 fd4a04eb ths
}
2535 fd4a04eb ths
2536 fd4a04eb ths
int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
2537 fd4a04eb ths
{
2538 fd4a04eb ths
    if (float64_is_signaling_nan(a) ||
2539 fd4a04eb ths
        float64_is_signaling_nan(b) ||
2540 fd4a04eb ths
        (sig && (float64_is_nan(a) || float64_is_nan(b)))) {
2541 fd4a04eb ths
        float_raise(float_flag_invalid, status);
2542 fd4a04eb ths
        return 1;
2543 fd4a04eb ths
    } else if (float64_is_nan(a) || float64_is_nan(b)) {
2544 fd4a04eb ths
        return 1;
2545 fd4a04eb ths
    } else {
2546 fd4a04eb ths
        return 0;
2547 fd4a04eb ths
    }
2548 fd4a04eb ths
}
2549 fd4a04eb ths
2550 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2551 fd4a04eb ths
 * but float*_is_unordered() is still called. */
2552 ead9360e ths
FOP_COND_D(f,   (float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status), 0))
2553 ead9360e ths
FOP_COND_D(un,  float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status))
2554 ead9360e ths
FOP_COND_D(eq,  !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_eq(FDT0, FDT1, &env->fpu->fp_status))
2555 ead9360e ths
FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status)  || float64_eq(FDT0, FDT1, &env->fpu->fp_status))
2556 ead9360e ths
FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_lt(FDT0, FDT1, &env->fpu->fp_status))
2557 ead9360e ths
FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status)  || float64_lt(FDT0, FDT1, &env->fpu->fp_status))
2558 ead9360e ths
FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status) && float64_le(FDT0, FDT1, &env->fpu->fp_status))
2559 ead9360e ths
FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fpu->fp_status)  || float64_le(FDT0, FDT1, &env->fpu->fp_status))
2560 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2561 fd4a04eb ths
 * but float*_is_unordered() is still called. */
2562 ead9360e ths
FOP_COND_D(sf,  (float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status), 0))
2563 ead9360e ths
FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status))
2564 ead9360e ths
FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_eq(FDT0, FDT1, &env->fpu->fp_status))
2565 ead9360e ths
FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status)  || float64_eq(FDT0, FDT1, &env->fpu->fp_status))
2566 ead9360e ths
FOP_COND_D(lt,  !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_lt(FDT0, FDT1, &env->fpu->fp_status))
2567 ead9360e ths
FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status)  || float64_lt(FDT0, FDT1, &env->fpu->fp_status))
2568 ead9360e ths
FOP_COND_D(le,  !float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status) && float64_le(FDT0, FDT1, &env->fpu->fp_status))
2569 ead9360e ths
FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fpu->fp_status)  || float64_le(FDT0, FDT1, &env->fpu->fp_status))
2570 fd4a04eb ths
2571 fd4a04eb ths
#define FOP_COND_S(op, cond)                   \
2572 fd4a04eb ths
void do_cmp_s_ ## op (long cc)                 \
2573 fd4a04eb ths
{                                              \
2574 fd4a04eb ths
    int c = cond;                              \
2575 fd4a04eb ths
    update_fcr31();                            \
2576 fd4a04eb ths
    if (c)                                     \
2577 ead9360e ths
        SET_FP_COND(cc, env->fpu);             \
2578 fd4a04eb ths
    else                                       \
2579 ead9360e ths
        CLEAR_FP_COND(cc, env->fpu);           \
2580 fd4a04eb ths
}                                              \
2581 fd4a04eb ths
void do_cmpabs_s_ ## op (long cc)              \
2582 fd4a04eb ths
{                                              \
2583 fd4a04eb ths
    int c;                                     \
2584 5747c073 pbrook
    FST0 = float32_abs(FST0);                  \
2585 5747c073 pbrook
    FST1 = float32_abs(FST1);                  \
2586 fd4a04eb ths
    c = cond;                                  \
2587 fd4a04eb ths
    update_fcr31();                            \
2588 fd4a04eb ths
    if (c)                                     \
2589 ead9360e ths
        SET_FP_COND(cc, env->fpu);             \
2590 fd4a04eb ths
    else                                       \
2591 ead9360e ths
        CLEAR_FP_COND(cc, env->fpu);           \
2592 fd4a04eb ths
}
2593 fd4a04eb ths
2594 fd4a04eb ths
flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
2595 fd4a04eb ths
{
2596 fd4a04eb ths
    if (float32_is_signaling_nan(a) ||
2597 fd4a04eb ths
        float32_is_signaling_nan(b) ||
2598 fd4a04eb ths
        (sig && (float32_is_nan(a) || float32_is_nan(b)))) {
2599 fd4a04eb ths
        float_raise(float_flag_invalid, status);
2600 fd4a04eb ths
        return 1;
2601 fd4a04eb ths
    } else if (float32_is_nan(a) || float32_is_nan(b)) {
2602 fd4a04eb ths
        return 1;
2603 fd4a04eb ths
    } else {
2604 fd4a04eb ths
        return 0;
2605 fd4a04eb ths
    }
2606 fd4a04eb ths
}
2607 fd4a04eb ths
2608 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2609 fd4a04eb ths
 * but float*_is_unordered() is still called. */
2610 ead9360e ths
FOP_COND_S(f,   (float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status), 0))
2611 ead9360e ths
FOP_COND_S(un,  float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status))
2612 ead9360e ths
FOP_COND_S(eq,  !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status))
2613 ead9360e ths
FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)  || float32_eq(FST0, FST1, &env->fpu->fp_status))
2614 ead9360e ths
FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status))
2615 ead9360e ths
FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)  || float32_lt(FST0, FST1, &env->fpu->fp_status))
2616 ead9360e ths
FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status))
2617 ead9360e ths
FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)  || float32_le(FST0, FST1, &env->fpu->fp_status))
2618 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2619 fd4a04eb ths
 * but float*_is_unordered() is still called. */
2620 ead9360e ths
FOP_COND_S(sf,  (float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status), 0))
2621 ead9360e ths
FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status))
2622 ead9360e ths
FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_eq(FST0, FST1, &env->fpu->fp_status))
2623 ead9360e ths
FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)  || float32_eq(FST0, FST1, &env->fpu->fp_status))
2624 ead9360e ths
FOP_COND_S(lt,  !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_lt(FST0, FST1, &env->fpu->fp_status))
2625 ead9360e ths
FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)  || float32_lt(FST0, FST1, &env->fpu->fp_status))
2626 ead9360e ths
FOP_COND_S(le,  !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status) && float32_le(FST0, FST1, &env->fpu->fp_status))
2627 ead9360e ths
FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)  || float32_le(FST0, FST1, &env->fpu->fp_status))
2628 fd4a04eb ths
2629 fd4a04eb ths
#define FOP_COND_PS(op, condl, condh)          \
2630 fd4a04eb ths
void do_cmp_ps_ ## op (long cc)                \
2631 fd4a04eb ths
{                                              \
2632 fd4a04eb ths
    int cl = condl;                            \
2633 fd4a04eb ths
    int ch = condh;                            \
2634 fd4a04eb ths
    update_fcr31();                            \
2635 fd4a04eb ths
    if (cl)                                    \
2636 ead9360e ths
        SET_FP_COND(cc, env->fpu);             \
2637 fd4a04eb ths
    else                                       \
2638 ead9360e ths
        CLEAR_FP_COND(cc, env->fpu);           \
2639 fd4a04eb ths
    if (ch)                                    \
2640 ead9360e ths
        SET_FP_COND(cc + 1, env->fpu);         \
2641 fd4a04eb ths
    else                                       \
2642 ead9360e ths
        CLEAR_FP_COND(cc + 1, env->fpu);       \
2643 fd4a04eb ths
}                                              \
2644 fd4a04eb ths
void do_cmpabs_ps_ ## op (long cc)             \
2645 fd4a04eb ths
{                                              \
2646 fd4a04eb ths
    int cl, ch;                                \
2647 5747c073 pbrook
    FST0 = float32_abs(FST0);                  \
2648 5747c073 pbrook
    FSTH0 = float32_abs(FSTH0);                \
2649 5747c073 pbrook
    FST1 = float32_abs(FST1);                  \
2650 5747c073 pbrook
    FSTH1 = float32_abs(FSTH1);                \
2651 fd4a04eb ths
    cl = condl;                                \
2652 fd4a04eb ths
    ch = condh;                                \
2653 fd4a04eb ths
    update_fcr31();                            \
2654 fd4a04eb ths
    if (cl)                                    \
2655 ead9360e ths
        SET_FP_COND(cc, env->fpu);             \
2656 fd4a04eb ths
    else                                       \
2657 ead9360e ths
        CLEAR_FP_COND(cc, env->fpu);           \
2658 fd4a04eb ths
    if (ch)                                    \
2659 ead9360e ths
        SET_FP_COND(cc + 1, env->fpu);         \
2660 fd4a04eb ths
    else                                       \
2661 ead9360e ths
        CLEAR_FP_COND(cc + 1, env->fpu);       \
2662 fd4a04eb ths
}
2663 fd4a04eb ths
2664 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2665 fd4a04eb ths
 * but float*_is_unordered() is still called. */
2666 ead9360e ths
FOP_COND_PS(f,   (float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status), 0),
2667 ead9360e ths
                 (float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status), 0))
2668 ead9360e ths
FOP_COND_PS(un,  float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status),
2669 ead9360e ths
                 float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status))
2670 ead9360e ths
FOP_COND_PS(eq,  !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)   && float32_eq(FST0, FST1, &env->fpu->fp_status),
2671 ead9360e ths
                 !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_eq(FSTH0, FSTH1, &env->fpu->fp_status))
2672 ead9360e ths
FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)    || float32_eq(FST0, FST1, &env->fpu->fp_status),
2673 ead9360e ths
                 float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status)  || float32_eq(FSTH0, FSTH1, &env->fpu->fp_status))
2674 ead9360e ths
FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)   && float32_lt(FST0, FST1, &env->fpu->fp_status),
2675 ead9360e ths
                 !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_lt(FSTH0, FSTH1, &env->fpu->fp_status))
2676 ead9360e ths
FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)    || float32_lt(FST0, FST1, &env->fpu->fp_status),
2677 ead9360e ths
                 float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status)  || float32_lt(FSTH0, FSTH1, &env->fpu->fp_status))
2678 ead9360e ths
FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)   && float32_le(FST0, FST1, &env->fpu->fp_status),
2679 ead9360e ths
                 !float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status) && float32_le(FSTH0, FSTH1, &env->fpu->fp_status))
2680 ead9360e ths
FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fpu->fp_status)    || float32_le(FST0, FST1, &env->fpu->fp_status),
2681 ead9360e ths
                 float32_is_unordered(0, FSTH1, FSTH0, &env->fpu->fp_status)  || float32_le(FSTH0, FSTH1, &env->fpu->fp_status))
2682 fd4a04eb ths
/* NOTE: the comma operator will make "cond" to eval to false,
2683 fd4a04eb ths
 * but float*_is_unordered() is still called. */
2684 ead9360e ths
FOP_COND_PS(sf,  (float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status), 0),
2685 ead9360e ths
                 (float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status), 0))
2686 ead9360e ths
FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status),
2687 ead9360e ths
                 float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status))
2688 ead9360e ths
FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)   && float32_eq(FST0, FST1, &env->fpu->fp_status),
2689 ead9360e ths
                 !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_eq(FSTH0, FSTH1, &env->fpu->fp_status))
2690 ead9360e ths
FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)    || float32_eq(FST0, FST1, &env->fpu->fp_status),
2691 ead9360e ths
                 float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status)  || float32_eq(FSTH0, FSTH1, &env->fpu->fp_status))
2692 ead9360e ths
FOP_COND_PS(lt,  !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)   && float32_lt(FST0, FST1, &env->fpu->fp_status),
2693 ead9360e ths
                 !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_lt(FSTH0, FSTH1, &env->fpu->fp_status))
2694 ead9360e ths
FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)    || float32_lt(FST0, FST1, &env->fpu->fp_status),
2695 ead9360e ths
                 float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status)  || float32_lt(FSTH0, FSTH1, &env->fpu->fp_status))
2696 ead9360e ths
FOP_COND_PS(le,  !float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)   && float32_le(FST0, FST1, &env->fpu->fp_status),
2697 ead9360e ths
                 !float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status) && float32_le(FSTH0, FSTH1, &env->fpu->fp_status))
2698 ead9360e ths
FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fpu->fp_status)    || float32_le(FST0, FST1, &env->fpu->fp_status),
2699 ead9360e ths
                 float32_is_unordered(1, FSTH1, FSTH0, &env->fpu->fp_status)  || float32_le(FSTH0, FSTH1, &env->fpu->fp_status))