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

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

unix.superglobalmegacorp.com