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

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 */
1.1.1.12! root     1362:     env->CP0_EBase = (env->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000);
1.1.1.6   root     1363: }
                   1364: 
1.1.1.8   root     1365: void helper_mtc0_config0 (target_ulong arg1)
1.1.1.6   root     1366: {
1.1.1.8   root     1367:     env->CP0_Config0 = (env->CP0_Config0 & 0x81FFFFF8) | (arg1 & 0x00000007);
1.1.1.6   root     1368: }
                   1369: 
1.1.1.8   root     1370: void helper_mtc0_config2 (target_ulong arg1)
1.1.1.6   root     1371: {
1.1.1.7   root     1372:     /* tertiary/secondary caches not implemented */
                   1373:     env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
1.1.1.6   root     1374: }
                   1375: 
1.1.1.9   root     1376: void helper_mtc0_lladdr (target_ulong arg1)
                   1377: {
                   1378:     target_long mask = env->CP0_LLAddr_rw_bitmask;
                   1379:     arg1 = arg1 << env->CP0_LLAddr_shift;
                   1380:     env->lladdr = (env->lladdr & ~mask) | (arg1 & mask);
                   1381: }
                   1382: 
1.1.1.8   root     1383: void helper_mtc0_watchlo (target_ulong arg1, uint32_t sel)
1.1.1.6   root     1384: {
1.1.1.7   root     1385:     /* Watch exceptions for instructions, data loads, data stores
                   1386:        not implemented. */
1.1.1.8   root     1387:     env->CP0_WatchLo[sel] = (arg1 & ~0x7);
1.1.1.6   root     1388: }
                   1389: 
1.1.1.8   root     1390: void helper_mtc0_watchhi (target_ulong arg1, uint32_t sel)
1.1.1.6   root     1391: {
1.1.1.8   root     1392:     env->CP0_WatchHi[sel] = (arg1 & 0x40FF0FF8);
                   1393:     env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7);
1.1.1.6   root     1394: }
                   1395: 
1.1.1.8   root     1396: void helper_mtc0_xcontext (target_ulong arg1)
1.1.1.6   root     1397: {
1.1.1.7   root     1398:     target_ulong mask = (1ULL << (env->SEGBITS - 7)) - 1;
1.1.1.8   root     1399:     env->CP0_XContext = (env->CP0_XContext & mask) | (arg1 & ~mask);
1.1.1.6   root     1400: }
                   1401: 
1.1.1.8   root     1402: void helper_mtc0_framemask (target_ulong arg1)
1.1.1.6   root     1403: {
1.1.1.8   root     1404:     env->CP0_Framemask = arg1; /* XXX */
1.1.1.6   root     1405: }
                   1406: 
1.1.1.8   root     1407: void helper_mtc0_debug (target_ulong arg1)
1.1.1.6   root     1408: {
1.1.1.8   root     1409:     env->CP0_Debug = (env->CP0_Debug & 0x8C03FC1F) | (arg1 & 0x13300120);
                   1410:     if (arg1 & (1 << CP0DB_DM))
1.1.1.7   root     1411:         env->hflags |= MIPS_HFLAG_DM;
                   1412:     else
                   1413:         env->hflags &= ~MIPS_HFLAG_DM;
1.1.1.6   root     1414: }
                   1415: 
1.1.1.8   root     1416: void helper_mttc0_debug(target_ulong arg1)
1.1.1.6   root     1417: {
1.1.1.7   root     1418:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.8   root     1419:     uint32_t val = arg1 & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt));
1.1.1.7   root     1420: 
                   1421:     /* XXX: Might be wrong, check with EJTAG spec. */
                   1422:     if (other_tc == env->current_tc)
                   1423:         env->active_tc.CP0_Debug_tcstatus = val;
                   1424:     else
                   1425:         env->tcs[other_tc].CP0_Debug_tcstatus = val;
                   1426:     env->CP0_Debug = (env->CP0_Debug & ((1 << CP0DB_SSt) | (1 << CP0DB_Halt))) |
1.1.1.8   root     1427:                      (arg1 & ~((1 << CP0DB_SSt) | (1 << CP0DB_Halt)));
1.1.1.6   root     1428: }
                   1429: 
1.1.1.8   root     1430: void helper_mtc0_performance0 (target_ulong arg1)
1.1.1.6   root     1431: {
1.1.1.8   root     1432:     env->CP0_Performance0 = arg1 & 0x000007ff;
1.1.1.6   root     1433: }
                   1434: 
1.1.1.8   root     1435: void helper_mtc0_taglo (target_ulong arg1)
1.1.1.5   root     1436: {
1.1.1.8   root     1437:     env->CP0_TagLo = arg1 & 0xFFFFFCF6;
1.1.1.5   root     1438: }
                   1439: 
1.1.1.8   root     1440: void helper_mtc0_datalo (target_ulong arg1)
1.1.1.5   root     1441: {
1.1.1.8   root     1442:     env->CP0_DataLo = arg1; /* XXX */
1.1.1.5   root     1443: }
                   1444: 
1.1.1.8   root     1445: void helper_mtc0_taghi (target_ulong arg1)
1.1.1.5   root     1446: {
1.1.1.8   root     1447:     env->CP0_TagHi = arg1; /* XXX */
1.1.1.5   root     1448: }
                   1449: 
1.1.1.8   root     1450: void helper_mtc0_datahi (target_ulong arg1)
1.1.1.5   root     1451: {
1.1.1.8   root     1452:     env->CP0_DataHi = arg1; /* XXX */
1.1.1.5   root     1453: }
                   1454: 
1.1.1.7   root     1455: /* MIPS MT functions */
1.1.1.8   root     1456: target_ulong helper_mftgpr(uint32_t sel)
1.1.1.5   root     1457: {
1.1.1.7   root     1458:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1459: 
                   1460:     if (other_tc == env->current_tc)
                   1461:         return env->active_tc.gpr[sel];
                   1462:     else
                   1463:         return env->tcs[other_tc].gpr[sel];
1.1.1.5   root     1464: }
                   1465: 
1.1.1.8   root     1466: target_ulong helper_mftlo(uint32_t sel)
1.1.1.5   root     1467: {
1.1.1.7   root     1468:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1469: 
                   1470:     if (other_tc == env->current_tc)
                   1471:         return env->active_tc.LO[sel];
                   1472:     else
                   1473:         return env->tcs[other_tc].LO[sel];
1.1.1.5   root     1474: }
                   1475: 
1.1.1.8   root     1476: target_ulong helper_mfthi(uint32_t sel)
1.1.1.5   root     1477: {
1.1.1.7   root     1478:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1479: 
                   1480:     if (other_tc == env->current_tc)
                   1481:         return env->active_tc.HI[sel];
                   1482:     else
                   1483:         return env->tcs[other_tc].HI[sel];
1.1.1.5   root     1484: }
                   1485: 
1.1.1.8   root     1486: target_ulong helper_mftacx(uint32_t sel)
1.1.1.5   root     1487: {
1.1.1.7   root     1488:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1489: 
                   1490:     if (other_tc == env->current_tc)
                   1491:         return env->active_tc.ACX[sel];
                   1492:     else
                   1493:         return env->tcs[other_tc].ACX[sel];
1.1.1.2   root     1494: }
                   1495: 
1.1.1.8   root     1496: target_ulong helper_mftdsp(void)
1.1.1.2   root     1497: {
1.1.1.7   root     1498:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1499: 
                   1500:     if (other_tc == env->current_tc)
                   1501:         return env->active_tc.DSPControl;
                   1502:     else
                   1503:         return env->tcs[other_tc].DSPControl;
1.1.1.2   root     1504: }
                   1505: 
1.1.1.8   root     1506: void helper_mttgpr(target_ulong arg1, uint32_t sel)
1.1.1.2   root     1507: {
1.1.1.7   root     1508:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1509: 
                   1510:     if (other_tc == env->current_tc)
1.1.1.8   root     1511:         env->active_tc.gpr[sel] = arg1;
1.1.1.7   root     1512:     else
1.1.1.8   root     1513:         env->tcs[other_tc].gpr[sel] = arg1;
1.1.1.2   root     1514: }
                   1515: 
1.1.1.8   root     1516: void helper_mttlo(target_ulong arg1, uint32_t sel)
1.1.1.2   root     1517: {
1.1.1.7   root     1518:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1519: 
                   1520:     if (other_tc == env->current_tc)
1.1.1.8   root     1521:         env->active_tc.LO[sel] = arg1;
1.1.1.7   root     1522:     else
1.1.1.8   root     1523:         env->tcs[other_tc].LO[sel] = arg1;
1.1.1.2   root     1524: }
                   1525: 
1.1.1.8   root     1526: void helper_mtthi(target_ulong arg1, uint32_t sel)
1.1.1.2   root     1527: {
1.1.1.7   root     1528:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1529: 
                   1530:     if (other_tc == env->current_tc)
1.1.1.8   root     1531:         env->active_tc.HI[sel] = arg1;
1.1.1.7   root     1532:     else
1.1.1.8   root     1533:         env->tcs[other_tc].HI[sel] = arg1;
1.1.1.2   root     1534: }
1.1.1.5   root     1535: 
1.1.1.8   root     1536: void helper_mttacx(target_ulong arg1, uint32_t sel)
1.1.1.5   root     1537: {
1.1.1.7   root     1538:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
1.1.1.5   root     1539: 
1.1.1.7   root     1540:     if (other_tc == env->current_tc)
1.1.1.8   root     1541:         env->active_tc.ACX[sel] = arg1;
1.1.1.7   root     1542:     else
1.1.1.8   root     1543:         env->tcs[other_tc].ACX[sel] = arg1;
1.1.1.7   root     1544: }
1.1.1.2   root     1545: 
1.1.1.8   root     1546: void helper_mttdsp(target_ulong arg1)
1.1       root     1547: {
1.1.1.7   root     1548:     int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
                   1549: 
                   1550:     if (other_tc == env->current_tc)
1.1.1.8   root     1551:         env->active_tc.DSPControl = arg1;
1.1.1.7   root     1552:     else
1.1.1.8   root     1553:         env->tcs[other_tc].DSPControl = arg1;
1.1.1.5   root     1554: }
1.1       root     1555: 
1.1.1.7   root     1556: /* MIPS MT functions */
1.1.1.12! root     1557: target_ulong helper_dmt(void)
1.1.1.5   root     1558: {
1.1.1.7   root     1559:     // TODO
1.1.1.12! root     1560:      return 0;
1.1       root     1561: }
                   1562: 
1.1.1.12! root     1563: target_ulong helper_emt(void)
1.1       root     1564: {
1.1.1.7   root     1565:     // TODO
1.1.1.12! root     1566:     return 0;
1.1.1.5   root     1567: }
1.1       root     1568: 
1.1.1.12! root     1569: target_ulong helper_dvpe(void)
1.1.1.5   root     1570: {
1.1.1.7   root     1571:     // TODO
1.1.1.12! root     1572:     return 0;
1.1       root     1573: }
                   1574: 
1.1.1.12! root     1575: target_ulong helper_evpe(void)
1.1.1.4   root     1576: {
1.1.1.7   root     1577:     // TODO
1.1.1.12! root     1578:     return 0;
1.1.1.7   root     1579: }
                   1580: #endif /* !CONFIG_USER_ONLY */
1.1.1.4   root     1581: 
1.1.1.8   root     1582: void helper_fork(target_ulong arg1, target_ulong arg2)
1.1.1.7   root     1583: {
1.1.1.8   root     1584:     // arg1 = rt, arg2 = rs
                   1585:     arg1 = 0;
1.1.1.7   root     1586:     // TODO: store to TC register
                   1587: }
                   1588: 
1.1.1.12! root     1589: target_ulong helper_yield(target_ulong arg)
1.1.1.7   root     1590: {
1.1.1.12! root     1591:     target_long arg1 = arg;
        !          1592: 
1.1.1.8   root     1593:     if (arg1 < 0) {
1.1.1.7   root     1594:         /* No scheduling policy implemented. */
1.1.1.8   root     1595:         if (arg1 != -2) {
1.1.1.7   root     1596:             if (env->CP0_VPEControl & (1 << CP0VPECo_YSI) &&
                   1597:                 env->active_tc.CP0_TCStatus & (1 << CP0TCSt_DT)) {
                   1598:                 env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
                   1599:                 env->CP0_VPEControl |= 4 << CP0VPECo_EXCPT;
1.1.1.8   root     1600:                 helper_raise_exception(EXCP_THREAD);
1.1.1.7   root     1601:             }
                   1602:         }
1.1.1.8   root     1603:     } else if (arg1 == 0) {
1.1.1.7   root     1604:         if (0 /* TODO: TC underflow */) {
                   1605:             env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
1.1.1.8   root     1606:             helper_raise_exception(EXCP_THREAD);
1.1.1.7   root     1607:         } else {
                   1608:             // TODO: Deallocate TC
                   1609:         }
1.1.1.8   root     1610:     } else if (arg1 > 0) {
1.1.1.7   root     1611:         /* Yield qualifier inputs not implemented. */
                   1612:         env->CP0_VPEControl &= ~(0x7 << CP0VPECo_EXCPT);
                   1613:         env->CP0_VPEControl |= 2 << CP0VPECo_EXCPT;
1.1.1.8   root     1614:         helper_raise_exception(EXCP_THREAD);
1.1.1.4   root     1615:     }
1.1.1.7   root     1616:     return env->CP0_YQMask;
1.1.1.4   root     1617: }
                   1618: 
1.1.1.7   root     1619: #ifndef CONFIG_USER_ONLY
1.1       root     1620: /* TLB management */
1.1.1.11  root     1621: static void cpu_mips_tlb_flush (CPUState *env, int flush_global)
1.1       root     1622: {
1.1.1.5   root     1623:     /* Flush qemu's TLB and discard all shadowed entries.  */
                   1624:     tlb_flush (env, flush_global);
1.1.1.6   root     1625:     env->tlb->tlb_in_use = env->tlb->nb_tlb;
1.1.1.5   root     1626: }
1.1       root     1627: 
1.1.1.6   root     1628: static void r4k_mips_tlb_flush_extra (CPUState *env, int first)
1.1.1.5   root     1629: {
                   1630:     /* Discard entries from env->tlb[first] onwards.  */
1.1.1.6   root     1631:     while (env->tlb->tlb_in_use > first) {
                   1632:         r4k_invalidate_tlb(env, --env->tlb->tlb_in_use, 0);
1.1       root     1633:     }
                   1634: }
                   1635: 
1.1.1.6   root     1636: static void r4k_fill_tlb (int idx)
1.1       root     1637: {
1.1.1.6   root     1638:     r4k_tlb_t *tlb;
1.1       root     1639: 
                   1640:     /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
1.1.1.6   root     1641:     tlb = &env->tlb->mmu.r4k.tlb[idx];
                   1642:     tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
                   1643: #if defined(TARGET_MIPS64)
                   1644:     tlb->VPN &= env->SEGMask;
                   1645: #endif
1.1.1.3   root     1646:     tlb->ASID = env->CP0_EntryHi & 0xFF;
1.1.1.5   root     1647:     tlb->PageMask = env->CP0_PageMask;
1.1       root     1648:     tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
1.1.1.3   root     1649:     tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
                   1650:     tlb->D0 = (env->CP0_EntryLo0 & 4) != 0;
                   1651:     tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7;
1.1       root     1652:     tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12;
1.1.1.3   root     1653:     tlb->V1 = (env->CP0_EntryLo1 & 2) != 0;
                   1654:     tlb->D1 = (env->CP0_EntryLo1 & 4) != 0;
                   1655:     tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7;
1.1       root     1656:     tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
                   1657: }
                   1658: 
1.1.1.8   root     1659: void r4k_helper_tlbwi (void)
1.1       root     1660: {
1.1.1.7   root     1661:     int idx;
                   1662: 
                   1663:     idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
                   1664: 
1.1.1.5   root     1665:     /* Discard cached TLB entries.  We could avoid doing this if the
                   1666:        tlbwi is just upgrading access permissions on the current entry;
                   1667:        that might be a further win.  */
1.1.1.6   root     1668:     r4k_mips_tlb_flush_extra (env, env->tlb->nb_tlb);
1.1.1.5   root     1669: 
1.1.1.7   root     1670:     r4k_invalidate_tlb(env, idx, 0);
                   1671:     r4k_fill_tlb(idx);
1.1       root     1672: }
                   1673: 
1.1.1.8   root     1674: void r4k_helper_tlbwr (void)
1.1       root     1675: {
                   1676:     int r = cpu_mips_get_random(env);
                   1677: 
1.1.1.6   root     1678:     r4k_invalidate_tlb(env, r, 1);
                   1679:     r4k_fill_tlb(r);
1.1       root     1680: }
                   1681: 
1.1.1.8   root     1682: void r4k_helper_tlbp (void)
1.1       root     1683: {
1.1.1.6   root     1684:     r4k_tlb_t *tlb;
                   1685:     target_ulong mask;
1.1       root     1686:     target_ulong tag;
1.1.1.6   root     1687:     target_ulong VPN;
1.1       root     1688:     uint8_t ASID;
                   1689:     int i;
                   1690: 
1.1.1.4   root     1691:     ASID = env->CP0_EntryHi & 0xFF;
1.1.1.6   root     1692:     for (i = 0; i < env->tlb->nb_tlb; i++) {
                   1693:         tlb = &env->tlb->mmu.r4k.tlb[i];
                   1694:         /* 1k pages are not supported. */
                   1695:         mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
                   1696:         tag = env->CP0_EntryHi & ~mask;
                   1697:         VPN = tlb->VPN & ~mask;
1.1       root     1698:         /* Check ASID, virtual page number & size */
1.1.1.6   root     1699:         if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1.1       root     1700:             /* TLB match */
1.1.1.5   root     1701:             env->CP0_Index = i;
1.1       root     1702:             break;
                   1703:         }
                   1704:     }
1.1.1.6   root     1705:     if (i == env->tlb->nb_tlb) {
1.1.1.5   root     1706:         /* No match.  Discard any shadow entries, if any of them match.  */
1.1.1.6   root     1707:         for (i = env->tlb->nb_tlb; i < env->tlb->tlb_in_use; i++) {
1.1.1.7   root     1708:             tlb = &env->tlb->mmu.r4k.tlb[i];
                   1709:             /* 1k pages are not supported. */
                   1710:             mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
                   1711:             tag = env->CP0_EntryHi & ~mask;
                   1712:             VPN = tlb->VPN & ~mask;
                   1713:             /* Check ASID, virtual page number & size */
                   1714:             if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
1.1.1.6   root     1715:                 r4k_mips_tlb_flush_extra (env, i);
1.1.1.7   root     1716:                 break;
                   1717:             }
                   1718:         }
1.1.1.5   root     1719: 
                   1720:         env->CP0_Index |= 0x80000000;
1.1       root     1721:     }
                   1722: }
                   1723: 
1.1.1.8   root     1724: void r4k_helper_tlbr (void)
1.1       root     1725: {
1.1.1.6   root     1726:     r4k_tlb_t *tlb;
1.1.1.3   root     1727:     uint8_t ASID;
1.1.1.7   root     1728:     int idx;
1.1       root     1729: 
1.1.1.3   root     1730:     ASID = env->CP0_EntryHi & 0xFF;
1.1.1.7   root     1731:     idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
                   1732:     tlb = &env->tlb->mmu.r4k.tlb[idx];
1.1.1.2   root     1733: 
                   1734:     /* If this will change the current ASID, flush qemu's TLB.  */
1.1.1.5   root     1735:     if (ASID != tlb->ASID)
                   1736:         cpu_mips_tlb_flush (env, 1);
                   1737: 
1.1.1.6   root     1738:     r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
1.1.1.2   root     1739: 
1.1       root     1740:     env->CP0_EntryHi = tlb->VPN | tlb->ASID;
1.1.1.5   root     1741:     env->CP0_PageMask = tlb->PageMask;
                   1742:     env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) |
                   1743:                         (tlb->C0 << 3) | (tlb->PFN[0] >> 6);
                   1744:     env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
                   1745:                         (tlb->C1 << 3) | (tlb->PFN[1] >> 6);
1.1       root     1746: }
                   1747: 
1.1.1.8   root     1748: void helper_tlbwi(void)
1.1.1.7   root     1749: {
1.1.1.8   root     1750:     env->tlb->helper_tlbwi();
1.1.1.7   root     1751: }
                   1752: 
1.1.1.8   root     1753: void helper_tlbwr(void)
1.1.1.7   root     1754: {
1.1.1.8   root     1755:     env->tlb->helper_tlbwr();
1.1.1.7   root     1756: }
                   1757: 
1.1.1.8   root     1758: void helper_tlbp(void)
1.1.1.7   root     1759: {
1.1.1.8   root     1760:     env->tlb->helper_tlbp();
1.1.1.7   root     1761: }
                   1762: 
1.1.1.8   root     1763: void helper_tlbr(void)
1.1.1.7   root     1764: {
1.1.1.8   root     1765:     env->tlb->helper_tlbr();
1.1.1.7   root     1766: }
                   1767: 
                   1768: /* Specials */
1.1.1.8   root     1769: target_ulong helper_di (void)
1.1.1.7   root     1770: {
                   1771:     target_ulong t0 = env->CP0_Status;
1.1.1.2   root     1772: 
1.1.1.7   root     1773:     env->CP0_Status = t0 & ~(1 << CP0St_IE);
                   1774:     return t0;
                   1775: }
                   1776: 
1.1.1.8   root     1777: target_ulong helper_ei (void)
1.1       root     1778: {
1.1.1.7   root     1779:     target_ulong t0 = env->CP0_Status;
                   1780: 
                   1781:     env->CP0_Status = t0 | (1 << CP0St_IE);
                   1782:     return t0;
1.1       root     1783: }
                   1784: 
1.1.1.7   root     1785: static void debug_pre_eret (void)
1.1       root     1786: {
1.1.1.7   root     1787:     if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
                   1788:         qemu_log("ERET: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
                   1789:                 env->active_tc.PC, env->CP0_EPC);
                   1790:         if (env->CP0_Status & (1 << CP0St_ERL))
                   1791:             qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
                   1792:         if (env->hflags & MIPS_HFLAG_DM)
                   1793:             qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
                   1794:         qemu_log("\n");
1.1       root     1795:     }
                   1796: }
                   1797: 
1.1.1.7   root     1798: static void debug_post_eret (void)
1.1       root     1799: {
1.1.1.7   root     1800:     if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
                   1801:         qemu_log("  =>  PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx,
                   1802:                 env->active_tc.PC, env->CP0_EPC);
                   1803:         if (env->CP0_Status & (1 << CP0St_ERL))
                   1804:             qemu_log(" ErrorEPC " TARGET_FMT_lx, env->CP0_ErrorEPC);
                   1805:         if (env->hflags & MIPS_HFLAG_DM)
                   1806:             qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
                   1807:         switch (env->hflags & MIPS_HFLAG_KSU) {
                   1808:         case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
                   1809:         case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
                   1810:         case MIPS_HFLAG_KM: qemu_log("\n"); break;
                   1811:         default: cpu_abort(env, "Invalid MMU mode!\n"); break;
                   1812:         }
                   1813:     }
1.1.1.6   root     1814: }
                   1815: 
1.1.1.11  root     1816: static void set_pc (target_ulong error_pc)
                   1817: {
                   1818:     env->active_tc.PC = error_pc & ~(target_ulong)1;
                   1819:     if (error_pc & 1) {
                   1820:         env->hflags |= MIPS_HFLAG_M16;
                   1821:     } else {
                   1822:         env->hflags &= ~(MIPS_HFLAG_M16);
                   1823:     }
                   1824: }
                   1825: 
1.1.1.8   root     1826: void helper_eret (void)
1.1.1.6   root     1827: {
1.1.1.7   root     1828:     debug_pre_eret();
                   1829:     if (env->CP0_Status & (1 << CP0St_ERL)) {
1.1.1.11  root     1830:         set_pc(env->CP0_ErrorEPC);
1.1.1.7   root     1831:         env->CP0_Status &= ~(1 << CP0St_ERL);
                   1832:     } else {
1.1.1.11  root     1833:         set_pc(env->CP0_EPC);
1.1.1.7   root     1834:         env->CP0_Status &= ~(1 << CP0St_EXL);
1.1       root     1835:     }
1.1.1.7   root     1836:     compute_hflags(env);
                   1837:     debug_post_eret();
1.1.1.9   root     1838:     env->lladdr = 1;
1.1.1.7   root     1839: }
                   1840: 
1.1.1.8   root     1841: void helper_deret (void)
1.1.1.7   root     1842: {
                   1843:     debug_pre_eret();
1.1.1.11  root     1844:     set_pc(env->CP0_DEPC);
                   1845: 
1.1.1.7   root     1846:     env->hflags &= MIPS_HFLAG_DM;
                   1847:     compute_hflags(env);
                   1848:     debug_post_eret();
1.1.1.9   root     1849:     env->lladdr = 1;
1.1.1.7   root     1850: }
                   1851: #endif /* !CONFIG_USER_ONLY */
                   1852: 
1.1.1.8   root     1853: target_ulong helper_rdhwr_cpunum(void)
1.1.1.7   root     1854: {
                   1855:     if ((env->hflags & MIPS_HFLAG_CP0) ||
                   1856:         (env->CP0_HWREna & (1 << 0)))
                   1857:         return env->CP0_EBase & 0x3ff;
                   1858:     else
1.1.1.8   root     1859:         helper_raise_exception(EXCP_RI);
1.1.1.7   root     1860: 
                   1861:     return 0;
                   1862: }
                   1863: 
1.1.1.8   root     1864: target_ulong helper_rdhwr_synci_step(void)
1.1.1.7   root     1865: {
                   1866:     if ((env->hflags & MIPS_HFLAG_CP0) ||
                   1867:         (env->CP0_HWREna & (1 << 1)))
                   1868:         return env->SYNCI_Step;
                   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_cc(void)
1.1.1.7   root     1876: {
                   1877:     if ((env->hflags & MIPS_HFLAG_CP0) ||
                   1878:         (env->CP0_HWREna & (1 << 2)))
                   1879:         return env->CP0_Count;
                   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_ccres(void)
1.1.1.7   root     1887: {
                   1888:     if ((env->hflags & MIPS_HFLAG_CP0) ||
                   1889:         (env->CP0_HWREna & (1 << 3)))
                   1890:         return env->CCRes;
                   1891:     else
1.1.1.8   root     1892:         helper_raise_exception(EXCP_RI);
1.1.1.7   root     1893: 
                   1894:     return 0;
1.1       root     1895: }
                   1896: 
1.1.1.8   root     1897: void helper_pmon (int function)
1.1       root     1898: {
                   1899:     function /= 2;
                   1900:     switch (function) {
                   1901:     case 2: /* TODO: char inbyte(int waitflag); */
1.1.1.7   root     1902:         if (env->active_tc.gpr[4] == 0)
                   1903:             env->active_tc.gpr[2] = -1;
1.1       root     1904:         /* Fall through */
                   1905:     case 11: /* TODO: char inbyte (void); */
1.1.1.7   root     1906:         env->active_tc.gpr[2] = -1;
1.1       root     1907:         break;
                   1908:     case 3:
                   1909:     case 12:
1.1.1.7   root     1910:         printf("%c", (char)(env->active_tc.gpr[4] & 0xFF));
1.1       root     1911:         break;
                   1912:     case 17:
                   1913:         break;
                   1914:     case 158:
                   1915:         {
1.1.1.7   root     1916:             unsigned char *fmt = (void *)(unsigned long)env->active_tc.gpr[4];
1.1       root     1917:             printf("%s", fmt);
                   1918:         }
                   1919:         break;
                   1920:     }
                   1921: }
                   1922: 
1.1.1.8   root     1923: void helper_wait (void)
1.1.1.7   root     1924: {
                   1925:     env->halted = 1;
1.1.1.8   root     1926:     helper_raise_exception(EXCP_HLT);
1.1.1.7   root     1927: }
                   1928: 
1.1.1.6   root     1929: #if !defined(CONFIG_USER_ONLY)
1.1       root     1930: 
1.1.1.2   root     1931: static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr);
                   1932: 
1.1       root     1933: #define MMUSUFFIX _mmu
1.1.1.2   root     1934: #define ALIGNED_ONLY
1.1       root     1935: 
                   1936: #define SHIFT 0
                   1937: #include "softmmu_template.h"
                   1938: 
                   1939: #define SHIFT 1
                   1940: #include "softmmu_template.h"
                   1941: 
                   1942: #define SHIFT 2
                   1943: #include "softmmu_template.h"
                   1944: 
                   1945: #define SHIFT 3
                   1946: #include "softmmu_template.h"
                   1947: 
1.1.1.2   root     1948: static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr)
                   1949: {
                   1950:     env->CP0_BadVAddr = addr;
                   1951:     do_restore_state (retaddr);
1.1.1.8   root     1952:     helper_raise_exception ((is_write == 1) ? EXCP_AdES : EXCP_AdEL);
1.1.1.2   root     1953: }
                   1954: 
1.1.1.6   root     1955: void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1.1       root     1956: {
                   1957:     TranslationBlock *tb;
                   1958:     CPUState *saved_env;
                   1959:     unsigned long pc;
                   1960:     int ret;
                   1961: 
                   1962:     /* XXX: hack to restore env in all cases, even if not called from
                   1963:        generated code */
                   1964:     saved_env = env;
                   1965:     env = cpu_single_env;
1.1.1.6   root     1966:     ret = cpu_mips_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1.1       root     1967:     if (ret) {
                   1968:         if (retaddr) {
                   1969:             /* now we have a real cpu fault */
                   1970:             pc = (unsigned long)retaddr;
                   1971:             tb = tb_find_pc(pc);
                   1972:             if (tb) {
                   1973:                 /* the PC is inside the translated code. It means that we have
                   1974:                    a virtual CPU fault */
                   1975:                 cpu_restore_state(tb, env, pc, NULL);
                   1976:             }
                   1977:         }
1.1.1.8   root     1978:         helper_raise_exception_err(env->exception_index, env->error_code);
1.1       root     1979:     }
                   1980:     env = saved_env;
                   1981: }
                   1982: 
1.1.1.6   root     1983: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1.1.1.7   root     1984:                           int unused, int size)
1.1.1.6   root     1985: {
                   1986:     if (is_exec)
1.1.1.8   root     1987:         helper_raise_exception(EXCP_IBE);
1.1.1.6   root     1988:     else
1.1.1.8   root     1989:         helper_raise_exception(EXCP_DBE);
1.1.1.6   root     1990: }
1.1.1.7   root     1991: #endif /* !CONFIG_USER_ONLY */
1.1.1.6   root     1992: 
                   1993: /* Complex FPU operations which may need stack space. */
                   1994: 
                   1995: #define FLOAT_ONE32 make_float32(0x3f8 << 20)
                   1996: #define FLOAT_ONE64 make_float64(0x3ffULL << 52)
                   1997: #define FLOAT_TWO32 make_float32(1 << 30)
                   1998: #define FLOAT_TWO64 make_float64(1ULL << 62)
                   1999: #define FLOAT_QNAN32 0x7fbfffff
                   2000: #define FLOAT_QNAN64 0x7ff7ffffffffffffULL
                   2001: #define FLOAT_SNAN32 0x7fffffff
                   2002: #define FLOAT_SNAN64 0x7fffffffffffffffULL
                   2003: 
                   2004: /* convert MIPS rounding mode in FCR31 to IEEE library */
1.1.1.9   root     2005: static unsigned int ieee_rm[] = {
1.1.1.6   root     2006:     float_round_nearest_even,
                   2007:     float_round_to_zero,
                   2008:     float_round_up,
                   2009:     float_round_down
                   2010: };
                   2011: 
                   2012: #define RESTORE_ROUNDING_MODE \
1.1.1.7   root     2013:     set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], &env->active_fpu.fp_status)
1.1.1.6   root     2014: 
1.1.1.8   root     2015: #define RESTORE_FLUSH_MODE \
                   2016:     set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0, &env->active_fpu.fp_status);
                   2017: 
                   2018: target_ulong helper_cfc1 (uint32_t reg)
1.1.1.6   root     2019: {
1.1.1.8   root     2020:     target_ulong arg1;
1.1.1.7   root     2021: 
1.1.1.6   root     2022:     switch (reg) {
                   2023:     case 0:
1.1.1.8   root     2024:         arg1 = (int32_t)env->active_fpu.fcr0;
1.1.1.6   root     2025:         break;
                   2026:     case 25:
1.1.1.8   root     2027:         arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1);
1.1.1.6   root     2028:         break;
                   2029:     case 26:
1.1.1.8   root     2030:         arg1 = env->active_fpu.fcr31 & 0x0003f07c;
1.1.1.6   root     2031:         break;
                   2032:     case 28:
1.1.1.8   root     2033:         arg1 = (env->active_fpu.fcr31 & 0x00000f83) | ((env->active_fpu.fcr31 >> 22) & 0x4);
1.1.1.6   root     2034:         break;
                   2035:     default:
1.1.1.8   root     2036:         arg1 = (int32_t)env->active_fpu.fcr31;
1.1.1.6   root     2037:         break;
                   2038:     }
1.1.1.7   root     2039: 
1.1.1.8   root     2040:     return arg1;
1.1.1.6   root     2041: }
                   2042: 
1.1.1.8   root     2043: void helper_ctc1 (target_ulong arg1, uint32_t reg)
1.1.1.6   root     2044: {
                   2045:     switch(reg) {
                   2046:     case 25:
1.1.1.8   root     2047:         if (arg1 & 0xffffff00)
1.1.1.6   root     2048:             return;
1.1.1.8   root     2049:         env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | ((arg1 & 0xfe) << 24) |
                   2050:                      ((arg1 & 0x1) << 23);
1.1.1.6   root     2051:         break;
                   2052:     case 26:
1.1.1.8   root     2053:         if (arg1 & 0x007c0000)
1.1.1.6   root     2054:             return;
1.1.1.8   root     2055:         env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfffc0f83) | (arg1 & 0x0003f07c);
1.1.1.6   root     2056:         break;
                   2057:     case 28:
1.1.1.8   root     2058:         if (arg1 & 0x007c0000)
1.1.1.6   root     2059:             return;
1.1.1.8   root     2060:         env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfefff07c) | (arg1 & 0x00000f83) |
                   2061:                      ((arg1 & 0x4) << 22);
1.1.1.6   root     2062:         break;
                   2063:     case 31:
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 = arg1;
1.1.1.6   root     2067:         break;
                   2068:     default:
                   2069:         return;
                   2070:     }
                   2071:     /* set rounding mode */
                   2072:     RESTORE_ROUNDING_MODE;
1.1.1.8   root     2073:     /* set flush-to-zero mode */
                   2074:     RESTORE_FLUSH_MODE;
1.1.1.7   root     2075:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2076:     if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31))
1.1.1.8   root     2077:         helper_raise_exception(EXCP_FPE);
1.1.1.6   root     2078: }
                   2079: 
1.1.1.7   root     2080: static inline char ieee_ex_to_mips(char xcpt)
1.1.1.6   root     2081: {
                   2082:     return (xcpt & float_flag_inexact) >> 5 |
                   2083:            (xcpt & float_flag_underflow) >> 3 |
                   2084:            (xcpt & float_flag_overflow) >> 1 |
                   2085:            (xcpt & float_flag_divbyzero) << 1 |
                   2086:            (xcpt & float_flag_invalid) << 4;
                   2087: }
                   2088: 
1.1.1.7   root     2089: static inline char mips_ex_to_ieee(char xcpt)
1.1.1.6   root     2090: {
                   2091:     return (xcpt & FP_INEXACT) << 5 |
                   2092:            (xcpt & FP_UNDERFLOW) << 3 |
                   2093:            (xcpt & FP_OVERFLOW) << 1 |
                   2094:            (xcpt & FP_DIV0) >> 1 |
                   2095:            (xcpt & FP_INVALID) >> 4;
                   2096: }
                   2097: 
1.1.1.7   root     2098: static inline void update_fcr31(void)
1.1.1.6   root     2099: {
1.1.1.7   root     2100:     int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->active_fpu.fp_status));
1.1.1.6   root     2101: 
1.1.1.7   root     2102:     SET_FP_CAUSE(env->active_fpu.fcr31, tmp);
                   2103:     if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp)
1.1.1.8   root     2104:         helper_raise_exception(EXCP_FPE);
1.1.1.6   root     2105:     else
1.1.1.7   root     2106:         UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp);
1.1.1.6   root     2107: }
                   2108: 
1.1.1.7   root     2109: /* Float support.
                   2110:    Single precition routines have a "s" suffix, double precision a
                   2111:    "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps",
                   2112:    paired single lower "pl", paired single upper "pu".  */
                   2113: 
                   2114: /* unary operations, modifying fp status  */
1.1.1.8   root     2115: uint64_t helper_float_sqrt_d(uint64_t fdt0)
1.1.1.7   root     2116: {
                   2117:     return float64_sqrt(fdt0, &env->active_fpu.fp_status);
                   2118: }
1.1.1.6   root     2119: 
1.1.1.8   root     2120: uint32_t helper_float_sqrt_s(uint32_t fst0)
1.1.1.6   root     2121: {
1.1.1.7   root     2122:     return float32_sqrt(fst0, &env->active_fpu.fp_status);
                   2123: }
                   2124: 
1.1.1.8   root     2125: uint64_t helper_float_cvtd_s(uint32_t fst0)
1.1.1.7   root     2126: {
                   2127:     uint64_t fdt2;
                   2128: 
                   2129:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2130:     fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2131:     update_fcr31();
1.1.1.7   root     2132:     return fdt2;
1.1.1.6   root     2133: }
1.1.1.7   root     2134: 
1.1.1.8   root     2135: uint64_t helper_float_cvtd_w(uint32_t wt0)
1.1.1.6   root     2136: {
1.1.1.7   root     2137:     uint64_t fdt2;
                   2138: 
                   2139:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2140:     fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status);
1.1.1.6   root     2141:     update_fcr31();
1.1.1.7   root     2142:     return fdt2;
1.1.1.6   root     2143: }
1.1.1.7   root     2144: 
1.1.1.8   root     2145: uint64_t helper_float_cvtd_l(uint64_t dt0)
1.1.1.6   root     2146: {
1.1.1.7   root     2147:     uint64_t fdt2;
                   2148: 
                   2149:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2150:     fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status);
1.1.1.6   root     2151:     update_fcr31();
1.1.1.7   root     2152:     return fdt2;
1.1.1.6   root     2153: }
1.1.1.7   root     2154: 
1.1.1.8   root     2155: uint64_t helper_float_cvtl_d(uint64_t fdt0)
1.1.1.6   root     2156: {
1.1.1.7   root     2157:     uint64_t dt2;
                   2158: 
                   2159:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2160:     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2161:     update_fcr31();
1.1.1.7   root     2162:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2163:         dt2 = FLOAT_SNAN64;
                   2164:     return dt2;
1.1.1.6   root     2165: }
1.1.1.7   root     2166: 
1.1.1.8   root     2167: uint64_t helper_float_cvtl_s(uint32_t fst0)
1.1.1.6   root     2168: {
1.1.1.7   root     2169:     uint64_t dt2;
                   2170: 
                   2171:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2172:     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2173:     update_fcr31();
1.1.1.7   root     2174:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2175:         dt2 = FLOAT_SNAN64;
                   2176:     return dt2;
1.1.1.6   root     2177: }
                   2178: 
1.1.1.8   root     2179: uint64_t helper_float_cvtps_pw(uint64_t dt0)
1.1.1.6   root     2180: {
1.1.1.7   root     2181:     uint32_t fst2;
                   2182:     uint32_t fsth2;
                   2183: 
                   2184:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2185:     fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
                   2186:     fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status);
1.1.1.6   root     2187:     update_fcr31();
1.1.1.7   root     2188:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2189: }
1.1.1.7   root     2190: 
1.1.1.8   root     2191: uint64_t helper_float_cvtpw_ps(uint64_t fdt0)
1.1.1.6   root     2192: {
1.1.1.7   root     2193:     uint32_t wt2;
                   2194:     uint32_t wth2;
                   2195: 
                   2196:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2197:     wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
                   2198:     wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status);
1.1.1.6   root     2199:     update_fcr31();
1.1.1.7   root     2200:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) {
                   2201:         wt2 = FLOAT_SNAN32;
                   2202:         wth2 = FLOAT_SNAN32;
                   2203:     }
                   2204:     return ((uint64_t)wth2 << 32) | wt2;
1.1.1.6   root     2205: }
1.1.1.7   root     2206: 
1.1.1.8   root     2207: uint32_t helper_float_cvts_d(uint64_t fdt0)
1.1.1.6   root     2208: {
1.1.1.7   root     2209:     uint32_t fst2;
                   2210: 
                   2211:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2212:     fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2213:     update_fcr31();
1.1.1.7   root     2214:     return fst2;
1.1.1.6   root     2215: }
1.1.1.7   root     2216: 
1.1.1.8   root     2217: uint32_t helper_float_cvts_w(uint32_t wt0)
1.1.1.6   root     2218: {
1.1.1.7   root     2219:     uint32_t fst2;
                   2220: 
                   2221:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2222:     fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status);
1.1.1.6   root     2223:     update_fcr31();
1.1.1.7   root     2224:     return fst2;
1.1.1.6   root     2225: }
1.1.1.7   root     2226: 
1.1.1.8   root     2227: uint32_t helper_float_cvts_l(uint64_t dt0)
1.1.1.6   root     2228: {
1.1.1.7   root     2229:     uint32_t fst2;
                   2230: 
                   2231:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2232:     fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status);
1.1.1.6   root     2233:     update_fcr31();
1.1.1.7   root     2234:     return fst2;
1.1.1.6   root     2235: }
1.1.1.7   root     2236: 
1.1.1.8   root     2237: uint32_t helper_float_cvts_pl(uint32_t wt0)
1.1.1.6   root     2238: {
1.1.1.7   root     2239:     uint32_t wt2;
                   2240: 
                   2241:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2242:     wt2 = wt0;
1.1.1.6   root     2243:     update_fcr31();
1.1.1.7   root     2244:     return wt2;
1.1.1.6   root     2245: }
1.1.1.7   root     2246: 
1.1.1.8   root     2247: uint32_t helper_float_cvts_pu(uint32_t wth0)
1.1.1.6   root     2248: {
1.1.1.7   root     2249:     uint32_t wt2;
                   2250: 
                   2251:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2252:     wt2 = wth0;
1.1.1.6   root     2253:     update_fcr31();
1.1.1.7   root     2254:     return wt2;
1.1.1.6   root     2255: }
1.1.1.7   root     2256: 
1.1.1.8   root     2257: uint32_t helper_float_cvtw_s(uint32_t fst0)
1.1.1.6   root     2258: {
1.1.1.7   root     2259:     uint32_t wt2;
                   2260: 
                   2261:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2262:     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2263:     update_fcr31();
1.1.1.7   root     2264:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2265:         wt2 = FLOAT_SNAN32;
                   2266:     return wt2;
1.1.1.6   root     2267: }
1.1.1.7   root     2268: 
1.1.1.8   root     2269: uint32_t helper_float_cvtw_d(uint64_t fdt0)
1.1.1.6   root     2270: {
1.1.1.7   root     2271:     uint32_t wt2;
                   2272: 
                   2273:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2274:     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2275:     update_fcr31();
1.1.1.7   root     2276:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2277:         wt2 = FLOAT_SNAN32;
                   2278:     return wt2;
1.1.1.6   root     2279: }
                   2280: 
1.1.1.8   root     2281: uint64_t helper_float_roundl_d(uint64_t fdt0)
1.1.1.6   root     2282: {
1.1.1.7   root     2283:     uint64_t dt2;
                   2284: 
                   2285:     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
                   2286:     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2287:     RESTORE_ROUNDING_MODE;
                   2288:     update_fcr31();
1.1.1.7   root     2289:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2290:         dt2 = FLOAT_SNAN64;
                   2291:     return dt2;
1.1.1.6   root     2292: }
1.1.1.7   root     2293: 
1.1.1.8   root     2294: uint64_t helper_float_roundl_s(uint32_t fst0)
1.1.1.6   root     2295: {
1.1.1.7   root     2296:     uint64_t dt2;
                   2297: 
                   2298:     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
                   2299:     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2300:     RESTORE_ROUNDING_MODE;
                   2301:     update_fcr31();
1.1.1.7   root     2302:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2303:         dt2 = FLOAT_SNAN64;
                   2304:     return dt2;
1.1.1.6   root     2305: }
1.1.1.7   root     2306: 
1.1.1.8   root     2307: uint32_t helper_float_roundw_d(uint64_t fdt0)
1.1.1.6   root     2308: {
1.1.1.7   root     2309:     uint32_t wt2;
                   2310: 
                   2311:     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
                   2312:     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2313:     RESTORE_ROUNDING_MODE;
                   2314:     update_fcr31();
1.1.1.7   root     2315:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2316:         wt2 = FLOAT_SNAN32;
                   2317:     return wt2;
1.1.1.6   root     2318: }
1.1.1.7   root     2319: 
1.1.1.8   root     2320: uint32_t helper_float_roundw_s(uint32_t fst0)
1.1.1.6   root     2321: {
1.1.1.7   root     2322:     uint32_t wt2;
                   2323: 
                   2324:     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
                   2325:     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2326:     RESTORE_ROUNDING_MODE;
                   2327:     update_fcr31();
1.1.1.7   root     2328:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2329:         wt2 = FLOAT_SNAN32;
                   2330:     return wt2;
1.1.1.6   root     2331: }
                   2332: 
1.1.1.8   root     2333: uint64_t helper_float_truncl_d(uint64_t fdt0)
1.1.1.6   root     2334: {
1.1.1.7   root     2335:     uint64_t dt2;
                   2336: 
                   2337:     dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2338:     update_fcr31();
1.1.1.7   root     2339:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2340:         dt2 = FLOAT_SNAN64;
                   2341:     return dt2;
1.1.1.6   root     2342: }
1.1.1.7   root     2343: 
1.1.1.8   root     2344: uint64_t helper_float_truncl_s(uint32_t fst0)
1.1.1.6   root     2345: {
1.1.1.7   root     2346:     uint64_t dt2;
                   2347: 
                   2348:     dt2 = float32_to_int64_round_to_zero(fst0, &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: uint32_t helper_float_truncw_d(uint64_t fdt0)
1.1.1.6   root     2356: {
1.1.1.7   root     2357:     uint32_t wt2;
                   2358: 
                   2359:     wt2 = float64_to_int32_round_to_zero(fdt0, &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:         wt2 = FLOAT_SNAN32;
                   2363:     return wt2;
1.1.1.6   root     2364: }
1.1.1.7   root     2365: 
1.1.1.8   root     2366: uint32_t helper_float_truncw_s(uint32_t fst0)
1.1.1.6   root     2367: {
1.1.1.7   root     2368:     uint32_t wt2;
                   2369: 
                   2370:     wt2 = float32_to_int32_round_to_zero(fst0, &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: }
                   2376: 
1.1.1.8   root     2377: uint64_t helper_float_ceill_d(uint64_t fdt0)
1.1.1.6   root     2378: {
1.1.1.7   root     2379:     uint64_t dt2;
                   2380: 
                   2381:     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
                   2382:     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2383:     RESTORE_ROUNDING_MODE;
                   2384:     update_fcr31();
1.1.1.7   root     2385:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2386:         dt2 = FLOAT_SNAN64;
                   2387:     return dt2;
1.1.1.6   root     2388: }
1.1.1.7   root     2389: 
1.1.1.8   root     2390: uint64_t helper_float_ceill_s(uint32_t fst0)
1.1.1.6   root     2391: {
1.1.1.7   root     2392:     uint64_t dt2;
                   2393: 
                   2394:     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
                   2395:     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2396:     RESTORE_ROUNDING_MODE;
                   2397:     update_fcr31();
1.1.1.7   root     2398:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2399:         dt2 = FLOAT_SNAN64;
                   2400:     return dt2;
1.1.1.6   root     2401: }
1.1.1.7   root     2402: 
1.1.1.8   root     2403: uint32_t helper_float_ceilw_d(uint64_t fdt0)
1.1.1.6   root     2404: {
1.1.1.7   root     2405:     uint32_t wt2;
                   2406: 
                   2407:     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
                   2408:     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2409:     RESTORE_ROUNDING_MODE;
                   2410:     update_fcr31();
1.1.1.7   root     2411:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2412:         wt2 = FLOAT_SNAN32;
                   2413:     return wt2;
1.1.1.6   root     2414: }
1.1.1.7   root     2415: 
1.1.1.8   root     2416: uint32_t helper_float_ceilw_s(uint32_t fst0)
1.1.1.6   root     2417: {
1.1.1.7   root     2418:     uint32_t wt2;
                   2419: 
                   2420:     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
                   2421:     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2422:     RESTORE_ROUNDING_MODE;
                   2423:     update_fcr31();
1.1.1.7   root     2424:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2425:         wt2 = FLOAT_SNAN32;
                   2426:     return wt2;
1.1.1.6   root     2427: }
                   2428: 
1.1.1.8   root     2429: uint64_t helper_float_floorl_d(uint64_t fdt0)
1.1.1.6   root     2430: {
1.1.1.7   root     2431:     uint64_t dt2;
                   2432: 
                   2433:     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
                   2434:     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2435:     RESTORE_ROUNDING_MODE;
                   2436:     update_fcr31();
1.1.1.7   root     2437:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2438:         dt2 = FLOAT_SNAN64;
                   2439:     return dt2;
1.1.1.6   root     2440: }
1.1.1.7   root     2441: 
1.1.1.8   root     2442: uint64_t helper_float_floorl_s(uint32_t fst0)
1.1.1.6   root     2443: {
1.1.1.7   root     2444:     uint64_t dt2;
                   2445: 
                   2446:     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
                   2447:     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2448:     RESTORE_ROUNDING_MODE;
                   2449:     update_fcr31();
1.1.1.7   root     2450:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2451:         dt2 = FLOAT_SNAN64;
                   2452:     return dt2;
1.1.1.6   root     2453: }
1.1.1.7   root     2454: 
1.1.1.8   root     2455: uint32_t helper_float_floorw_d(uint64_t fdt0)
1.1.1.6   root     2456: {
1.1.1.7   root     2457:     uint32_t wt2;
                   2458: 
                   2459:     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
                   2460:     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2461:     RESTORE_ROUNDING_MODE;
                   2462:     update_fcr31();
1.1.1.7   root     2463:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2464:         wt2 = FLOAT_SNAN32;
                   2465:     return wt2;
1.1.1.6   root     2466: }
1.1.1.7   root     2467: 
1.1.1.8   root     2468: uint32_t helper_float_floorw_s(uint32_t fst0)
1.1.1.6   root     2469: {
1.1.1.7   root     2470:     uint32_t wt2;
                   2471: 
                   2472:     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
                   2473:     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2474:     RESTORE_ROUNDING_MODE;
                   2475:     update_fcr31();
1.1.1.7   root     2476:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2477:         wt2 = FLOAT_SNAN32;
                   2478:     return wt2;
                   2479: }
                   2480: 
                   2481: /* unary operations, not modifying fp status  */
                   2482: #define FLOAT_UNOP(name)                                       \
1.1.1.8   root     2483: uint64_t helper_float_ ## name ## _d(uint64_t fdt0)                \
1.1.1.7   root     2484: {                                                              \
                   2485:     return float64_ ## name(fdt0);                             \
                   2486: }                                                              \
1.1.1.8   root     2487: uint32_t helper_float_ ## name ## _s(uint32_t fst0)                \
1.1.1.7   root     2488: {                                                              \
                   2489:     return float32_ ## name(fst0);                             \
                   2490: }                                                              \
1.1.1.8   root     2491: uint64_t helper_float_ ## name ## _ps(uint64_t fdt0)               \
1.1.1.7   root     2492: {                                                              \
                   2493:     uint32_t wt0;                                              \
                   2494:     uint32_t wth0;                                             \
                   2495:                                                                \
                   2496:     wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF);                 \
                   2497:     wth0 = float32_ ## name(fdt0 >> 32);                       \
                   2498:     return ((uint64_t)wth0 << 32) | wt0;                       \
                   2499: }
                   2500: FLOAT_UNOP(abs)
                   2501: FLOAT_UNOP(chs)
                   2502: #undef FLOAT_UNOP
1.1.1.6   root     2503: 
                   2504: /* MIPS specific unary operations */
1.1.1.8   root     2505: uint64_t helper_float_recip_d(uint64_t fdt0)
1.1.1.6   root     2506: {
1.1.1.7   root     2507:     uint64_t fdt2;
                   2508: 
                   2509:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2510:     fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2511:     update_fcr31();
1.1.1.7   root     2512:     return fdt2;
1.1.1.6   root     2513: }
1.1.1.7   root     2514: 
1.1.1.8   root     2515: uint32_t helper_float_recip_s(uint32_t fst0)
1.1.1.6   root     2516: {
1.1.1.7   root     2517:     uint32_t fst2;
                   2518: 
                   2519:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2520:     fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2521:     update_fcr31();
1.1.1.7   root     2522:     return fst2;
1.1.1.6   root     2523: }
                   2524: 
1.1.1.8   root     2525: uint64_t helper_float_rsqrt_d(uint64_t fdt0)
1.1.1.6   root     2526: {
1.1.1.7   root     2527:     uint64_t fdt2;
                   2528: 
                   2529:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2530:     fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
                   2531:     fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status);
1.1.1.6   root     2532:     update_fcr31();
1.1.1.7   root     2533:     return fdt2;
1.1.1.6   root     2534: }
1.1.1.7   root     2535: 
1.1.1.8   root     2536: uint32_t helper_float_rsqrt_s(uint32_t fst0)
1.1.1.6   root     2537: {
1.1.1.7   root     2538:     uint32_t fst2;
                   2539: 
                   2540:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2541:     fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
                   2542:     fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
1.1.1.6   root     2543:     update_fcr31();
1.1.1.7   root     2544:     return fst2;
1.1.1.6   root     2545: }
                   2546: 
1.1.1.8   root     2547: uint64_t helper_float_recip1_d(uint64_t fdt0)
1.1.1.6   root     2548: {
1.1.1.7   root     2549:     uint64_t fdt2;
                   2550: 
                   2551:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2552:     fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2553:     update_fcr31();
1.1.1.7   root     2554:     return fdt2;
1.1.1.6   root     2555: }
1.1.1.7   root     2556: 
1.1.1.8   root     2557: uint32_t helper_float_recip1_s(uint32_t fst0)
1.1.1.6   root     2558: {
1.1.1.7   root     2559:     uint32_t fst2;
                   2560: 
                   2561:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2562:     fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2563:     update_fcr31();
1.1.1.7   root     2564:     return fst2;
1.1.1.6   root     2565: }
1.1.1.7   root     2566: 
1.1.1.8   root     2567: uint64_t helper_float_recip1_ps(uint64_t fdt0)
1.1.1.6   root     2568: {
1.1.1.7   root     2569:     uint32_t fst2;
                   2570:     uint32_t fsth2;
                   2571: 
                   2572:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2573:     fst2 = float32_div(FLOAT_ONE32, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
                   2574:     fsth2 = float32_div(FLOAT_ONE32, fdt0 >> 32, &env->active_fpu.fp_status);
1.1.1.6   root     2575:     update_fcr31();
1.1.1.7   root     2576:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2577: }
                   2578: 
1.1.1.8   root     2579: uint64_t helper_float_rsqrt1_d(uint64_t fdt0)
1.1.1.6   root     2580: {
1.1.1.7   root     2581:     uint64_t fdt2;
                   2582: 
                   2583:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2584:     fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
                   2585:     fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status);
1.1.1.6   root     2586:     update_fcr31();
1.1.1.7   root     2587:     return fdt2;
1.1.1.6   root     2588: }
1.1.1.7   root     2589: 
1.1.1.8   root     2590: uint32_t helper_float_rsqrt1_s(uint32_t fst0)
1.1.1.6   root     2591: {
1.1.1.7   root     2592:     uint32_t fst2;
                   2593: 
                   2594:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2595:     fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
                   2596:     fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
1.1.1.6   root     2597:     update_fcr31();
1.1.1.7   root     2598:     return fst2;
1.1.1.6   root     2599: }
1.1.1.7   root     2600: 
1.1.1.8   root     2601: uint64_t helper_float_rsqrt1_ps(uint64_t fdt0)
1.1.1.6   root     2602: {
1.1.1.7   root     2603:     uint32_t fst2;
                   2604:     uint32_t fsth2;
                   2605: 
                   2606:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2607:     fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
                   2608:     fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status);
                   2609:     fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
                   2610:     fsth2 = float32_div(FLOAT_ONE32, fsth2, &env->active_fpu.fp_status);
1.1.1.6   root     2611:     update_fcr31();
1.1.1.7   root     2612:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2613: }
                   2614: 
1.1.1.8   root     2615: #define FLOAT_OP(name, p) void helper_float_##name##_##p(void)
1.1.1.7   root     2616: 
1.1.1.6   root     2617: /* binary operations */
1.1.1.7   root     2618: #define FLOAT_BINOP(name)                                          \
1.1.1.8   root     2619: uint64_t helper_float_ ## name ## _d(uint64_t fdt0, uint64_t fdt1)     \
1.1.1.7   root     2620: {                                                                  \
                   2621:     uint64_t dt2;                                                  \
                   2622:                                                                    \
                   2623:     set_float_exception_flags(0, &env->active_fpu.fp_status);            \
                   2624:     dt2 = float64_ ## name (fdt0, fdt1, &env->active_fpu.fp_status);     \
                   2625:     update_fcr31();                                                \
                   2626:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID)                \
                   2627:         dt2 = FLOAT_QNAN64;                                        \
                   2628:     return dt2;                                                    \
                   2629: }                                                                  \
                   2630:                                                                    \
1.1.1.8   root     2631: uint32_t helper_float_ ## name ## _s(uint32_t fst0, uint32_t fst1)     \
1.1.1.7   root     2632: {                                                                  \
                   2633:     uint32_t wt2;                                                  \
                   2634:                                                                    \
                   2635:     set_float_exception_flags(0, &env->active_fpu.fp_status);            \
                   2636:     wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status);     \
1.1.1.6   root     2637:     update_fcr31();                                                \
1.1.1.7   root     2638:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID)                \
                   2639:         wt2 = FLOAT_QNAN32;                                        \
                   2640:     return wt2;                                                    \
                   2641: }                                                                  \
                   2642:                                                                    \
1.1.1.8   root     2643: uint64_t helper_float_ ## name ## _ps(uint64_t fdt0, uint64_t fdt1)    \
1.1.1.7   root     2644: {                                                                  \
                   2645:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;                             \
                   2646:     uint32_t fsth0 = fdt0 >> 32;                                   \
                   2647:     uint32_t fst1 = fdt1 & 0XFFFFFFFF;                             \
                   2648:     uint32_t fsth1 = fdt1 >> 32;                                   \
                   2649:     uint32_t wt2;                                                  \
                   2650:     uint32_t wth2;                                                 \
                   2651:                                                                    \
                   2652:     set_float_exception_flags(0, &env->active_fpu.fp_status);            \
                   2653:     wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status);     \
                   2654:     wth2 = float32_ ## name (fsth0, fsth1, &env->active_fpu.fp_status);  \
1.1.1.6   root     2655:     update_fcr31();                                                \
1.1.1.7   root     2656:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) {              \
                   2657:         wt2 = FLOAT_QNAN32;                                        \
                   2658:         wth2 = FLOAT_QNAN32;                                       \
                   2659:     }                                                              \
                   2660:     return ((uint64_t)wth2 << 32) | wt2;                           \
1.1.1.6   root     2661: }
1.1.1.7   root     2662: 
1.1.1.6   root     2663: FLOAT_BINOP(add)
                   2664: FLOAT_BINOP(sub)
                   2665: FLOAT_BINOP(mul)
                   2666: FLOAT_BINOP(div)
                   2667: #undef FLOAT_BINOP
                   2668: 
1.1.1.7   root     2669: /* ternary operations */
                   2670: #define FLOAT_TERNOP(name1, name2)                                        \
1.1.1.8   root     2671: uint64_t helper_float_ ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1,  \
1.1.1.7   root     2672:                                            uint64_t fdt2)                 \
                   2673: {                                                                         \
                   2674:     fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status);          \
                   2675:     return float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status);          \
                   2676: }                                                                         \
                   2677:                                                                           \
1.1.1.8   root     2678: uint32_t helper_float_ ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1,  \
1.1.1.7   root     2679:                                            uint32_t fst2)                 \
                   2680: {                                                                         \
                   2681:     fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
                   2682:     return float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
                   2683: }                                                                         \
                   2684:                                                                           \
1.1.1.8   root     2685: uint64_t helper_float_ ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1, \
1.1.1.7   root     2686:                                             uint64_t fdt2)                \
                   2687: {                                                                         \
                   2688:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;                                    \
                   2689:     uint32_t fsth0 = fdt0 >> 32;                                          \
                   2690:     uint32_t fst1 = fdt1 & 0XFFFFFFFF;                                    \
                   2691:     uint32_t fsth1 = fdt1 >> 32;                                          \
                   2692:     uint32_t fst2 = fdt2 & 0XFFFFFFFF;                                    \
                   2693:     uint32_t fsth2 = fdt2 >> 32;                                          \
                   2694:                                                                           \
                   2695:     fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
                   2696:     fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status);       \
                   2697:     fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
                   2698:     fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status);       \
                   2699:     return ((uint64_t)fsth2 << 32) | fst2;                                \
                   2700: }
                   2701: 
                   2702: FLOAT_TERNOP(mul, add)
                   2703: FLOAT_TERNOP(mul, sub)
                   2704: #undef FLOAT_TERNOP
                   2705: 
                   2706: /* negated ternary operations */
                   2707: #define FLOAT_NTERNOP(name1, name2)                                       \
1.1.1.8   root     2708: uint64_t helper_float_n ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1, \
1.1.1.7   root     2709:                                            uint64_t fdt2)                 \
                   2710: {                                                                         \
                   2711:     fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status);          \
                   2712:     fdt2 = float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status);          \
                   2713:     return float64_chs(fdt2);                                             \
                   2714: }                                                                         \
                   2715:                                                                           \
1.1.1.8   root     2716: uint32_t helper_float_n ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1, \
1.1.1.7   root     2717:                                            uint32_t fst2)                 \
                   2718: {                                                                         \
                   2719:     fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
                   2720:     fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
                   2721:     return float32_chs(fst2);                                             \
                   2722: }                                                                         \
                   2723:                                                                           \
1.1.1.8   root     2724: uint64_t helper_float_n ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1,\
1.1.1.7   root     2725:                                            uint64_t fdt2)                 \
                   2726: {                                                                         \
                   2727:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;                                    \
                   2728:     uint32_t fsth0 = fdt0 >> 32;                                          \
                   2729:     uint32_t fst1 = fdt1 & 0XFFFFFFFF;                                    \
                   2730:     uint32_t fsth1 = fdt1 >> 32;                                          \
                   2731:     uint32_t fst2 = fdt2 & 0XFFFFFFFF;                                    \
                   2732:     uint32_t fsth2 = fdt2 >> 32;                                          \
                   2733:                                                                           \
                   2734:     fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
                   2735:     fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status);       \
                   2736:     fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
                   2737:     fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status);       \
                   2738:     fst2 = float32_chs(fst2);                                             \
                   2739:     fsth2 = float32_chs(fsth2);                                           \
                   2740:     return ((uint64_t)fsth2 << 32) | fst2;                                \
                   2741: }
                   2742: 
                   2743: FLOAT_NTERNOP(mul, add)
                   2744: FLOAT_NTERNOP(mul, sub)
                   2745: #undef FLOAT_NTERNOP
                   2746: 
1.1.1.6   root     2747: /* MIPS specific binary operations */
1.1.1.8   root     2748: uint64_t helper_float_recip2_d(uint64_t fdt0, uint64_t fdt2)
1.1.1.6   root     2749: {
1.1.1.7   root     2750:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2751:     fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
                   2752:     fdt2 = float64_chs(float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status));
1.1.1.6   root     2753:     update_fcr31();
1.1.1.7   root     2754:     return fdt2;
1.1.1.6   root     2755: }
1.1.1.7   root     2756: 
1.1.1.8   root     2757: uint32_t helper_float_recip2_s(uint32_t fst0, uint32_t fst2)
1.1.1.6   root     2758: {
1.1.1.7   root     2759:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2760:     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
                   2761:     fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status));
1.1.1.6   root     2762:     update_fcr31();
1.1.1.7   root     2763:     return fst2;
1.1.1.6   root     2764: }
1.1.1.7   root     2765: 
1.1.1.8   root     2766: uint64_t helper_float_recip2_ps(uint64_t fdt0, uint64_t fdt2)
1.1.1.6   root     2767: {
1.1.1.7   root     2768:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
                   2769:     uint32_t fsth0 = fdt0 >> 32;
                   2770:     uint32_t fst2 = fdt2 & 0XFFFFFFFF;
                   2771:     uint32_t fsth2 = fdt2 >> 32;
                   2772: 
                   2773:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2774:     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
                   2775:     fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
                   2776:     fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status));
                   2777:     fsth2 = float32_chs(float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status));
1.1.1.6   root     2778:     update_fcr31();
1.1.1.7   root     2779:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2780: }
                   2781: 
1.1.1.8   root     2782: uint64_t helper_float_rsqrt2_d(uint64_t fdt0, uint64_t fdt2)
1.1.1.6   root     2783: {
1.1.1.7   root     2784:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2785:     fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
                   2786:     fdt2 = float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status);
                   2787:     fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->active_fpu.fp_status));
1.1.1.6   root     2788:     update_fcr31();
1.1.1.7   root     2789:     return fdt2;
1.1.1.6   root     2790: }
1.1.1.7   root     2791: 
1.1.1.8   root     2792: uint32_t helper_float_rsqrt2_s(uint32_t fst0, uint32_t fst2)
1.1.1.6   root     2793: {
1.1.1.7   root     2794:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2795:     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
                   2796:     fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status);
                   2797:     fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
1.1.1.6   root     2798:     update_fcr31();
1.1.1.7   root     2799:     return fst2;
1.1.1.6   root     2800: }
1.1.1.7   root     2801: 
1.1.1.8   root     2802: uint64_t helper_float_rsqrt2_ps(uint64_t fdt0, uint64_t fdt2)
1.1.1.6   root     2803: {
1.1.1.7   root     2804:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
                   2805:     uint32_t fsth0 = fdt0 >> 32;
                   2806:     uint32_t fst2 = fdt2 & 0XFFFFFFFF;
                   2807:     uint32_t fsth2 = fdt2 >> 32;
                   2808: 
                   2809:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2810:     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
                   2811:     fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
                   2812:     fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status);
                   2813:     fsth2 = float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status);
                   2814:     fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
                   2815:     fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->active_fpu.fp_status));
1.1.1.6   root     2816:     update_fcr31();
1.1.1.7   root     2817:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2818: }
                   2819: 
1.1.1.8   root     2820: uint64_t helper_float_addr_ps(uint64_t fdt0, uint64_t fdt1)
1.1.1.6   root     2821: {
1.1.1.7   root     2822:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
                   2823:     uint32_t fsth0 = fdt0 >> 32;
                   2824:     uint32_t fst1 = fdt1 & 0XFFFFFFFF;
                   2825:     uint32_t fsth1 = fdt1 >> 32;
                   2826:     uint32_t fst2;
                   2827:     uint32_t fsth2;
                   2828: 
                   2829:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2830:     fst2 = float32_add (fst0, fsth0, &env->active_fpu.fp_status);
                   2831:     fsth2 = float32_add (fst1, fsth1, &env->active_fpu.fp_status);
1.1.1.6   root     2832:     update_fcr31();
1.1.1.7   root     2833:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2834: }
                   2835: 
1.1.1.8   root     2836: uint64_t helper_float_mulr_ps(uint64_t fdt0, uint64_t fdt1)
1.1.1.6   root     2837: {
1.1.1.7   root     2838:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
                   2839:     uint32_t fsth0 = fdt0 >> 32;
                   2840:     uint32_t fst1 = fdt1 & 0XFFFFFFFF;
                   2841:     uint32_t fsth1 = fdt1 >> 32;
                   2842:     uint32_t fst2;
                   2843:     uint32_t fsth2;
                   2844: 
                   2845:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2846:     fst2 = float32_mul (fst0, fsth0, &env->active_fpu.fp_status);
                   2847:     fsth2 = float32_mul (fst1, fsth1, &env->active_fpu.fp_status);
1.1.1.6   root     2848:     update_fcr31();
1.1.1.7   root     2849:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2850: }
                   2851: 
                   2852: /* compare operations */
1.1.1.7   root     2853: #define FOP_COND_D(op, cond)                                   \
1.1.1.8   root     2854: void helper_cmp_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
1.1.1.7   root     2855: {                                                              \
                   2856:     int c = cond;                                              \
                   2857:     update_fcr31();                                            \
                   2858:     if (c)                                                     \
                   2859:         SET_FP_COND(cc, env->active_fpu);                      \
                   2860:     else                                                       \
                   2861:         CLEAR_FP_COND(cc, env->active_fpu);                    \
                   2862: }                                                              \
1.1.1.8   root     2863: void helper_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
1.1.1.7   root     2864: {                                                              \
                   2865:     int c;                                                     \
                   2866:     fdt0 = float64_abs(fdt0);                                  \
                   2867:     fdt1 = float64_abs(fdt1);                                  \
                   2868:     c = cond;                                                  \
                   2869:     update_fcr31();                                            \
                   2870:     if (c)                                                     \
                   2871:         SET_FP_COND(cc, env->active_fpu);                      \
                   2872:     else                                                       \
                   2873:         CLEAR_FP_COND(cc, env->active_fpu);                    \
1.1.1.6   root     2874: }
                   2875: 
1.1.1.7   root     2876: static int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
1.1.1.6   root     2877: {
                   2878:     if (float64_is_signaling_nan(a) ||
                   2879:         float64_is_signaling_nan(b) ||
1.1.1.12! root     2880:         (sig && (float64_is_quiet_nan(a) || float64_is_quiet_nan(b)))) {
1.1.1.6   root     2881:         float_raise(float_flag_invalid, status);
                   2882:         return 1;
1.1.1.12! root     2883:     } else if (float64_is_quiet_nan(a) || float64_is_quiet_nan(b)) {
1.1.1.6   root     2884:         return 1;
                   2885:     } else {
                   2886:         return 0;
                   2887:     }
                   2888: }
                   2889: 
                   2890: /* NOTE: the comma operator will make "cond" to eval to false,
                   2891:  * but float*_is_unordered() is still called. */
1.1.1.7   root     2892: FOP_COND_D(f,   (float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status), 0))
                   2893: FOP_COND_D(un,  float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status))
                   2894: FOP_COND_D(eq,  !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
                   2895: FOP_COND_D(ueq, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
                   2896: FOP_COND_D(olt, !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
                   2897: FOP_COND_D(ult, float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
                   2898: FOP_COND_D(ole, !float64_is_unordered(0, fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
                   2899: 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     2900: /* NOTE: the comma operator will make "cond" to eval to false,
                   2901:  * but float*_is_unordered() is still called. */
1.1.1.7   root     2902: FOP_COND_D(sf,  (float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status), 0))
                   2903: FOP_COND_D(ngle,float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status))
                   2904: FOP_COND_D(seq, !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
                   2905: FOP_COND_D(ngl, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
                   2906: FOP_COND_D(lt,  !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
                   2907: FOP_COND_D(nge, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
                   2908: FOP_COND_D(le,  !float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status) && float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
                   2909: FOP_COND_D(ngt, float64_is_unordered(1, fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
                   2910: 
                   2911: #define FOP_COND_S(op, cond)                                   \
1.1.1.8   root     2912: void helper_cmp_s_ ## op (uint32_t fst0, uint32_t fst1, int cc)    \
1.1.1.7   root     2913: {                                                              \
                   2914:     int c = cond;                                              \
                   2915:     update_fcr31();                                            \
                   2916:     if (c)                                                     \
                   2917:         SET_FP_COND(cc, env->active_fpu);                      \
                   2918:     else                                                       \
                   2919:         CLEAR_FP_COND(cc, env->active_fpu);                    \
                   2920: }                                                              \
1.1.1.8   root     2921: void helper_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
1.1.1.7   root     2922: {                                                              \
                   2923:     int c;                                                     \
                   2924:     fst0 = float32_abs(fst0);                                  \
                   2925:     fst1 = float32_abs(fst1);                                  \
                   2926:     c = cond;                                                  \
                   2927:     update_fcr31();                                            \
                   2928:     if (c)                                                     \
                   2929:         SET_FP_COND(cc, env->active_fpu);                      \
                   2930:     else                                                       \
                   2931:         CLEAR_FP_COND(cc, env->active_fpu);                    \
1.1.1.6   root     2932: }
                   2933: 
1.1.1.7   root     2934: static flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
1.1.1.6   root     2935: {
                   2936:     if (float32_is_signaling_nan(a) ||
                   2937:         float32_is_signaling_nan(b) ||
1.1.1.12! root     2938:         (sig && (float32_is_quiet_nan(a) || float32_is_quiet_nan(b)))) {
1.1.1.6   root     2939:         float_raise(float_flag_invalid, status);
                   2940:         return 1;
1.1.1.12! root     2941:     } else if (float32_is_quiet_nan(a) || float32_is_quiet_nan(b)) {
1.1.1.6   root     2942:         return 1;
                   2943:     } else {
                   2944:         return 0;
                   2945:     }
                   2946: }
                   2947: 
                   2948: /* NOTE: the comma operator will make "cond" to eval to false,
                   2949:  * but float*_is_unordered() is still called. */
1.1.1.7   root     2950: FOP_COND_S(f,   (float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status), 0))
                   2951: FOP_COND_S(un,  float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status))
                   2952: FOP_COND_S(eq,  !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
                   2953: FOP_COND_S(ueq, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)  || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
                   2954: FOP_COND_S(olt, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
                   2955: FOP_COND_S(ult, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
                   2956: FOP_COND_S(ole, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
                   2957: 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     2958: /* NOTE: the comma operator will make "cond" to eval to false,
                   2959:  * but float*_is_unordered() is still called. */
1.1.1.7   root     2960: FOP_COND_S(sf,  (float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status), 0))
                   2961: FOP_COND_S(ngle,float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status))
                   2962: FOP_COND_S(seq, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_eq(fst0, fst1, &env->active_fpu.fp_status))
                   2963: FOP_COND_S(ngl, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)  || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
                   2964: FOP_COND_S(lt,  !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_lt(fst0, fst1, &env->active_fpu.fp_status))
                   2965: FOP_COND_S(nge, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
                   2966: FOP_COND_S(le,  !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status) && float32_le(fst0, fst1, &env->active_fpu.fp_status))
                   2967: FOP_COND_S(ngt, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)  || float32_le(fst0, fst1, &env->active_fpu.fp_status))
                   2968: 
                   2969: #define FOP_COND_PS(op, condl, condh)                           \
1.1.1.8   root     2970: void helper_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
1.1.1.7   root     2971: {                                                               \
                   2972:     uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF);             \
                   2973:     uint32_t fsth0 = float32_abs(fdt0 >> 32);                   \
                   2974:     uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF);             \
                   2975:     uint32_t fsth1 = float32_abs(fdt1 >> 32);                   \
                   2976:     int cl = condl;                                             \
                   2977:     int ch = condh;                                             \
                   2978:                                                                 \
                   2979:     update_fcr31();                                             \
                   2980:     if (cl)                                                     \
                   2981:         SET_FP_COND(cc, env->active_fpu);                       \
                   2982:     else                                                        \
                   2983:         CLEAR_FP_COND(cc, env->active_fpu);                     \
                   2984:     if (ch)                                                     \
                   2985:         SET_FP_COND(cc + 1, env->active_fpu);                   \
                   2986:     else                                                        \
                   2987:         CLEAR_FP_COND(cc + 1, env->active_fpu);                 \
                   2988: }                                                               \
1.1.1.8   root     2989: void helper_cmpabs_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
1.1.1.7   root     2990: {                                                               \
                   2991:     uint32_t fst0 = float32_abs(fdt0 & 0XFFFFFFFF);             \
                   2992:     uint32_t fsth0 = float32_abs(fdt0 >> 32);                   \
                   2993:     uint32_t fst1 = float32_abs(fdt1 & 0XFFFFFFFF);             \
                   2994:     uint32_t fsth1 = float32_abs(fdt1 >> 32);                   \
                   2995:     int cl = condl;                                             \
                   2996:     int ch = condh;                                             \
                   2997:                                                                 \
                   2998:     update_fcr31();                                             \
                   2999:     if (cl)                                                     \
                   3000:         SET_FP_COND(cc, env->active_fpu);                       \
                   3001:     else                                                        \
                   3002:         CLEAR_FP_COND(cc, env->active_fpu);                     \
                   3003:     if (ch)                                                     \
                   3004:         SET_FP_COND(cc + 1, env->active_fpu);                   \
                   3005:     else                                                        \
                   3006:         CLEAR_FP_COND(cc + 1, env->active_fpu);                 \
1.1.1.6   root     3007: }
                   3008: 
                   3009: /* NOTE: the comma operator will make "cond" to eval to false,
                   3010:  * but float*_is_unordered() is still called. */
1.1.1.7   root     3011: FOP_COND_PS(f,   (float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status), 0),
                   3012:                  (float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status), 0))
                   3013: FOP_COND_PS(un,  float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status),
                   3014:                  float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status))
                   3015: FOP_COND_PS(eq,  !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)   && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
                   3016:                  !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
                   3017: FOP_COND_PS(ueq, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)    || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
                   3018:                  float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
                   3019: FOP_COND_PS(olt, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)   && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
                   3020:                  !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
                   3021: FOP_COND_PS(ult, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
                   3022:                  float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
                   3023: FOP_COND_PS(ole, !float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)   && float32_le(fst0, fst1, &env->active_fpu.fp_status),
                   3024:                  !float32_is_unordered(0, fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
                   3025: FOP_COND_PS(ule, float32_is_unordered(0, fst1, fst0, &env->active_fpu.fp_status)    || float32_le(fst0, fst1, &env->active_fpu.fp_status),
                   3026:                  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     3027: /* NOTE: the comma operator will make "cond" to eval to false,
                   3028:  * but float*_is_unordered() is still called. */
1.1.1.7   root     3029: FOP_COND_PS(sf,  (float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status), 0),
                   3030:                  (float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status), 0))
                   3031: FOP_COND_PS(ngle,float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status),
                   3032:                  float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status))
                   3033: FOP_COND_PS(seq, !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)   && float32_eq(fst0, fst1, &env->active_fpu.fp_status),
                   3034:                  !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
                   3035: FOP_COND_PS(ngl, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)    || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
                   3036:                  float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
                   3037: FOP_COND_PS(lt,  !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)   && float32_lt(fst0, fst1, &env->active_fpu.fp_status),
                   3038:                  !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
                   3039: FOP_COND_PS(nge, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
                   3040:                  float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
                   3041: FOP_COND_PS(le,  !float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)   && float32_le(fst0, fst1, &env->active_fpu.fp_status),
                   3042:                  !float32_is_unordered(1, fsth1, fsth0, &env->active_fpu.fp_status) && float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
                   3043: FOP_COND_PS(ngt, float32_is_unordered(1, fst1, fst0, &env->active_fpu.fp_status)    || float32_le(fst0, fst1, &env->active_fpu.fp_status),
                   3044:                  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.