Annotation of qemu/target-mips/op_helper.c, revision 1.1.1.6

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.