Statistics
| Branch: | Revision:

root / target-mips / op_helper.c @ b6a8c26b

History | View | Annotate | Download (74.5 kB)

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