Annotation of qemu/target-mips/op.c, revision 1.1.1.4

1.1       root        1: /*
                      2:  *  MIPS emulation micro-operations for qemu.
                      3:  * 
                      4:  *  Copyright (c) 2004-2005 Jocelyn Mayer
1.1.1.4 ! root        5:  *  Copyright (c) 2006 Marius Groeger (FPU operations)
1.1       root        6:  *
                      7:  * This library is free software; you can redistribute it and/or
                      8:  * modify it under the terms of the GNU Lesser General Public
                      9:  * License as published by the Free Software Foundation; either
                     10:  * version 2 of the License, or (at your option) any later version.
                     11:  *
                     12:  * This library is distributed in the hope that it will be useful,
                     13:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     15:  * Lesser General Public License for more details.
                     16:  *
                     17:  * You should have received a copy of the GNU Lesser General Public
                     18:  * License along with this library; if not, write to the Free Software
                     19:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     20:  */
                     21: 
                     22: #include "config.h"
                     23: #include "exec.h"
                     24: 
                     25: #ifndef CALL_FROM_TB0
                     26: #define CALL_FROM_TB0(func) func();
                     27: #endif
                     28: #ifndef CALL_FROM_TB1
                     29: #define CALL_FROM_TB1(func, arg0) func(arg0);
                     30: #endif
                     31: #ifndef CALL_FROM_TB1_CONST16
                     32: #define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0);
                     33: #endif
                     34: #ifndef CALL_FROM_TB2
                     35: #define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1);
                     36: #endif
                     37: #ifndef CALL_FROM_TB2_CONST16
                     38: #define CALL_FROM_TB2_CONST16(func, arg0, arg1)     \
                     39: CALL_FROM_TB2(func, arg0, arg1);
                     40: #endif
                     41: #ifndef CALL_FROM_TB3
                     42: #define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2);
                     43: #endif
                     44: #ifndef CALL_FROM_TB4
                     45: #define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
                     46:         func(arg0, arg1, arg2, arg3);
                     47: #endif
                     48: 
                     49: #define REG 1
                     50: #include "op_template.c"
                     51: #undef REG
                     52: #define REG 2
                     53: #include "op_template.c"
                     54: #undef REG
                     55: #define REG 3
                     56: #include "op_template.c"
                     57: #undef REG
                     58: #define REG 4
                     59: #include "op_template.c"
                     60: #undef REG
                     61: #define REG 5
                     62: #include "op_template.c"
                     63: #undef REG
                     64: #define REG 6
                     65: #include "op_template.c"
                     66: #undef REG
                     67: #define REG 7
                     68: #include "op_template.c"
                     69: #undef REG
                     70: #define REG 8
                     71: #include "op_template.c"
                     72: #undef REG
                     73: #define REG 9
                     74: #include "op_template.c"
                     75: #undef REG
                     76: #define REG 10
                     77: #include "op_template.c"
                     78: #undef REG
                     79: #define REG 11
                     80: #include "op_template.c"
                     81: #undef REG
                     82: #define REG 12
                     83: #include "op_template.c"
                     84: #undef REG
                     85: #define REG 13
                     86: #include "op_template.c"
                     87: #undef REG
                     88: #define REG 14
                     89: #include "op_template.c"
                     90: #undef REG
                     91: #define REG 15
                     92: #include "op_template.c"
                     93: #undef REG
                     94: #define REG 16
                     95: #include "op_template.c"
                     96: #undef REG
                     97: #define REG 17
                     98: #include "op_template.c"
                     99: #undef REG
                    100: #define REG 18
                    101: #include "op_template.c"
                    102: #undef REG
                    103: #define REG 19
                    104: #include "op_template.c"
                    105: #undef REG
                    106: #define REG 20
                    107: #include "op_template.c"
                    108: #undef REG
                    109: #define REG 21
                    110: #include "op_template.c"
                    111: #undef REG
                    112: #define REG 22
                    113: #include "op_template.c"
                    114: #undef REG
                    115: #define REG 23
                    116: #include "op_template.c"
                    117: #undef REG
                    118: #define REG 24
                    119: #include "op_template.c"
                    120: #undef REG
                    121: #define REG 25
                    122: #include "op_template.c"
                    123: #undef REG
                    124: #define REG 26
                    125: #include "op_template.c"
                    126: #undef REG
                    127: #define REG 27
                    128: #include "op_template.c"
                    129: #undef REG
                    130: #define REG 28
                    131: #include "op_template.c"
                    132: #undef REG
                    133: #define REG 29
                    134: #include "op_template.c"
                    135: #undef REG
                    136: #define REG 30
                    137: #include "op_template.c"
                    138: #undef REG
                    139: #define REG 31
                    140: #include "op_template.c"
                    141: #undef REG
                    142: 
                    143: #define TN T0
                    144: #include "op_template.c"
                    145: #undef TN
                    146: #define TN T1
                    147: #include "op_template.c"
                    148: #undef TN
                    149: #define TN T2
                    150: #include "op_template.c"
                    151: #undef TN
                    152: 
1.1.1.4 ! root      153: #ifdef MIPS_USES_FPU
        !           154: 
        !           155: #define SFREG 0
        !           156: #define DFREG 0
        !           157: #include "fop_template.c"
        !           158: #undef SFREG
        !           159: #undef DFREG
        !           160: #define SFREG 1
        !           161: #include "fop_template.c"
        !           162: #undef SFREG
        !           163: #define SFREG 2
        !           164: #define DFREG 2
        !           165: #include "fop_template.c"
        !           166: #undef SFREG
        !           167: #undef DFREG
        !           168: #define SFREG 3
        !           169: #include "fop_template.c"
        !           170: #undef SFREG
        !           171: #define SFREG 4
        !           172: #define DFREG 4
        !           173: #include "fop_template.c"
        !           174: #undef SFREG
        !           175: #undef DFREG
        !           176: #define SFREG 5
        !           177: #include "fop_template.c"
        !           178: #undef SFREG
        !           179: #define SFREG 6
        !           180: #define DFREG 6
        !           181: #include "fop_template.c"
        !           182: #undef SFREG
        !           183: #undef DFREG
        !           184: #define SFREG 7
        !           185: #include "fop_template.c"
        !           186: #undef SFREG
        !           187: #define SFREG 8
        !           188: #define DFREG 8
        !           189: #include "fop_template.c"
        !           190: #undef SFREG
        !           191: #undef DFREG
        !           192: #define SFREG 9
        !           193: #include "fop_template.c"
        !           194: #undef SFREG
        !           195: #define SFREG 10
        !           196: #define DFREG 10
        !           197: #include "fop_template.c"
        !           198: #undef SFREG
        !           199: #undef DFREG
        !           200: #define SFREG 11
        !           201: #include "fop_template.c"
        !           202: #undef SFREG
        !           203: #define SFREG 12
        !           204: #define DFREG 12
        !           205: #include "fop_template.c"
        !           206: #undef SFREG
        !           207: #undef DFREG
        !           208: #define SFREG 13
        !           209: #include "fop_template.c"
        !           210: #undef SFREG
        !           211: #define SFREG 14
        !           212: #define DFREG 14
        !           213: #include "fop_template.c"
        !           214: #undef SFREG
        !           215: #undef DFREG
        !           216: #define SFREG 15
        !           217: #include "fop_template.c"
        !           218: #undef SFREG
        !           219: #define SFREG 16
        !           220: #define DFREG 16
        !           221: #include "fop_template.c"
        !           222: #undef SFREG
        !           223: #undef DFREG
        !           224: #define SFREG 17
        !           225: #include "fop_template.c"
        !           226: #undef SFREG
        !           227: #define SFREG 18
        !           228: #define DFREG 18
        !           229: #include "fop_template.c"
        !           230: #undef SFREG
        !           231: #undef DFREG
        !           232: #define SFREG 19
        !           233: #include "fop_template.c"
        !           234: #undef SFREG
        !           235: #define SFREG 20
        !           236: #define DFREG 20
        !           237: #include "fop_template.c"
        !           238: #undef SFREG
        !           239: #undef DFREG
        !           240: #define SFREG 21
        !           241: #include "fop_template.c"
        !           242: #undef SFREG
        !           243: #define SFREG 22
        !           244: #define DFREG 22
        !           245: #include "fop_template.c"
        !           246: #undef SFREG
        !           247: #undef DFREG
        !           248: #define SFREG 23
        !           249: #include "fop_template.c"
        !           250: #undef SFREG
        !           251: #define SFREG 24
        !           252: #define DFREG 24
        !           253: #include "fop_template.c"
        !           254: #undef SFREG
        !           255: #undef DFREG
        !           256: #define SFREG 25
        !           257: #include "fop_template.c"
        !           258: #undef SFREG
        !           259: #define SFREG 26
        !           260: #define DFREG 26
        !           261: #include "fop_template.c"
        !           262: #undef SFREG
        !           263: #undef DFREG
        !           264: #define SFREG 27
        !           265: #include "fop_template.c"
        !           266: #undef SFREG
        !           267: #define SFREG 28
        !           268: #define DFREG 28
        !           269: #include "fop_template.c"
        !           270: #undef SFREG
        !           271: #undef DFREG
        !           272: #define SFREG 29
        !           273: #include "fop_template.c"
        !           274: #undef SFREG
        !           275: #define SFREG 30
        !           276: #define DFREG 30
        !           277: #include "fop_template.c"
        !           278: #undef SFREG
        !           279: #undef DFREG
        !           280: #define SFREG 31
        !           281: #include "fop_template.c"
        !           282: #undef SFREG
        !           283: 
        !           284: #define FTN
        !           285: #include "fop_template.c"
        !           286: #undef FTN
        !           287: 
        !           288: #endif
        !           289: 
1.1       root      290: void op_dup_T0 (void)
                    291: {
                    292:     T2 = T0;
                    293:     RETURN();
                    294: }
                    295: 
                    296: void op_load_HI (void)
                    297: {
                    298:     T0 = env->HI;
                    299:     RETURN();
                    300: }
                    301: 
                    302: void op_store_HI (void)
                    303: {
                    304:     env->HI = T0;
                    305:     RETURN();
                    306: }
                    307: 
                    308: void op_load_LO (void)
                    309: {
                    310:     T0 = env->LO;
                    311:     RETURN();
                    312: }
                    313: 
                    314: void op_store_LO (void)
                    315: {
                    316:     env->LO = T0;
                    317:     RETURN();
                    318: }
                    319: 
                    320: /* Load and store */
                    321: #define MEMSUFFIX _raw
                    322: #include "op_mem.c"
                    323: #undef MEMSUFFIX
                    324: #if !defined(CONFIG_USER_ONLY)
                    325: #define MEMSUFFIX _user
                    326: #include "op_mem.c"
                    327: #undef MEMSUFFIX
                    328: 
                    329: #define MEMSUFFIX _kernel
                    330: #include "op_mem.c"
                    331: #undef MEMSUFFIX
                    332: #endif
                    333: 
                    334: /* Arithmetic */
                    335: void op_add (void)
                    336: {
                    337:     T0 += T1;
                    338:     RETURN();
                    339: }
                    340: 
                    341: void op_addo (void)
                    342: {
                    343:     target_ulong tmp;
                    344: 
                    345:     tmp = T0;
                    346:     T0 += T1;
1.1.1.3   root      347:     if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
                    348:        /* operands of same sign, result different sign */
1.1.1.2   root      349:         CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
1.1       root      350:     }
                    351:     RETURN();
                    352: }
                    353: 
                    354: void op_sub (void)
                    355: {
                    356:     T0 -= T1;
                    357:     RETURN();
                    358: }
                    359: 
                    360: void op_subo (void)
                    361: {
                    362:     target_ulong tmp;
                    363: 
                    364:     tmp = T0;
                    365:     T0 = (int32_t)T0 - (int32_t)T1;
1.1.1.3   root      366:     if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
                    367:        /* operands of different sign, first operand and result different sign */
1.1.1.2   root      368:         CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
1.1       root      369:     }
                    370:     RETURN();
                    371: }
                    372: 
                    373: void op_mul (void)
                    374: {
                    375:     T0 = (int32_t)T0 * (int32_t)T1;
                    376:     RETURN();
                    377: }
                    378: 
                    379: void op_div (void)
                    380: {
                    381:     if (T1 != 0) {
                    382:         env->LO = (int32_t)T0 / (int32_t)T1;
                    383:         env->HI = (int32_t)T0 % (int32_t)T1;
                    384:     }
                    385:     RETURN();
                    386: }
                    387: 
                    388: void op_divu (void)
                    389: {
                    390:     if (T1 != 0) {
                    391:         env->LO = T0 / T1;
                    392:         env->HI = T0 % T1;
                    393:     }
                    394:     RETURN();
                    395: }
                    396: 
                    397: /* Logical */
                    398: void op_and (void)
                    399: {
                    400:     T0 &= T1;
                    401:     RETURN();
                    402: }
                    403: 
                    404: void op_nor (void)
                    405: {
                    406:     T0 = ~(T0 | T1);
                    407:     RETURN();
                    408: }
                    409: 
                    410: void op_or (void)
                    411: {
                    412:     T0 |= T1;
                    413:     RETURN();
                    414: }
                    415: 
                    416: void op_xor (void)
                    417: {
                    418:     T0 ^= T1;
                    419:     RETURN();
                    420: }
                    421: 
                    422: void op_sll (void)
                    423: {
                    424:     T0 = T0 << T1;
                    425:     RETURN();
                    426: }
                    427: 
                    428: void op_sra (void)
                    429: {
                    430:     T0 = (int32_t)T0 >> T1;
                    431:     RETURN();
                    432: }
                    433: 
                    434: void op_srl (void)
                    435: {
                    436:     T0 = T0 >> T1;
                    437:     RETURN();
                    438: }
                    439: 
                    440: void op_sllv (void)
                    441: {
                    442:     T0 = T1 << (T0 & 0x1F);
                    443:     RETURN();
                    444: }
                    445: 
                    446: void op_srav (void)
                    447: {
                    448:     T0 = (int32_t)T1 >> (T0 & 0x1F);
                    449:     RETURN();
                    450: }
                    451: 
                    452: void op_srlv (void)
                    453: {
                    454:     T0 = T1 >> (T0 & 0x1F);
                    455:     RETURN();
                    456: }
                    457: 
                    458: void op_clo (void)
                    459: {
                    460:     int n;
                    461: 
                    462:     if (T0 == (target_ulong)-1) {
                    463:         T0 = 32;
                    464:     } else {
                    465:         for (n = 0; n < 32; n++) {
                    466:             if (!(T0 & (1 << 31)))
                    467:                 break;
                    468:             T0 = T0 << 1;
                    469:         }
                    470:         T0 = n;
                    471:     }
                    472:     RETURN();
                    473: }
                    474: 
                    475: void op_clz (void)
                    476: {
                    477:     int n;
                    478: 
                    479:     if (T0 == 0) {
                    480:         T0 = 32;
                    481:     } else {
                    482:         for (n = 0; n < 32; n++) {
                    483:             if (T0 & (1 << 31))
                    484:                 break;
                    485:             T0 = T0 << 1;
                    486:         }
                    487:         T0 = n;
                    488:     }
                    489:     RETURN();
                    490: }
                    491: 
                    492: /* 64 bits arithmetic */
                    493: #if (HOST_LONG_BITS == 64)
                    494: static inline uint64_t get_HILO (void)
                    495: {
                    496:     return ((uint64_t)env->HI << 32) | (uint64_t)env->LO;
                    497: }
                    498: 
                    499: static inline void set_HILO (uint64_t HILO)
                    500: {
                    501:     env->LO = HILO & 0xFFFFFFFF;
                    502:     env->HI = HILO >> 32;
                    503: }
                    504: 
                    505: void op_mult (void)
                    506: {
1.1.1.2   root      507:     set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1.1       root      508:     RETURN();
                    509: }
                    510: 
                    511: void op_multu (void)
                    512: {
                    513:     set_HILO((uint64_t)T0 * (uint64_t)T1);
                    514:     RETURN();
                    515: }
                    516: 
                    517: void op_madd (void)
                    518: {
                    519:     int64_t tmp;
                    520: 
1.1.1.2   root      521:     tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1.1       root      522:     set_HILO((int64_t)get_HILO() + tmp);
                    523:     RETURN();
                    524: }
                    525: 
                    526: void op_maddu (void)
                    527: {
                    528:     uint64_t tmp;
                    529: 
                    530:     tmp = ((uint64_t)T0 * (uint64_t)T1);
                    531:     set_HILO(get_HILO() + tmp);
                    532:     RETURN();
                    533: }
                    534: 
                    535: void op_msub (void)
                    536: {
                    537:     int64_t tmp;
                    538: 
1.1.1.2   root      539:     tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1.1       root      540:     set_HILO((int64_t)get_HILO() - tmp);
                    541:     RETURN();
                    542: }
                    543: 
                    544: void op_msubu (void)
                    545: {
                    546:     uint64_t tmp;
                    547: 
                    548:     tmp = ((uint64_t)T0 * (uint64_t)T1);
                    549:     set_HILO(get_HILO() - tmp);
                    550:     RETURN();
                    551: }
                    552: #else
                    553: void op_mult (void)
                    554: {
                    555:     CALL_FROM_TB0(do_mult);
                    556:     RETURN();
                    557: }
                    558: 
                    559: void op_multu (void)
                    560: {
                    561:     CALL_FROM_TB0(do_multu);
                    562:     RETURN();
                    563: }
                    564: 
                    565: void op_madd (void)
                    566: {
                    567:     CALL_FROM_TB0(do_madd);
                    568:     RETURN();
                    569: }
                    570: 
                    571: void op_maddu (void)
                    572: {
                    573:     CALL_FROM_TB0(do_maddu);
                    574:     RETURN();
                    575: }
                    576: 
                    577: void op_msub (void)
                    578: {
                    579:     CALL_FROM_TB0(do_msub);
                    580:     RETURN();
                    581: }
                    582: 
                    583: void op_msubu (void)
                    584: {
                    585:     CALL_FROM_TB0(do_msubu);
                    586:     RETURN();
                    587: }
                    588: #endif
                    589: 
                    590: /* Conditional moves */
                    591: void op_movn (void)
                    592: {
                    593:     if (T1 != 0)
                    594:         env->gpr[PARAM1] = T0;
                    595:     RETURN();
                    596: }
                    597: 
                    598: void op_movz (void)
                    599: {
                    600:     if (T1 == 0)
                    601:         env->gpr[PARAM1] = T0;
                    602:     RETURN();
                    603: }
                    604: 
                    605: /* Tests */
                    606: #define OP_COND(name, cond) \
                    607: void glue(op_, name) (void) \
                    608: {                           \
                    609:     if (cond) {             \
                    610:         T0 = 1;             \
                    611:     } else {                \
                    612:         T0 = 0;             \
                    613:     }                       \
                    614:     RETURN();               \
                    615: }
                    616: 
                    617: OP_COND(eq, T0 == T1);
                    618: OP_COND(ne, T0 != T1);
                    619: OP_COND(ge, (int32_t)T0 >= (int32_t)T1);
                    620: OP_COND(geu, T0 >= T1);
                    621: OP_COND(lt, (int32_t)T0 < (int32_t)T1);
                    622: OP_COND(ltu, T0 < T1);
                    623: OP_COND(gez, (int32_t)T0 >= 0);
                    624: OP_COND(gtz, (int32_t)T0 > 0);
                    625: OP_COND(lez, (int32_t)T0 <= 0);
                    626: OP_COND(ltz, (int32_t)T0 < 0);
                    627: 
                    628: /* Branchs */
                    629: //#undef USE_DIRECT_JUMP
1.1.1.2   root      630: 
                    631: void OPPROTO op_goto_tb0(void)
                    632: {
                    633:     GOTO_TB(op_goto_tb0, PARAM1, 0);
                    634: }
                    635: 
                    636: void OPPROTO op_goto_tb1(void)
                    637: {
                    638:     GOTO_TB(op_goto_tb1, PARAM1, 1);
                    639: }
1.1       root      640: 
                    641: /* Branch to register */
                    642: void op_save_breg_target (void)
                    643: {
                    644:     env->btarget = T2;
                    645: }
                    646: 
                    647: void op_restore_breg_target (void)
                    648: {
                    649:     T2 = env->btarget;
                    650: }
                    651: 
                    652: void op_breg (void)
                    653: {
                    654:     env->PC = T2;
                    655:     RETURN();
                    656: }
                    657: 
                    658: void op_save_btarget (void)
                    659: {
                    660:     env->btarget = PARAM1;
                    661:     RETURN();
                    662: }
                    663: 
                    664: /* Conditional branch */
                    665: void op_set_bcond (void)
                    666: {
                    667:     T2 = T0;
                    668:     RETURN();
                    669: }
                    670: 
                    671: void op_save_bcond (void)
                    672: {
                    673:     env->bcond = T2;
                    674:     RETURN();
                    675: }
                    676: 
                    677: void op_restore_bcond (void)
                    678: {
                    679:     T2 = env->bcond;
                    680:     RETURN();
                    681: }
                    682: 
1.1.1.2   root      683: void op_jnz_T2 (void)
1.1       root      684: {
1.1.1.2   root      685:     if (T2)
                    686:         GOTO_LABEL_PARAM(1);
1.1       root      687:     RETURN();
                    688: }
                    689: 
                    690: /* CP0 functions */
                    691: void op_mfc0 (void)
                    692: {
                    693:     CALL_FROM_TB2(do_mfc0, PARAM1, PARAM2);
                    694:     RETURN();
                    695: }
                    696: 
                    697: void op_mtc0 (void)
                    698: {
                    699:     CALL_FROM_TB2(do_mtc0, PARAM1, PARAM2);
                    700:     RETURN();
                    701: }
                    702: 
1.1.1.4 ! root      703: #ifdef MIPS_USES_FPU
        !           704: 
        !           705: #if 0
        !           706: # define DEBUG_FPU_STATE() CALL_FROM_TB1(dump_fpu, env)
        !           707: #else
        !           708: # define DEBUG_FPU_STATE() do { } while(0)
        !           709: #endif
        !           710: 
        !           711: void op_cp1_enabled(void)
        !           712: {
        !           713:     if (!(env->CP0_Status & (1 << CP0St_CU1))) {
        !           714:         CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 1);
        !           715:     }
        !           716:     RETURN();
        !           717: }
        !           718: 
        !           719: /* CP1 functions */
        !           720: void op_cfc1 (void)
        !           721: {
        !           722:     if (T1 == 0) {
        !           723:         T0 = env->fcr0;
        !           724:     }
        !           725:     else {
        !           726:         /* fetch fcr31, masking unused bits */
        !           727:         T0 = env->fcr31 & 0x0183FFFF;
        !           728:     }
        !           729:     DEBUG_FPU_STATE();
        !           730:     RETURN();
        !           731: }
        !           732: 
        !           733: /* convert MIPS rounding mode in FCR31 to IEEE library */
        !           734: unsigned int ieee_rm[] = { 
        !           735:     float_round_nearest_even,
        !           736:     float_round_to_zero,
        !           737:     float_round_up,
        !           738:     float_round_down
        !           739: };
        !           740: 
        !           741: #define RESTORE_ROUNDING_MODE \
        !           742:     set_float_rounding_mode(ieee_rm[env->fcr31 & 3], &env->fp_status)
        !           743: 
        !           744: void op_ctc1 (void)
        !           745: {
        !           746:     if (T1 == 0) {
        !           747:         /* XXX should this throw an exception?
        !           748:          * don't write to FCR0.
        !           749:          * env->fcr0 = T0; 
        !           750:          */
        !           751:     }
        !           752:     else {
        !           753:         /* store new fcr31, masking unused bits */  
        !           754:         env->fcr31 = T0 & 0x0183FFFF;
        !           755: 
        !           756:         /* set rounding mode */
        !           757:         RESTORE_ROUNDING_MODE;
        !           758: 
        !           759: #ifndef CONFIG_SOFTFLOAT
        !           760:         /* no floating point exception for native float */
        !           761:         SET_FP_ENABLE(env->fcr31, 0);
        !           762: #endif
        !           763:     }
        !           764:     DEBUG_FPU_STATE();
        !           765:     RETURN();
        !           766: }
        !           767: 
        !           768: void op_mfc1 (void)
        !           769: {
        !           770:     T0 = WT0;
        !           771:     DEBUG_FPU_STATE();
        !           772:     RETURN();
        !           773: }
        !           774: 
        !           775: void op_mtc1 (void)
        !           776: {
        !           777:     WT0 = T0;
        !           778:     DEBUG_FPU_STATE();
        !           779:     RETURN();
        !           780: }
        !           781: 
        !           782: /* Float support.
        !           783:    Single precition routines have a "s" suffix, double precision a
        !           784:    "d" suffix.  */
        !           785: 
        !           786: #define FLOAT_OP(name, p) void OPPROTO op_float_##name##_##p(void)
        !           787: 
        !           788: FLOAT_OP(cvtd, w)
        !           789: {
        !           790:     FDT2 = int32_to_float64(WT0, &env->fp_status);
        !           791:     DEBUG_FPU_STATE();
        !           792:     RETURN();
        !           793: }
        !           794: FLOAT_OP(cvts, w)
        !           795: {
        !           796:     FST2 = int32_to_float32(WT0, &env->fp_status);
        !           797:     DEBUG_FPU_STATE();
        !           798:     RETURN();
        !           799: }
        !           800: FLOAT_OP(cvtw, s)
        !           801: {
        !           802:     WT2 = float32_to_int32(FST0, &env->fp_status);
        !           803:     DEBUG_FPU_STATE();
        !           804:     RETURN();
        !           805: }
        !           806: FLOAT_OP(cvtw, d)
        !           807: {
        !           808:     WT2 = float64_to_int32(FDT0, &env->fp_status);
        !           809:     DEBUG_FPU_STATE();
        !           810:     RETURN();
        !           811: }
        !           812: 
        !           813: FLOAT_OP(roundw, d)
        !           814: {
        !           815:     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
        !           816:     WT2 = float64_round_to_int(FDT0, &env->fp_status);
        !           817:     RESTORE_ROUNDING_MODE;
        !           818: 
        !           819:     DEBUG_FPU_STATE();
        !           820:     RETURN();
        !           821: }
        !           822: FLOAT_OP(roundw, s)
        !           823: {
        !           824:     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
        !           825:     WT2 = float32_round_to_int(FST0, &env->fp_status);
        !           826:     RESTORE_ROUNDING_MODE;
        !           827:     DEBUG_FPU_STATE();
        !           828:     RETURN();
        !           829: }
        !           830: 
        !           831: FLOAT_OP(truncw, d)
        !           832: {
        !           833:     WT2 = float64_to_int32_round_to_zero(FDT0, &env->fp_status);
        !           834:     DEBUG_FPU_STATE();
        !           835:     RETURN();
        !           836: }
        !           837: FLOAT_OP(truncw, s)
        !           838: {
        !           839:     WT2 = float32_to_int32_round_to_zero(FST0, &env->fp_status);
        !           840:     DEBUG_FPU_STATE();
        !           841:     RETURN();
        !           842: }
        !           843: 
        !           844: FLOAT_OP(ceilw, d)
        !           845: {
        !           846:     set_float_rounding_mode(float_round_up, &env->fp_status);
        !           847:     WT2 = float64_round_to_int(FDT0, &env->fp_status);
        !           848:     RESTORE_ROUNDING_MODE;
        !           849: 
        !           850:     DEBUG_FPU_STATE();
        !           851:     RETURN();
        !           852: }
        !           853: FLOAT_OP(ceilw, s)
        !           854: {
        !           855:     set_float_rounding_mode(float_round_up, &env->fp_status);
        !           856:     WT2 = float32_round_to_int(FST0, &env->fp_status);
        !           857:     RESTORE_ROUNDING_MODE;
        !           858:     DEBUG_FPU_STATE();
        !           859:     RETURN();
        !           860: }
        !           861: 
        !           862: FLOAT_OP(floorw, d)
        !           863: {
        !           864:     set_float_rounding_mode(float_round_down, &env->fp_status);
        !           865:     WT2 = float64_round_to_int(FDT0, &env->fp_status);
        !           866:     RESTORE_ROUNDING_MODE;
        !           867: 
        !           868:     DEBUG_FPU_STATE();
        !           869:     RETURN();
        !           870: }
        !           871: FLOAT_OP(floorw, s)
        !           872: {
        !           873:     set_float_rounding_mode(float_round_down, &env->fp_status);
        !           874:     WT2 = float32_round_to_int(FST0, &env->fp_status);
        !           875:     RESTORE_ROUNDING_MODE;
        !           876:     DEBUG_FPU_STATE();
        !           877:     RETURN();
        !           878: }
        !           879: 
        !           880: /* binary operations */
        !           881: #define FLOAT_BINOP(name) \
        !           882: FLOAT_OP(name, d)         \
        !           883: {                         \
        !           884:     FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status);    \
        !           885:     DEBUG_FPU_STATE();    \
        !           886: }                         \
        !           887: FLOAT_OP(name, s)         \
        !           888: {                         \
        !           889:     FST2 = float32_ ## name (FST0, FST1, &env->fp_status);    \
        !           890:     DEBUG_FPU_STATE();    \
        !           891: }
        !           892: FLOAT_BINOP(add)
        !           893: FLOAT_BINOP(sub)
        !           894: FLOAT_BINOP(mul)
        !           895: FLOAT_BINOP(div)
        !           896: #undef FLOAT_BINOP
        !           897: 
        !           898: /* unary operations, modifying fp status  */
        !           899: #define FLOAT_UNOP(name)  \
        !           900: FLOAT_OP(name, d)         \
        !           901: {                         \
        !           902:     FDT2 = float64_ ## name(FDT0, &env->fp_status);   \
        !           903:     DEBUG_FPU_STATE();    \
        !           904: }                         \
        !           905: FLOAT_OP(name, s)         \
        !           906: {                         \
        !           907:     FST2 = float32_ ## name(FST0, &env->fp_status);   \
        !           908:     DEBUG_FPU_STATE();    \
        !           909: }
        !           910: FLOAT_UNOP(sqrt)
        !           911: #undef FLOAT_UNOP
        !           912: 
        !           913: /* unary operations, not modifying fp status  */
        !           914: #define FLOAT_UNOP(name)  \
        !           915: FLOAT_OP(name, d)         \
        !           916: {                         \
        !           917:     FDT2 = float64_ ## name(FDT0);   \
        !           918:     DEBUG_FPU_STATE();    \
        !           919: }                         \
        !           920: FLOAT_OP(name, s)         \
        !           921: {                         \
        !           922:     FST2 = float32_ ## name(FST0);   \
        !           923:     DEBUG_FPU_STATE();    \
        !           924: }
        !           925: FLOAT_UNOP(abs)
        !           926: FLOAT_UNOP(chs)
        !           927: #undef FLOAT_UNOP
        !           928: 
        !           929: FLOAT_OP(mov, d)
        !           930: {
        !           931:     FDT2 = FDT0;
        !           932:     DEBUG_FPU_STATE();
        !           933:     RETURN();
        !           934: }
        !           935: FLOAT_OP(mov, s)
        !           936: {
        !           937:     FST2 = FST0;
        !           938:     DEBUG_FPU_STATE();
        !           939:     RETURN();
        !           940: }
        !           941: 
        !           942: #ifdef CONFIG_SOFTFLOAT
        !           943: #define clear_invalid() do {                                \
        !           944:     int flags = get_float_exception_flags(&env->fp_status); \
        !           945:     flags &= ~float_flag_invalid;                           \
        !           946:     set_float_exception_flags(flags, &env->fp_status);      \
        !           947: } while(0)
        !           948: #else
        !           949: #define clear_invalid() do { } while(0)
        !           950: #endif
        !           951: 
        !           952: extern void dump_fpu_s(CPUState *env);
        !           953: 
        !           954: #define FOP_COND(fmt, op, sig, cond)           \
        !           955: void op_cmp_ ## fmt ## _ ## op (void)          \
        !           956: {                                              \
        !           957:     if (cond)                                  \
        !           958:         SET_FP_COND(env->fcr31);               \
        !           959:     else                                       \
        !           960:         CLEAR_FP_COND(env->fcr31);             \
        !           961:     if (!sig)                                  \
        !           962:         clear_invalid();                       \
        !           963:     /*CALL_FROM_TB1(dump_fpu_s, env);*/ \
        !           964:     DEBUG_FPU_STATE();                         \
        !           965:     RETURN();                                  \
        !           966: }
        !           967: 
        !           968: flag float64_is_unordered(float64 a, float64 b STATUS_PARAM)
        !           969: {
        !           970:     extern flag float64_is_nan( float64 a );
        !           971:     if (float64_is_nan(a) || float64_is_nan(b)) {
        !           972:         float_raise(float_flag_invalid, status);
        !           973:         return 1;
        !           974:     }
        !           975:     else {
        !           976:         return 0;
        !           977:     }
        !           978: }
        !           979: 
        !           980: FOP_COND(d, f,   0,                                                      0) 
        !           981: FOP_COND(d, un,  0, float64_is_unordered(FDT1, FDT0, &env->fp_status))
        !           982: FOP_COND(d, eq,  0,                                                      float64_eq(FDT0, FDT1, &env->fp_status))
        !           983: FOP_COND(d, ueq, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
        !           984: FOP_COND(d, olt, 0,                                                      float64_lt(FDT0, FDT1, &env->fp_status))
        !           985: FOP_COND(d, ult, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
        !           986: FOP_COND(d, ole, 0,                                                      float64_le(FDT0, FDT1, &env->fp_status))
        !           987: FOP_COND(d, ule, 0, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
        !           988: /* NOTE: the comma operator will make "cond" to eval to false,
        !           989:  * but float*_is_unordered() is still called
        !           990:  */
        !           991: FOP_COND(d, sf,  1,                                                      (float64_is_unordered(FDT0, FDT1, &env->fp_status), 0))
        !           992: FOP_COND(d, ngle,1, float64_is_unordered(FDT1, FDT0, &env->fp_status))
        !           993: FOP_COND(d, seq, 1,                                                      float64_eq(FDT0, FDT1, &env->fp_status))
        !           994: FOP_COND(d, ngl, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_eq(FDT0, FDT1, &env->fp_status))
        !           995: FOP_COND(d, lt,  1,                                                      float64_lt(FDT0, FDT1, &env->fp_status))
        !           996: FOP_COND(d, nge, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_lt(FDT0, FDT1, &env->fp_status))
        !           997: FOP_COND(d, le,  1,                                                      float64_le(FDT0, FDT1, &env->fp_status))
        !           998: FOP_COND(d, ngt, 1, float64_is_unordered(FDT1, FDT0, &env->fp_status) || float64_le(FDT0, FDT1, &env->fp_status))
        !           999: 
        !          1000: flag float32_is_unordered(float32 a, float32 b STATUS_PARAM)
        !          1001: {
        !          1002:     extern flag float32_is_nan( float32 a );
        !          1003:     if (float32_is_nan(a) || float32_is_nan(b)) {
        !          1004:         float_raise(float_flag_invalid, status);
        !          1005:         return 1;
        !          1006:     }
        !          1007:     else {
        !          1008:         return 0;
        !          1009:     }
        !          1010: }
        !          1011: 
        !          1012: /* NOTE: the comma operator will make "cond" to eval to false,
        !          1013:  * but float*_is_unordered() is still called
        !          1014:  */
        !          1015: FOP_COND(s, f,   0,                                                      0) 
        !          1016: FOP_COND(s, un,  0, float32_is_unordered(FST1, FST0, &env->fp_status))
        !          1017: FOP_COND(s, eq,  0,                                                      float32_eq(FST0, FST1, &env->fp_status))
        !          1018: FOP_COND(s, ueq, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
        !          1019: FOP_COND(s, olt, 0,                                                      float32_lt(FST0, FST1, &env->fp_status))
        !          1020: FOP_COND(s, ult, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
        !          1021: FOP_COND(s, ole, 0,                                                      float32_le(FST0, FST1, &env->fp_status))
        !          1022: FOP_COND(s, ule, 0, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
        !          1023: /* NOTE: the comma operator will make "cond" to eval to false,
        !          1024:  * but float*_is_unordered() is still called
        !          1025:  */
        !          1026: FOP_COND(s, sf,  1,                                                      (float32_is_unordered(FST0, FST1, &env->fp_status), 0))
        !          1027: FOP_COND(s, ngle,1, float32_is_unordered(FST1, FST0, &env->fp_status))
        !          1028: FOP_COND(s, seq, 1,                                                      float32_eq(FST0, FST1, &env->fp_status))
        !          1029: FOP_COND(s, ngl, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_eq(FST0, FST1, &env->fp_status))
        !          1030: FOP_COND(s, lt,  1,                                                      float32_lt(FST0, FST1, &env->fp_status))
        !          1031: FOP_COND(s, nge, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_lt(FST0, FST1, &env->fp_status))
        !          1032: FOP_COND(s, le,  1,                                                      float32_le(FST0, FST1, &env->fp_status))
        !          1033: FOP_COND(s, ngt, 1, float32_is_unordered(FST1, FST0, &env->fp_status) || float32_le(FST0, FST1, &env->fp_status))
        !          1034: 
        !          1035: void op_bc1f (void)
        !          1036: {
        !          1037:     T0 = ! IS_FP_COND_SET(env->fcr31);
        !          1038:     DEBUG_FPU_STATE();
        !          1039:     RETURN();
        !          1040: }
        !          1041: 
        !          1042: void op_bc1t (void)
        !          1043: {
        !          1044:     T0 = IS_FP_COND_SET(env->fcr31);
        !          1045:     DEBUG_FPU_STATE();
        !          1046:     RETURN();
        !          1047: }
        !          1048: #endif /* MIPS_USES_FPU */
        !          1049: 
1.1       root     1050: #if defined(MIPS_USES_R4K_TLB)
                   1051: void op_tlbwi (void)
                   1052: {
                   1053:     CALL_FROM_TB0(do_tlbwi);
                   1054:     RETURN();
                   1055: }
                   1056: 
                   1057: void op_tlbwr (void)
                   1058: {
                   1059:     CALL_FROM_TB0(do_tlbwr);
                   1060:     RETURN();
                   1061: }
                   1062: 
                   1063: void op_tlbp (void)
                   1064: {
                   1065:     CALL_FROM_TB0(do_tlbp);
                   1066:     RETURN();
                   1067: }
                   1068: 
                   1069: void op_tlbr (void)
                   1070: {
                   1071:     CALL_FROM_TB0(do_tlbr);
                   1072:     RETURN();
                   1073: }
                   1074: #endif
                   1075: 
                   1076: /* Specials */
                   1077: void op_pmon (void)
                   1078: {
                   1079:     CALL_FROM_TB1(do_pmon, PARAM1);
                   1080: }
                   1081: 
                   1082: void op_trap (void)
                   1083: {
                   1084:     if (T0) {
1.1.1.2   root     1085:         CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP);
1.1       root     1086:     }
                   1087:     RETURN();
                   1088: }
                   1089: 
1.1.1.2   root     1090: void op_debug (void)
                   1091: {
1.1.1.3   root     1092:   CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
1.1.1.2   root     1093: }
                   1094: 
1.1       root     1095: void op_set_lladdr (void)
                   1096: {
                   1097:     env->CP0_LLAddr = T2;
                   1098: }
                   1099: 
                   1100: void debug_eret (void);
                   1101: void op_eret (void)
                   1102: {
                   1103:     CALL_FROM_TB0(debug_eret);
                   1104:     if (env->hflags & MIPS_HFLAG_ERL) {
                   1105:         env->PC = env->CP0_ErrorEPC;
                   1106:         env->hflags &= ~MIPS_HFLAG_ERL;
1.1.1.4 ! root     1107:        env->CP0_Status &= ~(1 << CP0St_ERL);
1.1       root     1108:     } else {
                   1109:         env->PC = env->CP0_EPC;
                   1110:         env->hflags &= ~MIPS_HFLAG_EXL;
1.1.1.4 ! root     1111:        env->CP0_Status &= ~(1 << CP0St_EXL);
1.1       root     1112:     }
                   1113:     env->CP0_LLAddr = 1;
                   1114: }
                   1115: 
                   1116: void op_deret (void)
                   1117: {
                   1118:     CALL_FROM_TB0(debug_eret);
                   1119:     env->PC = env->CP0_DEPC;
                   1120: }
                   1121: 
                   1122: void op_save_state (void)
                   1123: {
                   1124:     env->hflags = PARAM1;
                   1125:     RETURN();
                   1126: }
                   1127: 
                   1128: void op_save_pc (void)
                   1129: {
                   1130:     env->PC = PARAM1;
                   1131:     RETURN();
                   1132: }
                   1133: 
                   1134: void op_raise_exception (void)
                   1135: {
                   1136:     CALL_FROM_TB1(do_raise_exception, PARAM1);
                   1137:     RETURN();
                   1138: }
                   1139: 
                   1140: void op_raise_exception_err (void)
                   1141: {
                   1142:     CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
                   1143:     RETURN();
                   1144: }
                   1145: 
                   1146: void op_exit_tb (void)
                   1147: {
                   1148:     EXIT_TB();
                   1149: }
                   1150: 
1.1.1.2   root     1151: void op_wait (void)
                   1152: {
                   1153:     env->halted = 1;
                   1154:     CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
                   1155: }

unix.superglobalmegacorp.com

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