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

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

unix.superglobalmegacorp.com

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