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

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;
1.1.1.13! root       41:     cpu_loop_exit(env);
1.1       root       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) {
1.1.1.13! root       57:         cpu_restore_state(tb, env, pc);
1.1.1.7   root       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) {
1.1.1.13! root      280:         cpu_loop_exit(env);
1.1.1.10  root      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 */
1.1.1.13! root     1975:                 cpu_restore_state(tb, env, pc);
1.1       root     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.13! root     1983: void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
        !          1984:                            int is_write, int is_exec, int unused, int size)
1.1.1.6   root     1985: {
1.1.1.13! root     1986:     env = env1;
        !          1987: 
1.1.1.6   root     1988:     if (is_exec)
1.1.1.8   root     1989:         helper_raise_exception(EXCP_IBE);
1.1.1.6   root     1990:     else
1.1.1.8   root     1991:         helper_raise_exception(EXCP_DBE);
1.1.1.6   root     1992: }
1.1.1.7   root     1993: #endif /* !CONFIG_USER_ONLY */
1.1.1.6   root     1994: 
                   1995: /* Complex FPU operations which may need stack space. */
                   1996: 
                   1997: #define FLOAT_ONE32 make_float32(0x3f8 << 20)
                   1998: #define FLOAT_ONE64 make_float64(0x3ffULL << 52)
                   1999: #define FLOAT_TWO32 make_float32(1 << 30)
                   2000: #define FLOAT_TWO64 make_float64(1ULL << 62)
                   2001: #define FLOAT_QNAN32 0x7fbfffff
                   2002: #define FLOAT_QNAN64 0x7ff7ffffffffffffULL
                   2003: #define FLOAT_SNAN32 0x7fffffff
                   2004: #define FLOAT_SNAN64 0x7fffffffffffffffULL
                   2005: 
                   2006: /* convert MIPS rounding mode in FCR31 to IEEE library */
1.1.1.9   root     2007: static unsigned int ieee_rm[] = {
1.1.1.6   root     2008:     float_round_nearest_even,
                   2009:     float_round_to_zero,
                   2010:     float_round_up,
                   2011:     float_round_down
                   2012: };
                   2013: 
                   2014: #define RESTORE_ROUNDING_MODE \
1.1.1.7   root     2015:     set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], &env->active_fpu.fp_status)
1.1.1.6   root     2016: 
1.1.1.8   root     2017: #define RESTORE_FLUSH_MODE \
                   2018:     set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0, &env->active_fpu.fp_status);
                   2019: 
                   2020: target_ulong helper_cfc1 (uint32_t reg)
1.1.1.6   root     2021: {
1.1.1.8   root     2022:     target_ulong arg1;
1.1.1.7   root     2023: 
1.1.1.6   root     2024:     switch (reg) {
                   2025:     case 0:
1.1.1.8   root     2026:         arg1 = (int32_t)env->active_fpu.fcr0;
1.1.1.6   root     2027:         break;
                   2028:     case 25:
1.1.1.8   root     2029:         arg1 = ((env->active_fpu.fcr31 >> 24) & 0xfe) | ((env->active_fpu.fcr31 >> 23) & 0x1);
1.1.1.6   root     2030:         break;
                   2031:     case 26:
1.1.1.8   root     2032:         arg1 = env->active_fpu.fcr31 & 0x0003f07c;
1.1.1.6   root     2033:         break;
                   2034:     case 28:
1.1.1.8   root     2035:         arg1 = (env->active_fpu.fcr31 & 0x00000f83) | ((env->active_fpu.fcr31 >> 22) & 0x4);
1.1.1.6   root     2036:         break;
                   2037:     default:
1.1.1.8   root     2038:         arg1 = (int32_t)env->active_fpu.fcr31;
1.1.1.6   root     2039:         break;
                   2040:     }
1.1.1.7   root     2041: 
1.1.1.8   root     2042:     return arg1;
1.1.1.6   root     2043: }
                   2044: 
1.1.1.8   root     2045: void helper_ctc1 (target_ulong arg1, uint32_t reg)
1.1.1.6   root     2046: {
                   2047:     switch(reg) {
                   2048:     case 25:
1.1.1.8   root     2049:         if (arg1 & 0xffffff00)
1.1.1.6   root     2050:             return;
1.1.1.8   root     2051:         env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0x017fffff) | ((arg1 & 0xfe) << 24) |
                   2052:                      ((arg1 & 0x1) << 23);
1.1.1.6   root     2053:         break;
                   2054:     case 26:
1.1.1.8   root     2055:         if (arg1 & 0x007c0000)
1.1.1.6   root     2056:             return;
1.1.1.8   root     2057:         env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfffc0f83) | (arg1 & 0x0003f07c);
1.1.1.6   root     2058:         break;
                   2059:     case 28:
1.1.1.8   root     2060:         if (arg1 & 0x007c0000)
1.1.1.6   root     2061:             return;
1.1.1.8   root     2062:         env->active_fpu.fcr31 = (env->active_fpu.fcr31 & 0xfefff07c) | (arg1 & 0x00000f83) |
                   2063:                      ((arg1 & 0x4) << 22);
1.1.1.6   root     2064:         break;
                   2065:     case 31:
1.1.1.8   root     2066:         if (arg1 & 0x007c0000)
1.1.1.6   root     2067:             return;
1.1.1.8   root     2068:         env->active_fpu.fcr31 = arg1;
1.1.1.6   root     2069:         break;
                   2070:     default:
                   2071:         return;
                   2072:     }
                   2073:     /* set rounding mode */
                   2074:     RESTORE_ROUNDING_MODE;
1.1.1.8   root     2075:     /* set flush-to-zero mode */
                   2076:     RESTORE_FLUSH_MODE;
1.1.1.7   root     2077:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2078:     if ((GET_FP_ENABLE(env->active_fpu.fcr31) | 0x20) & GET_FP_CAUSE(env->active_fpu.fcr31))
1.1.1.8   root     2079:         helper_raise_exception(EXCP_FPE);
1.1.1.6   root     2080: }
                   2081: 
1.1.1.13! root     2082: static inline int ieee_ex_to_mips(int xcpt)
1.1.1.6   root     2083: {
1.1.1.13! root     2084:     int ret = 0;
        !          2085:     if (xcpt) {
        !          2086:         if (xcpt & float_flag_invalid) {
        !          2087:             ret |= FP_INVALID;
        !          2088:         }
        !          2089:         if (xcpt & float_flag_overflow) {
        !          2090:             ret |= FP_OVERFLOW;
        !          2091:         }
        !          2092:         if (xcpt & float_flag_underflow) {
        !          2093:             ret |= FP_UNDERFLOW;
        !          2094:         }
        !          2095:         if (xcpt & float_flag_divbyzero) {
        !          2096:             ret |= FP_DIV0;
        !          2097:         }
        !          2098:         if (xcpt & float_flag_inexact) {
        !          2099:             ret |= FP_INEXACT;
        !          2100:         }
        !          2101:     }
        !          2102:     return ret;
1.1.1.6   root     2103: }
                   2104: 
1.1.1.7   root     2105: static inline void update_fcr31(void)
1.1.1.6   root     2106: {
1.1.1.7   root     2107:     int tmp = ieee_ex_to_mips(get_float_exception_flags(&env->active_fpu.fp_status));
1.1.1.6   root     2108: 
1.1.1.7   root     2109:     SET_FP_CAUSE(env->active_fpu.fcr31, tmp);
                   2110:     if (GET_FP_ENABLE(env->active_fpu.fcr31) & tmp)
1.1.1.8   root     2111:         helper_raise_exception(EXCP_FPE);
1.1.1.6   root     2112:     else
1.1.1.7   root     2113:         UPDATE_FP_FLAGS(env->active_fpu.fcr31, tmp);
1.1.1.6   root     2114: }
                   2115: 
1.1.1.7   root     2116: /* Float support.
                   2117:    Single precition routines have a "s" suffix, double precision a
                   2118:    "d" suffix, 32bit integer "w", 64bit integer "l", paired single "ps",
                   2119:    paired single lower "pl", paired single upper "pu".  */
                   2120: 
                   2121: /* unary operations, modifying fp status  */
1.1.1.8   root     2122: uint64_t helper_float_sqrt_d(uint64_t fdt0)
1.1.1.7   root     2123: {
                   2124:     return float64_sqrt(fdt0, &env->active_fpu.fp_status);
                   2125: }
1.1.1.6   root     2126: 
1.1.1.8   root     2127: uint32_t helper_float_sqrt_s(uint32_t fst0)
1.1.1.6   root     2128: {
1.1.1.7   root     2129:     return float32_sqrt(fst0, &env->active_fpu.fp_status);
                   2130: }
                   2131: 
1.1.1.8   root     2132: uint64_t helper_float_cvtd_s(uint32_t fst0)
1.1.1.7   root     2133: {
                   2134:     uint64_t fdt2;
                   2135: 
                   2136:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2137:     fdt2 = float32_to_float64(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2138:     update_fcr31();
1.1.1.7   root     2139:     return fdt2;
1.1.1.6   root     2140: }
1.1.1.7   root     2141: 
1.1.1.8   root     2142: uint64_t helper_float_cvtd_w(uint32_t wt0)
1.1.1.6   root     2143: {
1.1.1.7   root     2144:     uint64_t fdt2;
                   2145: 
                   2146:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2147:     fdt2 = int32_to_float64(wt0, &env->active_fpu.fp_status);
1.1.1.6   root     2148:     update_fcr31();
1.1.1.7   root     2149:     return fdt2;
1.1.1.6   root     2150: }
1.1.1.7   root     2151: 
1.1.1.8   root     2152: uint64_t helper_float_cvtd_l(uint64_t dt0)
1.1.1.6   root     2153: {
1.1.1.7   root     2154:     uint64_t fdt2;
                   2155: 
                   2156:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2157:     fdt2 = int64_to_float64(dt0, &env->active_fpu.fp_status);
1.1.1.6   root     2158:     update_fcr31();
1.1.1.7   root     2159:     return fdt2;
1.1.1.6   root     2160: }
1.1.1.7   root     2161: 
1.1.1.8   root     2162: uint64_t helper_float_cvtl_d(uint64_t fdt0)
1.1.1.6   root     2163: {
1.1.1.7   root     2164:     uint64_t dt2;
                   2165: 
                   2166:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2167:     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2168:     update_fcr31();
1.1.1.7   root     2169:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2170:         dt2 = FLOAT_SNAN64;
                   2171:     return dt2;
1.1.1.6   root     2172: }
1.1.1.7   root     2173: 
1.1.1.8   root     2174: uint64_t helper_float_cvtl_s(uint32_t fst0)
1.1.1.6   root     2175: {
1.1.1.7   root     2176:     uint64_t dt2;
                   2177: 
                   2178:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2179:     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2180:     update_fcr31();
1.1.1.7   root     2181:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2182:         dt2 = FLOAT_SNAN64;
                   2183:     return dt2;
1.1.1.6   root     2184: }
                   2185: 
1.1.1.8   root     2186: uint64_t helper_float_cvtps_pw(uint64_t dt0)
1.1.1.6   root     2187: {
1.1.1.7   root     2188:     uint32_t fst2;
                   2189:     uint32_t fsth2;
                   2190: 
                   2191:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2192:     fst2 = int32_to_float32(dt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
                   2193:     fsth2 = int32_to_float32(dt0 >> 32, &env->active_fpu.fp_status);
1.1.1.6   root     2194:     update_fcr31();
1.1.1.7   root     2195:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2196: }
1.1.1.7   root     2197: 
1.1.1.8   root     2198: uint64_t helper_float_cvtpw_ps(uint64_t fdt0)
1.1.1.6   root     2199: {
1.1.1.7   root     2200:     uint32_t wt2;
                   2201:     uint32_t wth2;
                   2202: 
                   2203:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2204:     wt2 = float32_to_int32(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
                   2205:     wth2 = float32_to_int32(fdt0 >> 32, &env->active_fpu.fp_status);
1.1.1.6   root     2206:     update_fcr31();
1.1.1.7   root     2207:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID)) {
                   2208:         wt2 = FLOAT_SNAN32;
                   2209:         wth2 = FLOAT_SNAN32;
                   2210:     }
                   2211:     return ((uint64_t)wth2 << 32) | wt2;
1.1.1.6   root     2212: }
1.1.1.7   root     2213: 
1.1.1.8   root     2214: uint32_t helper_float_cvts_d(uint64_t fdt0)
1.1.1.6   root     2215: {
1.1.1.7   root     2216:     uint32_t fst2;
                   2217: 
                   2218:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2219:     fst2 = float64_to_float32(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2220:     update_fcr31();
1.1.1.7   root     2221:     return fst2;
1.1.1.6   root     2222: }
1.1.1.7   root     2223: 
1.1.1.8   root     2224: uint32_t helper_float_cvts_w(uint32_t wt0)
1.1.1.6   root     2225: {
1.1.1.7   root     2226:     uint32_t fst2;
                   2227: 
                   2228:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2229:     fst2 = int32_to_float32(wt0, &env->active_fpu.fp_status);
1.1.1.6   root     2230:     update_fcr31();
1.1.1.7   root     2231:     return fst2;
1.1.1.6   root     2232: }
1.1.1.7   root     2233: 
1.1.1.8   root     2234: uint32_t helper_float_cvts_l(uint64_t dt0)
1.1.1.6   root     2235: {
1.1.1.7   root     2236:     uint32_t fst2;
                   2237: 
                   2238:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2239:     fst2 = int64_to_float32(dt0, &env->active_fpu.fp_status);
1.1.1.6   root     2240:     update_fcr31();
1.1.1.7   root     2241:     return fst2;
1.1.1.6   root     2242: }
1.1.1.7   root     2243: 
1.1.1.8   root     2244: uint32_t helper_float_cvts_pl(uint32_t wt0)
1.1.1.6   root     2245: {
1.1.1.7   root     2246:     uint32_t wt2;
                   2247: 
                   2248:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2249:     wt2 = wt0;
1.1.1.6   root     2250:     update_fcr31();
1.1.1.7   root     2251:     return wt2;
1.1.1.6   root     2252: }
1.1.1.7   root     2253: 
1.1.1.8   root     2254: uint32_t helper_float_cvts_pu(uint32_t wth0)
1.1.1.6   root     2255: {
1.1.1.7   root     2256:     uint32_t wt2;
                   2257: 
                   2258:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2259:     wt2 = wth0;
1.1.1.6   root     2260:     update_fcr31();
1.1.1.7   root     2261:     return wt2;
1.1.1.6   root     2262: }
1.1.1.7   root     2263: 
1.1.1.8   root     2264: uint32_t helper_float_cvtw_s(uint32_t fst0)
1.1.1.6   root     2265: {
1.1.1.7   root     2266:     uint32_t wt2;
                   2267: 
                   2268:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2269:     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2270:     update_fcr31();
1.1.1.7   root     2271:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2272:         wt2 = FLOAT_SNAN32;
                   2273:     return wt2;
1.1.1.6   root     2274: }
1.1.1.7   root     2275: 
1.1.1.8   root     2276: uint32_t helper_float_cvtw_d(uint64_t fdt0)
1.1.1.6   root     2277: {
1.1.1.7   root     2278:     uint32_t wt2;
                   2279: 
                   2280:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2281:     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2282:     update_fcr31();
1.1.1.7   root     2283:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2284:         wt2 = FLOAT_SNAN32;
                   2285:     return wt2;
1.1.1.6   root     2286: }
                   2287: 
1.1.1.8   root     2288: uint64_t helper_float_roundl_d(uint64_t fdt0)
1.1.1.6   root     2289: {
1.1.1.7   root     2290:     uint64_t dt2;
                   2291: 
1.1.1.13! root     2292:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2293:     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
                   2294:     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2295:     RESTORE_ROUNDING_MODE;
                   2296:     update_fcr31();
1.1.1.7   root     2297:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2298:         dt2 = FLOAT_SNAN64;
                   2299:     return dt2;
1.1.1.6   root     2300: }
1.1.1.7   root     2301: 
1.1.1.8   root     2302: uint64_t helper_float_roundl_s(uint32_t fst0)
1.1.1.6   root     2303: {
1.1.1.7   root     2304:     uint64_t dt2;
                   2305: 
1.1.1.13! root     2306:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2307:     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
                   2308:     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2309:     RESTORE_ROUNDING_MODE;
                   2310:     update_fcr31();
1.1.1.7   root     2311:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2312:         dt2 = FLOAT_SNAN64;
                   2313:     return dt2;
1.1.1.6   root     2314: }
1.1.1.7   root     2315: 
1.1.1.8   root     2316: uint32_t helper_float_roundw_d(uint64_t fdt0)
1.1.1.6   root     2317: {
1.1.1.7   root     2318:     uint32_t wt2;
                   2319: 
1.1.1.13! root     2320:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2321:     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
                   2322:     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2323:     RESTORE_ROUNDING_MODE;
                   2324:     update_fcr31();
1.1.1.7   root     2325:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2326:         wt2 = FLOAT_SNAN32;
                   2327:     return wt2;
1.1.1.6   root     2328: }
1.1.1.7   root     2329: 
1.1.1.8   root     2330: uint32_t helper_float_roundw_s(uint32_t fst0)
1.1.1.6   root     2331: {
1.1.1.7   root     2332:     uint32_t wt2;
                   2333: 
1.1.1.13! root     2334:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2335:     set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
                   2336:     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2337:     RESTORE_ROUNDING_MODE;
                   2338:     update_fcr31();
1.1.1.7   root     2339:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2340:         wt2 = FLOAT_SNAN32;
                   2341:     return wt2;
1.1.1.6   root     2342: }
                   2343: 
1.1.1.8   root     2344: uint64_t helper_float_truncl_d(uint64_t fdt0)
1.1.1.6   root     2345: {
1.1.1.7   root     2346:     uint64_t dt2;
                   2347: 
1.1.1.13! root     2348:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2349:     dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2350:     update_fcr31();
1.1.1.7   root     2351:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2352:         dt2 = FLOAT_SNAN64;
                   2353:     return dt2;
1.1.1.6   root     2354: }
1.1.1.7   root     2355: 
1.1.1.8   root     2356: uint64_t helper_float_truncl_s(uint32_t fst0)
1.1.1.6   root     2357: {
1.1.1.7   root     2358:     uint64_t dt2;
                   2359: 
1.1.1.13! root     2360:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2361:     dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2362:     update_fcr31();
1.1.1.7   root     2363:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2364:         dt2 = FLOAT_SNAN64;
                   2365:     return dt2;
1.1.1.6   root     2366: }
1.1.1.7   root     2367: 
1.1.1.8   root     2368: uint32_t helper_float_truncw_d(uint64_t fdt0)
1.1.1.6   root     2369: {
1.1.1.7   root     2370:     uint32_t wt2;
                   2371: 
1.1.1.13! root     2372:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2373:     wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2374:     update_fcr31();
1.1.1.7   root     2375:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2376:         wt2 = FLOAT_SNAN32;
                   2377:     return wt2;
1.1.1.6   root     2378: }
1.1.1.7   root     2379: 
1.1.1.8   root     2380: uint32_t helper_float_truncw_s(uint32_t fst0)
1.1.1.6   root     2381: {
1.1.1.7   root     2382:     uint32_t wt2;
                   2383: 
1.1.1.13! root     2384:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2385:     wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2386:     update_fcr31();
1.1.1.7   root     2387:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2388:         wt2 = FLOAT_SNAN32;
                   2389:     return wt2;
1.1.1.6   root     2390: }
                   2391: 
1.1.1.8   root     2392: uint64_t helper_float_ceill_d(uint64_t fdt0)
1.1.1.6   root     2393: {
1.1.1.7   root     2394:     uint64_t dt2;
                   2395: 
1.1.1.13! root     2396:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2397:     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
                   2398:     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2399:     RESTORE_ROUNDING_MODE;
                   2400:     update_fcr31();
1.1.1.7   root     2401:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2402:         dt2 = FLOAT_SNAN64;
                   2403:     return dt2;
1.1.1.6   root     2404: }
1.1.1.7   root     2405: 
1.1.1.8   root     2406: uint64_t helper_float_ceill_s(uint32_t fst0)
1.1.1.6   root     2407: {
1.1.1.7   root     2408:     uint64_t dt2;
                   2409: 
1.1.1.13! root     2410:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2411:     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
                   2412:     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2413:     RESTORE_ROUNDING_MODE;
                   2414:     update_fcr31();
1.1.1.7   root     2415:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2416:         dt2 = FLOAT_SNAN64;
                   2417:     return dt2;
1.1.1.6   root     2418: }
1.1.1.7   root     2419: 
1.1.1.8   root     2420: uint32_t helper_float_ceilw_d(uint64_t fdt0)
1.1.1.6   root     2421: {
1.1.1.7   root     2422:     uint32_t wt2;
                   2423: 
1.1.1.13! root     2424:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2425:     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
                   2426:     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2427:     RESTORE_ROUNDING_MODE;
                   2428:     update_fcr31();
1.1.1.7   root     2429:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2430:         wt2 = FLOAT_SNAN32;
                   2431:     return wt2;
1.1.1.6   root     2432: }
1.1.1.7   root     2433: 
1.1.1.8   root     2434: uint32_t helper_float_ceilw_s(uint32_t fst0)
1.1.1.6   root     2435: {
1.1.1.7   root     2436:     uint32_t wt2;
                   2437: 
1.1.1.13! root     2438:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2439:     set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
                   2440:     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2441:     RESTORE_ROUNDING_MODE;
                   2442:     update_fcr31();
1.1.1.7   root     2443:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2444:         wt2 = FLOAT_SNAN32;
                   2445:     return wt2;
1.1.1.6   root     2446: }
                   2447: 
1.1.1.8   root     2448: uint64_t helper_float_floorl_d(uint64_t fdt0)
1.1.1.6   root     2449: {
1.1.1.7   root     2450:     uint64_t dt2;
                   2451: 
1.1.1.13! root     2452:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2453:     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
                   2454:     dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2455:     RESTORE_ROUNDING_MODE;
                   2456:     update_fcr31();
1.1.1.7   root     2457:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2458:         dt2 = FLOAT_SNAN64;
                   2459:     return dt2;
1.1.1.6   root     2460: }
1.1.1.7   root     2461: 
1.1.1.8   root     2462: uint64_t helper_float_floorl_s(uint32_t fst0)
1.1.1.6   root     2463: {
1.1.1.7   root     2464:     uint64_t dt2;
                   2465: 
1.1.1.13! root     2466:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2467:     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
                   2468:     dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2469:     RESTORE_ROUNDING_MODE;
                   2470:     update_fcr31();
1.1.1.7   root     2471:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2472:         dt2 = FLOAT_SNAN64;
                   2473:     return dt2;
1.1.1.6   root     2474: }
1.1.1.7   root     2475: 
1.1.1.8   root     2476: uint32_t helper_float_floorw_d(uint64_t fdt0)
1.1.1.6   root     2477: {
1.1.1.7   root     2478:     uint32_t wt2;
                   2479: 
1.1.1.13! root     2480:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2481:     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
                   2482:     wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2483:     RESTORE_ROUNDING_MODE;
                   2484:     update_fcr31();
1.1.1.7   root     2485:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2486:         wt2 = FLOAT_SNAN32;
                   2487:     return wt2;
1.1.1.6   root     2488: }
1.1.1.7   root     2489: 
1.1.1.8   root     2490: uint32_t helper_float_floorw_s(uint32_t fst0)
1.1.1.6   root     2491: {
1.1.1.7   root     2492:     uint32_t wt2;
                   2493: 
1.1.1.13! root     2494:     set_float_exception_flags(0, &env->active_fpu.fp_status);
1.1.1.7   root     2495:     set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
                   2496:     wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2497:     RESTORE_ROUNDING_MODE;
                   2498:     update_fcr31();
1.1.1.7   root     2499:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
                   2500:         wt2 = FLOAT_SNAN32;
                   2501:     return wt2;
                   2502: }
                   2503: 
                   2504: /* unary operations, not modifying fp status  */
                   2505: #define FLOAT_UNOP(name)                                       \
1.1.1.8   root     2506: uint64_t helper_float_ ## name ## _d(uint64_t fdt0)                \
1.1.1.7   root     2507: {                                                              \
                   2508:     return float64_ ## name(fdt0);                             \
                   2509: }                                                              \
1.1.1.8   root     2510: uint32_t helper_float_ ## name ## _s(uint32_t fst0)                \
1.1.1.7   root     2511: {                                                              \
                   2512:     return float32_ ## name(fst0);                             \
                   2513: }                                                              \
1.1.1.8   root     2514: uint64_t helper_float_ ## name ## _ps(uint64_t fdt0)               \
1.1.1.7   root     2515: {                                                              \
                   2516:     uint32_t wt0;                                              \
                   2517:     uint32_t wth0;                                             \
                   2518:                                                                \
                   2519:     wt0 = float32_ ## name(fdt0 & 0XFFFFFFFF);                 \
                   2520:     wth0 = float32_ ## name(fdt0 >> 32);                       \
                   2521:     return ((uint64_t)wth0 << 32) | wt0;                       \
                   2522: }
                   2523: FLOAT_UNOP(abs)
                   2524: FLOAT_UNOP(chs)
                   2525: #undef FLOAT_UNOP
1.1.1.6   root     2526: 
                   2527: /* MIPS specific unary operations */
1.1.1.8   root     2528: uint64_t helper_float_recip_d(uint64_t fdt0)
1.1.1.6   root     2529: {
1.1.1.7   root     2530:     uint64_t fdt2;
                   2531: 
                   2532:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2533:     fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2534:     update_fcr31();
1.1.1.7   root     2535:     return fdt2;
1.1.1.6   root     2536: }
1.1.1.7   root     2537: 
1.1.1.8   root     2538: uint32_t helper_float_recip_s(uint32_t fst0)
1.1.1.6   root     2539: {
1.1.1.7   root     2540:     uint32_t fst2;
                   2541: 
                   2542:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2543:     fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2544:     update_fcr31();
1.1.1.7   root     2545:     return fst2;
1.1.1.6   root     2546: }
                   2547: 
1.1.1.8   root     2548: uint64_t helper_float_rsqrt_d(uint64_t fdt0)
1.1.1.6   root     2549: {
1.1.1.7   root     2550:     uint64_t fdt2;
                   2551: 
                   2552:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2553:     fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
                   2554:     fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status);
1.1.1.6   root     2555:     update_fcr31();
1.1.1.7   root     2556:     return fdt2;
1.1.1.6   root     2557: }
1.1.1.7   root     2558: 
1.1.1.8   root     2559: uint32_t helper_float_rsqrt_s(uint32_t fst0)
1.1.1.6   root     2560: {
1.1.1.7   root     2561:     uint32_t fst2;
                   2562: 
                   2563:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2564:     fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
                   2565:     fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
1.1.1.6   root     2566:     update_fcr31();
1.1.1.7   root     2567:     return fst2;
1.1.1.6   root     2568: }
                   2569: 
1.1.1.8   root     2570: uint64_t helper_float_recip1_d(uint64_t fdt0)
1.1.1.6   root     2571: {
1.1.1.7   root     2572:     uint64_t fdt2;
                   2573: 
                   2574:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2575:     fdt2 = float64_div(FLOAT_ONE64, fdt0, &env->active_fpu.fp_status);
1.1.1.6   root     2576:     update_fcr31();
1.1.1.7   root     2577:     return fdt2;
1.1.1.6   root     2578: }
1.1.1.7   root     2579: 
1.1.1.8   root     2580: uint32_t helper_float_recip1_s(uint32_t fst0)
1.1.1.6   root     2581: {
1.1.1.7   root     2582:     uint32_t fst2;
                   2583: 
                   2584:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2585:     fst2 = float32_div(FLOAT_ONE32, fst0, &env->active_fpu.fp_status);
1.1.1.6   root     2586:     update_fcr31();
1.1.1.7   root     2587:     return fst2;
1.1.1.6   root     2588: }
1.1.1.7   root     2589: 
1.1.1.8   root     2590: uint64_t helper_float_recip1_ps(uint64_t fdt0)
1.1.1.6   root     2591: {
1.1.1.7   root     2592:     uint32_t fst2;
                   2593:     uint32_t fsth2;
                   2594: 
                   2595:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2596:     fst2 = float32_div(FLOAT_ONE32, fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
                   2597:     fsth2 = float32_div(FLOAT_ONE32, fdt0 >> 32, &env->active_fpu.fp_status);
1.1.1.6   root     2598:     update_fcr31();
1.1.1.7   root     2599:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2600: }
                   2601: 
1.1.1.8   root     2602: uint64_t helper_float_rsqrt1_d(uint64_t fdt0)
1.1.1.6   root     2603: {
1.1.1.7   root     2604:     uint64_t fdt2;
                   2605: 
                   2606:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2607:     fdt2 = float64_sqrt(fdt0, &env->active_fpu.fp_status);
                   2608:     fdt2 = float64_div(FLOAT_ONE64, fdt2, &env->active_fpu.fp_status);
1.1.1.6   root     2609:     update_fcr31();
1.1.1.7   root     2610:     return fdt2;
1.1.1.6   root     2611: }
1.1.1.7   root     2612: 
1.1.1.8   root     2613: uint32_t helper_float_rsqrt1_s(uint32_t fst0)
1.1.1.6   root     2614: {
1.1.1.7   root     2615:     uint32_t fst2;
                   2616: 
                   2617:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2618:     fst2 = float32_sqrt(fst0, &env->active_fpu.fp_status);
                   2619:     fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
1.1.1.6   root     2620:     update_fcr31();
1.1.1.7   root     2621:     return fst2;
1.1.1.6   root     2622: }
1.1.1.7   root     2623: 
1.1.1.8   root     2624: uint64_t helper_float_rsqrt1_ps(uint64_t fdt0)
1.1.1.6   root     2625: {
1.1.1.7   root     2626:     uint32_t fst2;
                   2627:     uint32_t fsth2;
                   2628: 
                   2629:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2630:     fst2 = float32_sqrt(fdt0 & 0XFFFFFFFF, &env->active_fpu.fp_status);
                   2631:     fsth2 = float32_sqrt(fdt0 >> 32, &env->active_fpu.fp_status);
                   2632:     fst2 = float32_div(FLOAT_ONE32, fst2, &env->active_fpu.fp_status);
                   2633:     fsth2 = float32_div(FLOAT_ONE32, fsth2, &env->active_fpu.fp_status);
1.1.1.6   root     2634:     update_fcr31();
1.1.1.7   root     2635:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2636: }
                   2637: 
1.1.1.8   root     2638: #define FLOAT_OP(name, p) void helper_float_##name##_##p(void)
1.1.1.7   root     2639: 
1.1.1.6   root     2640: /* binary operations */
1.1.1.7   root     2641: #define FLOAT_BINOP(name)                                          \
1.1.1.8   root     2642: uint64_t helper_float_ ## name ## _d(uint64_t fdt0, uint64_t fdt1)     \
1.1.1.7   root     2643: {                                                                  \
                   2644:     uint64_t dt2;                                                  \
                   2645:                                                                    \
                   2646:     set_float_exception_flags(0, &env->active_fpu.fp_status);            \
                   2647:     dt2 = float64_ ## name (fdt0, fdt1, &env->active_fpu.fp_status);     \
                   2648:     update_fcr31();                                                \
                   2649:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID)                \
                   2650:         dt2 = FLOAT_QNAN64;                                        \
                   2651:     return dt2;                                                    \
                   2652: }                                                                  \
                   2653:                                                                    \
1.1.1.8   root     2654: uint32_t helper_float_ ## name ## _s(uint32_t fst0, uint32_t fst1)     \
1.1.1.7   root     2655: {                                                                  \
                   2656:     uint32_t wt2;                                                  \
                   2657:                                                                    \
                   2658:     set_float_exception_flags(0, &env->active_fpu.fp_status);            \
                   2659:     wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status);     \
1.1.1.6   root     2660:     update_fcr31();                                                \
1.1.1.7   root     2661:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID)                \
                   2662:         wt2 = FLOAT_QNAN32;                                        \
                   2663:     return wt2;                                                    \
                   2664: }                                                                  \
                   2665:                                                                    \
1.1.1.8   root     2666: uint64_t helper_float_ ## name ## _ps(uint64_t fdt0, uint64_t fdt1)    \
1.1.1.7   root     2667: {                                                                  \
                   2668:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;                             \
                   2669:     uint32_t fsth0 = fdt0 >> 32;                                   \
                   2670:     uint32_t fst1 = fdt1 & 0XFFFFFFFF;                             \
                   2671:     uint32_t fsth1 = fdt1 >> 32;                                   \
                   2672:     uint32_t wt2;                                                  \
                   2673:     uint32_t wth2;                                                 \
                   2674:                                                                    \
                   2675:     set_float_exception_flags(0, &env->active_fpu.fp_status);            \
                   2676:     wt2 = float32_ ## name (fst0, fst1, &env->active_fpu.fp_status);     \
                   2677:     wth2 = float32_ ## name (fsth0, fsth1, &env->active_fpu.fp_status);  \
1.1.1.6   root     2678:     update_fcr31();                                                \
1.1.1.7   root     2679:     if (GET_FP_CAUSE(env->active_fpu.fcr31) & FP_INVALID) {              \
                   2680:         wt2 = FLOAT_QNAN32;                                        \
                   2681:         wth2 = FLOAT_QNAN32;                                       \
                   2682:     }                                                              \
                   2683:     return ((uint64_t)wth2 << 32) | wt2;                           \
1.1.1.6   root     2684: }
1.1.1.7   root     2685: 
1.1.1.6   root     2686: FLOAT_BINOP(add)
                   2687: FLOAT_BINOP(sub)
                   2688: FLOAT_BINOP(mul)
                   2689: FLOAT_BINOP(div)
                   2690: #undef FLOAT_BINOP
                   2691: 
1.1.1.7   root     2692: /* ternary operations */
                   2693: #define FLOAT_TERNOP(name1, name2)                                        \
1.1.1.8   root     2694: uint64_t helper_float_ ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1,  \
1.1.1.7   root     2695:                                            uint64_t fdt2)                 \
                   2696: {                                                                         \
                   2697:     fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status);          \
                   2698:     return float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status);          \
                   2699: }                                                                         \
                   2700:                                                                           \
1.1.1.8   root     2701: uint32_t helper_float_ ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1,  \
1.1.1.7   root     2702:                                            uint32_t fst2)                 \
                   2703: {                                                                         \
                   2704:     fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
                   2705:     return float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
                   2706: }                                                                         \
                   2707:                                                                           \
1.1.1.8   root     2708: uint64_t helper_float_ ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1, \
1.1.1.7   root     2709:                                             uint64_t fdt2)                \
                   2710: {                                                                         \
                   2711:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;                                    \
                   2712:     uint32_t fsth0 = fdt0 >> 32;                                          \
                   2713:     uint32_t fst1 = fdt1 & 0XFFFFFFFF;                                    \
                   2714:     uint32_t fsth1 = fdt1 >> 32;                                          \
                   2715:     uint32_t fst2 = fdt2 & 0XFFFFFFFF;                                    \
                   2716:     uint32_t fsth2 = fdt2 >> 32;                                          \
                   2717:                                                                           \
                   2718:     fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
                   2719:     fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status);       \
                   2720:     fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
                   2721:     fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status);       \
                   2722:     return ((uint64_t)fsth2 << 32) | fst2;                                \
                   2723: }
                   2724: 
                   2725: FLOAT_TERNOP(mul, add)
                   2726: FLOAT_TERNOP(mul, sub)
                   2727: #undef FLOAT_TERNOP
                   2728: 
                   2729: /* negated ternary operations */
                   2730: #define FLOAT_NTERNOP(name1, name2)                                       \
1.1.1.8   root     2731: uint64_t helper_float_n ## name1 ## name2 ## _d(uint64_t fdt0, uint64_t fdt1, \
1.1.1.7   root     2732:                                            uint64_t fdt2)                 \
                   2733: {                                                                         \
                   2734:     fdt0 = float64_ ## name1 (fdt0, fdt1, &env->active_fpu.fp_status);          \
                   2735:     fdt2 = float64_ ## name2 (fdt0, fdt2, &env->active_fpu.fp_status);          \
                   2736:     return float64_chs(fdt2);                                             \
                   2737: }                                                                         \
                   2738:                                                                           \
1.1.1.8   root     2739: uint32_t helper_float_n ## name1 ## name2 ## _s(uint32_t fst0, uint32_t fst1, \
1.1.1.7   root     2740:                                            uint32_t fst2)                 \
                   2741: {                                                                         \
                   2742:     fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
                   2743:     fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
                   2744:     return float32_chs(fst2);                                             \
                   2745: }                                                                         \
                   2746:                                                                           \
1.1.1.8   root     2747: uint64_t helper_float_n ## name1 ## name2 ## _ps(uint64_t fdt0, uint64_t fdt1,\
1.1.1.7   root     2748:                                            uint64_t fdt2)                 \
                   2749: {                                                                         \
                   2750:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;                                    \
                   2751:     uint32_t fsth0 = fdt0 >> 32;                                          \
                   2752:     uint32_t fst1 = fdt1 & 0XFFFFFFFF;                                    \
                   2753:     uint32_t fsth1 = fdt1 >> 32;                                          \
                   2754:     uint32_t fst2 = fdt2 & 0XFFFFFFFF;                                    \
                   2755:     uint32_t fsth2 = fdt2 >> 32;                                          \
                   2756:                                                                           \
                   2757:     fst0 = float32_ ## name1 (fst0, fst1, &env->active_fpu.fp_status);          \
                   2758:     fsth0 = float32_ ## name1 (fsth0, fsth1, &env->active_fpu.fp_status);       \
                   2759:     fst2 = float32_ ## name2 (fst0, fst2, &env->active_fpu.fp_status);          \
                   2760:     fsth2 = float32_ ## name2 (fsth0, fsth2, &env->active_fpu.fp_status);       \
                   2761:     fst2 = float32_chs(fst2);                                             \
                   2762:     fsth2 = float32_chs(fsth2);                                           \
                   2763:     return ((uint64_t)fsth2 << 32) | fst2;                                \
                   2764: }
                   2765: 
                   2766: FLOAT_NTERNOP(mul, add)
                   2767: FLOAT_NTERNOP(mul, sub)
                   2768: #undef FLOAT_NTERNOP
                   2769: 
1.1.1.6   root     2770: /* MIPS specific binary operations */
1.1.1.8   root     2771: uint64_t helper_float_recip2_d(uint64_t fdt0, uint64_t fdt2)
1.1.1.6   root     2772: {
1.1.1.7   root     2773:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2774:     fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
                   2775:     fdt2 = float64_chs(float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status));
1.1.1.6   root     2776:     update_fcr31();
1.1.1.7   root     2777:     return fdt2;
1.1.1.6   root     2778: }
1.1.1.7   root     2779: 
1.1.1.8   root     2780: uint32_t helper_float_recip2_s(uint32_t fst0, uint32_t fst2)
1.1.1.6   root     2781: {
1.1.1.7   root     2782:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2783:     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
                   2784:     fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status));
1.1.1.6   root     2785:     update_fcr31();
1.1.1.7   root     2786:     return fst2;
1.1.1.6   root     2787: }
1.1.1.7   root     2788: 
1.1.1.8   root     2789: uint64_t helper_float_recip2_ps(uint64_t fdt0, uint64_t fdt2)
1.1.1.6   root     2790: {
1.1.1.7   root     2791:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
                   2792:     uint32_t fsth0 = fdt0 >> 32;
                   2793:     uint32_t fst2 = fdt2 & 0XFFFFFFFF;
                   2794:     uint32_t fsth2 = fdt2 >> 32;
                   2795: 
                   2796:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2797:     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
                   2798:     fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
                   2799:     fst2 = float32_chs(float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status));
                   2800:     fsth2 = float32_chs(float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status));
1.1.1.6   root     2801:     update_fcr31();
1.1.1.7   root     2802:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2803: }
                   2804: 
1.1.1.8   root     2805: uint64_t helper_float_rsqrt2_d(uint64_t fdt0, uint64_t fdt2)
1.1.1.6   root     2806: {
1.1.1.7   root     2807:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2808:     fdt2 = float64_mul(fdt0, fdt2, &env->active_fpu.fp_status);
                   2809:     fdt2 = float64_sub(fdt2, FLOAT_ONE64, &env->active_fpu.fp_status);
                   2810:     fdt2 = float64_chs(float64_div(fdt2, FLOAT_TWO64, &env->active_fpu.fp_status));
1.1.1.6   root     2811:     update_fcr31();
1.1.1.7   root     2812:     return fdt2;
1.1.1.6   root     2813: }
1.1.1.7   root     2814: 
1.1.1.8   root     2815: uint32_t helper_float_rsqrt2_s(uint32_t fst0, uint32_t fst2)
1.1.1.6   root     2816: {
1.1.1.7   root     2817:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2818:     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
                   2819:     fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status);
                   2820:     fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
1.1.1.6   root     2821:     update_fcr31();
1.1.1.7   root     2822:     return fst2;
1.1.1.6   root     2823: }
1.1.1.7   root     2824: 
1.1.1.8   root     2825: uint64_t helper_float_rsqrt2_ps(uint64_t fdt0, uint64_t fdt2)
1.1.1.6   root     2826: {
1.1.1.7   root     2827:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
                   2828:     uint32_t fsth0 = fdt0 >> 32;
                   2829:     uint32_t fst2 = fdt2 & 0XFFFFFFFF;
                   2830:     uint32_t fsth2 = fdt2 >> 32;
                   2831: 
                   2832:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2833:     fst2 = float32_mul(fst0, fst2, &env->active_fpu.fp_status);
                   2834:     fsth2 = float32_mul(fsth0, fsth2, &env->active_fpu.fp_status);
                   2835:     fst2 = float32_sub(fst2, FLOAT_ONE32, &env->active_fpu.fp_status);
                   2836:     fsth2 = float32_sub(fsth2, FLOAT_ONE32, &env->active_fpu.fp_status);
                   2837:     fst2 = float32_chs(float32_div(fst2, FLOAT_TWO32, &env->active_fpu.fp_status));
                   2838:     fsth2 = float32_chs(float32_div(fsth2, FLOAT_TWO32, &env->active_fpu.fp_status));
1.1.1.6   root     2839:     update_fcr31();
1.1.1.7   root     2840:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2841: }
                   2842: 
1.1.1.8   root     2843: uint64_t helper_float_addr_ps(uint64_t fdt0, uint64_t fdt1)
1.1.1.6   root     2844: {
1.1.1.7   root     2845:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
                   2846:     uint32_t fsth0 = fdt0 >> 32;
                   2847:     uint32_t fst1 = fdt1 & 0XFFFFFFFF;
                   2848:     uint32_t fsth1 = fdt1 >> 32;
                   2849:     uint32_t fst2;
                   2850:     uint32_t fsth2;
                   2851: 
                   2852:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2853:     fst2 = float32_add (fst0, fsth0, &env->active_fpu.fp_status);
                   2854:     fsth2 = float32_add (fst1, fsth1, &env->active_fpu.fp_status);
1.1.1.6   root     2855:     update_fcr31();
1.1.1.7   root     2856:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2857: }
                   2858: 
1.1.1.8   root     2859: uint64_t helper_float_mulr_ps(uint64_t fdt0, uint64_t fdt1)
1.1.1.6   root     2860: {
1.1.1.7   root     2861:     uint32_t fst0 = fdt0 & 0XFFFFFFFF;
                   2862:     uint32_t fsth0 = fdt0 >> 32;
                   2863:     uint32_t fst1 = fdt1 & 0XFFFFFFFF;
                   2864:     uint32_t fsth1 = fdt1 >> 32;
                   2865:     uint32_t fst2;
                   2866:     uint32_t fsth2;
                   2867: 
                   2868:     set_float_exception_flags(0, &env->active_fpu.fp_status);
                   2869:     fst2 = float32_mul (fst0, fsth0, &env->active_fpu.fp_status);
                   2870:     fsth2 = float32_mul (fst1, fsth1, &env->active_fpu.fp_status);
1.1.1.6   root     2871:     update_fcr31();
1.1.1.7   root     2872:     return ((uint64_t)fsth2 << 32) | fst2;
1.1.1.6   root     2873: }
                   2874: 
                   2875: /* compare operations */
1.1.1.7   root     2876: #define FOP_COND_D(op, cond)                                   \
1.1.1.8   root     2877: void helper_cmp_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
1.1.1.7   root     2878: {                                                              \
1.1.1.13! root     2879:     int c;                                                     \
        !          2880:     set_float_exception_flags(0, &env->active_fpu.fp_status);  \
        !          2881:     c = cond;                                                  \
1.1.1.7   root     2882:     update_fcr31();                                            \
                   2883:     if (c)                                                     \
                   2884:         SET_FP_COND(cc, env->active_fpu);                      \
                   2885:     else                                                       \
                   2886:         CLEAR_FP_COND(cc, env->active_fpu);                    \
                   2887: }                                                              \
1.1.1.8   root     2888: void helper_cmpabs_d_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
1.1.1.7   root     2889: {                                                              \
                   2890:     int c;                                                     \
1.1.1.13! root     2891:     set_float_exception_flags(0, &env->active_fpu.fp_status);  \
1.1.1.7   root     2892:     fdt0 = float64_abs(fdt0);                                  \
                   2893:     fdt1 = float64_abs(fdt1);                                  \
                   2894:     c = cond;                                                  \
                   2895:     update_fcr31();                                            \
                   2896:     if (c)                                                     \
                   2897:         SET_FP_COND(cc, env->active_fpu);                      \
                   2898:     else                                                       \
                   2899:         CLEAR_FP_COND(cc, env->active_fpu);                    \
1.1.1.6   root     2900: }
                   2901: 
                   2902: /* NOTE: the comma operator will make "cond" to eval to false,
1.1.1.13! root     2903:  * but float64_unordered_quiet() is still called. */
        !          2904: FOP_COND_D(f,   (float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status), 0))
        !          2905: FOP_COND_D(un,  float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status))
        !          2906: FOP_COND_D(eq,  float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
        !          2907: FOP_COND_D(ueq, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
        !          2908: FOP_COND_D(olt, float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
        !          2909: FOP_COND_D(ult, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
        !          2910: FOP_COND_D(ole, float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
        !          2911: FOP_COND_D(ule, float64_unordered_quiet(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le_quiet(fdt0, fdt1, &env->active_fpu.fp_status))
1.1.1.6   root     2912: /* NOTE: the comma operator will make "cond" to eval to false,
1.1.1.13! root     2913:  * but float64_unordered() is still called. */
        !          2914: FOP_COND_D(sf,  (float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status), 0))
        !          2915: FOP_COND_D(ngle,float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status))
        !          2916: FOP_COND_D(seq, float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
        !          2917: FOP_COND_D(ngl, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_eq(fdt0, fdt1, &env->active_fpu.fp_status))
        !          2918: FOP_COND_D(lt,  float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
        !          2919: FOP_COND_D(nge, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_lt(fdt0, fdt1, &env->active_fpu.fp_status))
        !          2920: FOP_COND_D(le,  float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
        !          2921: FOP_COND_D(ngt, float64_unordered(fdt1, fdt0, &env->active_fpu.fp_status)  || float64_le(fdt0, fdt1, &env->active_fpu.fp_status))
1.1.1.7   root     2922: 
                   2923: #define FOP_COND_S(op, cond)                                   \
1.1.1.8   root     2924: void helper_cmp_s_ ## op (uint32_t fst0, uint32_t fst1, int cc)    \
1.1.1.7   root     2925: {                                                              \
1.1.1.13! root     2926:     int c;                                                     \
        !          2927:     set_float_exception_flags(0, &env->active_fpu.fp_status);  \
        !          2928:     c = cond;                                                  \
1.1.1.7   root     2929:     update_fcr31();                                            \
                   2930:     if (c)                                                     \
                   2931:         SET_FP_COND(cc, env->active_fpu);                      \
                   2932:     else                                                       \
                   2933:         CLEAR_FP_COND(cc, env->active_fpu);                    \
                   2934: }                                                              \
1.1.1.8   root     2935: void helper_cmpabs_s_ ## op (uint32_t fst0, uint32_t fst1, int cc) \
1.1.1.7   root     2936: {                                                              \
                   2937:     int c;                                                     \
1.1.1.13! root     2938:     set_float_exception_flags(0, &env->active_fpu.fp_status);  \
1.1.1.7   root     2939:     fst0 = float32_abs(fst0);                                  \
                   2940:     fst1 = float32_abs(fst1);                                  \
                   2941:     c = cond;                                                  \
                   2942:     update_fcr31();                                            \
                   2943:     if (c)                                                     \
                   2944:         SET_FP_COND(cc, env->active_fpu);                      \
                   2945:     else                                                       \
                   2946:         CLEAR_FP_COND(cc, env->active_fpu);                    \
1.1.1.6   root     2947: }
                   2948: 
                   2949: /* NOTE: the comma operator will make "cond" to eval to false,
1.1.1.13! root     2950:  * but float32_unordered_quiet() is still called. */
        !          2951: FOP_COND_S(f,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0))
        !          2952: FOP_COND_S(un,  float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status))
        !          2953: FOP_COND_S(eq,  float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
        !          2954: FOP_COND_S(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status))
        !          2955: FOP_COND_S(olt, float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))
        !          2956: FOP_COND_S(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status))
        !          2957: FOP_COND_S(ole, float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))
        !          2958: FOP_COND_S(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)  || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status))
1.1.1.6   root     2959: /* NOTE: the comma operator will make "cond" to eval to false,
1.1.1.13! root     2960:  * but float32_unordered() is still called. */
        !          2961: FOP_COND_S(sf,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0))
        !          2962: FOP_COND_S(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status))
        !          2963: FOP_COND_S(seq, float32_eq(fst0, fst1, &env->active_fpu.fp_status))
        !          2964: FOP_COND_S(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_eq(fst0, fst1, &env->active_fpu.fp_status))
        !          2965: FOP_COND_S(lt,  float32_lt(fst0, fst1, &env->active_fpu.fp_status))
        !          2966: FOP_COND_S(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_lt(fst0, fst1, &env->active_fpu.fp_status))
        !          2967: FOP_COND_S(le,  float32_le(fst0, fst1, &env->active_fpu.fp_status))
        !          2968: FOP_COND_S(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)  || float32_le(fst0, fst1, &env->active_fpu.fp_status))
1.1.1.7   root     2969: 
                   2970: #define FOP_COND_PS(op, condl, condh)                           \
1.1.1.8   root     2971: void helper_cmp_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc)    \
1.1.1.7   root     2972: {                                                               \
1.1.1.13! root     2973:     uint32_t fst0, fsth0, fst1, fsth1;                          \
        !          2974:     int ch, cl;                                                 \
        !          2975:     set_float_exception_flags(0, &env->active_fpu.fp_status);   \
        !          2976:     fst0 = fdt0 & 0XFFFFFFFF;                                   \
        !          2977:     fsth0 = fdt0 >> 32;                                         \
        !          2978:     fst1 = fdt1 & 0XFFFFFFFF;                                   \
        !          2979:     fsth1 = fdt1 >> 32;                                         \
        !          2980:     cl = condl;                                                 \
        !          2981:     ch = condh;                                                 \
1.1.1.7   root     2982:     update_fcr31();                                             \
                   2983:     if (cl)                                                     \
                   2984:         SET_FP_COND(cc, env->active_fpu);                       \
                   2985:     else                                                        \
                   2986:         CLEAR_FP_COND(cc, env->active_fpu);                     \
                   2987:     if (ch)                                                     \
                   2988:         SET_FP_COND(cc + 1, env->active_fpu);                   \
                   2989:     else                                                        \
                   2990:         CLEAR_FP_COND(cc + 1, env->active_fpu);                 \
                   2991: }                                                               \
1.1.1.8   root     2992: void helper_cmpabs_ps_ ## op (uint64_t fdt0, uint64_t fdt1, int cc) \
1.1.1.7   root     2993: {                                                               \
1.1.1.13! root     2994:     uint32_t fst0, fsth0, fst1, fsth1;                          \
        !          2995:     int ch, cl;                                                 \
        !          2996:     fst0 = float32_abs(fdt0 & 0XFFFFFFFF);                      \
        !          2997:     fsth0 = float32_abs(fdt0 >> 32);                            \
        !          2998:     fst1 = float32_abs(fdt1 & 0XFFFFFFFF);                      \
        !          2999:     fsth1 = float32_abs(fdt1 >> 32);                            \
        !          3000:     cl = condl;                                                 \
        !          3001:     ch = condh;                                                 \
1.1.1.7   root     3002:     update_fcr31();                                             \
                   3003:     if (cl)                                                     \
                   3004:         SET_FP_COND(cc, env->active_fpu);                       \
                   3005:     else                                                        \
                   3006:         CLEAR_FP_COND(cc, env->active_fpu);                     \
                   3007:     if (ch)                                                     \
                   3008:         SET_FP_COND(cc + 1, env->active_fpu);                   \
                   3009:     else                                                        \
                   3010:         CLEAR_FP_COND(cc + 1, env->active_fpu);                 \
1.1.1.6   root     3011: }
                   3012: 
                   3013: /* NOTE: the comma operator will make "cond" to eval to false,
1.1.1.13! root     3014:  * but float32_unordered_quiet() is still called. */
        !          3015: FOP_COND_PS(f,   (float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status), 0),
        !          3016:                  (float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status), 0))
        !          3017: FOP_COND_PS(un,  float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status),
        !          3018:                  float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status))
        !          3019: FOP_COND_PS(eq,  float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
        !          3020:                  float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
        !          3021: FOP_COND_PS(ueq, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq_quiet(fst0, fst1, &env->active_fpu.fp_status),
        !          3022:                  float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
        !          3023: FOP_COND_PS(olt, float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status),
        !          3024:                  float32_lt_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
        !          3025: FOP_COND_PS(ult, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_lt_quiet(fst0, fst1, &env->active_fpu.fp_status),
        !          3026:                  float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
        !          3027: FOP_COND_PS(ole, float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status),
        !          3028:                  float32_le_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
        !          3029: FOP_COND_PS(ule, float32_unordered_quiet(fst1, fst0, &env->active_fpu.fp_status)    || float32_le_quiet(fst0, fst1, &env->active_fpu.fp_status),
        !          3030:                  float32_unordered_quiet(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_le_quiet(fsth0, fsth1, &env->active_fpu.fp_status))
1.1.1.6   root     3031: /* NOTE: the comma operator will make "cond" to eval to false,
1.1.1.13! root     3032:  * but float32_unordered() is still called. */
        !          3033: FOP_COND_PS(sf,  (float32_unordered(fst1, fst0, &env->active_fpu.fp_status), 0),
        !          3034:                  (float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status), 0))
        !          3035: FOP_COND_PS(ngle,float32_unordered(fst1, fst0, &env->active_fpu.fp_status),
        !          3036:                  float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status))
        !          3037: FOP_COND_PS(seq, float32_eq(fst0, fst1, &env->active_fpu.fp_status),
        !          3038:                  float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
        !          3039: FOP_COND_PS(ngl, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_eq(fst0, fst1, &env->active_fpu.fp_status),
        !          3040:                  float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_eq(fsth0, fsth1, &env->active_fpu.fp_status))
        !          3041: FOP_COND_PS(lt,  float32_lt(fst0, fst1, &env->active_fpu.fp_status),
        !          3042:                  float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
        !          3043: FOP_COND_PS(nge, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_lt(fst0, fst1, &env->active_fpu.fp_status),
        !          3044:                  float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)  || float32_lt(fsth0, fsth1, &env->active_fpu.fp_status))
        !          3045: FOP_COND_PS(le,  float32_le(fst0, fst1, &env->active_fpu.fp_status),
        !          3046:                  float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
        !          3047: FOP_COND_PS(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)    || float32_le(fst0, fst1, &env->active_fpu.fp_status),
        !          3048:                  float32_unordered(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.