]> Git Repo - qemu.git/blame - target-mips/op_helper.c
Fix writes to pages containing watchpoints for the RAM not at 0x0 cases.
[qemu.git] / target-mips / op_helper.c
CommitLineData
6af0bf9c
FB
1/*
2 * MIPS emulation helpers for qemu.
3 *
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
2d0e944d 20#include <stdlib.h>
6af0bf9c
FB
21#include "exec.h"
22
4ad40f36
FB
23#define GETPC() (__builtin_return_address(0))
24
6af0bf9c
FB
25/*****************************************************************************/
26/* Exceptions processing helpers */
6af0bf9c 27
6af0bf9c
FB
28void do_raise_exception_err (uint32_t exception, int error_code)
29{
30#if 1
31 if (logfile && exception < 0x100)
32 fprintf(logfile, "%s: %d %d\n", __func__, exception, error_code);
33#endif
34 env->exception_index = exception;
35 env->error_code = error_code;
36 T0 = 0;
37 cpu_loop_exit();
38}
39
6af0bf9c
FB
40void do_raise_exception (uint32_t exception)
41{
42 do_raise_exception_err(exception, 0);
43}
44
4ad40f36
FB
45void do_restore_state (void *pc_ptr)
46{
47 TranslationBlock *tb;
48 unsigned long pc = (unsigned long) pc_ptr;
49
50 tb = tb_find_pc (pc);
51 cpu_restore_state (tb, env, pc, NULL);
52}
53
e397ee33 54void do_raise_exception_direct_err (uint32_t exception, int error_code)
4ad40f36
FB
55{
56 do_restore_state (GETPC ());
e397ee33
TS
57 do_raise_exception_err (exception, error_code);
58}
59
60void do_raise_exception_direct (uint32_t exception)
61{
62 do_raise_exception_direct_err (exception, 0);
4ad40f36
FB
63}
64
6af0bf9c
FB
65#define MEMSUFFIX _raw
66#include "op_helper_mem.c"
67#undef MEMSUFFIX
68#if !defined(CONFIG_USER_ONLY)
69#define MEMSUFFIX _user
70#include "op_helper_mem.c"
71#undef MEMSUFFIX
72#define MEMSUFFIX _kernel
73#include "op_helper_mem.c"
74#undef MEMSUFFIX
75#endif
76
60aa19ab 77#ifdef TARGET_MIPS64
c570fd16
TS
78#if TARGET_LONG_BITS > HOST_LONG_BITS
79/* Those might call libgcc functions. */
80void do_dsll (void)
81{
82 T0 = T0 << T1;
83}
84
85void do_dsll32 (void)
86{
87 T0 = T0 << (T1 + 32);
88}
89
90void do_dsra (void)
91{
92 T0 = (int64_t)T0 >> T1;
93}
94
95void do_dsra32 (void)
96{
97 T0 = (int64_t)T0 >> (T1 + 32);
98}
99
100void do_dsrl (void)
101{
102 T0 = T0 >> T1;
103}
104
105void do_dsrl32 (void)
106{
107 T0 = T0 >> (T1 + 32);
108}
109
110void do_drotr (void)
111{
112 target_ulong tmp;
113
114 if (T1) {
115 tmp = T0 << (0x40 - T1);
116 T0 = (T0 >> T1) | tmp;
5a63bcb2 117 }
c570fd16
TS
118}
119
120void do_drotr32 (void)
121{
122 target_ulong tmp;
123
124 if (T1) {
125 tmp = T0 << (0x40 - (32 + T1));
126 T0 = (T0 >> (32 + T1)) | tmp;
5a63bcb2 127 }
c570fd16
TS
128}
129
130void do_dsllv (void)
131{
132 T0 = T1 << (T0 & 0x3F);
133}
134
135void do_dsrav (void)
136{
137 T0 = (int64_t)T1 >> (T0 & 0x3F);
138}
139
140void do_dsrlv (void)
141{
142 T0 = T1 >> (T0 & 0x3F);
143}
144
145void do_drotrv (void)
146{
147 target_ulong tmp;
148
149 T0 &= 0x3F;
150 if (T0) {
151 tmp = T1 << (0x40 - T0);
152 T0 = (T1 >> T0) | tmp;
153 } else
154 T0 = T1;
155}
156#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
60aa19ab 157#endif /* TARGET_MIPS64 */
c570fd16 158
6af0bf9c 159/* 64 bits arithmetic for 32 bits hosts */
c570fd16 160#if TARGET_LONG_BITS > HOST_LONG_BITS
6af0bf9c
FB
161static inline uint64_t get_HILO (void)
162{
7495fd0f 163 return (env->HI << 32) | (uint32_t)env->LO;
6af0bf9c
FB
164}
165
166static inline void set_HILO (uint64_t HILO)
167{
7495fd0f 168 env->LO = (int32_t)HILO;
5dc4b744 169 env->HI = (int32_t)(HILO >> 32);
6af0bf9c
FB
170}
171
172void do_mult (void)
173{
4ad40f36 174 set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
6af0bf9c
FB
175}
176
177void do_multu (void)
178{
c570fd16 179 set_HILO((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
6af0bf9c
FB
180}
181
182void do_madd (void)
183{
184 int64_t tmp;
185
4ad40f36 186 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
6af0bf9c
FB
187 set_HILO((int64_t)get_HILO() + tmp);
188}
189
190void do_maddu (void)
191{
192 uint64_t tmp;
193
c570fd16 194 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
6af0bf9c
FB
195 set_HILO(get_HILO() + tmp);
196}
197
198void do_msub (void)
199{
200 int64_t tmp;
201
4ad40f36 202 tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
6af0bf9c
FB
203 set_HILO((int64_t)get_HILO() - tmp);
204}
205
206void do_msubu (void)
207{
208 uint64_t tmp;
209
c570fd16 210 tmp = ((uint64_t)(uint32_t)T0 * (uint64_t)(uint32_t)T1);
6af0bf9c
FB
211 set_HILO(get_HILO() - tmp);
212}
213#endif
214
80c27194
TS
215#if HOST_LONG_BITS < 64
216void do_div (void)
217{
218 /* 64bit datatypes because we may see overflow/underflow. */
219 if (T1 != 0) {
220 env->LO = (int32_t)((int64_t)(int32_t)T0 / (int32_t)T1);
221 env->HI = (int32_t)((int64_t)(int32_t)T0 % (int32_t)T1);
222 }
223}
224#endif
225
60aa19ab 226#ifdef TARGET_MIPS64
c570fd16
TS
227void do_ddiv (void)
228{
229 if (T1 != 0) {
2d0e944d
TS
230 lldiv_t res = lldiv((int64_t)T0, (int64_t)T1);
231 env->LO = res.quot;
232 env->HI = res.rem;
c570fd16
TS
233 }
234}
235
12a4b2aa 236#if TARGET_LONG_BITS > HOST_LONG_BITS
c570fd16
TS
237void do_ddivu (void)
238{
239 if (T1 != 0) {
12a4b2aa
TS
240 env->LO = T0 / T1;
241 env->HI = T0 % T1;
c570fd16
TS
242 }
243}
244#endif
12a4b2aa 245#endif /* TARGET_MIPS64 */
c570fd16 246
048f6b4d 247#if defined(CONFIG_USER_ONLY)
873eb012 248void do_mfc0_random (void)
048f6b4d 249{
873eb012 250 cpu_abort(env, "mfc0 random\n");
048f6b4d 251}
873eb012
TS
252
253void do_mfc0_count (void)
254{
255 cpu_abort(env, "mfc0 count\n");
256}
257
8c0fdd85 258void cpu_mips_store_count(CPUState *env, uint32_t value)
048f6b4d 259{
8c0fdd85
TS
260 cpu_abort(env, "mtc0 count\n");
261}
262
263void cpu_mips_store_compare(CPUState *env, uint32_t value)
264{
265 cpu_abort(env, "mtc0 compare\n");
266}
267
4de9b249
TS
268void cpu_mips_update_irq(CPUState *env)
269{
270 cpu_abort(env, "mtc0 status / mtc0 cause\n");
271}
272
8c0fdd85
TS
273void do_mtc0_status_debug(uint32_t old, uint32_t val)
274{
7a387fff 275 cpu_abort(env, "mtc0 status debug\n");
8c0fdd85
TS
276}
277
7a387fff 278void do_mtc0_status_irqraise_debug (void)
8c0fdd85 279{
7a387fff 280 cpu_abort(env, "mtc0 status irqraise debug\n");
048f6b4d
FB
281}
282
8c0fdd85
TS
283void cpu_mips_tlb_flush (CPUState *env, int flush_global)
284{
285 cpu_abort(env, "mips_tlb_flush\n");
286}
287
048f6b4d
FB
288#else
289
6af0bf9c 290/* CP0 helpers */
873eb012 291void do_mfc0_random (void)
6af0bf9c 292{
5dc4b744 293 T0 = (int32_t)cpu_mips_get_random(env);
873eb012 294}
6af0bf9c 295
873eb012
TS
296void do_mfc0_count (void)
297{
5dc4b744 298 T0 = (int32_t)cpu_mips_get_count(env);
6af0bf9c
FB
299}
300
8c0fdd85 301void do_mtc0_status_debug(uint32_t old, uint32_t val)
6af0bf9c 302{
f41c52f1
TS
303 fprintf(logfile, "Status %08x (%08x) => %08x (%08x) Cause %08x",
304 old, old & env->CP0_Cause & CP0Ca_IP_mask,
305 val, val & env->CP0_Cause & CP0Ca_IP_mask,
306 env->CP0_Cause);
307 (env->hflags & MIPS_HFLAG_UM) ? fputs(", UM\n", logfile)
308 : fputs("\n", logfile);
8c0fdd85
TS
309}
310
311void do_mtc0_status_irqraise_debug(void)
312{
313 fprintf(logfile, "Raise pending IRQs\n");
6af0bf9c
FB
314}
315
6ea83fed
FB
316void fpu_handle_exception(void)
317{
318#ifdef CONFIG_SOFTFLOAT
319 int flags = get_float_exception_flags(&env->fp_status);
320 unsigned int cpuflags = 0, enable, cause = 0;
321
322 enable = GET_FP_ENABLE(env->fcr31);
323
324 /* determine current flags */
325 if (flags & float_flag_invalid) {
326 cpuflags |= FP_INVALID;
327 cause |= FP_INVALID & enable;
328 }
329 if (flags & float_flag_divbyzero) {
330 cpuflags |= FP_DIV0;
331 cause |= FP_DIV0 & enable;
332 }
333 if (flags & float_flag_overflow) {
334 cpuflags |= FP_OVERFLOW;
335 cause |= FP_OVERFLOW & enable;
336 }
337 if (flags & float_flag_underflow) {
338 cpuflags |= FP_UNDERFLOW;
339 cause |= FP_UNDERFLOW & enable;
340 }
341 if (flags & float_flag_inexact) {
342 cpuflags |= FP_INEXACT;
343 cause |= FP_INEXACT & enable;
344 }
345 SET_FP_FLAGS(env->fcr31, cpuflags);
346 SET_FP_CAUSE(env->fcr31, cause);
347#else
348 SET_FP_FLAGS(env->fcr31, 0);
349 SET_FP_CAUSE(env->fcr31, 0);
350#endif
351}
6ea83fed 352
6af0bf9c 353/* TLB management */
814b9a47
TS
354void cpu_mips_tlb_flush (CPUState *env, int flush_global)
355{
356 /* Flush qemu's TLB and discard all shadowed entries. */
357 tlb_flush (env, flush_global);
fcb4a419 358 env->tlb_in_use = env->nb_tlb;
814b9a47
TS
359}
360
29929e34 361static void r4k_mips_tlb_flush_extra (CPUState *env, int first)
814b9a47
TS
362{
363 /* Discard entries from env->tlb[first] onwards. */
364 while (env->tlb_in_use > first) {
29929e34 365 r4k_invalidate_tlb(env, --env->tlb_in_use, 0);
814b9a47
TS
366 }
367}
368
29929e34 369static void r4k_fill_tlb (int idx)
6af0bf9c 370{
29929e34 371 r4k_tlb_t *tlb;
6af0bf9c
FB
372
373 /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
29929e34 374 tlb = &env->mmu.r4k.tlb[idx];
f2e9ebef 375 tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
100ce988 376#ifdef TARGET_MIPS64
e034e2c3 377 tlb->VPN &= env->SEGMask;
100ce988 378#endif
98c1b82b 379 tlb->ASID = env->CP0_EntryHi & 0xFF;
3b1c8be4 380 tlb->PageMask = env->CP0_PageMask;
6af0bf9c 381 tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
98c1b82b
PB
382 tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
383 tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
384 tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
6af0bf9c 385 tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
98c1b82b
PB
386 tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
387 tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
388 tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
6af0bf9c
FB
389 tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
390}
391
29929e34 392void r4k_do_tlbwi (void)
6af0bf9c 393{
814b9a47
TS
394 /* Discard cached TLB entries. We could avoid doing this if the
395 tlbwi is just upgrading access permissions on the current entry;
396 that might be a further win. */
29929e34 397 r4k_mips_tlb_flush_extra (env, env->nb_tlb);
814b9a47 398
29929e34
TS
399 r4k_invalidate_tlb(env, env->CP0_Index % env->nb_tlb, 0);
400 r4k_fill_tlb(env->CP0_Index % env->nb_tlb);
6af0bf9c
FB
401}
402
29929e34 403void r4k_do_tlbwr (void)
6af0bf9c
FB
404{
405 int r = cpu_mips_get_random(env);
406
29929e34
TS
407 r4k_invalidate_tlb(env, r, 1);
408 r4k_fill_tlb(r);
6af0bf9c
FB
409}
410
29929e34 411void r4k_do_tlbp (void)
6af0bf9c 412{
29929e34 413 r4k_tlb_t *tlb;
f2e9ebef 414 target_ulong mask;
6af0bf9c 415 target_ulong tag;
f2e9ebef 416 target_ulong VPN;
6af0bf9c
FB
417 uint8_t ASID;
418 int i;
419
3d9fb9fe 420 ASID = env->CP0_EntryHi & 0xFF;
fcb4a419 421 for (i = 0; i < env->nb_tlb; i++) {
29929e34 422 tlb = &env->mmu.r4k.tlb[i];
f2e9ebef
TS
423 /* 1k pages are not supported. */
424 mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
425 tag = env->CP0_EntryHi & ~mask;
426 VPN = tlb->VPN & ~mask;
6af0bf9c 427 /* Check ASID, virtual page number & size */
f2e9ebef 428 if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
6af0bf9c 429 /* TLB match */
9c2149c8 430 env->CP0_Index = i;
6af0bf9c
FB
431 break;
432 }
433 }
fcb4a419 434 if (i == env->nb_tlb) {
814b9a47 435 /* No match. Discard any shadow entries, if any of them match. */
fcb4a419 436 for (i = env->nb_tlb; i < env->tlb_in_use; i++) {
29929e34 437 tlb = &env->mmu.r4k.tlb[i];
f2e9ebef
TS
438 /* 1k pages are not supported. */
439 mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
440 tag = env->CP0_EntryHi & ~mask;
441 VPN = tlb->VPN & ~mask;
814b9a47 442 /* Check ASID, virtual page number & size */
f2e9ebef 443 if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
29929e34 444 r4k_mips_tlb_flush_extra (env, i);
814b9a47
TS
445 break;
446 }
447 }
448
9c2149c8 449 env->CP0_Index |= 0x80000000;
6af0bf9c
FB
450 }
451}
452
29929e34 453void r4k_do_tlbr (void)
6af0bf9c 454{
29929e34 455 r4k_tlb_t *tlb;
09c56b84 456 uint8_t ASID;
6af0bf9c 457
09c56b84 458 ASID = env->CP0_EntryHi & 0xFF;
29929e34 459 tlb = &env->mmu.r4k.tlb[env->CP0_Index % env->nb_tlb];
4ad40f36
FB
460
461 /* If this will change the current ASID, flush qemu's TLB. */
814b9a47
TS
462 if (ASID != tlb->ASID)
463 cpu_mips_tlb_flush (env, 1);
464
29929e34 465 r4k_mips_tlb_flush_extra(env, env->nb_tlb);
4ad40f36 466
6af0bf9c 467 env->CP0_EntryHi = tlb->VPN | tlb->ASID;
3b1c8be4 468 env->CP0_PageMask = tlb->PageMask;
7495fd0f
TS
469 env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
470 (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
471 env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
472 (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
6af0bf9c 473}
6af0bf9c 474
048f6b4d
FB
475#endif /* !CONFIG_USER_ONLY */
476
c570fd16 477void dump_ldst (const unsigned char *func)
6af0bf9c
FB
478{
479 if (loglevel)
3594c774 480 fprintf(logfile, "%s => " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__, T0, T1);
6af0bf9c
FB
481}
482
483void dump_sc (void)
484{
485 if (loglevel) {
3594c774 486 fprintf(logfile, "%s " TARGET_FMT_lx " at " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", __func__,
6af0bf9c
FB
487 T1, T0, env->CP0_LLAddr);
488 }
489}
490
f41c52f1 491void debug_pre_eret (void)
6af0bf9c 492{
f41c52f1
TS
493 fprintf(logfile, "ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
494 env->PC, env->CP0_EPC);
495 if (env->CP0_Status & (1 << CP0St_ERL))
496 fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
497 if (env->hflags & MIPS_HFLAG_DM)
498 fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC);
499 fputs("\n", logfile);
500}
501
502void debug_post_eret (void)
503{
744e0915 504 fprintf(logfile, " => PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
f41c52f1
TS
505 env->PC, env->CP0_EPC);
506 if (env->CP0_Status & (1 << CP0St_ERL))
507 fprintf(logfile, " ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
508 if (env->hflags & MIPS_HFLAG_DM)
509 fprintf(logfile, " DEPC " TARGET_FMT_lx, env->CP0_DEPC);
510 if (env->hflags & MIPS_HFLAG_UM)
511 fputs(", UM\n", logfile);
512 else
24c7b0e3 513 fputs("\n", logfile);
6af0bf9c
FB
514}
515
6af0bf9c
FB
516void do_pmon (int function)
517{
518 function /= 2;
519 switch (function) {
520 case 2: /* TODO: char inbyte(int waitflag); */
521 if (env->gpr[4] == 0)
522 env->gpr[2] = -1;
523 /* Fall through */
524 case 11: /* TODO: char inbyte (void); */
525 env->gpr[2] = -1;
526 break;
527 case 3:
528 case 12:
c570fd16 529 printf("%c", (char)(env->gpr[4] & 0xFF));
6af0bf9c
FB
530 break;
531 case 17:
532 break;
533 case 158:
534 {
c570fd16 535 unsigned char *fmt = (void *)(unsigned long)env->gpr[4];
6af0bf9c
FB
536 printf("%s", fmt);
537 }
538 break;
539 }
540}
e37e863f
FB
541
542#if !defined(CONFIG_USER_ONLY)
543
4ad40f36
FB
544static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
545
e37e863f 546#define MMUSUFFIX _mmu
4ad40f36 547#define ALIGNED_ONLY
e37e863f
FB
548
549#define SHIFT 0
550#include "softmmu_template.h"
551
552#define SHIFT 1
553#include "softmmu_template.h"
554
555#define SHIFT 2
556#include "softmmu_template.h"
557
558#define SHIFT 3
559#include "softmmu_template.h"
560
4ad40f36
FB
561static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
562{
563 env->CP0_BadVAddr = addr;
564 do_restore_state (retaddr);
565 do_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
566}
567
e37e863f
FB
568void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr)
569{
570 TranslationBlock *tb;
571 CPUState *saved_env;
572 unsigned long pc;
573 int ret;
574
575 /* XXX: hack to restore env in all cases, even if not called from
576 generated code */
577 saved_env = env;
578 env = cpu_single_env;
579 ret = cpu_mips_handle_mmu_fault(env, addr, is_write, is_user, 1);
580 if (ret) {
581 if (retaddr) {
582 /* now we have a real cpu fault */
583 pc = (unsigned long)retaddr;
584 tb = tb_find_pc(pc);
585 if (tb) {
586 /* the PC is inside the translated code. It means that we have
587 a virtual CPU fault */
588 cpu_restore_state(tb, env, pc, NULL);
589 }
590 }
591 do_raise_exception_err(env->exception_index, env->error_code);
592 }
593 env = saved_env;
594}
595
596#endif
fd4a04eb
TS
597
598/* Complex FPU operations which may need stack space. */
599
600/* convert MIPS rounding mode in FCR31 to IEEE library */
601unsigned int ieee_rm[] = {
602 float_round_nearest_even,
603 float_round_to_zero,
604 float_round_up,
605 float_round_down
606};
607
608#define RESTORE_ROUNDING_MODE \
609 set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
610
611void do_ctc1 (void)
612{
613 switch(T1) {
614 case 25:
615 if (T0 & 0xffffff00)
616 return;
617 env->fcr31 = (env->fcr31 & 0x017fffff) | ((T0 & 0xfe) << 24) |
618 ((T0 & 0x1) << 23);
619 break;
620 case 26:
621 if (T0 & 0x007c0000)
622 return;
623 env->fcr31 = (env->fcr31 & 0xfffc0f83) | (T0 & 0x0003f07c);
624 break;
625 case 28:
626 if (T0 & 0x007c0000)
627 return;
628 env->fcr31 = (env->fcr31 & 0xfefff07c) | (T0 & 0x00000f83) |
629 ((T0 & 0x4) << 22);
630 break;
631 case 31:
632 if (T0 & 0x007c0000)
633 return;
634 env->fcr31 = T0;
635 break;
636 default:
637 return;
638 }
639 /* set rounding mode */
640 RESTORE_ROUNDING_MODE;
641 set_float_exception_flags(0, &env->fp_status);
642 if ((GET_FP_ENABLE(env->fcr31) | 0x20) & GET_FP_CAUSE(env->fcr31))
643 do_raise_exception(EXCP_FPE);
644}
645
646inline char ieee_ex_to_mips(char xcpt)
647{
648 return (xcpt & float_flag_inexact) >> 5 |
649 (xcpt & float_flag_underflow) >> 3 |
650 (xcpt & float_flag_overflow) >> 1 |
651 (xcpt & float_flag_divbyzero) << 1 |
652 (xcpt & float_flag_invalid) << 4;
653}
654
655inline char mips_ex_to_ieee(char xcpt)
656{
657 return (xcpt & FP_INEXACT) << 5 |
658 (xcpt & FP_UNDERFLOW) << 3 |
659 (xcpt & FP_OVERFLOW) << 1 |
660 (xcpt & FP_DIV0) >> 1 |
661 (xcpt & FP_INVALID) >> 4;
662}
663
664inline void update_fcr31(void)
665{
666 int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->fp_status));
667
668 SET_FP_CAUSE(env->fcr31, tmp);
669 if (GET_FP_ENABLE(env->fcr31) & tmp)
670 do_raise_exception(EXCP_FPE);
671 else
672 UPDATE_FP_FLAGS(env->fcr31, tmp);
673}
674
675#define FLOAT_OP(name, p) void do_float_##name##_##p(void)
676
677FLOAT_OP(cvtd, s)
678{
679 set_float_exception_flags(0, &env->fp_status);
680 FDT2 = float32_to_float64(FST0, &env->fp_status);
681 update_fcr31();
682}
683FLOAT_OP(cvtd, w)
684{
685 set_float_exception_flags(0, &env->fp_status);
686 FDT2 = int32_to_float64(WT0, &env->fp_status);
687 update_fcr31();
688}
689FLOAT_OP(cvtd, l)
690{
691 set_float_exception_flags(0, &env->fp_status);
692 FDT2 = int64_to_float64(DT0, &env->fp_status);
693 update_fcr31();
694}
695FLOAT_OP(cvtl, d)
696{
697 set_float_exception_flags(0, &env->fp_status);
698 DT2 = float64_to_int64(FDT0, &env->fp_status);
699 update_fcr31();
700 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
701 DT2 = 0x7fffffffffffffffULL;
702}
703FLOAT_OP(cvtl, s)
704{
705 set_float_exception_flags(0, &env->fp_status);
706 DT2 = float32_to_int64(FST0, &env->fp_status);
707 update_fcr31();
708 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
709 DT2 = 0x7fffffffffffffffULL;
710}
711
712FLOAT_OP(cvtps, pw)
713{
714 set_float_exception_flags(0, &env->fp_status);
715 FST2 = int32_to_float32(WT0, &env->fp_status);
716 FSTH2 = int32_to_float32(WTH0, &env->fp_status);
717 update_fcr31();
718}
719FLOAT_OP(cvtpw, ps)
720{
721 set_float_exception_flags(0, &env->fp_status);
722 WT2 = float32_to_int32(FST0, &env->fp_status);
723 WTH2 = float32_to_int32(FSTH0, &env->fp_status);
724 update_fcr31();
725 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
726 WT2 = 0x7fffffff;
727}
728FLOAT_OP(cvts, d)
729{
730 set_float_exception_flags(0, &env->fp_status);
731 FST2 = float64_to_float32(FDT0, &env->fp_status);
732 update_fcr31();
733}
734FLOAT_OP(cvts, w)
735{
736 set_float_exception_flags(0, &env->fp_status);
737 FST2 = int32_to_float32(WT0, &env->fp_status);
738 update_fcr31();
739}
740FLOAT_OP(cvts, l)
741{
742 set_float_exception_flags(0, &env->fp_status);
743 FST2 = int64_to_float32(DT0, &env->fp_status);
744 update_fcr31();
745}
746FLOAT_OP(cvts, pl)
747{
748 set_float_exception_flags(0, &env->fp_status);
749 WT2 = WT0;
750 update_fcr31();
751}
752FLOAT_OP(cvts, pu)
753{
754 set_float_exception_flags(0, &env->fp_status);
755 WT2 = WTH0;
756 update_fcr31();
757}
758FLOAT_OP(cvtw, s)
759{
760 set_float_exception_flags(0, &env->fp_status);
761 WT2 = float32_to_int32(FST0, &env->fp_status);
762 update_fcr31();
763 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
764 WT2 = 0x7fffffff;
765}
766FLOAT_OP(cvtw, d)
767{
768 set_float_exception_flags(0, &env->fp_status);
769 WT2 = float64_to_int32(FDT0, &env->fp_status);
770 update_fcr31();
771 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
772 WT2 = 0x7fffffff;
773}
774
775FLOAT_OP(roundl, d)
776{
777 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
778 DT2 = float64_round_to_int(FDT0, &env->fp_status);
779 RESTORE_ROUNDING_MODE;
780 update_fcr31();
781 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
782 DT2 = 0x7fffffffffffffffULL;
783}
784FLOAT_OP(roundl, s)
785{
786 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
787 DT2 = float32_round_to_int(FST0, &env->fp_status);
788 RESTORE_ROUNDING_MODE;
789 update_fcr31();
790 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
791 DT2 = 0x7fffffffffffffffULL;
792}
793FLOAT_OP(roundw, d)
794{
795 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
796 WT2 = float64_round_to_int(FDT0, &env->fp_status);
797 RESTORE_ROUNDING_MODE;
798 update_fcr31();
799 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
800 WT2 = 0x7fffffff;
801}
802FLOAT_OP(roundw, s)
803{
804 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
805 WT2 = float32_round_to_int(FST0, &env->fp_status);
806 RESTORE_ROUNDING_MODE;
807 update_fcr31();
808 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
809 WT2 = 0x7fffffff;
810}
811
812FLOAT_OP(truncl, d)
813{
814 DT2 = float64_to_int64_round_to_zero(FDT0, &env->fp_status);
815 update_fcr31();
816 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
817 DT2 = 0x7fffffffffffffffULL;
818}
819FLOAT_OP(truncl, s)
820{
821 DT2 = float32_to_int64_round_to_zero(FST0, &env->fp_status);
822 update_fcr31();
823 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
824 DT2 = 0x7fffffffffffffffULL;
825}
826FLOAT_OP(truncw, d)
827{
828 WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
829 update_fcr31();
830 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
831 WT2 = 0x7fffffff;
832}
833FLOAT_OP(truncw, s)
834{
835 WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status);
836 update_fcr31();
837 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
838 WT2 = 0x7fffffff;
839}
840
841FLOAT_OP(ceill, d)
842{
843 set_float_rounding_mode(float_round_up, &env->fp_status);
844 DT2 = float64_round_to_int(FDT0, &env->fp_status);
845 RESTORE_ROUNDING_MODE;
846 update_fcr31();
847 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
848 DT2 = 0x7fffffffffffffffULL;
849}
850FLOAT_OP(ceill, s)
851{
852 set_float_rounding_mode(float_round_up, &env->fp_status);
853 DT2 = float32_round_to_int(FST0, &env->fp_status);
854 RESTORE_ROUNDING_MODE;
855 update_fcr31();
856 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
857 DT2 = 0x7fffffffffffffffULL;
858}
859FLOAT_OP(ceilw, d)
860{
861 set_float_rounding_mode(float_round_up, &env->fp_status);
862 WT2 = float64_round_to_int(FDT0, &env->fp_status);
863 RESTORE_ROUNDING_MODE;
864 update_fcr31();
865 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
866 WT2 = 0x7fffffff;
867}
868FLOAT_OP(ceilw, s)
869{
870 set_float_rounding_mode(float_round_up, &env->fp_status);
871 WT2 = float32_round_to_int(FST0, &env->fp_status);
872 RESTORE_ROUNDING_MODE;
873 update_fcr31();
874 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
875 WT2 = 0x7fffffff;
876}
877
878FLOAT_OP(floorl, d)
879{
880 set_float_rounding_mode(float_round_down, &env->fp_status);
881 DT2 = float64_round_to_int(FDT0, &env->fp_status);
882 RESTORE_ROUNDING_MODE;
883 update_fcr31();
884 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
885 DT2 = 0x7fffffffffffffffULL;
886}
887FLOAT_OP(floorl, s)
888{
889 set_float_rounding_mode(float_round_down, &env->fp_status);
890 DT2 = float32_round_to_int(FST0, &env->fp_status);
891 RESTORE_ROUNDING_MODE;
892 update_fcr31();
893 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
894 DT2 = 0x7fffffffffffffffULL;
895}
896FLOAT_OP(floorw, d)
897{
898 set_float_rounding_mode(float_round_down, &env->fp_status);
899 WT2 = float64_round_to_int(FDT0, &env->fp_status);
900 RESTORE_ROUNDING_MODE;
901 update_fcr31();
902 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
903 WT2 = 0x7fffffff;
904}
905FLOAT_OP(floorw, s)
906{
907 set_float_rounding_mode(float_round_down, &env->fp_status);
908 WT2 = float32_round_to_int(FST0, &env->fp_status);
909 RESTORE_ROUNDING_MODE;
910 update_fcr31();
911 if (GET_FP_CAUSE(env->fcr31) & (FP_OVERFLOW | FP_INVALID))
912 WT2 = 0x7fffffff;
913}
914
57fa1fb3
TS
915/* unary operations, MIPS specific, s and d */
916#define FLOAT_UNOP(name) \
917FLOAT_OP(name, d) \
918{ \
919 set_float_exception_flags(0, &env->fp_status); \
920/* XXX: not implemented */ \
921/* FDT2 = float64_ ## name (FDT0, &env->fp_status);*/ \
922do_raise_exception(EXCP_RI); \
923 update_fcr31(); \
924} \
925FLOAT_OP(name, s) \
926{ \
927 set_float_exception_flags(0, &env->fp_status); \
928/* XXX: not implemented */ \
929/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \
930do_raise_exception(EXCP_RI); \
931 update_fcr31(); \
932}
933FLOAT_UNOP(rsqrt)
934FLOAT_UNOP(recip)
935#undef FLOAT_UNOP
936
937/* unary operations, MIPS specific, s, d and ps */
938#define FLOAT_UNOP(name) \
939FLOAT_OP(name, d) \
940{ \
941 set_float_exception_flags(0, &env->fp_status); \
942/* XXX: not implemented */ \
943/* FDT2 = float64_ ## name (FDT0, &env->fp_status);*/ \
944do_raise_exception(EXCP_RI); \
945 update_fcr31(); \
946} \
947FLOAT_OP(name, s) \
948{ \
949 set_float_exception_flags(0, &env->fp_status); \
950/* XXX: not implemented */ \
951/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \
952do_raise_exception(EXCP_RI); \
953 update_fcr31(); \
954} \
955FLOAT_OP(name, ps) \
956{ \
957 set_float_exception_flags(0, &env->fp_status); \
958/* XXX: not implemented */ \
959/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \
960/* FSTH2 = float32_ ## name (FSTH0, &env->fp_status);*/ \
961do_raise_exception(EXCP_RI); \
962 update_fcr31(); \
963}
964FLOAT_UNOP(rsqrt1)
965FLOAT_UNOP(recip1)
966#undef FLOAT_UNOP
967
fd4a04eb
TS
968/* binary operations */
969#define FLOAT_BINOP(name) \
970FLOAT_OP(name, d) \
971{ \
972 set_float_exception_flags(0, &env->fp_status); \
973 FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \
3a5b360d
TS
974 update_fcr31(); \
975 if (GET_FP_CAUSE(env->fcr31) & FP_INVALID) \
976 FDT2 = 0x7ff7ffffffffffffULL; \
977 else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \
978 if ((env->fcr31 & 0x3) == 0) \
979 FDT2 &= 0x8000000000000000ULL; \
980 } \
fd4a04eb
TS
981} \
982FLOAT_OP(name, s) \
983{ \
984 set_float_exception_flags(0, &env->fp_status); \
985 FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
3a5b360d
TS
986 update_fcr31(); \
987 if (GET_FP_CAUSE(env->fcr31) & FP_INVALID) \
988 FST2 = 0x7fbfffff; \
989 else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \
990 if ((env->fcr31 & 0x3) == 0) \
991 FST2 &= 0x80000000ULL; \
992 } \
fd4a04eb
TS
993} \
994FLOAT_OP(name, ps) \
995{ \
996 set_float_exception_flags(0, &env->fp_status); \
997 FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \
998 FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \
999 update_fcr31(); \
3a5b360d
TS
1000 if (GET_FP_CAUSE(env->fcr31) & FP_INVALID) { \
1001 FST2 = 0x7fbfffff; \
1002 FSTH2 = 0x7fbfffff; \
1003 } else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \
1004 if ((env->fcr31 & 0x3) == 0) { \
1005 FST2 &= 0x80000000ULL; \
1006 FSTH2 &= 0x80000000ULL; \
1007 } \
1008 } \
fd4a04eb
TS
1009}
1010FLOAT_BINOP(add)
1011FLOAT_BINOP(sub)
1012FLOAT_BINOP(mul)
1013FLOAT_BINOP(div)
1014#undef FLOAT_BINOP
1015
57fa1fb3
TS
1016/* binary operations, MIPS specific */
1017#define FLOAT_BINOP(name) \
1018FLOAT_OP(name, d) \
1019{ \
1020 set_float_exception_flags(0, &env->fp_status); \
1021/* XXX: not implemented */ \
1022/* FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status);*/ \
1023do_raise_exception(EXCP_RI); \
1024 update_fcr31(); \
1025} \
1026FLOAT_OP(name, s) \
1027{ \
1028 set_float_exception_flags(0, &env->fp_status); \
1029/* XXX: not implemented */ \
1030/* FST2 = float32_ ## name (FST0, FST1, &env->fp_status);*/ \
1031do_raise_exception(EXCP_RI); \
1032 update_fcr31(); \
1033} \
1034FLOAT_OP(name, ps) \
1035{ \
1036 set_float_exception_flags(0, &env->fp_status); \
1037/* XXX: not implemented */ \
1038/* FST2 = float32_ ## name (FST0, FST1, &env->fp_status);*/ \
1039/* FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status);*/ \
1040do_raise_exception(EXCP_RI); \
1041 update_fcr31(); \
1042}
1043FLOAT_BINOP(rsqrt2)
1044FLOAT_BINOP(recip2)
1045#undef FLOAT_BINOP
1046
fd4a04eb
TS
1047FLOAT_OP(addr, ps)
1048{
1049 set_float_exception_flags(0, &env->fp_status);
1050 FST2 = float32_add (FST0, FSTH0, &env->fp_status);
1051 FSTH2 = float32_add (FST1, FSTH1, &env->fp_status);
1052 update_fcr31();
1053}
1054
57fa1fb3
TS
1055FLOAT_OP(mulr, ps)
1056{
1057 set_float_exception_flags(0, &env->fp_status);
1058 FST2 = float32_mul (FST0, FSTH0, &env->fp_status);
1059 FSTH2 = float32_mul (FST1, FSTH1, &env->fp_status);
1060 update_fcr31();
1061}
1062
fd4a04eb
TS
1063#define FOP_COND_D(op, cond) \
1064void do_cmp_d_ ## op (long cc) \
1065{ \
1066 int c = cond; \
1067 update_fcr31(); \
1068 if (c) \
1069 SET_FP_COND(cc, env); \
1070 else \
1071 CLEAR_FP_COND(cc, env); \
1072} \
1073void do_cmpabs_d_ ## op (long cc) \
1074{ \
1075 int c; \
1076 FDT0 &= ~(1ULL << 63); \
1077 FDT1 &= ~(1ULL << 63); \
1078 c = cond; \
1079 update_fcr31(); \
1080 if (c) \
1081 SET_FP_COND(cc, env); \
1082 else \
1083 CLEAR_FP_COND(cc, env); \
1084}
1085
1086int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
1087{
1088 if (float64_is_signaling_nan(a) ||
1089 float64_is_signaling_nan(b) ||
1090 (sig && (float64_is_nan(a) || float64_is_nan(b)))) {
1091 float_raise(float_flag_invalid, status);
1092 return 1;
1093 } else if (float64_is_nan(a) || float64_is_nan(b)) {
1094 return 1;
1095 } else {
1096 return 0;
1097 }
1098}
1099
1100/* NOTE: the comma operator will make "cond" to eval to false,
1101 * but float*_is_unordered() is still called. */
1102FOP_COND_D(f, (float64_is_unordered(0, FDT1, FDT0, &env->fp_status), 0))
1103FOP_COND_D(un, float64_is_unordered(0, FDT1, FDT0, &env->fp_status))
1104FOP_COND_D(eq, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status))
1105FOP_COND_D(ueq, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
1106FOP_COND_D(olt, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status))
1107FOP_COND_D(ult, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
1108FOP_COND_D(ole, !float64_is_unordered(0, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status))
1109FOP_COND_D(ule, float64_is_unordered(0, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
1110/* NOTE: the comma operator will make "cond" to eval to false,
1111 * but float*_is_unordered() is still called. */
1112FOP_COND_D(sf, (float64_is_unordered(1, FDT1, FDT0, &env->fp_status), 0))
1113FOP_COND_D(ngle,float64_is_unordered(1, FDT1, FDT0, &env->fp_status))
1114FOP_COND_D(seq, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_eq(FDT0, FDT1, &env->fp_status))
1115FOP_COND_D(ngl, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
1116FOP_COND_D(lt, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_lt(FDT0, FDT1, &env->fp_status))
1117FOP_COND_D(nge, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
1118FOP_COND_D(le, !float64_is_unordered(1, FDT1, FDT0, &env->fp_status) && float64_le(FDT0, FDT1, &env->fp_status))
1119FOP_COND_D(ngt, float64_is_unordered(1, FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
1120
1121#define FOP_COND_S(op, cond) \
1122void do_cmp_s_ ## op (long cc) \
1123{ \
1124 int c = cond; \
1125 update_fcr31(); \
1126 if (c) \
1127 SET_FP_COND(cc, env); \
1128 else \
1129 CLEAR_FP_COND(cc, env); \
1130} \
1131void do_cmpabs_s_ ## op (long cc) \
1132{ \
1133 int c; \
1134 FST0 &= ~(1 << 31); \
1135 FST1 &= ~(1 << 31); \
1136 c = cond; \
1137 update_fcr31(); \
1138 if (c) \
1139 SET_FP_COND(cc, env); \
1140 else \
1141 CLEAR_FP_COND(cc, env); \
1142}
1143
1144flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
1145{
fd4a04eb
TS
1146 if (float32_is_signaling_nan(a) ||
1147 float32_is_signaling_nan(b) ||
1148 (sig && (float32_is_nan(a) || float32_is_nan(b)))) {
1149 float_raise(float_flag_invalid, status);
1150 return 1;
1151 } else if (float32_is_nan(a) || float32_is_nan(b)) {
1152 return 1;
1153 } else {
1154 return 0;
1155 }
1156}
1157
1158/* NOTE: the comma operator will make "cond" to eval to false,
1159 * but float*_is_unordered() is still called. */
1160FOP_COND_S(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0))
1161FOP_COND_S(un, float32_is_unordered(0, FST1, FST0, &env->fp_status))
1162FOP_COND_S(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status))
1163FOP_COND_S(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1164FOP_COND_S(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status))
1165FOP_COND_S(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1166FOP_COND_S(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status))
1167FOP_COND_S(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1168/* NOTE: the comma operator will make "cond" to eval to false,
1169 * but float*_is_unordered() is still called. */
1170FOP_COND_S(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0))
1171FOP_COND_S(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status))
1172FOP_COND_S(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status))
1173FOP_COND_S(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
1174FOP_COND_S(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status))
1175FOP_COND_S(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
1176FOP_COND_S(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status))
1177FOP_COND_S(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
1178
1179#define FOP_COND_PS(op, condl, condh) \
1180void do_cmp_ps_ ## op (long cc) \
1181{ \
1182 int cl = condl; \
1183 int ch = condh; \
1184 update_fcr31(); \
1185 if (cl) \
1186 SET_FP_COND(cc, env); \
1187 else \
1188 CLEAR_FP_COND(cc, env); \
1189 if (ch) \
1190 SET_FP_COND(cc + 1, env); \
1191 else \
1192 CLEAR_FP_COND(cc + 1, env); \
1193} \
1194void do_cmpabs_ps_ ## op (long cc) \
1195{ \
1196 int cl, ch; \
1197 FST0 &= ~(1 << 31); \
1198 FSTH0 &= ~(1 << 31); \
1199 FST1 &= ~(1 << 31); \
1200 FSTH1 &= ~(1 << 31); \
1201 cl = condl; \
1202 ch = condh; \
1203 update_fcr31(); \
1204 if (cl) \
1205 SET_FP_COND(cc, env); \
1206 else \
1207 CLEAR_FP_COND(cc, env); \
1208 if (ch) \
1209 SET_FP_COND(cc + 1, env); \
1210 else \
1211 CLEAR_FP_COND(cc + 1, env); \
1212}
1213
1214/* NOTE: the comma operator will make "cond" to eval to false,
1215 * but float*_is_unordered() is still called. */
1216FOP_COND_PS(f, (float32_is_unordered(0, FST1, FST0, &env->fp_status), 0),
1217 (float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status), 0))
1218FOP_COND_PS(un, float32_is_unordered(0, FST1, FST0, &env->fp_status),
1219 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status))
1220FOP_COND_PS(eq, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status),
1221 !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status))
1222FOP_COND_PS(ueq, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status),
1223 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status))
1224FOP_COND_PS(olt, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status),
1225 !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status))
1226FOP_COND_PS(ult, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status),
1227 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status))
1228FOP_COND_PS(ole, !float32_is_unordered(0, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status),
1229 !float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status))
1230FOP_COND_PS(ule, float32_is_unordered(0, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status),
1231 float32_is_unordered(0, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status))
1232/* NOTE: the comma operator will make "cond" to eval to false,
1233 * but float*_is_unordered() is still called. */
1234FOP_COND_PS(sf, (float32_is_unordered(1, FST1, FST0, &env->fp_status), 0),
1235 (float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status), 0))
1236FOP_COND_PS(ngle,float32_is_unordered(1, FST1, FST0, &env->fp_status),
1237 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status))
1238FOP_COND_PS(seq, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_eq(FST0, FST1, &env->fp_status),
1239 !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_eq(FSTH0, FSTH1, &env->fp_status))
1240FOP_COND_PS(ngl, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status),
1241 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_eq(FSTH0, FSTH1, &env->fp_status))
1242FOP_COND_PS(lt, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_lt(FST0, FST1, &env->fp_status),
1243 !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_lt(FSTH0, FSTH1, &env->fp_status))
1244FOP_COND_PS(nge, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status),
1245 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_lt(FSTH0, FSTH1, &env->fp_status))
1246FOP_COND_PS(le, !float32_is_unordered(1, FST1, FST0, &env->fp_status) && float32_le(FST0, FST1, &env->fp_status),
1247 !float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) && float32_le(FSTH0, FSTH1, &env->fp_status))
1248FOP_COND_PS(ngt, float32_is_unordered(1, FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status),
1249 float32_is_unordered(1, FSTH1, FSTH0, &env->fp_status) || float32_le(FSTH0, FSTH1, &env->fp_status))
This page took 0.228286 seconds and 4 git commands to generate.