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

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

unix.superglobalmegacorp.com

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