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

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

unix.superglobalmegacorp.com

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