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

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
1.1.1.8   root       17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1       root       18:  */
1.1.1.6   root       19: #include <stdlib.h>
1.1       root       20: #include "exec.h"
                     21: 
1.1.1.6   root       22: #include "host-utils.h"
1.1       root       23: 
1.1.1.7   root       24: #include "helper.h"
1.1.1.11! root       25: 
        !            26: #ifndef CONFIG_USER_ONLY
        !            27: static inline void cpu_mips_tlb_flush (CPUState *env, int flush_global);
        !            28: #endif
        !            29: 
1.1       root       30: /*****************************************************************************/
                     31: /* Exceptions processing helpers */
                     32: 
1.1.1.8   root       33: void helper_raise_exception_err (uint32_t exception, int error_code)
1.1       root       34: {
                     35: #if 1
1.1.1.7   root       36:     if (exception < 0x100)
                     37:         qemu_log("%s: %d %d\n", __func__, exception, error_code);
1.1       root       38: #endif
                     39:     env->exception_index = exception;
                     40:     env->error_code = error_code;
                     41:     cpu_loop_exit();
                     42: }
                     43: 
1.1.1.8   root       44: void helper_raise_exception (uint32_t exception)
1.1       root       45: {
1.1.1.8   root       46:     helper_raise_exception_err(exception, 0);
1.1       root       47: }
                     48: 
1.1.1.7   root       49: #if !defined(CONFIG_USER_ONLY)
                     50: static void do_restore_state (void *pc_ptr)
                     51: {
                     52:     TranslationBlock *tb;
                     53:     unsigned long pc = (unsigned long) pc_ptr;
                     54:     
                     55:     tb = tb_find_pc (pc);
                     56:     if (tb) {
                     57:         cpu_restore_state (tb, env, pc, NULL);
                     58:     }
1.1.1.2   root       59: }
1.1.1.7   root       60: #endif
1.1.1.2   root       61: 
1.1.1.9   root       62: #if defined(CONFIG_USER_ONLY)
                     63: #define HELPER_LD(name, insn, type)                                     \
                     64: static inline type do_##name(target_ulong addr, int mem_idx)            \
                     65: {                                                                       \
                     66:     return (type) insn##_raw(addr);                                     \
                     67: }
                     68: #else
                     69: #define HELPER_LD(name, insn, type)                                     \
                     70: static inline type do_##name(target_ulong addr, int mem_idx)            \
                     71: {                                                                       \
                     72:     switch (mem_idx)                                                    \
                     73:     {                                                                   \
                     74:     case 0: return (type) insn##_kernel(addr); break;                   \
                     75:     case 1: return (type) insn##_super(addr); break;                    \
                     76:     default:                                                            \
                     77:     case 2: return (type) insn##_user(addr); break;                     \
                     78:     }                                                                   \
                     79: }
                     80: #endif
                     81: HELPER_LD(lbu, ldub, uint8_t)
                     82: HELPER_LD(lw, ldl, int32_t)
                     83: #ifdef TARGET_MIPS64
                     84: HELPER_LD(ld, ldq, int64_t)
                     85: #endif
                     86: #undef HELPER_LD
                     87: 
                     88: #if defined(CONFIG_USER_ONLY)
                     89: #define HELPER_ST(name, insn, type)                                     \
                     90: static inline void do_##name(target_ulong addr, type val, int mem_idx)  \
                     91: {                                                                       \
                     92:     insn##_raw(addr, val);                                              \
                     93: }
                     94: #else
                     95: #define HELPER_ST(name, insn, type)                                     \
                     96: static inline void do_##name(target_ulong addr, type val, int mem_idx)  \
                     97: {                                                                       \
                     98:     switch (mem_idx)                                                    \
                     99:     {                                                                   \
                    100:     case 0: insn##_kernel(addr, val); break;                            \
                    101:     case 1: insn##_super(addr, val); break;                             \
                    102:     default:                                                            \
                    103:     case 2: insn##_user(addr, val); break;                              \
                    104:     }                                                                   \
                    105: }
                    106: #endif
                    107: HELPER_ST(sb, stb, uint8_t)
                    108: HELPER_ST(sw, stl, uint32_t)
                    109: #ifdef TARGET_MIPS64
                    110: HELPER_ST(sd, stq, uint64_t)
                    111: #endif
                    112: #undef HELPER_ST
                    113: 
1.1.1.8   root      114: target_ulong helper_clo (target_ulong arg1)
1.1.1.2   root      115: {
1.1.1.8   root      116:     return clo32(arg1);
1.1.1.2   root      117: }
                    118: 
1.1.1.8   root      119: target_ulong helper_clz (target_ulong arg1)
1.1.1.6   root      120: {
1.1.1.8   root      121:     return clz32(arg1);
1.1.1.6   root      122: }
1.1       root      123: 
1.1.1.6   root      124: #if defined(TARGET_MIPS64)
1.1.1.8   root      125: target_ulong helper_dclo (target_ulong arg1)
1.1.1.7   root      126: {
1.1.1.8   root      127:     return clo64(arg1);
1.1.1.7   root      128: }
                    129: 
1.1.1.8   root      130: target_ulong helper_dclz (target_ulong arg1)
1.1.1.7   root      131: {
1.1.1.8   root      132:     return clz64(arg1);
1.1.1.7   root      133: }
                    134: #endif /* TARGET_MIPS64 */
                    135: 
                    136: /* 64 bits arithmetic for 32 bits hosts */
                    137: static inline uint64_t get_HILO (void)
                    138: {
                    139:     return ((uint64_t)(env->active_tc.HI[0]) << 32) | (uint32_t)env->active_tc.LO[0];
                    140: }
                    141: 
                    142: static inline void set_HILO (uint64_t HILO)
                    143: {
                    144:     env->active_tc.LO[0] = (int32_t)HILO;
                    145:     env->active_tc.HI[0] = (int32_t)(HILO >> 32);
                    146: }
                    147: 
1.1.1.8   root      148: static inline void set_HIT0_LO (target_ulong arg1, uint64_t HILO)
1.1.1.7   root      149: {
                    150:     env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
1.1.1.8   root      151:     arg1 = env->active_tc.HI[0] = (int32_t)(HILO >> 32);
1.1.1.7   root      152: }
                    153: 
1.1.1.8   root      154: static inline void set_HI_LOT0 (target_ulong arg1, uint64_t HILO)
1.1.1.7   root      155: {
1.1.1.8   root      156:     arg1 = env->active_tc.LO[0] = (int32_t)(HILO & 0xFFFFFFFF);
1.1.1.7   root      157:     env->active_tc.HI[0] = (int32_t)(HILO >> 32);
                    158: }
                    159: 
                    160: /* Multiplication variants of the vr54xx. */
1.1.1.8   root      161: target_ulong helper_muls (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      162: {
1.1.1.8   root      163:     set_HI_LOT0(arg1, 0 - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
1.1.1.7   root      164: 
1.1.1.8   root      165:     return arg1;
1.1.1.7   root      166: }
                    167: 
1.1.1.8   root      168: target_ulong helper_mulsu (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      169: {
1.1.1.8   root      170:     set_HI_LOT0(arg1, 0 - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
1.1.1.7   root      171: 
1.1.1.8   root      172:     return arg1;
1.1.1.7   root      173: }
                    174: 
1.1.1.8   root      175: target_ulong helper_macc (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      176: {
1.1.1.8   root      177:     set_HI_LOT0(arg1, ((int64_t)get_HILO()) + ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
1.1.1.7   root      178: 
1.1.1.8   root      179:     return arg1;
1.1.1.7   root      180: }
                    181: 
1.1.1.8   root      182: target_ulong helper_macchi (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      183: {
1.1.1.8   root      184:     set_HIT0_LO(arg1, ((int64_t)get_HILO()) + ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
1.1.1.7   root      185: 
1.1.1.8   root      186:     return arg1;
1.1.1.7   root      187: }
                    188: 
1.1.1.8   root      189: target_ulong helper_maccu (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      190: {
1.1.1.8   root      191:     set_HI_LOT0(arg1, ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
1.1.1.7   root      192: 
1.1.1.8   root      193:     return arg1;
1.1.1.7   root      194: }
                    195: 
1.1.1.8   root      196: target_ulong helper_macchiu (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      197: {
1.1.1.8   root      198:     set_HIT0_LO(arg1, ((uint64_t)get_HILO()) + ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
1.1.1.7   root      199: 
1.1.1.8   root      200:     return arg1;
1.1.1.7   root      201: }
                    202: 
1.1.1.8   root      203: target_ulong helper_msac (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      204: {
1.1.1.8   root      205:     set_HI_LOT0(arg1, ((int64_t)get_HILO()) - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
1.1.1.7   root      206: 
1.1.1.8   root      207:     return arg1;
1.1.1.7   root      208: }
                    209: 
1.1.1.8   root      210: target_ulong helper_msachi (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      211: {
1.1.1.8   root      212:     set_HIT0_LO(arg1, ((int64_t)get_HILO()) - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
1.1.1.7   root      213: 
1.1.1.8   root      214:     return arg1;
1.1.1.7   root      215: }
                    216: 
1.1.1.8   root      217: target_ulong helper_msacu (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      218: {
1.1.1.8   root      219:     set_HI_LOT0(arg1, ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
1.1.1.7   root      220: 
1.1.1.8   root      221:     return arg1;
1.1.1.7   root      222: }
                    223: 
1.1.1.8   root      224: target_ulong helper_msachiu (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      225: {
1.1.1.8   root      226:     set_HIT0_LO(arg1, ((uint64_t)get_HILO()) - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
1.1.1.7   root      227: 
1.1.1.8   root      228:     return arg1;
1.1.1.7   root      229: }
                    230: 
1.1.1.8   root      231: target_ulong helper_mulhi (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      232: {
1.1.1.8   root      233:     set_HIT0_LO(arg1, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2);
1.1.1.7   root      234: 
1.1.1.8   root      235:     return arg1;
1.1.1.7   root      236: }
                    237: 
1.1.1.8   root      238: target_ulong helper_mulhiu (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      239: {
1.1.1.8   root      240:     set_HIT0_LO(arg1, (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2);
1.1.1.7   root      241: 
1.1.1.8   root      242:     return arg1;
1.1.1.7   root      243: }
                    244: 
1.1.1.8   root      245: target_ulong helper_mulshi (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      246: {
1.1.1.8   root      247:     set_HIT0_LO(arg1, 0 - ((int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2));
1.1.1.7   root      248: 
1.1.1.8   root      249:     return arg1;
1.1.1.7   root      250: }
                    251: 
1.1.1.8   root      252: target_ulong helper_mulshiu (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      253: {
1.1.1.8   root      254:     set_HIT0_LO(arg1, 0 - ((uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2));
1.1.1.7   root      255: 
1.1.1.8   root      256:     return arg1;
1.1.1.7   root      257: }
                    258: 
                    259: #ifdef TARGET_MIPS64
1.1.1.8   root      260: void helper_dmult (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      261: {
1.1.1.8   root      262:     muls64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
1.1.1.7   root      263: }
                    264: 
1.1.1.8   root      265: void helper_dmultu (target_ulong arg1, target_ulong arg2)
1.1.1.7   root      266: {
1.1.1.8   root      267:     mulu64(&(env->active_tc.LO[0]), &(env->active_tc.HI[0]), arg1, arg2);
1.1.1.7   root      268: }
                    269: #endif
                    270: 
1.1.1.9   root      271: #ifndef CONFIG_USER_ONLY
1.1.1.10  root      272: 
                    273: static inline target_phys_addr_t do_translate_address(target_ulong address, int rw)
                    274: {
                    275:     target_phys_addr_t lladdr;
                    276: 
                    277:     lladdr = cpu_mips_translate_address(env, address, rw);
                    278: 
                    279:     if (lladdr == -1LL) {
                    280:         cpu_loop_exit();
                    281:     } else {
                    282:         return lladdr;
                    283:     }
                    284: }
                    285: 
1.1.1.9   root      286: #define HELPER_LD_ATOMIC(name, insn)                                          \
                    287: target_ulong helper_##name(target_ulong arg, int mem_idx)                     \
                    288: {                                                                             \
1.1.1.10  root      289:     env->lladdr = do_translate_address(arg, 0);                               \
1.1.1.9   root      290:     env->llval = do_##insn(arg, mem_idx);                                     \
                    291:     return env->llval;                                                        \
                    292: }
                    293: HELPER_LD_ATOMIC(ll, lw)
                    294: #ifdef TARGET_MIPS64
                    295: HELPER_LD_ATOMIC(lld, ld)
                    296: #endif
                    297: #undef HELPER_LD_ATOMIC
                    298: 
                    299: #define HELPER_ST_ATOMIC(name, ld_insn, st_insn, almask)                      \
                    300: target_ulong helper_##name(target_ulong arg1, target_ulong arg2, int mem_idx) \
                    301: {                                                                             \
                    302:     target_long tmp;                                                          \
                    303:                                                                               \
                    304:     if (arg2 & almask) {                                                      \
                    305:         env->CP0_BadVAddr = arg2;                                             \
                    306:         helper_raise_exception(EXCP_AdES);                                    \
                    307:     }                                                                         \
1.1.1.10  root      308:     if (do_translate_address(arg2, 1) == env->lladdr) {                       \
1.1.1.9   root      309:         tmp = do_##ld_insn(arg2, mem_idx);                                    \
                    310:         if (tmp == env->llval) {                                              \
                    311:             do_##st_insn(arg2, arg1, mem_idx);                                \
                    312:             return 1;                                                         \
                    313:         }                                                                     \
                    314:     }                                                                         \
                    315:     return 0;                                                                 \
                    316: }
                    317: HELPER_ST_ATOMIC(sc, lw, sw, 0x3)
                    318: #ifdef TARGET_MIPS64
                    319: HELPER_ST_ATOMIC(scd, ld, sd, 0x7)
                    320: #endif
                    321: #undef HELPER_ST_ATOMIC
                    322: #endif
                    323: 
1.1.1.7   root      324: #ifdef TARGET_WORDS_BIGENDIAN
                    325: #define GET_LMASK(v) ((v) & 3)
                    326: #define GET_OFFSET(addr, offset) (addr + (offset))
                    327: #else
                    328: #define GET_LMASK(v) (((v) & 3) ^ 3)
                    329: #define GET_OFFSET(addr, offset) (addr - (offset))
                    330: #endif
                    331: 
1.1.1.8   root      332: target_ulong helper_lwl(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7   root      333: {
                    334:     target_ulong tmp;
                    335: 
1.1.1.9   root      336:     tmp = do_lbu(arg2, mem_idx);
1.1.1.8   root      337:     arg1 = (arg1 & 0x00FFFFFF) | (tmp << 24);
1.1.1.7   root      338: 
1.1.1.8   root      339:     if (GET_LMASK(arg2) <= 2) {
1.1.1.9   root      340:         tmp = do_lbu(GET_OFFSET(arg2, 1), mem_idx);
1.1.1.8   root      341:         arg1 = (arg1 & 0xFF00FFFF) | (tmp << 16);
1.1.1.7   root      342:     }
                    343: 
1.1.1.8   root      344:     if (GET_LMASK(arg2) <= 1) {
1.1.1.9   root      345:         tmp = do_lbu(GET_OFFSET(arg2, 2), mem_idx);
1.1.1.8   root      346:         arg1 = (arg1 & 0xFFFF00FF) | (tmp << 8);
1.1.1.7   root      347:     }
                    348: 
1.1.1.8   root      349:     if (GET_LMASK(arg2) == 0) {
1.1.1.9   root      350:         tmp = do_lbu(GET_OFFSET(arg2, 3), mem_idx);
1.1.1.8   root      351:         arg1 = (arg1 & 0xFFFFFF00) | tmp;
1.1.1.7   root      352:     }
1.1.1.8   root      353:     return (int32_t)arg1;
1.1.1.7   root      354: }
                    355: 
1.1.1.8   root      356: target_ulong helper_lwr(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7   root      357: {
                    358:     target_ulong tmp;
                    359: 
1.1.1.9   root      360:     tmp = do_lbu(arg2, mem_idx);
1.1.1.8   root      361:     arg1 = (arg1 & 0xFFFFFF00) | tmp;
1.1.1.7   root      362: 
1.1.1.8   root      363:     if (GET_LMASK(arg2) >= 1) {
1.1.1.9   root      364:         tmp = do_lbu(GET_OFFSET(arg2, -1), mem_idx);
1.1.1.8   root      365:         arg1 = (arg1 & 0xFFFF00FF) | (tmp << 8);
1.1.1.7   root      366:     }
                    367: 
1.1.1.8   root      368:     if (GET_LMASK(arg2) >= 2) {
1.1.1.9   root      369:         tmp = do_lbu(GET_OFFSET(arg2, -2), mem_idx);
1.1.1.8   root      370:         arg1 = (arg1 & 0xFF00FFFF) | (tmp << 16);
1.1.1.7   root      371:     }
                    372: 
1.1.1.8   root      373:     if (GET_LMASK(arg2) == 3) {
1.1.1.9   root      374:         tmp = do_lbu(GET_OFFSET(arg2, -3), mem_idx);
1.1.1.8   root      375:         arg1 = (arg1 & 0x00FFFFFF) | (tmp << 24);
1.1.1.7   root      376:     }
1.1.1.8   root      377:     return (int32_t)arg1;
1.1.1.7   root      378: }
                    379: 
1.1.1.8   root      380: void helper_swl(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7   root      381: {
1.1.1.9   root      382:     do_sb(arg2, (uint8_t)(arg1 >> 24), mem_idx);
1.1.1.7   root      383: 
1.1.1.8   root      384:     if (GET_LMASK(arg2) <= 2)
1.1.1.9   root      385:         do_sb(GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 16), mem_idx);
1.1.1.7   root      386: 
1.1.1.8   root      387:     if (GET_LMASK(arg2) <= 1)
1.1.1.9   root      388:         do_sb(GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 8), mem_idx);
1.1.1.7   root      389: 
1.1.1.8   root      390:     if (GET_LMASK(arg2) == 0)
1.1.1.9   root      391:         do_sb(GET_OFFSET(arg2, 3), (uint8_t)arg1, mem_idx);
1.1.1.7   root      392: }
                    393: 
1.1.1.8   root      394: void helper_swr(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7   root      395: {
1.1.1.9   root      396:     do_sb(arg2, (uint8_t)arg1, mem_idx);
1.1.1.7   root      397: 
1.1.1.8   root      398:     if (GET_LMASK(arg2) >= 1)
1.1.1.9   root      399:         do_sb(GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx);
1.1.1.7   root      400: 
1.1.1.8   root      401:     if (GET_LMASK(arg2) >= 2)
1.1.1.9   root      402:         do_sb(GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx);
1.1.1.7   root      403: 
1.1.1.8   root      404:     if (GET_LMASK(arg2) == 3)
1.1.1.9   root      405:         do_sb(GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx);
1.1.1.7   root      406: }
                    407: 
                    408: #if defined(TARGET_MIPS64)
                    409: /* "half" load and stores.  We must do the memory access inline,
                    410:    or fault handling won't work.  */
                    411: 
                    412: #ifdef TARGET_WORDS_BIGENDIAN
                    413: #define GET_LMASK64(v) ((v) & 7)
                    414: #else
                    415: #define GET_LMASK64(v) (((v) & 7) ^ 7)
                    416: #endif
                    417: 
1.1.1.8   root      418: target_ulong helper_ldl(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7   root      419: {
                    420:     uint64_t tmp;
                    421: 
1.1.1.9   root      422:     tmp = do_lbu(arg2, mem_idx);
1.1.1.8   root      423:     arg1 = (arg1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
1.1.1.7   root      424: 
1.1.1.8   root      425:     if (GET_LMASK64(arg2) <= 6) {
1.1.1.9   root      426:         tmp = do_lbu(GET_OFFSET(arg2, 1), mem_idx);
1.1.1.8   root      427:         arg1 = (arg1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
1.1.1.7   root      428:     }
                    429: 
1.1.1.8   root      430:     if (GET_LMASK64(arg2) <= 5) {
1.1.1.9   root      431:         tmp = do_lbu(GET_OFFSET(arg2, 2), mem_idx);
1.1.1.8   root      432:         arg1 = (arg1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
1.1.1.7   root      433:     }
                    434: 
1.1.1.8   root      435:     if (GET_LMASK64(arg2) <= 4) {
1.1.1.9   root      436:         tmp = do_lbu(GET_OFFSET(arg2, 3), mem_idx);
1.1.1.8   root      437:         arg1 = (arg1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
1.1.1.7   root      438:     }
                    439: 
1.1.1.8   root      440:     if (GET_LMASK64(arg2) <= 3) {
1.1.1.9   root      441:         tmp = do_lbu(GET_OFFSET(arg2, 4), mem_idx);
1.1.1.8   root      442:         arg1 = (arg1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
1.1.1.7   root      443:     }
                    444: 
1.1.1.8   root      445:     if (GET_LMASK64(arg2) <= 2) {
1.1.1.9   root      446:         tmp = do_lbu(GET_OFFSET(arg2, 5), mem_idx);
1.1.1.8   root      447:         arg1 = (arg1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
1.1.1.7   root      448:     }
                    449: 
1.1.1.8   root      450:     if (GET_LMASK64(arg2) <= 1) {
1.1.1.9   root      451:         tmp = do_lbu(GET_OFFSET(arg2, 6), mem_idx);
1.1.1.8   root      452:         arg1 = (arg1 & 0xFFFFFFFFFFFF00FFULL) | (tmp << 8);
1.1.1.7   root      453:     }
                    454: 
1.1.1.8   root      455:     if (GET_LMASK64(arg2) == 0) {
1.1.1.9   root      456:         tmp = do_lbu(GET_OFFSET(arg2, 7), mem_idx);
1.1.1.8   root      457:         arg1 = (arg1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
1.1.1.7   root      458:     }
                    459: 
1.1.1.8   root      460:     return arg1;
1.1.1.7   root      461: }
                    462: 
1.1.1.8   root      463: target_ulong helper_ldr(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7   root      464: {
                    465:     uint64_t tmp;
                    466: 
1.1.1.9   root      467:     tmp = do_lbu(arg2, mem_idx);
1.1.1.8   root      468:     arg1 = (arg1 & 0xFFFFFFFFFFFFFF00ULL) | tmp;
1.1.1.7   root      469: 
1.1.1.8   root      470:     if (GET_LMASK64(arg2) >= 1) {
1.1.1.9   root      471:         tmp = do_lbu(GET_OFFSET(arg2, -1), mem_idx);
1.1.1.8   root      472:         arg1 = (arg1 & 0xFFFFFFFFFFFF00FFULL) | (tmp  << 8);
1.1.1.7   root      473:     }
                    474: 
1.1.1.8   root      475:     if (GET_LMASK64(arg2) >= 2) {
1.1.1.9   root      476:         tmp = do_lbu(GET_OFFSET(arg2, -2), mem_idx);
1.1.1.8   root      477:         arg1 = (arg1 & 0xFFFFFFFFFF00FFFFULL) | (tmp << 16);
1.1.1.7   root      478:     }
                    479: 
1.1.1.8   root      480:     if (GET_LMASK64(arg2) >= 3) {
1.1.1.9   root      481:         tmp = do_lbu(GET_OFFSET(arg2, -3), mem_idx);
1.1.1.8   root      482:         arg1 = (arg1 & 0xFFFFFFFF00FFFFFFULL) | (tmp << 24);
1.1.1.7   root      483:     }
                    484: 
1.1.1.8   root      485:     if (GET_LMASK64(arg2) >= 4) {
1.1.1.9   root      486:         tmp = do_lbu(GET_OFFSET(arg2, -4), mem_idx);
1.1.1.8   root      487:         arg1 = (arg1 & 0xFFFFFF00FFFFFFFFULL) | (tmp << 32);
1.1.1.7   root      488:     }
                    489: 
1.1.1.8   root      490:     if (GET_LMASK64(arg2) >= 5) {
1.1.1.9   root      491:         tmp = do_lbu(GET_OFFSET(arg2, -5), mem_idx);
1.1.1.8   root      492:         arg1 = (arg1 & 0xFFFF00FFFFFFFFFFULL) | (tmp << 40);
1.1.1.7   root      493:     }
                    494: 
1.1.1.8   root      495:     if (GET_LMASK64(arg2) >= 6) {
1.1.1.9   root      496:         tmp = do_lbu(GET_OFFSET(arg2, -6), mem_idx);
1.1.1.8   root      497:         arg1 = (arg1 & 0xFF00FFFFFFFFFFFFULL) | (tmp << 48);
1.1.1.7   root      498:     }
                    499: 
1.1.1.8   root      500:     if (GET_LMASK64(arg2) == 7) {
1.1.1.9   root      501:         tmp = do_lbu(GET_OFFSET(arg2, -7), mem_idx);
1.1.1.8   root      502:         arg1 = (arg1 & 0x00FFFFFFFFFFFFFFULL) | (tmp << 56);
1.1.1.7   root      503:     }
                    504: 
1.1.1.8   root      505:     return arg1;
1.1.1.7   root      506: }
                    507: 
1.1.1.8   root      508: void helper_sdl(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7   root      509: {
1.1.1.9   root      510:     do_sb(arg2, (uint8_t)(arg1 >> 56), mem_idx);
1.1.1.7   root      511: 
1.1.1.8   root      512:     if (GET_LMASK64(arg2) <= 6)
1.1.1.9   root      513:         do_sb(GET_OFFSET(arg2, 1), (uint8_t)(arg1 >> 48), mem_idx);
1.1.1.7   root      514: 
1.1.1.8   root      515:     if (GET_LMASK64(arg2) <= 5)
1.1.1.9   root      516:         do_sb(GET_OFFSET(arg2, 2), (uint8_t)(arg1 >> 40), mem_idx);
1.1.1.7   root      517: 
1.1.1.8   root      518:     if (GET_LMASK64(arg2) <= 4)
1.1.1.9   root      519:         do_sb(GET_OFFSET(arg2, 3), (uint8_t)(arg1 >> 32), mem_idx);
1.1.1.7   root      520: 
1.1.1.8   root      521:     if (GET_LMASK64(arg2) <= 3)
1.1.1.9   root      522:         do_sb(GET_OFFSET(arg2, 4), (uint8_t)(arg1 >> 24), mem_idx);
1.1.1.7   root      523: 
1.1.1.8   root      524:     if (GET_LMASK64(arg2) <= 2)
1.1.1.9   root      525:         do_sb(GET_OFFSET(arg2, 5), (uint8_t)(arg1 >> 16), mem_idx);
1.1.1.7   root      526: 
1.1.1.8   root      527:     if (GET_LMASK64(arg2) <= 1)
1.1.1.9   root      528:         do_sb(GET_OFFSET(arg2, 6), (uint8_t)(arg1 >> 8), mem_idx);
1.1.1.7   root      529: 
1.1.1.8   root      530:     if (GET_LMASK64(arg2) <= 0)
1.1.1.9   root      531:         do_sb(GET_OFFSET(arg2, 7), (uint8_t)arg1, mem_idx);
1.1.1.7   root      532: }
                    533: 
1.1.1.8   root      534: void helper_sdr(target_ulong arg1, target_ulong arg2, int mem_idx)
1.1.1.7   root      535: {
1.1.1.9   root      536:     do_sb(arg2, (uint8_t)arg1, mem_idx);
1.1.1.7   root      537: 
1.1.1.8   root      538:     if (GET_LMASK64(arg2) >= 1)
1.1.1.9   root      539:         do_sb(GET_OFFSET(arg2, -1), (uint8_t)(arg1 >> 8), mem_idx);
1.1.1.7   root      540: 
1.1.1.8   root      541:     if (GET_LMASK64(arg2) >= 2)
1.1.1.9   root      542:         do_sb(GET_OFFSET(arg2, -2), (uint8_t)(arg1 >> 16), mem_idx);
1.1.1.7   root      543: 
1.1.1.8   root      544:     if (GET_LMASK64(arg2) >= 3)
1.1.1.9   root      545:         do_sb(GET_OFFSET(arg2, -3), (uint8_t)(arg1 >> 24), mem_idx);
1.1.1.7   root      546: 
1.1.1.8   root      547:     if (GET_LMASK64(arg2) >= 4)
1.1.1.9   root      548:         do_sb(GET_OFFSET(arg2, -4), (uint8_t)(arg1 >> 32), mem_idx);
1.1.1.7   root      549: 
1.1.1.8   root      550:     if (GET_LMASK64(arg2) >= 5)
1.1.1.9   root      551:         do_sb(GET_OFFSET(arg2, -5), (uint8_t)(arg1 >> 40), mem_idx);
1.1.1.7   root      552: 
1.1.1.8   root      553:     if (GET_LMASK64(arg2) >= 6)
1.1.1.9   root      554:         do_sb(GET_OFFSET(arg2, -6), (uint8_t)(arg1 >> 48), mem_idx);
1.1.1.7   root      555: 
1.1.1.8   root      556:     if (GET_LMASK64(arg2) == 7)
1.1.1.9   root      557:         do_sb(GET_OFFSET(arg2, -7), (uint8_t)(arg1 >> 56), mem_idx);
1.1.1.7   root      558: }
                    559: #endif /* TARGET_MIPS64 */
                    560: 
1.1.1.11! root      561: static const int multiple_regs[] = { 16, 17, 18, 19, 20, 21, 22, 23, 30 };
        !           562: 
        !           563: void helper_lwm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
        !           564: {
        !           565:     target_ulong base_reglist = reglist & 0xf;
        !           566:     target_ulong do_r31 = reglist & 0x10;
        !           567: #ifdef CONFIG_USER_ONLY
        !           568: #undef ldfun
        !           569: #define ldfun ldl_raw
        !           570: #else
        !           571:     uint32_t (*ldfun)(target_ulong);
        !           572: 
        !           573:     switch (mem_idx)
        !           574:     {
        !           575:     case 0: ldfun = ldl_kernel; break;
        !           576:     case 1: ldfun = ldl_super; break;
        !           577:     default:
        !           578:     case 2: ldfun = ldl_user; break;
        !           579:     }
        !           580: #endif
        !           581: 
        !           582:     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
        !           583:         target_ulong i;
        !           584: 
        !           585:         for (i = 0; i < base_reglist; i++) {
        !           586:             env->active_tc.gpr[multiple_regs[i]] = (target_long) ldfun(addr);
        !           587:             addr += 4;
        !           588:         }
        !           589:     }
        !           590: 
        !           591:     if (do_r31) {
        !           592:         env->active_tc.gpr[31] = (target_long) ldfun(addr);
        !           593:     }
        !           594: }
        !           595: 
        !           596: void helper_swm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
        !           597: {
        !           598:     target_ulong base_reglist = reglist & 0xf;
        !           599:     target_ulong do_r31 = reglist & 0x10;
        !           600: #ifdef CONFIG_USER_ONLY
        !           601: #undef stfun
        !           602: #define stfun stl_raw
        !           603: #else
        !           604:     void (*stfun)(target_ulong, uint32_t);
        !           605: 
        !           606:     switch (mem_idx)
        !           607:     {
        !           608:     case 0: stfun = stl_kernel; break;
        !           609:     case 1: stfun = stl_super; break;
        !           610:      default:
        !           611:     case 2: stfun = stl_user; break;
        !           612:     }
        !           613: #endif
        !           614: 
        !           615:     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
        !           616:         target_ulong i;
        !           617: 
        !           618:         for (i = 0; i < base_reglist; i++) {
        !           619:             stfun(addr, env->active_tc.gpr[multiple_regs[i]]);
        !           620:             addr += 4;
        !           621:         }
        !           622:     }
        !           623: 
        !           624:     if (do_r31) {
        !           625:         stfun(addr, env->active_tc.gpr[31]);
        !           626:     }
        !           627: }
        !           628: 
        !           629: #if defined(TARGET_MIPS64)
        !           630: void helper_ldm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
        !           631: {
        !           632:     target_ulong base_reglist = reglist & 0xf;
        !           633:     target_ulong do_r31 = reglist & 0x10;
        !           634: #ifdef CONFIG_USER_ONLY
        !           635: #undef ldfun
        !           636: #define ldfun ldq_raw
        !           637: #else
        !           638:     uint64_t (*ldfun)(target_ulong);
        !           639: 
        !           640:     switch (mem_idx)
        !           641:     {
        !           642:     case 0: ldfun = ldq_kernel; break;
        !           643:     case 1: ldfun = ldq_super; break;
        !           644:     default:
        !           645:     case 2: ldfun = ldq_user; break;
        !           646:     }
        !           647: #endif
        !           648: 
        !           649:     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
        !           650:         target_ulong i;
        !           651: 
        !           652:         for (i = 0; i < base_reglist; i++) {
        !           653:             env->active_tc.gpr[multiple_regs[i]] = ldfun(addr);
        !           654:             addr += 8;
        !           655:         }
        !           656:     }
        !           657: 
        !           658:     if (do_r31) {
        !           659:         env->active_tc.gpr[31] = ldfun(addr);
        !           660:     }
        !           661: }
        !           662: 
        !           663: void helper_sdm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
        !           664: {
        !           665:     target_ulong base_reglist = reglist & 0xf;
        !           666:     target_ulong do_r31 = reglist & 0x10;
        !           667: #ifdef CONFIG_USER_ONLY
        !           668: #undef stfun
        !           669: #define stfun stq_raw
        !           670: #else
        !           671:     void (*stfun)(target_ulong, uint64_t);
        !           672: 
        !           673:     switch (mem_idx)
        !           674:     {
        !           675:     case 0: stfun = stq_kernel; break;
        !           676:     case 1: stfun = stq_super; break;
        !           677:      default:
        !           678:     case 2: stfun = stq_user; break;
        !           679:     }
        !           680: #endif
        !           681: 
        !           682:     if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
        !           683:         target_ulong i;
        !           684: 
        !           685:         for (i = 0; i < base_reglist; i++) {
        !           686:             stfun(addr, env->active_tc.gpr[multiple_regs[i]]);
        !           687:             addr += 8;
        !           688:         }
        !           689:     }
        !           690: 
        !           691:     if (do_r31) {
        !           692:         stfun(addr, env->active_tc.gpr[31]);
        !           693:     }
        !           694: }
        !           695: #endif
        !           696: 
1.1.1.7   root      697: #ifndef CONFIG_USER_ONLY
                    698: /* CP0 helpers */
1.1.1.8   root      699: target_ulong helper_mfc0_mvpcontrol (void)
1.1.1.7   root      700: {
                    701:     return env->mvp->CP0_MVPControl;
                    702: }
                    703: 
1.1.1.8   root      704: target_ulong helper_mfc0_mvpconf0 (void)
1.1.1.7   root      705: {
                    706:     return env->mvp->CP0_MVPConf0;
                    707: }
                    708: 
1.1.1.8   root      709: target_ulong helper_mfc0_mvpconf1 (void)
1.1.1.7   root      710: {
                    711:     return env->mvp->CP0_MVPConf1;
                    712: }
                    713: 
1.1.1.8   root      714: target_ulong helper_mfc0_random (void)
1.1.1.7   root      715: {
                    716:     return (int32_t)cpu_mips_get_random(env);
                    717: }
                    718: 
1.1.1.8   root      719: target_ulong helper_mfc0_tcstatus (void)
1.1.1.7   root      720: {
                    721:     return env->active_tc.CP0_TCStatus;
                    722: }
                    723: 
1.1.1.8   root      724: target_ulong helper_mftc0_tcstatus(void)
1.1.1.7   root      725: {
                    726:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                    727: 
                    728:     if (other_tc == env->current_tc)
                    729:         return env->active_tc.CP0_TCStatus;
                    730:     else
                    731:         return env->tcs[other_tc].CP0_TCStatus;
                    732: }
                    733: 
1.1.1.8   root      734: target_ulong helper_mfc0_tcbind (void)
1.1.1.7   root      735: {
                    736:     return env->active_tc.CP0_TCBind;
                    737: }
                    738: 
1.1.1.8   root      739: target_ulong helper_mftc0_tcbind(void)
1.1.1.7   root      740: {
                    741:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                    742: 
                    743:     if (other_tc == env->current_tc)
                    744:         return env->active_tc.CP0_TCBind;
                    745:     else
                    746:         return env->tcs[other_tc].CP0_TCBind;
                    747: }
                    748: 
1.1.1.8   root      749: target_ulong helper_mfc0_tcrestart (void)
1.1.1.7   root      750: {
                    751:     return env->active_tc.PC;
                    752: }
                    753: 
1.1.1.8   root      754: target_ulong helper_mftc0_tcrestart(void)
1.1.1.7   root      755: {
                    756:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                    757: 
                    758:     if (other_tc == env->current_tc)
                    759:         return env->active_tc.PC;
                    760:     else
                    761:         return env->tcs[other_tc].PC;
                    762: }
                    763: 
1.1.1.8   root      764: target_ulong helper_mfc0_tchalt (void)
1.1.1.7   root      765: {
                    766:     return env->active_tc.CP0_TCHalt;
                    767: }
                    768: 
1.1.1.8   root      769: target_ulong helper_mftc0_tchalt(void)
1.1.1.7   root      770: {
                    771:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                    772: 
                    773:     if (other_tc == env->current_tc)
                    774:         return env->active_tc.CP0_TCHalt;
                    775:     else
                    776:         return env->tcs[other_tc].CP0_TCHalt;
                    777: }
                    778: 
1.1.1.8   root      779: target_ulong helper_mfc0_tccontext (void)
1.1.1.7   root      780: {
                    781:     return env->active_tc.CP0_TCContext;
                    782: }
                    783: 
1.1.1.8   root      784: target_ulong helper_mftc0_tccontext(void)
1.1.1.5   root      785: {
1.1.1.7   root      786:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                    787: 
                    788:     if (other_tc == env->current_tc)
                    789:         return env->active_tc.CP0_TCContext;
                    790:     else
                    791:         return env->tcs[other_tc].CP0_TCContext;
1.1.1.5   root      792: }
                    793: 
1.1.1.8   root      794: target_ulong helper_mfc0_tcschedule (void)
1.1.1.5   root      795: {
1.1.1.7   root      796:     return env->active_tc.CP0_TCSchedule;
1.1.1.5   root      797: }
                    798: 
1.1.1.8   root      799: target_ulong helper_mftc0_tcschedule(void)
1.1.1.5   root      800: {
1.1.1.7   root      801:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                    802: 
                    803:     if (other_tc == env->current_tc)
                    804:         return env->active_tc.CP0_TCSchedule;
                    805:     else
                    806:         return env->tcs[other_tc].CP0_TCSchedule;
1.1.1.5   root      807: }
                    808: 
1.1.1.8   root      809: target_ulong helper_mfc0_tcschefback (void)
1.1.1.5   root      810: {
1.1.1.7   root      811:     return env->active_tc.CP0_TCScheFBack;
1.1.1.5   root      812: }
                    813: 
1.1.1.8   root      814: target_ulong helper_mftc0_tcschefback(void)
1.1.1.5   root      815: {
1.1.1.7   root      816:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                    817: 
                    818:     if (other_tc == env->current_tc)
                    819:         return env->active_tc.CP0_TCScheFBack;
                    820:     else
                    821:         return env->tcs[other_tc].CP0_TCScheFBack;
                    822: }
                    823: 
1.1.1.8   root      824: target_ulong helper_mfc0_count (void)
1.1.1.7   root      825: {
                    826:     return (int32_t)cpu_mips_get_count(env);
                    827: }
                    828: 
1.1.1.8   root      829: target_ulong helper_mftc0_entryhi(void)
1.1.1.7   root      830: {
                    831:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                    832:     int32_t tcstatus;
                    833: 
                    834:     if (other_tc == env->current_tc)
                    835:         tcstatus = env->active_tc.CP0_TCStatus;
                    836:     else
                    837:         tcstatus = env->tcs[other_tc].CP0_TCStatus;
                    838: 
                    839:     return (env->CP0_EntryHi & ~0xff) | (tcstatus & 0xff);
                    840: }
                    841: 
1.1.1.8   root      842: target_ulong helper_mftc0_status(void)
1.1.1.7   root      843: {
                    844:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                    845:     target_ulong t0;
                    846:     int32_t tcstatus;
                    847: 
                    848:     if (other_tc == env->current_tc)
                    849:         tcstatus = env->active_tc.CP0_TCStatus;
                    850:     else
                    851:         tcstatus = env->tcs[other_tc].CP0_TCStatus;
                    852: 
                    853:     t0 = env->CP0_Status & ~0xf1000018;
                    854:     t0 |= tcstatus & (0xf << CP0TCSt_TCU0);
                    855:     t0 |= (tcstatus & (1 << CP0TCSt_TMX)) >> (CP0TCSt_TMX - CP0St_MX);
                    856:     t0 |= (tcstatus & (0x3 << CP0TCSt_TKSU)) >> (CP0TCSt_TKSU - CP0St_KSU);
                    857: 
                    858:     return t0;
                    859: }
                    860: 
1.1.1.8   root      861: target_ulong helper_mfc0_lladdr (void)
1.1.1.7   root      862: {
1.1.1.9   root      863:     return (int32_t)(env->lladdr >> env->CP0_LLAddr_shift);
1.1.1.7   root      864: }
                    865: 
1.1.1.8   root      866: target_ulong helper_mfc0_watchlo (uint32_t sel)
1.1.1.7   root      867: {
                    868:     return (int32_t)env->CP0_WatchLo[sel];
                    869: }
                    870: 
1.1.1.8   root      871: target_ulong helper_mfc0_watchhi (uint32_t sel)
1.1.1.7   root      872: {
                    873:     return env->CP0_WatchHi[sel];
                    874: }
                    875: 
1.1.1.8   root      876: target_ulong helper_mfc0_debug (void)
1.1.1.7   root      877: {
                    878:     target_ulong t0 = env->CP0_Debug;
                    879:     if (env->hflags & MIPS_HFLAG_DM)
                    880:         t0 |= 1 << CP0DB_DM;
                    881: 
                    882:     return t0;
                    883: }
                    884: 
1.1.1.8   root      885: target_ulong helper_mftc0_debug(void)
1.1.1.7   root      886: {
                    887:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                    888:     int32_t tcstatus;
                    889: 
                    890:     if (other_tc == env->current_tc)
                    891:         tcstatus = env->active_tc.CP0_Debug_tcstatus;
                    892:     else
                    893:         tcstatus = env->tcs[other_tc].CP0_Debug_tcstatus;
                    894: 
                    895:     /* XXX: Might be wrong, check with EJTAG spec. */
                    896:     return (env->CP0_Debug & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
                    897:             (tcstatus & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
                    898: }
                    899: 
                    900: #if defined(TARGET_MIPS64)
1.1.1.8   root      901: target_ulong helper_dmfc0_tcrestart (void)
1.1.1.7   root      902: {
                    903:     return env->active_tc.PC;
                    904: }
                    905: 
1.1.1.8   root      906: target_ulong helper_dmfc0_tchalt (void)
1.1.1.7   root      907: {
                    908:     return env->active_tc.CP0_TCHalt;
                    909: }
                    910: 
1.1.1.8   root      911: target_ulong helper_dmfc0_tccontext (void)
1.1.1.7   root      912: {
                    913:     return env->active_tc.CP0_TCContext;
                    914: }
                    915: 
1.1.1.8   root      916: target_ulong helper_dmfc0_tcschedule (void)
1.1.1.7   root      917: {
                    918:     return env->active_tc.CP0_TCSchedule;
                    919: }
                    920: 
1.1.1.8   root      921: target_ulong helper_dmfc0_tcschefback (void)
1.1.1.7   root      922: {
                    923:     return env->active_tc.CP0_TCScheFBack;
                    924: }
                    925: 
1.1.1.8   root      926: target_ulong helper_dmfc0_lladdr (void)
1.1.1.7   root      927: {
1.1.1.9   root      928:     return env->lladdr >> env->CP0_LLAddr_shift;
1.1.1.7   root      929: }
                    930: 
1.1.1.8   root      931: target_ulong helper_dmfc0_watchlo (uint32_t sel)
1.1.1.7   root      932: {
                    933:     return env->CP0_WatchLo[sel];
                    934: }
                    935: #endif /* TARGET_MIPS64 */
                    936: 
1.1.1.8   root      937: void helper_mtc0_index (target_ulong arg1)
1.1.1.7   root      938: {
                    939:     int num = 1;
                    940:     unsigned int tmp = env->tlb->nb_tlb;
                    941: 
                    942:     do {
                    943:         tmp >>= 1;
                    944:         num <<= 1;
                    945:     } while (tmp);
1.1.1.8   root      946:     env->CP0_Index = (env->CP0_Index & 0x80000000) | (arg1 & (num - 1));
1.1.1.7   root      947: }
                    948: 
1.1.1.8   root      949: void helper_mtc0_mvpcontrol (target_ulong arg1)
1.1.1.7   root      950: {
                    951:     uint32_t mask = 0;
                    952:     uint32_t newval;
                    953: 
                    954:     if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP))
                    955:         mask |= (1 << CP0MVPCo_CPA) | (1 << CP0MVPCo_VPC) |
                    956:                 (1 << CP0MVPCo_EVP);
                    957:     if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
                    958:         mask |= (1 << CP0MVPCo_STLB);
1.1.1.8   root      959:     newval = (env->mvp->CP0_MVPControl & ~mask) | (arg1 & mask);
1.1.1.7   root      960: 
                    961:     // TODO: Enable/disable shared TLB, enable/disable VPEs.
                    962: 
                    963:     env->mvp->CP0_MVPControl = newval;
                    964: }
                    965: 
1.1.1.8   root      966: void helper_mtc0_vpecontrol (target_ulong arg1)
1.1.1.7   root      967: {
                    968:     uint32_t mask;
                    969:     uint32_t newval;
                    970: 
                    971:     mask = (1 << CP0VPECo_YSI) | (1 << CP0VPECo_GSI) |
                    972:            (1 << CP0VPECo_TE) | (0xff << CP0VPECo_TargTC);
1.1.1.8   root      973:     newval = (env->CP0_VPEControl & ~mask) | (arg1 & mask);
1.1.1.7   root      974: 
                    975:     /* Yield scheduler intercept not implemented. */
                    976:     /* Gating storage scheduler intercept not implemented. */
                    977: 
                    978:     // TODO: Enable/disable TCs.
                    979: 
                    980:     env->CP0_VPEControl = newval;
                    981: }
                    982: 
1.1.1.8   root      983: void helper_mtc0_vpeconf0 (target_ulong arg1)
1.1.1.7   root      984: {
                    985:     uint32_t mask = 0;
                    986:     uint32_t newval;
                    987: 
                    988:     if (env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) {
                    989:         if (env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))
                    990:             mask |= (0xff << CP0VPEC0_XTC);
                    991:         mask |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
                    992:     }
1.1.1.8   root      993:     newval = (env->CP0_VPEConf0 & ~mask) | (arg1 & mask);
1.1.1.7   root      994: 
                    995:     // TODO: TC exclusive handling due to ERL/EXL.
                    996: 
                    997:     env->CP0_VPEConf0 = newval;
                    998: }
                    999: 
1.1.1.8   root     1000: void helper_mtc0_vpeconf1 (target_ulong arg1)
1.1.1.7   root     1001: {
                   1002:     uint32_t mask = 0;
                   1003:     uint32_t newval;
                   1004: 
                   1005:     if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
                   1006:         mask |= (0xff << CP0VPEC1_NCX) | (0xff << CP0VPEC1_NCP2) |
                   1007:                 (0xff << CP0VPEC1_NCP1);
1.1.1.8   root     1008:     newval = (env->CP0_VPEConf1 & ~mask) | (arg1 & mask);
1.1.1.7   root     1009: 
                   1010:     /* UDI not implemented. */
                   1011:     /* CP2 not implemented. */
                   1012: 
                   1013:     // TODO: Handle FPU (CP1) binding.
                   1014: 
                   1015:     env->CP0_VPEConf1 = newval;
                   1016: }
                   1017: 
1.1.1.8   root     1018: void helper_mtc0_yqmask (target_ulong arg1)
1.1.1.7   root     1019: {
                   1020:     /* Yield qualifier inputs not implemented. */
                   1021:     env->CP0_YQMask = 0x00000000;
                   1022: }
                   1023: 
1.1.1.8   root     1024: void helper_mtc0_vpeopt (target_ulong arg1)
1.1.1.7   root     1025: {
1.1.1.8   root     1026:     env->CP0_VPEOpt = arg1 & 0x0000ffff;
1.1.1.7   root     1027: }
                   1028: 
1.1.1.8   root     1029: void helper_mtc0_entrylo0 (target_ulong arg1)
1.1.1.7   root     1030: {
                   1031:     /* Large physaddr (PABITS) not implemented */
                   1032:     /* 1k pages not implemented */
1.1.1.8   root     1033:     env->CP0_EntryLo0 = arg1 & 0x3FFFFFFF;
1.1.1.7   root     1034: }
                   1035: 
1.1.1.8   root     1036: void helper_mtc0_tcstatus (target_ulong arg1)
1.1.1.7   root     1037: {
                   1038:     uint32_t mask = env->CP0_TCStatus_rw_bitmask;
                   1039:     uint32_t newval;
                   1040: 
1.1.1.8   root     1041:     newval = (env->active_tc.CP0_TCStatus & ~mask) | (arg1 & mask);
1.1.1.7   root     1042: 
                   1043:     // TODO: Sync with CP0_Status.
                   1044: 
                   1045:     env->active_tc.CP0_TCStatus = newval;
                   1046: }
                   1047: 
1.1.1.8   root     1048: void helper_mttc0_tcstatus (target_ulong arg1)
1.1.1.7   root     1049: {
                   1050:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1051: 
                   1052:     // TODO: Sync with CP0_Status.
                   1053: 
                   1054:     if (other_tc == env->current_tc)
1.1.1.8   root     1055:         env->active_tc.CP0_TCStatus = arg1;
1.1.1.7   root     1056:     else
1.1.1.8   root     1057:         env->tcs[other_tc].CP0_TCStatus = arg1;
1.1.1.7   root     1058: }
                   1059: 
1.1.1.8   root     1060: void helper_mtc0_tcbind (target_ulong arg1)
1.1.1.7   root     1061: {
                   1062:     uint32_t mask = (1 << CP0TCBd_TBE);
                   1063:     uint32_t newval;
                   1064: 
                   1065:     if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
                   1066:         mask |= (1 << CP0TCBd_CurVPE);
1.1.1.8   root     1067:     newval = (env->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
1.1.1.7   root     1068:     env->active_tc.CP0_TCBind = newval;
                   1069: }
                   1070: 
1.1.1.8   root     1071: void helper_mttc0_tcbind (target_ulong arg1)
1.1.1.7   root     1072: {
                   1073:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1074:     uint32_t mask = (1 << CP0TCBd_TBE);
                   1075:     uint32_t newval;
                   1076: 
                   1077:     if (env->mvp->CP0_MVPControl & (1 << CP0MVPCo_VPC))
                   1078:         mask |= (1 << CP0TCBd_CurVPE);
                   1079:     if (other_tc == env->current_tc) {
1.1.1.8   root     1080:         newval = (env->active_tc.CP0_TCBind & ~mask) | (arg1 & mask);
1.1.1.7   root     1081:         env->active_tc.CP0_TCBind = newval;
                   1082:     } else {
1.1.1.8   root     1083:         newval = (env->tcs[other_tc].CP0_TCBind & ~mask) | (arg1 & mask);
1.1.1.7   root     1084:         env->tcs[other_tc].CP0_TCBind = newval;
                   1085:     }
                   1086: }
                   1087: 
1.1.1.8   root     1088: void helper_mtc0_tcrestart (target_ulong arg1)
1.1.1.7   root     1089: {
1.1.1.8   root     1090:     env->active_tc.PC = arg1;
1.1.1.7   root     1091:     env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
1.1.1.9   root     1092:     env->lladdr = 0ULL;
1.1.1.7   root     1093:     /* MIPS16 not implemented. */
                   1094: }
                   1095: 
1.1.1.8   root     1096: void helper_mttc0_tcrestart (target_ulong arg1)
1.1.1.7   root     1097: {
                   1098:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1099: 
                   1100:     if (other_tc == env->current_tc) {
1.1.1.8   root     1101:         env->active_tc.PC = arg1;
1.1.1.7   root     1102:         env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
1.1.1.9   root     1103:         env->lladdr = 0ULL;
1.1.1.7   root     1104:         /* MIPS16 not implemented. */
                   1105:     } else {
1.1.1.8   root     1106:         env->tcs[other_tc].PC = arg1;
1.1.1.7   root     1107:         env->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
1.1.1.9   root     1108:         env->lladdr = 0ULL;
1.1.1.7   root     1109:         /* MIPS16 not implemented. */
                   1110:     }
                   1111: }
                   1112: 
1.1.1.8   root     1113: void helper_mtc0_tchalt (target_ulong arg1)
1.1.1.7   root     1114: {
1.1.1.8   root     1115:     env->active_tc.CP0_TCHalt = arg1 & 0x1;
1.1.1.7   root     1116: 
                   1117:     // TODO: Halt TC / Restart (if allocated+active) TC.
                   1118: }
                   1119: 
1.1.1.8   root     1120: void helper_mttc0_tchalt (target_ulong arg1)
1.1.1.7   root     1121: {
                   1122:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1123: 
                   1124:     // TODO: Halt TC / Restart (if allocated+active) TC.
                   1125: 
                   1126:     if (other_tc == env->current_tc)
1.1.1.8   root     1127:         env->active_tc.CP0_TCHalt = arg1;
1.1.1.7   root     1128:     else
1.1.1.8   root     1129:         env->tcs[other_tc].CP0_TCHalt = arg1;
1.1.1.7   root     1130: }
                   1131: 
1.1.1.8   root     1132: void helper_mtc0_tccontext (target_ulong arg1)
1.1.1.7   root     1133: {
1.1.1.8   root     1134:     env->active_tc.CP0_TCContext = arg1;
1.1.1.7   root     1135: }
                   1136: 
1.1.1.8   root     1137: void helper_mttc0_tccontext (target_ulong arg1)
1.1.1.7   root     1138: {
                   1139:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1140: 
                   1141:     if (other_tc == env->current_tc)
1.1.1.8   root     1142:         env->active_tc.CP0_TCContext = arg1;
1.1.1.7   root     1143:     else
1.1.1.8   root     1144:         env->tcs[other_tc].CP0_TCContext = arg1;
1.1.1.7   root     1145: }
                   1146: 
1.1.1.8   root     1147: void helper_mtc0_tcschedule (target_ulong arg1)
1.1.1.7   root     1148: {
1.1.1.8   root     1149:     env->active_tc.CP0_TCSchedule = arg1;
1.1.1.7   root     1150: }
                   1151: 
1.1.1.8   root     1152: void helper_mttc0_tcschedule (target_ulong arg1)
1.1.1.7   root     1153: {
                   1154:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1155: 
                   1156:     if (other_tc == env->current_tc)
1.1.1.8   root     1157:         env->active_tc.CP0_TCSchedule = arg1;
1.1.1.7   root     1158:     else
1.1.1.8   root     1159:         env->tcs[other_tc].CP0_TCSchedule = arg1;
1.1.1.5   root     1160: }
                   1161: 
1.1.1.8   root     1162: void helper_mtc0_tcschefback (target_ulong arg1)
1.1.1.5   root     1163: {
1.1.1.8   root     1164:     env->active_tc.CP0_TCScheFBack = arg1;
1.1.1.5   root     1165: }
                   1166: 
1.1.1.8   root     1167: void helper_mttc0_tcschefback (target_ulong arg1)
1.1.1.5   root     1168: {
1.1.1.7   root     1169:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.5   root     1170: 
1.1.1.7   root     1171:     if (other_tc == env->current_tc)
1.1.1.8   root     1172:         env->active_tc.CP0_TCScheFBack = arg1;
1.1.1.7   root     1173:     else
1.1.1.8   root     1174:         env->tcs[other_tc].CP0_TCScheFBack = arg1;
1.1.1.5   root     1175: }
                   1176: 
1.1.1.8   root     1177: void helper_mtc0_entrylo1 (target_ulong arg1)
1.1.1.5   root     1178: {
1.1.1.7   root     1179:     /* Large physaddr (PABITS) not implemented */
                   1180:     /* 1k pages not implemented */
1.1.1.8   root     1181:     env->CP0_EntryLo1 = arg1 & 0x3FFFFFFF;
1.1.1.5   root     1182: }
                   1183: 
1.1.1.8   root     1184: void helper_mtc0_context (target_ulong arg1)
1.1.1.5   root     1185: {
1.1.1.8   root     1186:     env->CP0_Context = (env->CP0_Context & 0x007FFFFF) | (arg1 & ~0x007FFFFF);
1.1.1.5   root     1187: }
                   1188: 
1.1.1.8   root     1189: void helper_mtc0_pagemask (target_ulong arg1)
1.1.1.5   root     1190: {
1.1.1.7   root     1191:     /* 1k pages not implemented */
1.1.1.8   root     1192:     env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1.1.1.5   root     1193: }
                   1194: 
1.1.1.8   root     1195: void helper_mtc0_pagegrain (target_ulong arg1)
1.1.1.5   root     1196: {
1.1.1.7   root     1197:     /* SmartMIPS not implemented */
                   1198:     /* Large physaddr (PABITS) not implemented */
                   1199:     /* 1k pages not implemented */
                   1200:     env->CP0_PageGrain = 0;
1.1.1.5   root     1201: }
                   1202: 
1.1.1.8   root     1203: void helper_mtc0_wired (target_ulong arg1)
1.1.1.5   root     1204: {
1.1.1.8   root     1205:     env->CP0_Wired = arg1 % env->tlb->nb_tlb;
1.1.1.6   root     1206: }
                   1207: 
1.1.1.8   root     1208: void helper_mtc0_srsconf0 (target_ulong arg1)
1.1.1.6   root     1209: {
1.1.1.8   root     1210:     env->CP0_SRSConf0 |= arg1 & env->CP0_SRSConf0_rw_bitmask;
1.1.1.6   root     1211: }
                   1212: 
1.1.1.8   root     1213: void helper_mtc0_srsconf1 (target_ulong arg1)
1.1.1.6   root     1214: {
1.1.1.8   root     1215:     env->CP0_SRSConf1 |= arg1 & env->CP0_SRSConf1_rw_bitmask;
1.1.1.5   root     1216: }
1.1.1.6   root     1217: 
1.1.1.8   root     1218: void helper_mtc0_srsconf2 (target_ulong arg1)
1.1.1.6   root     1219: {
1.1.1.8   root     1220:     env->CP0_SRSConf2 |= arg1 & env->CP0_SRSConf2_rw_bitmask;
1.1.1.6   root     1221: }
                   1222: 
1.1.1.8   root     1223: void helper_mtc0_srsconf3 (target_ulong arg1)
1.1.1.6   root     1224: {
1.1.1.8   root     1225:     env->CP0_SRSConf3 |= arg1 & env->CP0_SRSConf3_rw_bitmask;
1.1.1.6   root     1226: }
                   1227: 
1.1.1.8   root     1228: void helper_mtc0_srsconf4 (target_ulong arg1)
1.1       root     1229: {
1.1.1.8   root     1230:     env->CP0_SRSConf4 |= arg1 & env->CP0_SRSConf4_rw_bitmask;
1.1       root     1231: }
                   1232: 
1.1.1.8   root     1233: void helper_mtc0_hwrena (target_ulong arg1)
1.1       root     1234: {
1.1.1.8   root     1235:     env->CP0_HWREna = arg1 & 0x0000000F;
1.1       root     1236: }
                   1237: 
1.1.1.8   root     1238: void helper_mtc0_count (target_ulong arg1)
1.1       root     1239: {
1.1.1.8   root     1240:     cpu_mips_store_count(env, arg1);
1.1       root     1241: }
                   1242: 
1.1.1.8   root     1243: void helper_mtc0_entryhi (target_ulong arg1)
1.1       root     1244: {
1.1.1.7   root     1245:     target_ulong old, val;
                   1246: 
                   1247:     /* 1k pages not implemented */
1.1.1.8   root     1248:     val = arg1 & ((TARGET_PAGE_MASK << 1) | 0xFF);
1.1.1.7   root     1249: #if defined(TARGET_MIPS64)
                   1250:     val &= env->SEGMask;
                   1251: #endif
                   1252:     old = env->CP0_EntryHi;
                   1253:     env->CP0_EntryHi = val;
                   1254:     if (env->CP0_Config3 & (1 << CP0C3_MT)) {
                   1255:         uint32_t tcst = env->active_tc.CP0_TCStatus & ~0xff;
                   1256:         env->active_tc.CP0_TCStatus = tcst | (val & 0xff);
                   1257:     }
                   1258:     /* If the ASID changes, flush qemu's TLB.  */
                   1259:     if ((old & 0xFF) != (val & 0xFF))
                   1260:         cpu_mips_tlb_flush(env, 1);
                   1261: }
                   1262: 
1.1.1.8   root     1263: void helper_mttc0_entryhi(target_ulong arg1)
1.1.1.7   root     1264: {
                   1265:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1266:     int32_t tcstatus;
                   1267: 
1.1.1.8   root     1268:     env->CP0_EntryHi = (env->CP0_EntryHi & 0xff) | (arg1 & ~0xff);
1.1.1.7   root     1269:     if (other_tc == env->current_tc) {
1.1.1.8   root     1270:         tcstatus = (env->active_tc.CP0_TCStatus & ~0xff) | (arg1 & 0xff);
1.1.1.7   root     1271:         env->active_tc.CP0_TCStatus = tcstatus;
                   1272:     } else {
1.1.1.8   root     1273:         tcstatus = (env->tcs[other_tc].CP0_TCStatus & ~0xff) | (arg1 & 0xff);
1.1.1.7   root     1274:         env->tcs[other_tc].CP0_TCStatus = tcstatus;
                   1275:     }
1.1       root     1276: }
                   1277: 
1.1.1.8   root     1278: void helper_mtc0_compare (target_ulong arg1)
1.1       root     1279: {
1.1.1.8   root     1280:     cpu_mips_store_compare(env, arg1);
1.1       root     1281: }
                   1282: 
1.1.1.8   root     1283: void helper_mtc0_status (target_ulong arg1)
1.1       root     1284: {
1.1.1.7   root     1285:     uint32_t val, old;
                   1286:     uint32_t mask = env->CP0_Status_rw_bitmask;
1.1       root     1287: 
1.1.1.8   root     1288:     val = arg1 & mask;
1.1.1.7   root     1289:     old = env->CP0_Status;
                   1290:     env->CP0_Status = (env->CP0_Status & ~mask) | val;
                   1291:     compute_hflags(env);
1.1.1.8   root     1292:     if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
                   1293:         qemu_log("Status %08x (%08x) => %08x (%08x) Cause %08x",
                   1294:                 old, old & env->CP0_Cause & CP0Ca_IP_mask,
                   1295:                 val, val & env->CP0_Cause & CP0Ca_IP_mask,
                   1296:                 env->CP0_Cause);
                   1297:         switch (env->hflags & MIPS_HFLAG_KSU) {
                   1298:         case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
                   1299:         case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
                   1300:         case MIPS_HFLAG_KM: qemu_log("\n"); break;
                   1301:         default: cpu_abort(env, "Invalid MMU mode!\n"); break;
1.1.1.9   root     1302:         }
1.1.1.8   root     1303:     }
1.1       root     1304: }
                   1305: 
1.1.1.8   root     1306: void helper_mttc0_status(target_ulong arg1)
1.1       root     1307: {
1.1.1.7   root     1308:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1309:     int32_t tcstatus = env->tcs[other_tc].CP0_TCStatus;
1.1       root     1310: 
1.1.1.8   root     1311:     env->CP0_Status = arg1 & ~0xf1000018;
                   1312:     tcstatus = (tcstatus & ~(0xf << CP0TCSt_TCU0)) | (arg1 & (0xf << CP0St_CU0));
                   1313:     tcstatus = (tcstatus & ~(1 << CP0TCSt_TMX)) | ((arg1 & (1 << CP0St_MX)) << (CP0TCSt_TMX - CP0St_MX));
                   1314:     tcstatus = (tcstatus & ~(0x3 << CP0TCSt_TKSU)) | ((arg1 & (0x3 << CP0St_KSU)) << (CP0TCSt_TKSU - CP0St_KSU));
1.1.1.7   root     1315:     if (other_tc == env->current_tc)
                   1316:         env->active_tc.CP0_TCStatus = tcstatus;
                   1317:     else
                   1318:         env->tcs[other_tc].CP0_TCStatus = tcstatus;
1.1       root     1319: }
                   1320: 
1.1.1.8   root     1321: void helper_mtc0_intctl (target_ulong arg1)
1.1       root     1322: {
1.1.1.7   root     1323:     /* vectored interrupts not implemented, no performance counters. */
1.1.1.8   root     1324:     env->CP0_IntCtl = (env->CP0_IntCtl & ~0x000002e0) | (arg1 & 0x000002e0);
1.1       root     1325: }
                   1326: 
1.1.1.8   root     1327: void helper_mtc0_srsctl (target_ulong arg1)
1.1.1.6   root     1328: {
1.1.1.7   root     1329:     uint32_t mask = (0xf << CP0SRSCtl_ESS) | (0xf << CP0SRSCtl_PSS);
1.1.1.8   root     1330:     env->CP0_SRSCtl = (env->CP0_SRSCtl & ~mask) | (arg1 & mask);
1.1.1.6   root     1331: }
                   1332: 
1.1.1.8   root     1333: void helper_mtc0_cause (target_ulong arg1)
1.1.1.6   root     1334: {
1.1.1.7   root     1335:     uint32_t mask = 0x00C00300;
                   1336:     uint32_t old = env->CP0_Cause;
1.1.1.11! root     1337:     int i;
1.1.1.7   root     1338: 
                   1339:     if (env->insn_flags & ISA_MIPS32R2)
                   1340:         mask |= 1 << CP0Ca_DC;
                   1341: 
1.1.1.8   root     1342:     env->CP0_Cause = (env->CP0_Cause & ~mask) | (arg1 & mask);
1.1.1.7   root     1343: 
                   1344:     if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) {
                   1345:         if (env->CP0_Cause & (1 << CP0Ca_DC))
                   1346:             cpu_mips_stop_count(env);
                   1347:         else
                   1348:             cpu_mips_start_count(env);
                   1349:     }
                   1350: 
1.1.1.11! root     1351:     /* Set/reset software interrupts */
        !          1352:     for (i = 0 ; i < 2 ; i++) {
        !          1353:         if ((old ^ env->CP0_Cause) & (1 << (CP0Ca_IP + i))) {
        !          1354:             cpu_mips_soft_irq(env, i, env->CP0_Cause & (1 << (CP0Ca_IP + i)));
        !          1355:         }
1.1.1.7   root     1356:     }
1.1.1.6   root     1357: }
                   1358: 
1.1.1.8   root     1359: void helper_mtc0_ebase (target_ulong arg1)
1.1.1.6   root     1360: {
1.1.1.7   root     1361:     /* vectored interrupts not implemented */
                   1362:     /* Multi-CPU not implemented */
1.1.1.8   root     1363:     env->CP0_EBase = 0x80000000 | (arg1 & 0x3FFFF000);
1.1.1.6   root     1364: }
                   1365: 
1.1.1.8   root     1366: void helper_mtc0_config0 (target_ulong arg1)
1.1.1.6   root     1367: {
1.1.1.8   root     1368:     env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (arg1 & 0x00000007);
1.1.1.6   root     1369: }
                   1370: 
1.1.1.8   root     1371: void helper_mtc0_config2 (target_ulong arg1)
1.1.1.6   root     1372: {
1.1.1.7   root     1373:     /* tertiary/secondary caches not implemented */
                   1374:     env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1.1.1.6   root     1375: }
                   1376: 
1.1.1.9   root     1377: void helper_mtc0_lladdr (target_ulong arg1)
                   1378: {
                   1379:     target_long mask = env->CP0_LLAddr_rw_bitmask;
                   1380:     arg1 = arg1 << env->CP0_LLAddr_shift;
                   1381:     env->lladdr = (env->lladdr & ~mask) | (arg1 & mask);
                   1382: }
                   1383: 
1.1.1.8   root     1384: void helper_mtc0_watchlo (target_ulong arg1, uint32_t sel)
1.1.1.6   root     1385: {
1.1.1.7   root     1386:     /* Watch exceptions for instructions, data loads, data stores
                   1387:        not implemented. */
1.1.1.8   root     1388:     env->CP0_WatchLo[sel] = (arg1 & ~0x7);
1.1.1.6   root     1389: }
                   1390: 
1.1.1.8   root     1391: void helper_mtc0_watchhi (target_ulong arg1, uint32_t sel)
1.1.1.6   root     1392: {
1.1.1.8   root     1393:     env->CP0_WatchHi[sel] = (arg1 & 0x40FF0FF8);
                   1394:     env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7);
1.1.1.6   root     1395: }
                   1396: 
1.1.1.8   root     1397: void helper_mtc0_xcontext (target_ulong arg1)
1.1.1.6   root     1398: {
1.1.1.7   root     1399:     target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1.1.1.8   root     1400:     env->CP0_XContext = (env->CP0_XContext & mask) | (arg1 & ~mask);
1.1.1.6   root     1401: }
                   1402: 
1.1.1.8   root     1403: void helper_mtc0_framemask (target_ulong arg1)
1.1.1.6   root     1404: {
1.1.1.8   root     1405:     env->CP0_Framemask = arg1; /* XXX */
1.1.1.6   root     1406: }
                   1407: 
1.1.1.8   root     1408: void helper_mtc0_debug (target_ulong arg1)
1.1.1.6   root     1409: {
1.1.1.8   root     1410:     env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (arg1 & 0x13300120);
                   1411:     if (arg1 & (1 << CP0DB_DM))
1.1.1.7   root     1412:         env->hflags |= MIPS_HFLAG_DM;
                   1413:     else
                   1414:         env->hflags &= ~MIPS_HFLAG_DM;
1.1.1.6   root     1415: }
                   1416: 
1.1.1.8   root     1417: void helper_mttc0_debug(target_ulong arg1)
1.1.1.6   root     1418: {
1.1.1.7   root     1419:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.8   root     1420:     uint32_t val = arg1 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1.1.1.7   root     1421: 
                   1422:     /* XXX: Might be wrong, check with EJTAG spec. */
                   1423:     if (other_tc == env->current_tc)
                   1424:         env->active_tc.CP0_Debug_tcstatus = val;
                   1425:     else
                   1426:         env->tcs[other_tc].CP0_Debug_tcstatus = val;
                   1427:     env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1.1.1.8   root     1428:                      (arg1 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1.1.1.6   root     1429: }
                   1430: 
1.1.1.8   root     1431: void helper_mtc0_performance0 (target_ulong arg1)
1.1.1.6   root     1432: {
1.1.1.8   root     1433:     env->CP0_Performance0 = arg1 & 0x000007ff;
1.1.1.6   root     1434: }
                   1435: 
1.1.1.8   root     1436: void helper_mtc0_taglo (target_ulong arg1)
1.1.1.5   root     1437: {
1.1.1.8   root     1438:     env->CP0_TagLo = arg1 & 0xFFFFFCF6;
1.1.1.5   root     1439: }
                   1440: 
1.1.1.8   root     1441: void helper_mtc0_datalo (target_ulong arg1)
1.1.1.5   root     1442: {
1.1.1.8   root     1443:     env->CP0_DataLo = arg1; /* XXX */
1.1.1.5   root     1444: }
                   1445: 
1.1.1.8   root     1446: void helper_mtc0_taghi (target_ulong arg1)
1.1.1.5   root     1447: {
1.1.1.8   root     1448:     env->CP0_TagHi = arg1; /* XXX */
1.1.1.5   root     1449: }
                   1450: 
1.1.1.8   root     1451: void helper_mtc0_datahi (target_ulong arg1)
1.1.1.5   root     1452: {
1.1.1.8   root     1453:     env->CP0_DataHi = arg1; /* XXX */
1.1.1.5   root     1454: }
                   1455: 
1.1.1.7   root     1456: /* MIPS MT functions */
1.1.1.8   root     1457: target_ulong helper_mftgpr(uint32_t sel)
1.1.1.5   root     1458: {
1.1.1.7   root     1459:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1460: 
                   1461:     if (other_tc == env->current_tc)
                   1462:         return env->active_tc.gpr[sel];
                   1463:     else
                   1464:         return env->tcs[other_tc].gpr[sel];
1.1.1.5   root     1465: }
                   1466: 
1.1.1.8   root     1467: target_ulong helper_mftlo(uint32_t sel)
1.1.1.5   root     1468: {
1.1.1.7   root     1469:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1470: 
                   1471:     if (other_tc == env->current_tc)
                   1472:         return env->active_tc.LO[sel];
                   1473:     else
                   1474:         return env->tcs[other_tc].LO[sel];
1.1.1.5   root     1475: }
                   1476: 
1.1.1.8   root     1477: target_ulong helper_mfthi(uint32_t sel)
1.1.1.5   root     1478: {
1.1.1.7   root     1479:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1480: 
                   1481:     if (other_tc == env->current_tc)
                   1482:         return env->active_tc.HI[sel];
                   1483:     else
                   1484:         return env->tcs[other_tc].HI[sel];
1.1.1.5   root     1485: }
                   1486: 
1.1.1.8   root     1487: target_ulong helper_mftacx(uint32_t sel)
1.1.1.5   root     1488: {
1.1.1.7   root     1489:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1490: 
                   1491:     if (other_tc == env->current_tc)
                   1492:         return env->active_tc.ACX[sel];
                   1493:     else
                   1494:         return env->tcs[other_tc].ACX[sel];
1.1.1.2   root     1495: }
                   1496: 
1.1.1.8   root     1497: target_ulong helper_mftdsp(void)
1.1.1.2   root     1498: {
1.1.1.7   root     1499:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1500: 
                   1501:     if (other_tc == env->current_tc)
                   1502:         return env->active_tc.DSPControl;
                   1503:     else
                   1504:         return env->tcs[other_tc].DSPControl;
1.1.1.2   root     1505: }
                   1506: 
1.1.1.8   root     1507: void helper_mttgpr(target_ulong arg1, uint32_t sel)
1.1.1.2   root     1508: {
1.1.1.7   root     1509:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1510: 
                   1511:     if (other_tc == env->current_tc)
1.1.1.8   root     1512:         env->active_tc.gpr[sel] = arg1;
1.1.1.7   root     1513:     else
1.1.1.8   root     1514:         env->tcs[other_tc].gpr[sel] = arg1;
1.1.1.2   root     1515: }
                   1516: 
1.1.1.8   root     1517: void helper_mttlo(target_ulong arg1, uint32_t sel)
1.1.1.2   root     1518: {
1.1.1.7   root     1519:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1520: 
                   1521:     if (other_tc == env->current_tc)
1.1.1.8   root     1522:         env->active_tc.LO[sel] = arg1;
1.1.1.7   root     1523:     else
1.1.1.8   root     1524:         env->tcs[other_tc].LO[sel] = arg1;
1.1.1.2   root     1525: }
                   1526: 
1.1.1.8   root     1527: void helper_mtthi(target_ulong arg1, uint32_t sel)
1.1.1.2   root     1528: {
1.1.1.7   root     1529:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1530: 
                   1531:     if (other_tc == env->current_tc)
1.1.1.8   root     1532:         env->active_tc.HI[sel] = arg1;
1.1.1.7   root     1533:     else
1.1.1.8   root     1534:         env->tcs[other_tc].HI[sel] = arg1;
1.1.1.2   root     1535: }
1.1.1.5   root     1536: 
1.1.1.8   root     1537: void helper_mttacx(target_ulong arg1, uint32_t sel)
1.1.1.5   root     1538: {
1.1.1.7   root     1539:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.5   root     1540: 
1.1.1.7   root     1541:     if (other_tc == env->current_tc)
1.1.1.8   root     1542:         env->active_tc.ACX[sel] = arg1;
1.1.1.7   root     1543:     else
1.1.1.8   root     1544:         env->tcs[other_tc].ACX[sel] = arg1;
1.1.1.7   root     1545: }
1.1.1.2   root     1546: 
1.1.1.8   root     1547: void helper_mttdsp(target_ulong arg1)
1.1       root     1548: {
1.1.1.7   root     1549:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1550: 
                   1551:     if (other_tc == env->current_tc)
1.1.1.8   root     1552:         env->active_tc.DSPControl = arg1;
1.1.1.7   root     1553:     else
1.1.1.8   root     1554:         env->tcs[other_tc].DSPControl = arg1;
1.1.1.5   root     1555: }
1.1       root     1556: 
1.1.1.7   root     1557: /* MIPS MT functions */
1.1.1.8   root     1558: target_ulong helper_dmt(target_ulong arg1)
1.1.1.5   root     1559: {
1.1.1.7   root     1560:     // TODO
1.1.1.8   root     1561:     arg1 = 0;
                   1562:     // rt = arg1
1.1.1.7   root     1563: 
1.1.1.8   root     1564:     return arg1;
1.1       root     1565: }
                   1566: 
1.1.1.8   root     1567: target_ulong helper_emt(target_ulong arg1)
1.1       root     1568: {
1.1.1.7   root     1569:     // TODO
1.1.1.8   root     1570:     arg1 = 0;
                   1571:     // rt = arg1
1.1.1.7   root     1572: 
1.1.1.8   root     1573:     return arg1;
1.1.1.5   root     1574: }
1.1       root     1575: 
1.1.1.8   root     1576: target_ulong helper_dvpe(target_ulong arg1)
1.1.1.5   root     1577: {
1.1.1.7   root     1578:     // TODO
1.1.1.8   root     1579:     arg1 = 0;
                   1580:     // rt = arg1
1.1.1.7   root     1581: 
1.1.1.8   root     1582:     return arg1;
1.1       root     1583: }
                   1584: 
1.1.1.8   root     1585: target_ulong helper_evpe(target_ulong arg1)
1.1.1.4   root     1586: {
1.1.1.7   root     1587:     // TODO
1.1.1.8   root     1588:     arg1 = 0;
                   1589:     // rt = arg1
1.1.1.4   root     1590: 
1.1.1.8   root     1591:     return arg1;
1.1.1.7   root     1592: }
                   1593: #endif /* !CONFIG_USER_ONLY */
1.1.1.4   root     1594: 
1.1.1.8   root     1595: void helper_fork(target_ulong arg1, target_ulong arg2)
1.1.1.7   root     1596: {
1.1.1.8   root     1597:     // arg1 = rt, arg2 = rs
                   1598:     arg1 = 0;
1.1.1.7   root     1599:     // TODO: store to TC register
                   1600: }
                   1601: 
1.1.1.8   root     1602: target_ulong helper_yield(target_ulong arg1)
1.1.1.7   root     1603: {
1.1.1.8   root     1604:     if (arg1 < 0) {
1.1.1.7   root     1605:         /* No scheduling policy implemented. */
1.1.1.8   root     1606:         if (arg1 != -2) {
1.1.1.7   root     1607:             if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
                   1608:                 env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) {
                   1609:                 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
                   1610:                 env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
1.1.1.8   root     1611:                 helper_raise_exception(EXCP_THREAD);
1.1.1.7   root     1612:             }
                   1613:         }
1.1.1.8   root     1614:     } else if (arg1 == 0) {
1.1.1.7   root     1615:         if (0 /* TODO: TC underflow */) {
                   1616:             env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1.1.1.8   root     1617:             helper_raise_exception(EXCP_THREAD);
1.1.1.7   root     1618:         } else {
                   1619:             // TODO: Deallocate TC
                   1620:         }
1.1.1.8   root     1621:     } else if (arg1 > 0) {
1.1.1.7   root     1622:         /* Yield qualifier inputs not implemented. */
                   1623:         env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
                   1624:         env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
1.1.1.8   root     1625:         helper_raise_exception(EXCP_THREAD);
1.1.1.4   root     1626:     }
1.1.1.7   root     1627:     return env->CP0_YQMask;
1.1.1.4   root     1628: }
                   1629: 
1.1.1.7   root     1630: #ifndef CONFIG_USER_ONLY
1.1       root     1631: /* TLB management */
1.1.1.11! root     1632: static void cpu_mips_tlb_flush (CPUState *env, int flush_global)
1.1       root     1633: {
1.1.1.5   root     1634:     /* Flush qemu's TLB and discard all shadowed entries.  */
                   1635:     tlb_flush (env, flush_global);
1.1.1.6   root     1636:     env->tlb->tlb_in_use = env->tlb->nb_tlb;
1.1.1.5   root     1637: }
1.1       root     1638: 
1.1.1.6   root     1639: static void r4k_mips_tlb_flush_extra (CPUState *env, int first)
1.1.1.5   root     1640: {
                   1641:     /* Discard entries from env->tlb[first] onwards.  */
1.1.1.6   root     1642:     while (env->tlb->tlb_in_use > first) {
                   1643:         r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0);
1.1       root     1644:     }
                   1645: }
                   1646: 
1.1.1.6   root     1647: static void r4k_fill_tlb (int idx)
1.1       root     1648: {
1.1.1.6   root     1649:     r4k_tlb_t *tlb;
1.1       root     1650: 
                   1651:     /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
1.1.1.6   root     1652:     tlb = &env->tlb->mmu.r4k.tlb[idx];
                   1653:     tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
                   1654: #if defined(TARGET_MIPS64)
                   1655:     tlb->VPN &= env->SEGMask;
                   1656: #endif
1.1.1.3   root     1657:     tlb->ASID = env->CP0_EntryHi & 0xFF;
1.1.1.5   root     1658:     tlb->PageMask = env->CP0_PageMask;
1.1       root     1659:     tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
1.1.1.3   root     1660:     tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
                   1661:     tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
                   1662:     tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
1.1       root     1663:     tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
1.1.1.3   root     1664:     tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
                   1665:     tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
                   1666:     tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
1.1       root     1667:     tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
                   1668: }
                   1669: 
1.1.1.8   root     1670: void r4k_helper_tlbwi (void)
1.1       root     1671: {
1.1.1.7   root     1672:     int idx;
                   1673: 
                   1674:     idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
                   1675: 
1.1.1.5   root     1676:     /* Discard cached TLB entries.  We could avoid doing this if the
                   1677:        tlbwi is just upgrading access permissions on the current entry;
                   1678:        that might be a further win.  */
1.1.1.6   root     1679:     r4k_mips_tlb_flush_extra (env, env->tlb->nb_tlb);
1.1.1.5   root     1680: 
1.1.1.7   root     1681:     r4k_invalidate_tlb(env, idx, 0);
                   1682:     r4k_fill_tlb(idx);
1.1       root     1683: }
                   1684: 
1.1.1.8   root     1685: void r4k_helper_tlbwr (void)
1.1       root     1686: {
                   1687:     int r = cpu_mips_get_random(env);
                   1688: 
1.1.1.6   root     1689:     r4k_invalidate_tlb(env, r, 1);
                   1690:     r4k_fill_tlb(r);
1.1       root     1691: }
                   1692: 
1.1.1.8   root     1693: void r4k_helper_tlbp (void)
1.1       root     1694: {
1.1.1.6   root     1695:     r4k_tlb_t *tlb;
                   1696:     target_ulong mask;
1.1       root     1697:     target_ulong tag;
1.1.1.6   root     1698:     target_ulong VPN;
1.1       root     1699:     uint8_t ASID;
                   1700:     int i;
                   1701: 
1.1.1.4   root     1702:     ASID = env->CP0_EntryHi & 0xFF;
1.1.1.6   root     1703:     for (i = 0; i < env->tlb->nb_tlb; i++) {
                   1704:         tlb = &env->tlb->mmu.r4k.tlb[i];
                   1705:         /* 1k pages are not supported. */
                   1706:         mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
                   1707:         tag = env->CP0_EntryHi & ~mask;
                   1708:         VPN = tlb->VPN & ~mask;
1.1       root     1709:         /* Check ASID, virtual page number & size */
1.1.1.6   root     1710:         if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1.1       root     1711:             /* TLB match */
1.1.1.5   root     1712:             env->CP0_Index = i;
1.1       root     1713:             break;
                   1714:         }
                   1715:     }
1.1.1.6   root     1716:     if (i == env->tlb->nb_tlb) {
1.1.1.5   root     1717:         /* No match.  Discard any shadow entries, if any of them match.  */
1.1.1.6   root     1718:         for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) {
1.1.1.7   root     1719:             tlb = &env->tlb->mmu.r4k.tlb[i];
                   1720:             /* 1k pages are not supported. */
                   1721:             mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
                   1722:             tag = env->CP0_EntryHi & ~mask;
                   1723:             VPN = tlb->VPN & ~mask;
                   1724:             /* Check ASID, virtual page number & size */
                   1725:             if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1.1.1.6   root     1726:                 r4k_mips_tlb_flush_extra (env, i);
1.1.1.7   root     1727:                 break;
                   1728:             }
                   1729:         }
1.1.1.5   root     1730: 
                   1731:         env->CP0_Index |= 0x80000000;
1.1       root     1732:     }
                   1733: }
                   1734: 
1.1.1.8   root     1735: void r4k_helper_tlbr (void)
1.1       root     1736: {
1.1.1.6   root     1737:     r4k_tlb_t *tlb;
1.1.1.3   root     1738:     uint8_t ASID;
1.1.1.7   root     1739:     int idx;
1.1       root     1740: 
1.1.1.3   root     1741:     ASID = env->CP0_EntryHi & 0xFF;
1.1.1.7   root     1742:     idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
                   1743:     tlb = &env->tlb->mmu.r4k.tlb[idx];
1.1.1.2   root     1744: 
                   1745:     /* If this will change the current ASID, flush qemu's TLB.  */
1.1.1.5   root     1746:     if (ASID != tlb->ASID)
                   1747:         cpu_mips_tlb_flush (env, 1);
                   1748: 
1.1.1.6   root     1749:     r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
1.1.1.2   root     1750: 
1.1       root     1751:     env->CP0_EntryHi = tlb->VPN | tlb->ASID;
1.1.1.5   root     1752:     env->CP0_PageMask = tlb->PageMask;
                   1753:     env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
                   1754:                         (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
                   1755:     env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
                   1756:                         (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
1.1       root     1757: }
                   1758: 
1.1.1.8   root     1759: void helper_tlbwi(void)
1.1.1.7   root     1760: {
1.1.1.8   root     1761:     env->tlb->helper_tlbwi();
1.1.1.7   root     1762: }
                   1763: 
1.1.1.8   root     1764: void helper_tlbwr(void)
1.1.1.7   root     1765: {
1.1.1.8   root     1766:     env->tlb->helper_tlbwr();
1.1.1.7   root     1767: }
                   1768: 
1.1.1.8   root     1769: void helper_tlbp(void)
1.1.1.7   root     1770: {
1.1.1.8   root     1771:     env->tlb->helper_tlbp();
1.1.1.7   root     1772: }
                   1773: 
1.1.1.8   root     1774: void helper_tlbr(void)
1.1.1.7   root     1775: {
1.1.1.8   root     1776:     env->tlb->helper_tlbr();
1.1.1.7   root     1777: }
                   1778: 
                   1779: /* Specials */
1.1.1.8   root     1780: target_ulong helper_di (void)
1.1.1.7   root     1781: {
                   1782:     target_ulong t0 = env->CP0_Status;
1.1.1.2   root     1783: 
1.1.1.7   root     1784:     env->CP0_Status = t0 & ~(1 << CP0St_IE);
                   1785:     return t0;
                   1786: }
                   1787: 
1.1.1.8   root     1788: target_ulong helper_ei (void)
1.1       root     1789: {
1.1.1.7   root     1790:     target_ulong t0 = env->CP0_Status;
                   1791: 
                   1792:     env->CP0_Status = t0 | (1 << CP0St_IE);
                   1793:     return t0;
1.1       root     1794: }
                   1795: 
1.1.1.7   root     1796: static void debug_pre_eret (void)
1.1       root     1797: {
1.1.1.7   root     1798:     if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
                   1799:         qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
                   1800:                 env->active_tc.PC, env->CP0_EPC);
                   1801:         if (env->CP0_Status & (1 << CP0St_ERL))
                   1802:             qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
                   1803:         if (env->hflags & MIPS_HFLAG_DM)
                   1804:             qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
                   1805:         qemu_log("\n");
1.1       root     1806:     }
                   1807: }
                   1808: 
1.1.1.7   root     1809: static void debug_post_eret (void)
1.1       root     1810: {
1.1.1.7   root     1811:     if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
                   1812:         qemu_log("  =>  PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
                   1813:                 env->active_tc.PC, env->CP0_EPC);
                   1814:         if (env->CP0_Status & (1 << CP0St_ERL))
                   1815:             qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
                   1816:         if (env->hflags & MIPS_HFLAG_DM)
                   1817:             qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
                   1818:         switch (env->hflags & MIPS_HFLAG_KSU) {
                   1819:         case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
                   1820:         case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
                   1821:         case MIPS_HFLAG_KM: qemu_log("\n"); break;
                   1822:         default: cpu_abort(env, "Invalid MMU mode!\n"); break;
                   1823:         }
                   1824:     }
1.1.1.6   root     1825: }
                   1826: 
1.1.1.11! root     1827: static void set_pc (target_ulong error_pc)
        !          1828: {
        !          1829:     env->active_tc.PC = error_pc & ~(target_ulong)1;
        !          1830:     if (error_pc & 1) {
        !          1831:         env->hflags |= MIPS_HFLAG_M16;
        !          1832:     } else {
        !          1833:         env->hflags &= ~(MIPS_HFLAG_M16);
        !          1834:     }
        !          1835: }
        !          1836: 
1.1.1.8   root     1837: void helper_eret (void)
1.1.1.6   root     1838: {
1.1.1.7   root     1839:     debug_pre_eret();
                   1840:     if (env->CP0_Status & (1 << CP0St_ERL)) {
1.1.1.11! root     1841:         set_pc(env->CP0_ErrorEPC);
1.1.1.7   root     1842:         env->CP0_Status &= ~(1 << CP0St_ERL);
                   1843:     } else {
1.1.1.11! root     1844:         set_pc(env->CP0_EPC);
1.1.1.7   root     1845:         env->CP0_Status &= ~(1 << CP0St_EXL);
1.1       root     1846:     }
1.1.1.7   root     1847:     compute_hflags(env);
                   1848:     debug_post_eret();
1.1.1.9   root     1849:     env->lladdr = 1;
1.1.1.7   root     1850: }
                   1851: 
1.1.1.8   root     1852: void helper_deret (void)
1.1.1.7   root     1853: {
                   1854:     debug_pre_eret();
1.1.1.11! root     1855:     set_pc(env->CP0_DEPC);
        !          1856: 
1.1.1.7   root     1857:     env->hflags &= MIPS_HFLAG_DM;
                   1858:     compute_hflags(env);
                   1859:     debug_post_eret();
1.1.1.9   root     1860:     env->lladdr = 1;
1.1.1.7   root     1861: }
                   1862: #endif /* !CONFIG_USER_ONLY */
                   1863: 
1.1.1.8   root     1864: target_ulong helper_rdhwr_cpunum(void)
1.1.1.7   root     1865: {
                   1866:     if ((env->hflags & MIPS_HFLAG_CP0) ||
                   1867:         (env->CP0_HWREna & (1 << 0)))
                   1868:         return env->CP0_EBase & 0x3ff;
                   1869:     else
1.1.1.8   root     1870:         helper_raise_exception(EXCP_RI);
1.1.1.7   root     1871: 
                   1872:     return 0;
                   1873: }
                   1874: 
1.1.1.8   root     1875: target_ulong helper_rdhwr_synci_step(void)
1.1.1.7   root     1876: {
                   1877:     if ((env->hflags & MIPS_HFLAG_CP0) ||
                   1878:         (env->CP0_HWREna & (1 << 1)))
                   1879:         return env->SYNCI_Step;
                   1880:     else
1.1.1.8   root     1881:         helper_raise_exception(EXCP_RI);
1.1.1.7   root     1882: 
                   1883:     return 0;
                   1884: }
                   1885: 
1.1.1.8   root     1886: target_ulong helper_rdhwr_cc(void)
1.1.1.7   root     1887: {
                   1888:     if ((env->hflags & MIPS_HFLAG_CP0) ||
                   1889:         (env->CP0_HWREna & (1 << 2)))
                   1890:         return env->CP0_Count;
                   1891:     else
1.1.1.8   root     1892:         helper_raise_exception(EXCP_RI);
1.1.1.7   root     1893: 
                   1894:     return 0;
                   1895: }
                   1896: 
1.1.1.8   root     1897: target_ulong helper_rdhwr_ccres(void)
1.1.1.7   root     1898: {
                   1899:     if ((env->hflags & MIPS_HFLAG_CP0) ||
                   1900:         (env->CP0_HWREna & (1 << 3)))
                   1901:         return env->CCRes;
                   1902:     else
1.1.1.8   root     1903:         helper_raise_exception(EXCP_RI);
1.1.1.7   root     1904: 
                   1905:     return 0;
1.1       root     1906: }
                   1907: 
1.1.1.8   root     1908: void helper_pmon (int function)
1.1       root     1909: {
                   1910:     function /= 2;
                   1911:     switch (function) {
                   1912:     case 2: /* TODO: char inbyte(int waitflag); */
1.1.1.7   root     1913:         if (env->active_tc.gpr[4] == 0)
                   1914:             env->active_tc.gpr[2] = -1;
1.1       root     1915:         /* Fall through */
                   1916:     case 11: /* TODO: char inbyte (void); */
1.1.1.7   root     1917:         env->active_tc.gpr[2] = -1;
1.1       root     1918:         break;
                   1919:     case 3:
                   1920:     case 12:
1.1.1.7   root     1921:         printf("%c", (char)(env->active_tc.gpr[4] & 0xFF));
1.1       root     1922:         break;
                   1923:     case 17:
                   1924:         break;
                   1925:     case 158:
                   1926:         {
1.1.1.7   root     1927:             unsigned char *fmt = (void *)(unsigned long)env->active_tc.gpr[4];
1.1       root     1928:             printf("%s", fmt);
                   1929:         }
                   1930:         break;
                   1931:     }
                   1932: }
                   1933: 
1.1.1.8   root     1934: void helper_wait (void)
1.1.1.7   root     1935: {
                   1936:     env->halted = 1;
1.1.1.8   root     1937:     helper_raise_exception(EXCP_HLT);
1.1.1.7   root     1938: }
                   1939: 
1.1.1.6   root     1940: #if !defined(CONFIG_USER_ONLY)
1.1       root     1941: 
1.1.1.2   root     1942: static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
                   1943: 
1.1       root     1944: #define MMUSUFFIX _mmu
1.1.1.2   root     1945: #define ALIGNED_ONLY
1.1       root     1946: 
                   1947: #define SHIFT 0
                   1948: #include "softmmu_template.h"
                   1949: 
                   1950: #define SHIFT 1
                   1951: #include "softmmu_template.h"
                   1952: 
                   1953: #define SHIFT 2
                   1954: #include "softmmu_template.h"
                   1955: 
                   1956: #define SHIFT 3
                   1957: #include "softmmu_template.h"
                   1958: 
1.1.1.2   root     1959: static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
                   1960: {
                   1961:     env->CP0_BadVAddr = addr;
                   1962:     do_restore_state (retaddr);
1.1.1.8   root     1963:     helper_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
1.1.1.2   root     1964: }
                   1965: 
1.1.1.6   root     1966: void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1.1       root     1967: {
                   1968:     TranslationBlock *tb;
                   1969:     CPUState *saved_env;
                   1970:     unsigned long pc;
                   1971:     int ret;
                   1972: 
                   1973:     /* XXX: hack to restore env in all cases, even if not called from
                   1974:        generated code */
                   1975:     saved_env = env;
                   1976:     env = cpu_single_env;
1.1.1.6   root     1977:     ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1.1       root     1978:     if (ret) {
                   1979:         if (retaddr) {
                   1980:             /* now we have a real cpu fault */
                   1981:             pc = (unsigned long)retaddr;
                   1982:             tb = tb_find_pc(pc);
                   1983:             if (tb) {
                   1984:                 /* the PC is inside the translated code. It means that we have
                   1985:                    a virtual CPU fault */
                   1986:                 cpu_restore_state(tb, env, pc, NULL);
                   1987:             }
                   1988:         }
1.1.1.8   root     1989:         helper_raise_exception_err(env->exception_index, env->error_code);
1.1       root     1990:     }
                   1991:     env = saved_env;
                   1992: }
                   1993: 
1.1.1.6   root     1994: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1.1.1.7   root     1995:                           int unused, int size)
1.1.1.6   root     1996: {
                   1997:     if (is_exec)
1.1.1.8   root     1998:         helper_raise_exception(EXCP_IBE);
1.1.1.6   root     1999:     else
1.1.1.8   root     2000:         helper_raise_exception(EXCP_DBE);
1.1.1.6   root     2001: }
1.1.1.7   root     2002: #endif /* !CONFIG_USER_ONLY */
1.1.1.6   root     2003: 
                   2004: /* Complex FPU operations which may need stack space. */
                   2005: 
                   2006: #define FLOAT_ONE32 make_float32(0x3f8 << 20)
                   2007: #define FLOAT_ONE64 make_float64(0x3ffULL << 52)
                   2008: #define FLOAT_TWO32 make_float32(1 << 30)
                   2009: #define FLOAT_TWO64 make_float64(1ULL << 62)
                   2010: #define FLOAT_QNAN32 0x7fbfffff
                   2011: #define FLOAT_QNAN64 0x7ff7ffffffffffffULL
                   2012: #define FLOAT_SNAN32 0x7fffffff
                   2013: #define FLOAT_SNAN64 0x7fffffffffffffffULL
                   2014: 
                   2015: /* convert MIPS rounding mode in FCR31 to IEEE library */
1.1.1.9   root     2016: static unsigned int ieee_rm[] = {
1.1.1.6   root     2017:     float_round_nearest_even,
                   2018:     float_round_to_zero,
                   2019:     float_round_up,
                   2020:     float_round_down
                   2021: };
                   2022: 
                   2023: #define RESTORE_ROUNDING_MODE \
1.1.1.7   root     2024:     set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], &env->active_fpu.fp_status)
1.1.1.6   root     2025: 
1.1.1.8   root     2026: #define RESTORE_FLUSH_MODE \
                   2027:     set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0, &env->active_fpu.fp_status);
                   2028: 
                   2029: target_ulong helper_cfc1 (uint32_t reg)
1.1.1.6   root     2030: {
1.1.1.8   root     2031:     target_ulong arg1;
1.1.1.7   root     2032: 
1.1.1.6   root     2033:     switch (reg) {
                   2034:     case 0:
1.1.1.8   root     2035:         arg1 = (int32_t)env->active_fpu.fcr0;
1.1.1.6   root     2036:         break;
                   2037:     case 25:
1.1.1.8   root     2038:         arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1);
1.1.1.6   root     2039:         break;
                   2040:     case 26:
1.1.1.8   root     2041:         arg1 = env->active_fpu.fcr31 & 0x0003f07c;
1.1.1.6   root     2042:         break;
                   2043:     case 28:
1.1.1.8   root     2044:         arg1 = (env->active_fpu.fcr31 & 0x00000f83) | ((env->active_fpu.fcr31 >> 22) & 0x4);
1.1.1.6   root     2045:         break;
                   2046:     default:
1.1.1.8   root     2047:         arg1 = (int32_t)env->active_fpu.fcr31;
1.1.1.6   root     2048:         break;
                   2049:     }
1.1.1.7   root     2050: 
1.1.1.8   root     2051:     return arg1;
1.1.1.6   root     2052: }
                   2053: 
1.1.1.8   root     2054: void helper_ctc1 (target_ulong arg1, uint32_t reg)
1.1.1.6   root     2055: {
                   2056:     switch(reg) {
                   2057:     case 25:
1.1.1.8   root     2058:         if (arg1 & 0xffffff00)
1.1.1.6   root     2059:             return;
1.1.1.8   root     2060:         env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | ((arg1 & 0xfe) << 24) |
                   2061:                      ((arg1 & 0x1) << 23);
1.1.1.6   root     2062:         break;
                   2063:     case 26:
1.1.1.8   root     2064:         if (arg1 & 0x007c0000)
1.1.1.6   root     2065:             return;
1.1.1.8   root     2066:         env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfffc0f83) | (arg1 & 0x0003f07c);
1.1.1.6   root     2067:         break;
                   2068:     case 28:
1.1.1.8   root     2069:         if (arg1 & 0x007c0000)
1.1.1.6   root     2070:             return;
1.1.1.8   root     2071:         env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfefff07c) | (arg1 & 0x00000f83) |
                   2072:                      ((arg1 & 0x4) << 22);
1.1.1.6   root     2073:         break;
                   2074:     case 31:
1.1.1.8   root     2075:         if (arg1 & 0x007c0000)
1.1.1.6   root     2076:             return;
1.1.1.8   root     2077:         env->active_fpu.fcr31 = arg1;
1.1.1.6   root     2078:         break;
                   2079:     default:
                   2080:         return;
                   2081:     }
                   2082:     /* set rounding mode */
                   2083:     RESTORE_ROUNDING_MODE;
1.1.1.8   root     2084:     /* set flush-to-zero mode */
                   2085:     RESTORE_FLUSH_MODE;
1.1.1.7   root     2086:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2087:     if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31))
1.1.1.8   root     2088:         helper_raise_exception(EXCP_FPE);
1.1.1.6   root     2089: }
                   2090: 
1.1.1.7   root     2091: static inline char ieee_ex_to_mips(char xcpt)
1.1.1.6   root     2092: {
                   2093:     return (xcpt & float_flag_inexact) >> 5 |
                   2094:            (xcpt & float_flag_underflow) >> 3 |
                   2095:            (xcpt & float_flag_overflow) >> 1 |
                   2096:            (xcpt & float_flag_divbyzero) << 1 |
                   2097:            (xcpt & float_flag_invalid) << 4;
                   2098: }
                   2099: 
1.1.1.7   root     2100: static inline char mips_ex_to_ieee(char xcpt)
1.1.1.6   root     2101: {
                   2102:     return (xcpt & FP_INEXACT) << 5 |
                   2103:            (xcpt & FP_UNDERFLOW) << 3 |
                   2104:            (xcpt & FP_OVERFLOW) << 1 |
                   2105:            (xcpt & FP_DIV0) >> 1 |
                   2106:            (xcpt & FP_INVALID) >> 4;
                   2107: }
                   2108: 
1.1.1.7   root     2109: static inline void update_fcr31(void)
1.1.1.6   root     2110: {
1.1.1.7   root     2111:     int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->active_fpu.fp_status));
1.1.1.6   root     2112: 
1.1.1.7   root     2113:     SET_FP_CAUSE(env->active_fpu.fcr31, tmp);
                   2114:     if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp)
1.1.1.8   root     2115:         helper_raise_exception(EXCP_FPE);
1.1.1.6   root     2116:     else
1.1.1.7   root     2117:         UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp);
1.1.1.6   root     2118: }
                   2119: 
1.1.1.7   root     2120: /* Float support.
                   2121:    Single precition routines have a "s" suffix, double precision a
                   2122:    "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps",
                   2123:    paired single lower "pl", paired single upper "pu".  */
                   2124: 
                   2125: /* unary operations, modifying fp status  */
1.1.1.8   root     2126: uint64_t helper_float_sqrt_d(uint64_t fdt0)
1.1.1.7   root     2127: {
                   2128:     return float64_sqrt(fdt0, &env->active_fpu.fp_status);
                   2129: }
1.1.1.6   root     2130: 
1.1.1.8   root     2131: uint32_t helper_float_sqrt_s(uint32_t fst0)
1.1.1.6   root     2132: {
1.1.1.7   root     2133:     return float32_sqrt(fst0, &env->active_fpu.fp_status);
                   2134: }
                   2135: 
1.1.1.8   root     2136: uint64_t helper_float_cvtd_s(uint32_t fst0)
1.1.1.7   root     2137: {
                   2138:     uint64_t fdt2;
                   2139: 
                   2140:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2141:     fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2142:     update_fcr31();
1.1.1.7   root     2143:     return fdt2;
1.1.1.6   root     2144: }
1.1.1.7   root     2145: 
1.1.1.8   root     2146: uint64_t helper_float_cvtd_w(uint32_t wt0)
1.1.1.6   root     2147: {
1.1.1.7   root     2148:     uint64_t fdt2;
                   2149: 
                   2150:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2151:     fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status);
1.1.1.6   root     2152:     update_fcr31();
1.1.1.7   root     2153:     return fdt2;
1.1.1.6   root     2154: }
1.1.1.7   root     2155: 
1.1.1.8   root     2156: uint64_t helper_float_cvtd_l(uint64_t dt0)
1.1.1.6   root     2157: {
1.1.1.7   root     2158:     uint64_t fdt2;
                   2159: 
                   2160:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2161:     fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status);
1.1.1.6   root     2162:     update_fcr31();
1.1.1.7   root     2163:     return fdt2;
1.1.1.6   root     2164: }
1.1.1.7   root     2165: 
1.1.1.8   root     2166: uint64_t helper_float_cvtl_d(uint64_t fdt0)
1.1.1.6   root     2167: {
1.1.1.7   root     2168:     uint64_t dt2;
                   2169: 
                   2170:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2171:     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2172:     update_fcr31();
1.1.1.7   root     2173:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2174:         dt2 = FLOAT_SNAN64;
                   2175:     return dt2;
1.1.1.6   root     2176: }
1.1.1.7   root     2177: 
1.1.1.8   root     2178: uint64_t helper_float_cvtl_s(uint32_t fst0)
1.1.1.6   root     2179: {
1.1.1.7   root     2180:     uint64_t dt2;
                   2181: 
                   2182:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2183:     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2184:     update_fcr31();
1.1.1.7   root     2185:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2186:         dt2 = FLOAT_SNAN64;
                   2187:     return dt2;
1.1.1.6   root     2188: }
                   2189: 
1.1.1.8   root     2190: uint64_t helper_float_cvtps_pw(uint64_t dt0)
1.1.1.6   root     2191: {
1.1.1.7   root     2192:     uint32_t fst2;
                   2193:     uint32_t fsth2;
                   2194: 
                   2195:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2196:     fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
                   2197:     fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status);
1.1.1.6   root     2198:     update_fcr31();
1.1.1.7   root     2199:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2200: }
1.1.1.7   root     2201: 
1.1.1.8   root     2202: uint64_t helper_float_cvtpw_ps(uint64_t fdt0)
1.1.1.6   root     2203: {
1.1.1.7   root     2204:     uint32_t wt2;
                   2205:     uint32_t wth2;
                   2206: 
                   2207:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2208:     wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
                   2209:     wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status);
1.1.1.6   root     2210:     update_fcr31();
1.1.1.7   root     2211:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) {
                   2212:         wt2 = FLOAT_SNAN32;
                   2213:         wth2 = FLOAT_SNAN32;
                   2214:     }
                   2215:     return ((uint64_t)wth2 << 32) | wt2;
1.1.1.6   root     2216: }
1.1.1.7   root     2217: 
1.1.1.8   root     2218: uint32_t helper_float_cvts_d(uint64_t fdt0)
1.1.1.6   root     2219: {
1.1.1.7   root     2220:     uint32_t fst2;
                   2221: 
                   2222:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2223:     fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2224:     update_fcr31();
1.1.1.7   root     2225:     return fst2;
1.1.1.6   root     2226: }
1.1.1.7   root     2227: 
1.1.1.8   root     2228: uint32_t helper_float_cvts_w(uint32_t wt0)
1.1.1.6   root     2229: {
1.1.1.7   root     2230:     uint32_t fst2;
                   2231: 
                   2232:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2233:     fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status);
1.1.1.6   root     2234:     update_fcr31();
1.1.1.7   root     2235:     return fst2;
1.1.1.6   root     2236: }
1.1.1.7   root     2237: 
1.1.1.8   root     2238: uint32_t helper_float_cvts_l(uint64_t dt0)
1.1.1.6   root     2239: {
1.1.1.7   root     2240:     uint32_t fst2;
                   2241: 
                   2242:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2243:     fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status);
1.1.1.6   root     2244:     update_fcr31();
1.1.1.7   root     2245:     return fst2;
1.1.1.6   root     2246: }
1.1.1.7   root     2247: 
1.1.1.8   root     2248: uint32_t helper_float_cvts_pl(uint32_t wt0)
1.1.1.6   root     2249: {
1.1.1.7   root     2250:     uint32_t wt2;
                   2251: 
                   2252:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2253:     wt2 = wt0;
1.1.1.6   root     2254:     update_fcr31();
1.1.1.7   root     2255:     return wt2;
1.1.1.6   root     2256: }
1.1.1.7   root     2257: 
1.1.1.8   root     2258: uint32_t helper_float_cvts_pu(uint32_t wth0)
1.1.1.6   root     2259: {
1.1.1.7   root     2260:     uint32_t wt2;
                   2261: 
                   2262:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2263:     wt2 = wth0;
1.1.1.6   root     2264:     update_fcr31();
1.1.1.7   root     2265:     return wt2;
1.1.1.6   root     2266: }
1.1.1.7   root     2267: 
1.1.1.8   root     2268: uint32_t helper_float_cvtw_s(uint32_t fst0)
1.1.1.6   root     2269: {
1.1.1.7   root     2270:     uint32_t wt2;
                   2271: 
                   2272:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2273:     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2274:     update_fcr31();
1.1.1.7   root     2275:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2276:         wt2 = FLOAT_SNAN32;
                   2277:     return wt2;
1.1.1.6   root     2278: }
1.1.1.7   root     2279: 
1.1.1.8   root     2280: uint32_t helper_float_cvtw_d(uint64_t fdt0)
1.1.1.6   root     2281: {
1.1.1.7   root     2282:     uint32_t wt2;
                   2283: 
                   2284:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2285:     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2286:     update_fcr31();
1.1.1.7   root     2287:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2288:         wt2 = FLOAT_SNAN32;
                   2289:     return wt2;
1.1.1.6   root     2290: }
                   2291: 
1.1.1.8   root     2292: uint64_t helper_float_roundl_d(uint64_t fdt0)
1.1.1.6   root     2293: {
1.1.1.7   root     2294:     uint64_t dt2;
                   2295: 
                   2296:     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
                   2297:     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2298:     RESTORE_ROUNDING_MODE;
                   2299:     update_fcr31();
1.1.1.7   root     2300:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2301:         dt2 = FLOAT_SNAN64;
                   2302:     return dt2;
1.1.1.6   root     2303: }
1.1.1.7   root     2304: 
1.1.1.8   root     2305: uint64_t helper_float_roundl_s(uint32_t fst0)
1.1.1.6   root     2306: {
1.1.1.7   root     2307:     uint64_t dt2;
                   2308: 
                   2309:     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
                   2310:     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2311:     RESTORE_ROUNDING_MODE;
                   2312:     update_fcr31();
1.1.1.7   root     2313:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2314:         dt2 = FLOAT_SNAN64;
                   2315:     return dt2;
1.1.1.6   root     2316: }
1.1.1.7   root     2317: 
1.1.1.8   root     2318: uint32_t helper_float_roundw_d(uint64_t fdt0)
1.1.1.6   root     2319: {
1.1.1.7   root     2320:     uint32_t wt2;
                   2321: 
                   2322:     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
                   2323:     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2324:     RESTORE_ROUNDING_MODE;
                   2325:     update_fcr31();
1.1.1.7   root     2326:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2327:         wt2 = FLOAT_SNAN32;
                   2328:     return wt2;
1.1.1.6   root     2329: }
1.1.1.7   root     2330: 
1.1.1.8   root     2331: uint32_t helper_float_roundw_s(uint32_t fst0)
1.1.1.6   root     2332: {
1.1.1.7   root     2333:     uint32_t wt2;
                   2334: 
                   2335:     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
                   2336:     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2337:     RESTORE_ROUNDING_MODE;
                   2338:     update_fcr31();
1.1.1.7   root     2339:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2340:         wt2 = FLOAT_SNAN32;
                   2341:     return wt2;
1.1.1.6   root     2342: }
                   2343: 
1.1.1.8   root     2344: uint64_t helper_float_truncl_d(uint64_t fdt0)
1.1.1.6   root     2345: {
1.1.1.7   root     2346:     uint64_t dt2;
                   2347: 
                   2348:     dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2349:     update_fcr31();
1.1.1.7   root     2350:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2351:         dt2 = FLOAT_SNAN64;
                   2352:     return dt2;
1.1.1.6   root     2353: }
1.1.1.7   root     2354: 
1.1.1.8   root     2355: uint64_t helper_float_truncl_s(uint32_t fst0)
1.1.1.6   root     2356: {
1.1.1.7   root     2357:     uint64_t dt2;
                   2358: 
                   2359:     dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2360:     update_fcr31();
1.1.1.7   root     2361:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2362:         dt2 = FLOAT_SNAN64;
                   2363:     return dt2;
1.1.1.6   root     2364: }
1.1.1.7   root     2365: 
1.1.1.8   root     2366: uint32_t helper_float_truncw_d(uint64_t fdt0)
1.1.1.6   root     2367: {
1.1.1.7   root     2368:     uint32_t wt2;
                   2369: 
                   2370:     wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2371:     update_fcr31();
1.1.1.7   root     2372:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2373:         wt2 = FLOAT_SNAN32;
                   2374:     return wt2;
1.1.1.6   root     2375: }
1.1.1.7   root     2376: 
1.1.1.8   root     2377: uint32_t helper_float_truncw_s(uint32_t fst0)
1.1.1.6   root     2378: {
1.1.1.7   root     2379:     uint32_t wt2;
                   2380: 
                   2381:     wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2382:     update_fcr31();
1.1.1.7   root     2383:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2384:         wt2 = FLOAT_SNAN32;
                   2385:     return wt2;
1.1.1.6   root     2386: }
                   2387: 
1.1.1.8   root     2388: uint64_t helper_float_ceill_d(uint64_t fdt0)
1.1.1.6   root     2389: {
1.1.1.7   root     2390:     uint64_t dt2;
                   2391: 
                   2392:     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
                   2393:     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2394:     RESTORE_ROUNDING_MODE;
                   2395:     update_fcr31();
1.1.1.7   root     2396:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2397:         dt2 = FLOAT_SNAN64;
                   2398:     return dt2;
1.1.1.6   root     2399: }
1.1.1.7   root     2400: 
1.1.1.8   root     2401: uint64_t helper_float_ceill_s(uint32_t fst0)
1.1.1.6   root     2402: {
1.1.1.7   root     2403:     uint64_t dt2;
                   2404: 
                   2405:     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
                   2406:     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2407:     RESTORE_ROUNDING_MODE;
                   2408:     update_fcr31();
1.1.1.7   root     2409:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2410:         dt2 = FLOAT_SNAN64;
                   2411:     return dt2;
1.1.1.6   root     2412: }
1.1.1.7   root     2413: 
1.1.1.8   root     2414: uint32_t helper_float_ceilw_d(uint64_t fdt0)
1.1.1.6   root     2415: {
1.1.1.7   root     2416:     uint32_t wt2;
                   2417: 
                   2418:     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
                   2419:     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2420:     RESTORE_ROUNDING_MODE;
                   2421:     update_fcr31();
1.1.1.7   root     2422:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2423:         wt2 = FLOAT_SNAN32;
                   2424:     return wt2;
1.1.1.6   root     2425: }
1.1.1.7   root     2426: 
1.1.1.8   root     2427: uint32_t helper_float_ceilw_s(uint32_t fst0)
1.1.1.6   root     2428: {
1.1.1.7   root     2429:     uint32_t wt2;
                   2430: 
                   2431:     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
                   2432:     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2433:     RESTORE_ROUNDING_MODE;
                   2434:     update_fcr31();
1.1.1.7   root     2435:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2436:         wt2 = FLOAT_SNAN32;
                   2437:     return wt2;
1.1.1.6   root     2438: }
                   2439: 
1.1.1.8   root     2440: uint64_t helper_float_floorl_d(uint64_t fdt0)
1.1.1.6   root     2441: {
1.1.1.7   root     2442:     uint64_t dt2;
                   2443: 
                   2444:     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
                   2445:     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2446:     RESTORE_ROUNDING_MODE;
                   2447:     update_fcr31();
1.1.1.7   root     2448:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2449:         dt2 = FLOAT_SNAN64;
                   2450:     return dt2;
1.1.1.6   root     2451: }
1.1.1.7   root     2452: 
1.1.1.8   root     2453: uint64_t helper_float_floorl_s(uint32_t fst0)
1.1.1.6   root     2454: {
1.1.1.7   root     2455:     uint64_t dt2;
                   2456: 
                   2457:     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
                   2458:     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2459:     RESTORE_ROUNDING_MODE;
                   2460:     update_fcr31();
1.1.1.7   root     2461:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2462:         dt2 = FLOAT_SNAN64;
                   2463:     return dt2;
1.1.1.6   root     2464: }
1.1.1.7   root     2465: 
1.1.1.8   root     2466: uint32_t helper_float_floorw_d(uint64_t fdt0)
1.1.1.6   root     2467: {
1.1.1.7   root     2468:     uint32_t wt2;
                   2469: 
                   2470:     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
                   2471:     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2472:     RESTORE_ROUNDING_MODE;
                   2473:     update_fcr31();
1.1.1.7   root     2474:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2475:         wt2 = FLOAT_SNAN32;
                   2476:     return wt2;
1.1.1.6   root     2477: }
1.1.1.7   root     2478: 
1.1.1.8   root     2479: uint32_t helper_float_floorw_s(uint32_t fst0)
1.1.1.6   root     2480: {
1.1.1.7   root     2481:     uint32_t wt2;
                   2482: 
                   2483:     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
                   2484:     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2485:     RESTORE_ROUNDING_MODE;
                   2486:     update_fcr31();
1.1.1.7   root     2487:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2488:         wt2 = FLOAT_SNAN32;
                   2489:     return wt2;
                   2490: }
                   2491: 
                   2492: /* unary operations, not modifying fp status  */
                   2493: #define FLOAT_UNOP(name)                                       \
1.1.1.8   root     2494: uint64_t helper_float_ ## name ## _d(uint64_t fdt0)                \
1.1.1.7   root     2495: {                                                              \
                   2496:     return float64_ ## name(fdt0);                             \
                   2497: }                                                              \
1.1.1.8   root     2498: uint32_t helper_float_ ## name ## _s(uint32_t fst0)                \
1.1.1.7   root     2499: {                                                              \
                   2500:     return float32_ ## name(fst0);                             \
                   2501: }                                                              \
1.1.1.8   root     2502: uint64_t helper_float_ ## name ## _ps(uint64_t fdt0)               \
1.1.1.7   root     2503: {                                                              \
                   2504:     uint32_t wt0;                                              \
                   2505:     uint32_t wth0;                                             \
                   2506:                                                                \
                   2507:     wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF);                 \
                   2508:     wth0 = float32_ ## name(fdt0 >> 32);                       \
                   2509:     return ((uint64_t)wth0 << 32) | wt0;                       \
                   2510: }
                   2511: FLOAT_UNOP(abs)
                   2512: FLOAT_UNOP(chs)
                   2513: #undef FLOAT_UNOP
1.1.1.6   root     2514: 
                   2515: /* MIPS specific unary operations */
1.1.1.8   root     2516: uint64_t helper_float_recip_d(uint64_t fdt0)
1.1.1.6   root     2517: {
1.1.1.7   root     2518:     uint64_t fdt2;
                   2519: 
                   2520:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2521:     fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2522:     update_fcr31();
1.1.1.7   root     2523:     return fdt2;
1.1.1.6   root     2524: }
1.1.1.7   root     2525: 
1.1.1.8   root     2526: uint32_t helper_float_recip_s(uint32_t fst0)
1.1.1.6   root     2527: {
1.1.1.7   root     2528:     uint32_t fst2;
                   2529: 
                   2530:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2531:     fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2532:     update_fcr31();
1.1.1.7   root     2533:     return fst2;
1.1.1.6   root     2534: }
                   2535: 
1.1.1.8   root     2536: uint64_t helper_float_rsqrt_d(uint64_t fdt0)
1.1.1.6   root     2537: {
1.1.1.7   root     2538:     uint64_t fdt2;
                   2539: 
                   2540:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2541:     fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
                   2542:     fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status);
1.1.1.6   root     2543:     update_fcr31();
1.1.1.7   root     2544:     return fdt2;
1.1.1.6   root     2545: }
1.1.1.7   root     2546: 
1.1.1.8   root     2547: uint32_t helper_float_rsqrt_s(uint32_t fst0)
1.1.1.6   root     2548: {
1.1.1.7   root     2549:     uint32_t fst2;
                   2550: 
                   2551:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2552:     fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
                   2553:     fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
1.1.1.6   root     2554:     update_fcr31();
1.1.1.7   root     2555:     return fst2;
1.1.1.6   root     2556: }
                   2557: 
1.1.1.8   root     2558: uint64_t helper_float_recip1_d(uint64_t fdt0)
1.1.1.6   root     2559: {
1.1.1.7   root     2560:     uint64_t fdt2;
                   2561: 
                   2562:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2563:     fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2564:     update_fcr31();
1.1.1.7   root     2565:     return fdt2;
1.1.1.6   root     2566: }
1.1.1.7   root     2567: 
1.1.1.8   root     2568: uint32_t helper_float_recip1_s(uint32_t fst0)
1.1.1.6   root     2569: {
1.1.1.7   root     2570:     uint32_t fst2;
                   2571: 
                   2572:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2573:     fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2574:     update_fcr31();
1.1.1.7   root     2575:     return fst2;
1.1.1.6   root     2576: }
1.1.1.7   root     2577: 
1.1.1.8   root     2578: uint64_t helper_float_recip1_ps(uint64_t fdt0)
1.1.1.6   root     2579: {
1.1.1.7   root     2580:     uint32_t fst2;
                   2581:     uint32_t fsth2;
                   2582: 
                   2583:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2584:     fst2 = float32_div(FLOAT_ONE32, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
                   2585:     fsth2 = float32_div(FLOAT_ONE32, fdt0 >> 32, &env->active_fpu.fp_status);
1.1.1.6   root     2586:     update_fcr31();
1.1.1.7   root     2587:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2588: }
                   2589: 
1.1.1.8   root     2590: uint64_t helper_float_rsqrt1_d(uint64_t fdt0)
1.1.1.6   root     2591: {
1.1.1.7   root     2592:     uint64_t fdt2;
                   2593: 
                   2594:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2595:     fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
                   2596:     fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status);
1.1.1.6   root     2597:     update_fcr31();
1.1.1.7   root     2598:     return fdt2;
1.1.1.6   root     2599: }
1.1.1.7   root     2600: 
1.1.1.8   root     2601: uint32_t helper_float_rsqrt1_s(uint32_t fst0)
1.1.1.6   root     2602: {
1.1.1.7   root     2603:     uint32_t fst2;
                   2604: 
                   2605:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2606:     fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
                   2607:     fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
1.1.1.6   root     2608:     update_fcr31();
1.1.1.7   root     2609:     return fst2;
1.1.1.6   root     2610: }
1.1.1.7   root     2611: 
1.1.1.8   root     2612: uint64_t helper_float_rsqrt1_ps(uint64_t fdt0)
1.1.1.6   root     2613: {
1.1.1.7   root     2614:     uint32_t fst2;
                   2615:     uint32_t fsth2;
                   2616: 
                   2617:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2618:     fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
                   2619:     fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status);
                   2620:     fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
                   2621:     fsth2 = float32_div(FLOAT_ONE32, fsth2, &env->active_fpu.fp_status);
1.1.1.6   root     2622:     update_fcr31();
1.1.1.7   root     2623:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2624: }
                   2625: 
1.1.1.8   root     2626: #define FLOAT_OP(name, p) void helper_float_##name##_##p(void)
1.1.1.7   root     2627: 
1.1.1.6   root     2628: /* binary operations */
1.1.1.7   root     2629: #define FLOAT_BINOP(name)                                          \
1.1.1.8   root     2630: uint64_t helper_float_ ## name ## _d(uint64_t fdt0, uint64_t fdt1)     \
1.1.1.7   root     2631: {                                                                  \
                   2632:     uint64_t dt2;                                                  \
                   2633:                                                                    \
                   2634:     set_float_exception_flags(0, &env->active_fpu.fp_status);            \
                   2635:     dt2 = float64_ ## name (fdt0, fdt1, &env->active_fpu.fp_status);     \
                   2636:     update_fcr31();                                                \
                   2637:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID)                \
                   2638:         dt2 = FLOAT_QNAN64;                                        \
                   2639:     return dt2;                                                    \
                   2640: }                                                                  \
                   2641:                                                                    \
1.1.1.8   root     2642: uint32_t helper_float_ ## name ## _s(uint32_t fst0, uint32_t fst1)     \
1.1.1.7   root     2643: {                                                                  \
                   2644:     uint32_t wt2;                                                  \
                   2645:                                                                    \
                   2646:     set_float_exception_flags(0, &env->active_fpu.fp_status);            \
                   2647:     wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status);     \
1.1.1.6   root     2648:     update_fcr31();                                                \
1.1.1.7   root     2649:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID)                \
                   2650:         wt2 = FLOAT_QNAN32;                                        \
                   2651:     return wt2;                                                    \
                   2652: }                                                                  \
                   2653:                                                                    \
1.1.1.8   root     2654: uint64_t helper_float_ ## name ## _ps(uint64_t fdt0, uint64_t fdt1)    \
1.1.1.7   root     2655: {                                                                  \
                   2656:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;                             \
                   2657:     uint32_t fsth0 = fdt0 >> 32;                                   \
                   2658:     uint32_t fst1 = fdt1 & 0XFFFFFFFF;                             \
                   2659:     uint32_t fsth1 = fdt1 >> 32;                                   \
                   2660:     uint32_t wt2;                                                  \
                   2661:     uint32_t wth2;                                                 \
                   2662:                                                                    \
                   2663:     set_float_exception_flags(0, &env->active_fpu.fp_status);            \
                   2664:     wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status);     \
                   2665:     wth2 = float32_ ## name (fsth0, fsth1, &env->active_fpu.fp_status);  \
1.1.1.6   root     2666:     update_fcr31();                                                \
1.1.1.7   root     2667:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) {              \
                   2668:         wt2 = FLOAT_QNAN32;                                        \
                   2669:         wth2 = FLOAT_QNAN32;                                       \
                   2670:     }                                                              \
                   2671:     return ((uint64_t)wth2 << 32) | wt2;                           \
1.1.1.6   root     2672: }
1.1.1.7   root     2673: 
1.1.1.6   root     2674: FLOAT_BINOP(add)
                   2675: FLOAT_BINOP(sub)
                   2676: FLOAT_BINOP(mul)
                   2677: FLOAT_BINOP(div)
                   2678: #undef FLOAT_BINOP
                   2679: 
1.1.1.7   root     2680: /* ternary operations */
                   2681: #define FLOAT_TERNOP(name1, name2)                                        \
1.1.1.8   root     2682: uint64_t helper_float_ ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1,  \
1.1.1.7   root     2683:                                            uint64_t fdt2)                 \
                   2684: {                                                                         \
                   2685:     fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status);          \
                   2686:     return float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status);          \
                   2687: }                                                                         \
                   2688:                                                                           \
1.1.1.8   root     2689: uint32_t helper_float_ ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1,  \
1.1.1.7   root     2690:                                            uint32_t fst2)                 \
                   2691: {                                                                         \
                   2692:     fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
                   2693:     return float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
                   2694: }                                                                         \
                   2695:                                                                           \
1.1.1.8   root     2696: uint64_t helper_float_ ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1, \
1.1.1.7   root     2697:                                             uint64_t fdt2)                \
                   2698: {                                                                         \
                   2699:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;                                    \
                   2700:     uint32_t fsth0 = fdt0 >> 32;                                          \
                   2701:     uint32_t fst1 = fdt1 & 0XFFFFFFFF;                                    \
                   2702:     uint32_t fsth1 = fdt1 >> 32;                                          \
                   2703:     uint32_t fst2 = fdt2 & 0XFFFFFFFF;                                    \
                   2704:     uint32_t fsth2 = fdt2 >> 32;                                          \
                   2705:                                                                           \
                   2706:     fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
                   2707:     fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status);       \
                   2708:     fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
                   2709:     fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status);       \
                   2710:     return ((uint64_t)fsth2 << 32) | fst2;                                \
                   2711: }
                   2712: 
                   2713: FLOAT_TERNOP(mul, add)
                   2714: FLOAT_TERNOP(mul, sub)
                   2715: #undef FLOAT_TERNOP
                   2716: 
                   2717: /* negated ternary operations */
                   2718: #define FLOAT_NTERNOP(name1, name2)                                       \
1.1.1.8   root     2719: uint64_t helper_float_n ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1, \
1.1.1.7   root     2720:                                            uint64_t fdt2)                 \
                   2721: {                                                                         \
                   2722:     fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status);          \
                   2723:     fdt2 = float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status);          \
                   2724:     return float64_chs(fdt2);                                             \
                   2725: }                                                                         \
                   2726:                                                                           \
1.1.1.8   root     2727: uint32_t helper_float_n ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1, \
1.1.1.7   root     2728:                                            uint32_t fst2)                 \
                   2729: {                                                                         \
                   2730:     fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
                   2731:     fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
                   2732:     return float32_chs(fst2);                                             \
                   2733: }                                                                         \
                   2734:                                                                           \
1.1.1.8   root     2735: uint64_t helper_float_n ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1,\
1.1.1.7   root     2736:                                            uint64_t fdt2)                 \
                   2737: {                                                                         \
                   2738:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;                                    \
                   2739:     uint32_t fsth0 = fdt0 >> 32;                                          \
                   2740:     uint32_t fst1 = fdt1 & 0XFFFFFFFF;                                    \
                   2741:     uint32_t fsth1 = fdt1 >> 32;                                          \
                   2742:     uint32_t fst2 = fdt2 & 0XFFFFFFFF;                                    \
                   2743:     uint32_t fsth2 = fdt2 >> 32;                                          \
                   2744:                                                                           \
                   2745:     fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
                   2746:     fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status);       \
                   2747:     fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
                   2748:     fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status);       \
                   2749:     fst2 = float32_chs(fst2);                                             \
                   2750:     fsth2 = float32_chs(fsth2);                                           \
                   2751:     return ((uint64_t)fsth2 << 32) | fst2;                                \
                   2752: }
                   2753: 
                   2754: FLOAT_NTERNOP(mul, add)
                   2755: FLOAT_NTERNOP(mul, sub)
                   2756: #undef FLOAT_NTERNOP
                   2757: 
1.1.1.6   root     2758: /* MIPS specific binary operations */
1.1.1.8   root     2759: uint64_t helper_float_recip2_d(uint64_t fdt0, uint64_t fdt2)
1.1.1.6   root     2760: {
1.1.1.7   root     2761:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2762:     fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
                   2763:     fdt2 = float64_chs(float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status));
1.1.1.6   root     2764:     update_fcr31();
1.1.1.7   root     2765:     return fdt2;
1.1.1.6   root     2766: }
1.1.1.7   root     2767: 
1.1.1.8   root     2768: uint32_t helper_float_recip2_s(uint32_t fst0, uint32_t fst2)
1.1.1.6   root     2769: {
1.1.1.7   root     2770:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2771:     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
                   2772:     fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status));
1.1.1.6   root     2773:     update_fcr31();
1.1.1.7   root     2774:     return fst2;
1.1.1.6   root     2775: }
1.1.1.7   root     2776: 
1.1.1.8   root     2777: uint64_t helper_float_recip2_ps(uint64_t fdt0, uint64_t fdt2)
1.1.1.6   root     2778: {
1.1.1.7   root     2779:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
                   2780:     uint32_t fsth0 = fdt0 >> 32;
                   2781:     uint32_t fst2 = fdt2 & 0XFFFFFFFF;
                   2782:     uint32_t fsth2 = fdt2 >> 32;
                   2783: 
                   2784:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2785:     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
                   2786:     fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
                   2787:     fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status));
                   2788:     fsth2 = float32_chs(float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status));
1.1.1.6   root     2789:     update_fcr31();
1.1.1.7   root     2790:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2791: }
                   2792: 
1.1.1.8   root     2793: uint64_t helper_float_rsqrt2_d(uint64_t fdt0, uint64_t fdt2)
1.1.1.6   root     2794: {
1.1.1.7   root     2795:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2796:     fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
                   2797:     fdt2 = float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status);
                   2798:     fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->active_fpu.fp_status));
1.1.1.6   root     2799:     update_fcr31();
1.1.1.7   root     2800:     return fdt2;
1.1.1.6   root     2801: }
1.1.1.7   root     2802: 
1.1.1.8   root     2803: uint32_t helper_float_rsqrt2_s(uint32_t fst0, uint32_t fst2)
1.1.1.6   root     2804: {
1.1.1.7   root     2805:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2806:     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
                   2807:     fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status);
                   2808:     fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
1.1.1.6   root     2809:     update_fcr31();
1.1.1.7   root     2810:     return fst2;
1.1.1.6   root     2811: }
1.1.1.7   root     2812: 
1.1.1.8   root     2813: uint64_t helper_float_rsqrt2_ps(uint64_t fdt0, uint64_t fdt2)
1.1.1.6   root     2814: {
1.1.1.7   root     2815:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
                   2816:     uint32_t fsth0 = fdt0 >> 32;
                   2817:     uint32_t fst2 = fdt2 & 0XFFFFFFFF;
                   2818:     uint32_t fsth2 = fdt2 >> 32;
                   2819: 
                   2820:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2821:     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
                   2822:     fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
                   2823:     fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status);
                   2824:     fsth2 = float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status);
                   2825:     fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
                   2826:     fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->active_fpu.fp_status));
1.1.1.6   root     2827:     update_fcr31();
1.1.1.7   root     2828:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2829: }
                   2830: 
1.1.1.8   root     2831: uint64_t helper_float_addr_ps(uint64_t fdt0, uint64_t fdt1)
1.1.1.6   root     2832: {
1.1.1.7   root     2833:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
                   2834:     uint32_t fsth0 = fdt0 >> 32;
                   2835:     uint32_t fst1 = fdt1 & 0XFFFFFFFF;
                   2836:     uint32_t fsth1 = fdt1 >> 32;
                   2837:     uint32_t fst2;
                   2838:     uint32_t fsth2;
                   2839: 
                   2840:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2841:     fst2 = float32_add (fst0, fsth0, &env->active_fpu.fp_status);
                   2842:     fsth2 = float32_add (fst1, fsth1, &env->active_fpu.fp_status);
1.1.1.6   root     2843:     update_fcr31();
1.1.1.7   root     2844:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2845: }
                   2846: 
1.1.1.8   root     2847: uint64_t helper_float_mulr_ps(uint64_t fdt0, uint64_t fdt1)
1.1.1.6   root     2848: {
1.1.1.7   root     2849:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
                   2850:     uint32_t fsth0 = fdt0 >> 32;
                   2851:     uint32_t fst1 = fdt1 & 0XFFFFFFFF;
                   2852:     uint32_t fsth1 = fdt1 >> 32;
                   2853:     uint32_t fst2;
                   2854:     uint32_t fsth2;
                   2855: 
                   2856:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2857:     fst2 = float32_mul (fst0, fsth0, &env->active_fpu.fp_status);
                   2858:     fsth2 = float32_mul (fst1, fsth1, &env->active_fpu.fp_status);
1.1.1.6   root     2859:     update_fcr31();
1.1.1.7   root     2860:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2861: }
                   2862: 
                   2863: /* compare operations */
1.1.1.7   root     2864: #define FOP_COND_D(op, cond)                                   \
1.1.1.8   root     2865: void helper_cmp_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
1.1.1.7   root     2866: {                                                              \
                   2867:     int c = cond;                                              \
                   2868:     update_fcr31();                                            \
                   2869:     if (c)                                                     \
                   2870:         SET_FP_COND(cc, env->active_fpu);                      \
                   2871:     else                                                       \
                   2872:         CLEAR_FP_COND(cc, env->active_fpu);                    \
                   2873: }                                                              \
1.1.1.8   root     2874: void helper_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
1.1.1.7   root     2875: {                                                              \
                   2876:     int c;                                                     \
                   2877:     fdt0 = float64_abs(fdt0);                                  \
                   2878:     fdt1 = float64_abs(fdt1);                                  \
                   2879:     c = cond;                                                  \
                   2880:     update_fcr31();                                            \
                   2881:     if (c)                                                     \
                   2882:         SET_FP_COND(cc, env->active_fpu);                      \
                   2883:     else                                                       \
                   2884:         CLEAR_FP_COND(cc, env->active_fpu);                    \
1.1.1.6   root     2885: }
                   2886: 
1.1.1.7   root     2887: static int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
1.1.1.6   root     2888: {
                   2889:     if (float64_is_signaling_nan(a) ||
                   2890:         float64_is_signaling_nan(b) ||
                   2891:         (sig && (float64_is_nan(a) || float64_is_nan(b)))) {
                   2892:         float_raise(float_flag_invalid, status);
                   2893:         return 1;
                   2894:     } else if (float64_is_nan(a) || float64_is_nan(b)) {
                   2895:         return 1;
                   2896:     } else {
                   2897:         return 0;
                   2898:     }
                   2899: }
                   2900: 
                   2901: /* NOTE: the comma operator will make "cond" to eval to false,
                   2902:  * but float*_is_unordered() is still called. */
1.1.1.7   root     2903: FOP_COND_D(f,   (float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status), 0))
                   2904: FOP_COND_D(un,  float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status))
                   2905: FOP_COND_D(eq,  !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
                   2906: FOP_COND_D(ueq, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
                   2907: FOP_COND_D(olt, !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
                   2908: FOP_COND_D(ult, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
                   2909: FOP_COND_D(ole, !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
                   2910: FOP_COND_D(ule, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
1.1.1.6   root     2911: /* NOTE: the comma operator will make "cond" to eval to false,
                   2912:  * but float*_is_unordered() is still called. */
1.1.1.7   root     2913: FOP_COND_D(sf,  (float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status), 0))
                   2914: FOP_COND_D(ngle,float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status))
                   2915: FOP_COND_D(seq, !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
                   2916: FOP_COND_D(ngl, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
                   2917: FOP_COND_D(lt,  !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
                   2918: FOP_COND_D(nge, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
                   2919: FOP_COND_D(le,  !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
                   2920: FOP_COND_D(ngt, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
                   2921: 
                   2922: #define FOP_COND_S(op, cond)                                   \
1.1.1.8   root     2923: void helper_cmp_s_ ## op (uint32_t fst0, uint32_t fst1, int cc)    \
1.1.1.7   root     2924: {                                                              \
                   2925:     int c = cond;                                              \
                   2926:     update_fcr31();                                            \
                   2927:     if (c)                                                     \
                   2928:         SET_FP_COND(cc, env->active_fpu);                      \
                   2929:     else                                                       \
                   2930:         CLEAR_FP_COND(cc, env->active_fpu);                    \
                   2931: }                                                              \
1.1.1.8   root     2932: void helper_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
1.1.1.7   root     2933: {                                                              \
                   2934:     int c;                                                     \
                   2935:     fst0 = float32_abs(fst0);                                  \
                   2936:     fst1 = float32_abs(fst1);                                  \
                   2937:     c = cond;                                                  \
                   2938:     update_fcr31();                                            \
                   2939:     if (c)                                                     \
                   2940:         SET_FP_COND(cc, env->active_fpu);                      \
                   2941:     else                                                       \
                   2942:         CLEAR_FP_COND(cc, env->active_fpu);                    \
1.1.1.6   root     2943: }
                   2944: 
1.1.1.7   root     2945: static flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
1.1.1.6   root     2946: {
                   2947:     if (float32_is_signaling_nan(a) ||
                   2948:         float32_is_signaling_nan(b) ||
                   2949:         (sig && (float32_is_nan(a) || float32_is_nan(b)))) {
                   2950:         float_raise(float_flag_invalid, status);
                   2951:         return 1;
                   2952:     } else if (float32_is_nan(a) || float32_is_nan(b)) {
                   2953:         return 1;
                   2954:     } else {
                   2955:         return 0;
                   2956:     }
                   2957: }
                   2958: 
                   2959: /* NOTE: the comma operator will make "cond" to eval to false,
                   2960:  * but float*_is_unordered() is still called. */
1.1.1.7   root     2961: FOP_COND_S(f,   (float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status), 0))
                   2962: FOP_COND_S(un,  float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status))
                   2963: FOP_COND_S(eq,  !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
                   2964: FOP_COND_S(ueq, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)  || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
                   2965: FOP_COND_S(olt, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
                   2966: FOP_COND_S(ult, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
                   2967: FOP_COND_S(ole, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
                   2968: FOP_COND_S(ule, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)  || float32_le(fst0, fst1, &env->active_fpu.fp_status))
1.1.1.6   root     2969: /* NOTE: the comma operator will make "cond" to eval to false,
                   2970:  * but float*_is_unordered() is still called. */
1.1.1.7   root     2971: FOP_COND_S(sf,  (float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status), 0))
                   2972: FOP_COND_S(ngle,float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status))
                   2973: FOP_COND_S(seq, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
                   2974: FOP_COND_S(ngl, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)  || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
                   2975: FOP_COND_S(lt,  !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
                   2976: FOP_COND_S(nge, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
                   2977: FOP_COND_S(le,  !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
                   2978: FOP_COND_S(ngt, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)  || float32_le(fst0, fst1, &env->active_fpu.fp_status))
                   2979: 
                   2980: #define FOP_COND_PS(op, condl, condh)                           \
1.1.1.8   root     2981: void helper_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
1.1.1.7   root     2982: {                                                               \
                   2983:     uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF);             \
                   2984:     uint32_t fsth0 = float32_abs(fdt0 >> 32);                   \
                   2985:     uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF);             \
                   2986:     uint32_t fsth1 = float32_abs(fdt1 >> 32);                   \
                   2987:     int cl = condl;                                             \
                   2988:     int ch = condh;                                             \
                   2989:                                                                 \
                   2990:     update_fcr31();                                             \
                   2991:     if (cl)                                                     \
                   2992:         SET_FP_COND(cc, env->active_fpu);                       \
                   2993:     else                                                        \
                   2994:         CLEAR_FP_COND(cc, env->active_fpu);                     \
                   2995:     if (ch)                                                     \
                   2996:         SET_FP_COND(cc + 1, env->active_fpu);                   \
                   2997:     else                                                        \
                   2998:         CLEAR_FP_COND(cc + 1, env->active_fpu);                 \
                   2999: }                                                               \
1.1.1.8   root     3000: void helper_cmpabs_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
1.1.1.7   root     3001: {                                                               \
                   3002:     uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF);             \
                   3003:     uint32_t fsth0 = float32_abs(fdt0 >> 32);                   \
                   3004:     uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF);             \
                   3005:     uint32_t fsth1 = float32_abs(fdt1 >> 32);                   \
                   3006:     int cl = condl;                                             \
                   3007:     int ch = condh;                                             \
                   3008:                                                                 \
                   3009:     update_fcr31();                                             \
                   3010:     if (cl)                                                     \
                   3011:         SET_FP_COND(cc, env->active_fpu);                       \
                   3012:     else                                                        \
                   3013:         CLEAR_FP_COND(cc, env->active_fpu);                     \
                   3014:     if (ch)                                                     \
                   3015:         SET_FP_COND(cc + 1, env->active_fpu);                   \
                   3016:     else                                                        \
                   3017:         CLEAR_FP_COND(cc + 1, env->active_fpu);                 \
1.1.1.6   root     3018: }
                   3019: 
                   3020: /* NOTE: the comma operator will make "cond" to eval to false,
                   3021:  * but float*_is_unordered() is still called. */
1.1.1.7   root     3022: FOP_COND_PS(f,   (float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status), 0),
                   3023:                  (float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status), 0))
                   3024: FOP_COND_PS(un,  float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status),
                   3025:                  float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status))
                   3026: FOP_COND_PS(eq,  !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)   && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
                   3027:                  !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
                   3028: FOP_COND_PS(ueq, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)    || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
                   3029:                  float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
                   3030: FOP_COND_PS(olt, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)   && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
                   3031:                  !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
                   3032: FOP_COND_PS(ult, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
                   3033:                  float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
                   3034: FOP_COND_PS(ole, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)   && float32_le(fst0, fst1, &env->active_fpu.fp_status),
                   3035:                  !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
                   3036: FOP_COND_PS(ule, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)    || float32_le(fst0, fst1, &env->active_fpu.fp_status),
                   3037:                  float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
1.1.1.6   root     3038: /* NOTE: the comma operator will make "cond" to eval to false,
                   3039:  * but float*_is_unordered() is still called. */
1.1.1.7   root     3040: FOP_COND_PS(sf,  (float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status), 0),
                   3041:                  (float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status), 0))
                   3042: FOP_COND_PS(ngle,float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status),
                   3043:                  float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status))
                   3044: FOP_COND_PS(seq, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)   && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
                   3045:                  !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
                   3046: FOP_COND_PS(ngl, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)    || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
                   3047:                  float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
                   3048: FOP_COND_PS(lt,  !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)   && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
                   3049:                  !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
                   3050: FOP_COND_PS(nge, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
                   3051:                  float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
                   3052: FOP_COND_PS(le,  !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)   && float32_le(fst0, fst1, &env->active_fpu.fp_status),
                   3053:                  !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
                   3054: FOP_COND_PS(ngt, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)    || float32_le(fst0, fst1, &env->active_fpu.fp_status),
                   3055:                  float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le(fsth0, fsth1, &env->active_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.