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

1.1       root        1: /*
                      2:  *  MIPS emulation micro-operations for qemu.
                      3:  * 
                      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
                     18:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     19:  */
                     20: 
                     21: #include "config.h"
                     22: #include "exec.h"
                     23: 
                     24: #ifndef CALL_FROM_TB0
                     25: #define CALL_FROM_TB0(func) func();
                     26: #endif
                     27: #ifndef CALL_FROM_TB1
                     28: #define CALL_FROM_TB1(func, arg0) func(arg0);
                     29: #endif
                     30: #ifndef CALL_FROM_TB1_CONST16
                     31: #define CALL_FROM_TB1_CONST16(func, arg0) CALL_FROM_TB1(func, arg0);
                     32: #endif
                     33: #ifndef CALL_FROM_TB2
                     34: #define CALL_FROM_TB2(func, arg0, arg1) func(arg0, arg1);
                     35: #endif
                     36: #ifndef CALL_FROM_TB2_CONST16
                     37: #define CALL_FROM_TB2_CONST16(func, arg0, arg1)     \
                     38: CALL_FROM_TB2(func, arg0, arg1);
                     39: #endif
                     40: #ifndef CALL_FROM_TB3
                     41: #define CALL_FROM_TB3(func, arg0, arg1, arg2) func(arg0, arg1, arg2);
                     42: #endif
                     43: #ifndef CALL_FROM_TB4
                     44: #define CALL_FROM_TB4(func, arg0, arg1, arg2, arg3) \
                     45:         func(arg0, arg1, arg2, arg3);
                     46: #endif
                     47: 
                     48: #define REG 1
                     49: #include "op_template.c"
                     50: #undef REG
                     51: #define REG 2
                     52: #include "op_template.c"
                     53: #undef REG
                     54: #define REG 3
                     55: #include "op_template.c"
                     56: #undef REG
                     57: #define REG 4
                     58: #include "op_template.c"
                     59: #undef REG
                     60: #define REG 5
                     61: #include "op_template.c"
                     62: #undef REG
                     63: #define REG 6
                     64: #include "op_template.c"
                     65: #undef REG
                     66: #define REG 7
                     67: #include "op_template.c"
                     68: #undef REG
                     69: #define REG 8
                     70: #include "op_template.c"
                     71: #undef REG
                     72: #define REG 9
                     73: #include "op_template.c"
                     74: #undef REG
                     75: #define REG 10
                     76: #include "op_template.c"
                     77: #undef REG
                     78: #define REG 11
                     79: #include "op_template.c"
                     80: #undef REG
                     81: #define REG 12
                     82: #include "op_template.c"
                     83: #undef REG
                     84: #define REG 13
                     85: #include "op_template.c"
                     86: #undef REG
                     87: #define REG 14
                     88: #include "op_template.c"
                     89: #undef REG
                     90: #define REG 15
                     91: #include "op_template.c"
                     92: #undef REG
                     93: #define REG 16
                     94: #include "op_template.c"
                     95: #undef REG
                     96: #define REG 17
                     97: #include "op_template.c"
                     98: #undef REG
                     99: #define REG 18
                    100: #include "op_template.c"
                    101: #undef REG
                    102: #define REG 19
                    103: #include "op_template.c"
                    104: #undef REG
                    105: #define REG 20
                    106: #include "op_template.c"
                    107: #undef REG
                    108: #define REG 21
                    109: #include "op_template.c"
                    110: #undef REG
                    111: #define REG 22
                    112: #include "op_template.c"
                    113: #undef REG
                    114: #define REG 23
                    115: #include "op_template.c"
                    116: #undef REG
                    117: #define REG 24
                    118: #include "op_template.c"
                    119: #undef REG
                    120: #define REG 25
                    121: #include "op_template.c"
                    122: #undef REG
                    123: #define REG 26
                    124: #include "op_template.c"
                    125: #undef REG
                    126: #define REG 27
                    127: #include "op_template.c"
                    128: #undef REG
                    129: #define REG 28
                    130: #include "op_template.c"
                    131: #undef REG
                    132: #define REG 29
                    133: #include "op_template.c"
                    134: #undef REG
                    135: #define REG 30
                    136: #include "op_template.c"
                    137: #undef REG
                    138: #define REG 31
                    139: #include "op_template.c"
                    140: #undef REG
                    141: 
                    142: #define TN T0
                    143: #include "op_template.c"
                    144: #undef TN
                    145: #define TN T1
                    146: #include "op_template.c"
                    147: #undef TN
                    148: #define TN T2
                    149: #include "op_template.c"
                    150: #undef TN
                    151: 
                    152: void op_dup_T0 (void)
                    153: {
                    154:     T2 = T0;
                    155:     RETURN();
                    156: }
                    157: 
                    158: void op_load_HI (void)
                    159: {
                    160:     T0 = env->HI;
                    161:     RETURN();
                    162: }
                    163: 
                    164: void op_store_HI (void)
                    165: {
                    166:     env->HI = T0;
                    167:     RETURN();
                    168: }
                    169: 
                    170: void op_load_LO (void)
                    171: {
                    172:     T0 = env->LO;
                    173:     RETURN();
                    174: }
                    175: 
                    176: void op_store_LO (void)
                    177: {
                    178:     env->LO = T0;
                    179:     RETURN();
                    180: }
                    181: 
                    182: /* Load and store */
                    183: #define MEMSUFFIX _raw
                    184: #include "op_mem.c"
                    185: #undef MEMSUFFIX
                    186: #if !defined(CONFIG_USER_ONLY)
                    187: #define MEMSUFFIX _user
                    188: #include "op_mem.c"
                    189: #undef MEMSUFFIX
                    190: 
                    191: #define MEMSUFFIX _kernel
                    192: #include "op_mem.c"
                    193: #undef MEMSUFFIX
                    194: #endif
                    195: 
                    196: /* Arithmetic */
                    197: void op_add (void)
                    198: {
                    199:     T0 += T1;
                    200:     RETURN();
                    201: }
                    202: 
                    203: void op_addo (void)
                    204: {
                    205:     target_ulong tmp;
                    206: 
                    207:     tmp = T0;
                    208:     T0 += T1;
1.1.1.3 ! root      209:     if (((tmp ^ T1 ^ (-1)) & (T0 ^ T1)) >> 31) {
        !           210:        /* operands of same sign, result different sign */
1.1.1.2   root      211:         CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
1.1       root      212:     }
                    213:     RETURN();
                    214: }
                    215: 
                    216: void op_sub (void)
                    217: {
                    218:     T0 -= T1;
                    219:     RETURN();
                    220: }
                    221: 
                    222: void op_subo (void)
                    223: {
                    224:     target_ulong tmp;
                    225: 
                    226:     tmp = T0;
                    227:     T0 = (int32_t)T0 - (int32_t)T1;
1.1.1.3 ! root      228:     if (((tmp ^ T1) & (tmp ^ T0)) >> 31) {
        !           229:        /* operands of different sign, first operand and result different sign */
1.1.1.2   root      230:         CALL_FROM_TB1(do_raise_exception_direct, EXCP_OVERFLOW);
1.1       root      231:     }
                    232:     RETURN();
                    233: }
                    234: 
                    235: void op_mul (void)
                    236: {
                    237:     T0 = (int32_t)T0 * (int32_t)T1;
                    238:     RETURN();
                    239: }
                    240: 
                    241: void op_div (void)
                    242: {
                    243:     if (T1 != 0) {
                    244:         env->LO = (int32_t)T0 / (int32_t)T1;
                    245:         env->HI = (int32_t)T0 % (int32_t)T1;
                    246:     }
                    247:     RETURN();
                    248: }
                    249: 
                    250: void op_divu (void)
                    251: {
                    252:     if (T1 != 0) {
                    253:         env->LO = T0 / T1;
                    254:         env->HI = T0 % T1;
                    255:     }
                    256:     RETURN();
                    257: }
                    258: 
                    259: /* Logical */
                    260: void op_and (void)
                    261: {
                    262:     T0 &= T1;
                    263:     RETURN();
                    264: }
                    265: 
                    266: void op_nor (void)
                    267: {
                    268:     T0 = ~(T0 | T1);
                    269:     RETURN();
                    270: }
                    271: 
                    272: void op_or (void)
                    273: {
                    274:     T0 |= T1;
                    275:     RETURN();
                    276: }
                    277: 
                    278: void op_xor (void)
                    279: {
                    280:     T0 ^= T1;
                    281:     RETURN();
                    282: }
                    283: 
                    284: void op_sll (void)
                    285: {
                    286:     T0 = T0 << T1;
                    287:     RETURN();
                    288: }
                    289: 
                    290: void op_sra (void)
                    291: {
                    292:     T0 = (int32_t)T0 >> T1;
                    293:     RETURN();
                    294: }
                    295: 
                    296: void op_srl (void)
                    297: {
                    298:     T0 = T0 >> T1;
                    299:     RETURN();
                    300: }
                    301: 
                    302: void op_sllv (void)
                    303: {
                    304:     T0 = T1 << (T0 & 0x1F);
                    305:     RETURN();
                    306: }
                    307: 
                    308: void op_srav (void)
                    309: {
                    310:     T0 = (int32_t)T1 >> (T0 & 0x1F);
                    311:     RETURN();
                    312: }
                    313: 
                    314: void op_srlv (void)
                    315: {
                    316:     T0 = T1 >> (T0 & 0x1F);
                    317:     RETURN();
                    318: }
                    319: 
                    320: void op_clo (void)
                    321: {
                    322:     int n;
                    323: 
                    324:     if (T0 == (target_ulong)-1) {
                    325:         T0 = 32;
                    326:     } else {
                    327:         for (n = 0; n < 32; n++) {
                    328:             if (!(T0 & (1 << 31)))
                    329:                 break;
                    330:             T0 = T0 << 1;
                    331:         }
                    332:         T0 = n;
                    333:     }
                    334:     RETURN();
                    335: }
                    336: 
                    337: void op_clz (void)
                    338: {
                    339:     int n;
                    340: 
                    341:     if (T0 == 0) {
                    342:         T0 = 32;
                    343:     } else {
                    344:         for (n = 0; n < 32; n++) {
                    345:             if (T0 & (1 << 31))
                    346:                 break;
                    347:             T0 = T0 << 1;
                    348:         }
                    349:         T0 = n;
                    350:     }
                    351:     RETURN();
                    352: }
                    353: 
                    354: /* 64 bits arithmetic */
                    355: #if (HOST_LONG_BITS == 64)
                    356: static inline uint64_t get_HILO (void)
                    357: {
                    358:     return ((uint64_t)env->HI << 32) | (uint64_t)env->LO;
                    359: }
                    360: 
                    361: static inline void set_HILO (uint64_t HILO)
                    362: {
                    363:     env->LO = HILO & 0xFFFFFFFF;
                    364:     env->HI = HILO >> 32;
                    365: }
                    366: 
                    367: void op_mult (void)
                    368: {
1.1.1.2   root      369:     set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1.1       root      370:     RETURN();
                    371: }
                    372: 
                    373: void op_multu (void)
                    374: {
                    375:     set_HILO((uint64_t)T0 * (uint64_t)T1);
                    376:     RETURN();
                    377: }
                    378: 
                    379: void op_madd (void)
                    380: {
                    381:     int64_t tmp;
                    382: 
1.1.1.2   root      383:     tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1.1       root      384:     set_HILO((int64_t)get_HILO() + tmp);
                    385:     RETURN();
                    386: }
                    387: 
                    388: void op_maddu (void)
                    389: {
                    390:     uint64_t tmp;
                    391: 
                    392:     tmp = ((uint64_t)T0 * (uint64_t)T1);
                    393:     set_HILO(get_HILO() + tmp);
                    394:     RETURN();
                    395: }
                    396: 
                    397: void op_msub (void)
                    398: {
                    399:     int64_t tmp;
                    400: 
1.1.1.2   root      401:     tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);
1.1       root      402:     set_HILO((int64_t)get_HILO() - tmp);
                    403:     RETURN();
                    404: }
                    405: 
                    406: void op_msubu (void)
                    407: {
                    408:     uint64_t tmp;
                    409: 
                    410:     tmp = ((uint64_t)T0 * (uint64_t)T1);
                    411:     set_HILO(get_HILO() - tmp);
                    412:     RETURN();
                    413: }
                    414: #else
                    415: void op_mult (void)
                    416: {
                    417:     CALL_FROM_TB0(do_mult);
                    418:     RETURN();
                    419: }
                    420: 
                    421: void op_multu (void)
                    422: {
                    423:     CALL_FROM_TB0(do_multu);
                    424:     RETURN();
                    425: }
                    426: 
                    427: void op_madd (void)
                    428: {
                    429:     CALL_FROM_TB0(do_madd);
                    430:     RETURN();
                    431: }
                    432: 
                    433: void op_maddu (void)
                    434: {
                    435:     CALL_FROM_TB0(do_maddu);
                    436:     RETURN();
                    437: }
                    438: 
                    439: void op_msub (void)
                    440: {
                    441:     CALL_FROM_TB0(do_msub);
                    442:     RETURN();
                    443: }
                    444: 
                    445: void op_msubu (void)
                    446: {
                    447:     CALL_FROM_TB0(do_msubu);
                    448:     RETURN();
                    449: }
                    450: #endif
                    451: 
                    452: /* Conditional moves */
                    453: void op_movn (void)
                    454: {
                    455:     if (T1 != 0)
                    456:         env->gpr[PARAM1] = T0;
                    457:     RETURN();
                    458: }
                    459: 
                    460: void op_movz (void)
                    461: {
                    462:     if (T1 == 0)
                    463:         env->gpr[PARAM1] = T0;
                    464:     RETURN();
                    465: }
                    466: 
                    467: /* Tests */
                    468: #define OP_COND(name, cond) \
                    469: void glue(op_, name) (void) \
                    470: {                           \
                    471:     if (cond) {             \
                    472:         T0 = 1;             \
                    473:     } else {                \
                    474:         T0 = 0;             \
                    475:     }                       \
                    476:     RETURN();               \
                    477: }
                    478: 
                    479: OP_COND(eq, T0 == T1);
                    480: OP_COND(ne, T0 != T1);
                    481: OP_COND(ge, (int32_t)T0 >= (int32_t)T1);
                    482: OP_COND(geu, T0 >= T1);
                    483: OP_COND(lt, (int32_t)T0 < (int32_t)T1);
                    484: OP_COND(ltu, T0 < T1);
                    485: OP_COND(gez, (int32_t)T0 >= 0);
                    486: OP_COND(gtz, (int32_t)T0 > 0);
                    487: OP_COND(lez, (int32_t)T0 <= 0);
                    488: OP_COND(ltz, (int32_t)T0 < 0);
                    489: 
                    490: /* Branchs */
                    491: //#undef USE_DIRECT_JUMP
1.1.1.2   root      492: 
                    493: void OPPROTO op_goto_tb0(void)
                    494: {
                    495:     GOTO_TB(op_goto_tb0, PARAM1, 0);
                    496: }
                    497: 
                    498: void OPPROTO op_goto_tb1(void)
                    499: {
                    500:     GOTO_TB(op_goto_tb1, PARAM1, 1);
                    501: }
1.1       root      502: 
                    503: /* Branch to register */
                    504: void op_save_breg_target (void)
                    505: {
                    506:     env->btarget = T2;
                    507: }
                    508: 
                    509: void op_restore_breg_target (void)
                    510: {
                    511:     T2 = env->btarget;
                    512: }
                    513: 
                    514: void op_breg (void)
                    515: {
                    516:     env->PC = T2;
                    517:     RETURN();
                    518: }
                    519: 
                    520: void op_save_btarget (void)
                    521: {
                    522:     env->btarget = PARAM1;
                    523:     RETURN();
                    524: }
                    525: 
                    526: /* Conditional branch */
                    527: void op_set_bcond (void)
                    528: {
                    529:     T2 = T0;
                    530:     RETURN();
                    531: }
                    532: 
                    533: void op_save_bcond (void)
                    534: {
                    535:     env->bcond = T2;
                    536:     RETURN();
                    537: }
                    538: 
                    539: void op_restore_bcond (void)
                    540: {
                    541:     T2 = env->bcond;
                    542:     RETURN();
                    543: }
                    544: 
1.1.1.2   root      545: void op_jnz_T2 (void)
1.1       root      546: {
1.1.1.2   root      547:     if (T2)
                    548:         GOTO_LABEL_PARAM(1);
1.1       root      549:     RETURN();
                    550: }
                    551: 
                    552: /* CP0 functions */
                    553: void op_mfc0 (void)
                    554: {
                    555:     CALL_FROM_TB2(do_mfc0, PARAM1, PARAM2);
                    556:     RETURN();
                    557: }
                    558: 
                    559: void op_mtc0 (void)
                    560: {
                    561:     CALL_FROM_TB2(do_mtc0, PARAM1, PARAM2);
                    562:     RETURN();
                    563: }
                    564: 
                    565: #if defined(MIPS_USES_R4K_TLB)
                    566: void op_tlbwi (void)
                    567: {
                    568:     CALL_FROM_TB0(do_tlbwi);
                    569:     RETURN();
                    570: }
                    571: 
                    572: void op_tlbwr (void)
                    573: {
                    574:     CALL_FROM_TB0(do_tlbwr);
                    575:     RETURN();
                    576: }
                    577: 
                    578: void op_tlbp (void)
                    579: {
                    580:     CALL_FROM_TB0(do_tlbp);
                    581:     RETURN();
                    582: }
                    583: 
                    584: void op_tlbr (void)
                    585: {
                    586:     CALL_FROM_TB0(do_tlbr);
                    587:     RETURN();
                    588: }
                    589: #endif
                    590: 
                    591: /* Specials */
                    592: void op_pmon (void)
                    593: {
                    594:     CALL_FROM_TB1(do_pmon, PARAM1);
                    595: }
                    596: 
                    597: void op_trap (void)
                    598: {
                    599:     if (T0) {
1.1.1.2   root      600:         CALL_FROM_TB1(do_raise_exception_direct, EXCP_TRAP);
1.1       root      601:     }
                    602:     RETURN();
                    603: }
                    604: 
1.1.1.2   root      605: void op_debug (void)
                    606: {
1.1.1.3 ! root      607:   CALL_FROM_TB1(do_raise_exception, EXCP_DEBUG);
1.1.1.2   root      608: }
                    609: 
1.1       root      610: void op_set_lladdr (void)
                    611: {
                    612:     env->CP0_LLAddr = T2;
                    613: }
                    614: 
                    615: void debug_eret (void);
                    616: void op_eret (void)
                    617: {
                    618:     CALL_FROM_TB0(debug_eret);
                    619:     if (env->hflags & MIPS_HFLAG_ERL) {
                    620:         env->PC = env->CP0_ErrorEPC;
                    621:         env->hflags &= ~MIPS_HFLAG_ERL;
                    622:     } else {
                    623:         env->PC = env->CP0_EPC;
                    624:         env->hflags &= ~MIPS_HFLAG_EXL;
                    625:     }
                    626:     env->CP0_LLAddr = 1;
                    627: }
                    628: 
                    629: void op_deret (void)
                    630: {
                    631:     CALL_FROM_TB0(debug_eret);
                    632:     env->PC = env->CP0_DEPC;
                    633: }
                    634: 
                    635: void op_save_state (void)
                    636: {
                    637:     env->hflags = PARAM1;
                    638:     RETURN();
                    639: }
                    640: 
                    641: void op_save_pc (void)
                    642: {
                    643:     env->PC = PARAM1;
                    644:     RETURN();
                    645: }
                    646: 
                    647: void op_raise_exception (void)
                    648: {
                    649:     CALL_FROM_TB1(do_raise_exception, PARAM1);
                    650:     RETURN();
                    651: }
                    652: 
                    653: void op_raise_exception_err (void)
                    654: {
                    655:     CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
                    656:     RETURN();
                    657: }
                    658: 
                    659: void op_exit_tb (void)
                    660: {
                    661:     EXIT_TB();
                    662: }
                    663: 
1.1.1.2   root      664: void op_wait (void)
                    665: {
                    666:     env->halted = 1;
                    667:     CALL_FROM_TB1(do_raise_exception, EXCP_HLT);
                    668: }

unix.superglobalmegacorp.com

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