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

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;
        !           209:     if ((T0 >> 31) ^ (T1 >> 31) ^ (tmp >> 31)) {
        !           210:         CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
        !           211:     }
        !           212:     RETURN();
        !           213: }
        !           214: 
        !           215: void op_sub (void)
        !           216: {
        !           217:     T0 -= T1;
        !           218:     RETURN();
        !           219: }
        !           220: 
        !           221: void op_subo (void)
        !           222: {
        !           223:     target_ulong tmp;
        !           224: 
        !           225:     tmp = T0;
        !           226:     T0 = (int32_t)T0 - (int32_t)T1;
        !           227:     if (!((T0 >> 31) ^ (T1 >> 31) ^ (tmp >> 31))) {
        !           228:         CALL_FROM_TB1(do_raise_exception, EXCP_OVERFLOW);
        !           229:     }
        !           230:     RETURN();
        !           231: }
        !           232: 
        !           233: void op_mul (void)
        !           234: {
        !           235:     T0 = (int32_t)T0 * (int32_t)T1;
        !           236:     RETURN();
        !           237: }
        !           238: 
        !           239: void op_div (void)
        !           240: {
        !           241:     if (T1 != 0) {
        !           242:         env->LO = (int32_t)T0 / (int32_t)T1;
        !           243:         env->HI = (int32_t)T0 % (int32_t)T1;
        !           244:     }
        !           245:     RETURN();
        !           246: }
        !           247: 
        !           248: void op_divu (void)
        !           249: {
        !           250:     if (T1 != 0) {
        !           251:         env->LO = T0 / T1;
        !           252:         env->HI = T0 % T1;
        !           253:     }
        !           254:     RETURN();
        !           255: }
        !           256: 
        !           257: /* Logical */
        !           258: void op_and (void)
        !           259: {
        !           260:     T0 &= T1;
        !           261:     RETURN();
        !           262: }
        !           263: 
        !           264: void op_nor (void)
        !           265: {
        !           266:     T0 = ~(T0 | T1);
        !           267:     RETURN();
        !           268: }
        !           269: 
        !           270: void op_or (void)
        !           271: {
        !           272:     T0 |= T1;
        !           273:     RETURN();
        !           274: }
        !           275: 
        !           276: void op_xor (void)
        !           277: {
        !           278:     T0 ^= T1;
        !           279:     RETURN();
        !           280: }
        !           281: 
        !           282: void op_sll (void)
        !           283: {
        !           284:     T0 = T0 << T1;
        !           285:     RETURN();
        !           286: }
        !           287: 
        !           288: void op_sra (void)
        !           289: {
        !           290:     T0 = (int32_t)T0 >> T1;
        !           291:     RETURN();
        !           292: }
        !           293: 
        !           294: void op_srl (void)
        !           295: {
        !           296:     T0 = T0 >> T1;
        !           297:     RETURN();
        !           298: }
        !           299: 
        !           300: void op_sllv (void)
        !           301: {
        !           302:     T0 = T1 << (T0 & 0x1F);
        !           303:     RETURN();
        !           304: }
        !           305: 
        !           306: void op_srav (void)
        !           307: {
        !           308:     T0 = (int32_t)T1 >> (T0 & 0x1F);
        !           309:     RETURN();
        !           310: }
        !           311: 
        !           312: void op_srlv (void)
        !           313: {
        !           314:     T0 = T1 >> (T0 & 0x1F);
        !           315:     RETURN();
        !           316: }
        !           317: 
        !           318: void op_clo (void)
        !           319: {
        !           320:     int n;
        !           321: 
        !           322:     if (T0 == (target_ulong)-1) {
        !           323:         T0 = 32;
        !           324:     } else {
        !           325:         for (n = 0; n < 32; n++) {
        !           326:             if (!(T0 & (1 << 31)))
        !           327:                 break;
        !           328:             T0 = T0 << 1;
        !           329:         }
        !           330:         T0 = n;
        !           331:     }
        !           332:     RETURN();
        !           333: }
        !           334: 
        !           335: void op_clz (void)
        !           336: {
        !           337:     int n;
        !           338: 
        !           339:     if (T0 == 0) {
        !           340:         T0 = 32;
        !           341:     } else {
        !           342:         for (n = 0; n < 32; n++) {
        !           343:             if (T0 & (1 << 31))
        !           344:                 break;
        !           345:             T0 = T0 << 1;
        !           346:         }
        !           347:         T0 = n;
        !           348:     }
        !           349:     RETURN();
        !           350: }
        !           351: 
        !           352: /* 64 bits arithmetic */
        !           353: #if (HOST_LONG_BITS == 64)
        !           354: static inline uint64_t get_HILO (void)
        !           355: {
        !           356:     return ((uint64_t)env->HI << 32) | (uint64_t)env->LO;
        !           357: }
        !           358: 
        !           359: static inline void set_HILO (uint64_t HILO)
        !           360: {
        !           361:     env->LO = HILO & 0xFFFFFFFF;
        !           362:     env->HI = HILO >> 32;
        !           363: }
        !           364: 
        !           365: void op_mult (void)
        !           366: {
        !           367:     set_HILO((int64_t)T0 * (int64_t)T1);
        !           368:     RETURN();
        !           369: }
        !           370: 
        !           371: void op_multu (void)
        !           372: {
        !           373:     set_HILO((uint64_t)T0 * (uint64_t)T1);
        !           374:     RETURN();
        !           375: }
        !           376: 
        !           377: void op_madd (void)
        !           378: {
        !           379:     int64_t tmp;
        !           380: 
        !           381:     tmp = ((int64_t)T0 * (int64_t)T1);
        !           382:     set_HILO((int64_t)get_HILO() + tmp);
        !           383:     RETURN();
        !           384: }
        !           385: 
        !           386: void op_maddu (void)
        !           387: {
        !           388:     uint64_t tmp;
        !           389: 
        !           390:     tmp = ((uint64_t)T0 * (uint64_t)T1);
        !           391:     set_HILO(get_HILO() + tmp);
        !           392:     RETURN();
        !           393: }
        !           394: 
        !           395: void op_msub (void)
        !           396: {
        !           397:     int64_t tmp;
        !           398: 
        !           399:     tmp = ((int64_t)T0 * (int64_t)T1);
        !           400:     set_HILO((int64_t)get_HILO() - tmp);
        !           401:     RETURN();
        !           402: }
        !           403: 
        !           404: void op_msubu (void)
        !           405: {
        !           406:     uint64_t tmp;
        !           407: 
        !           408:     tmp = ((uint64_t)T0 * (uint64_t)T1);
        !           409:     set_HILO(get_HILO() - tmp);
        !           410:     RETURN();
        !           411: }
        !           412: #else
        !           413: void op_mult (void)
        !           414: {
        !           415:     CALL_FROM_TB0(do_mult);
        !           416:     RETURN();
        !           417: }
        !           418: 
        !           419: void op_multu (void)
        !           420: {
        !           421:     CALL_FROM_TB0(do_multu);
        !           422:     RETURN();
        !           423: }
        !           424: 
        !           425: void op_madd (void)
        !           426: {
        !           427:     CALL_FROM_TB0(do_madd);
        !           428:     RETURN();
        !           429: }
        !           430: 
        !           431: void op_maddu (void)
        !           432: {
        !           433:     CALL_FROM_TB0(do_maddu);
        !           434:     RETURN();
        !           435: }
        !           436: 
        !           437: void op_msub (void)
        !           438: {
        !           439:     CALL_FROM_TB0(do_msub);
        !           440:     RETURN();
        !           441: }
        !           442: 
        !           443: void op_msubu (void)
        !           444: {
        !           445:     CALL_FROM_TB0(do_msubu);
        !           446:     RETURN();
        !           447: }
        !           448: #endif
        !           449: 
        !           450: /* Conditional moves */
        !           451: void op_movn (void)
        !           452: {
        !           453:     if (T1 != 0)
        !           454:         env->gpr[PARAM1] = T0;
        !           455:     RETURN();
        !           456: }
        !           457: 
        !           458: void op_movz (void)
        !           459: {
        !           460:     if (T1 == 0)
        !           461:         env->gpr[PARAM1] = T0;
        !           462:     RETURN();
        !           463: }
        !           464: 
        !           465: /* Tests */
        !           466: #define OP_COND(name, cond) \
        !           467: void glue(op_, name) (void) \
        !           468: {                           \
        !           469:     if (cond) {             \
        !           470:         T0 = 1;             \
        !           471:     } else {                \
        !           472:         T0 = 0;             \
        !           473:     }                       \
        !           474:     RETURN();               \
        !           475: }
        !           476: 
        !           477: OP_COND(eq, T0 == T1);
        !           478: OP_COND(ne, T0 != T1);
        !           479: OP_COND(ge, (int32_t)T0 >= (int32_t)T1);
        !           480: OP_COND(geu, T0 >= T1);
        !           481: OP_COND(lt, (int32_t)T0 < (int32_t)T1);
        !           482: OP_COND(ltu, T0 < T1);
        !           483: OP_COND(gez, (int32_t)T0 >= 0);
        !           484: OP_COND(gtz, (int32_t)T0 > 0);
        !           485: OP_COND(lez, (int32_t)T0 <= 0);
        !           486: OP_COND(ltz, (int32_t)T0 < 0);
        !           487: 
        !           488: /* Branchs */
        !           489: //#undef USE_DIRECT_JUMP
        !           490: #define EIP env->PC
        !           491: 
        !           492: /* Branch to register */
        !           493: void op_save_breg_target (void)
        !           494: {
        !           495:     env->btarget = T2;
        !           496: }
        !           497: 
        !           498: void op_restore_breg_target (void)
        !           499: {
        !           500:     T2 = env->btarget;
        !           501: }
        !           502: 
        !           503: void op_breg (void)
        !           504: {
        !           505:     env->PC = T2;
        !           506:     RETURN();
        !           507: }
        !           508: 
        !           509: /* Unconditional branch */
        !           510: void op_branch (void)
        !           511: {
        !           512:     JUMP_TB(branch, PARAM1, 0, PARAM2);
        !           513:     RETURN();
        !           514: }
        !           515: 
        !           516: void op_save_btarget (void)
        !           517: {
        !           518:     env->btarget = PARAM1;
        !           519:     RETURN();
        !           520: }
        !           521: 
        !           522: /* Conditional branch */
        !           523: void op_set_bcond (void)
        !           524: {
        !           525:     T2 = T0;
        !           526:     RETURN();
        !           527: }
        !           528: 
        !           529: void op_save_bcond (void)
        !           530: {
        !           531:     env->bcond = T2;
        !           532:     RETURN();
        !           533: }
        !           534: 
        !           535: void op_restore_bcond (void)
        !           536: {
        !           537:     T2 = env->bcond;
        !           538:     RETURN();
        !           539: }
        !           540: 
        !           541: void op_bcond (void)
        !           542: {
        !           543:     if (T2) {
        !           544:         JUMP_TB(bcond, PARAM1, 0, PARAM2);
        !           545:     } else {
        !           546:         JUMP_TB(bcond, PARAM1, 1, PARAM3);
        !           547:     }
        !           548:     RETURN();
        !           549: }
        !           550: 
        !           551: /* Likely branch (used to skip the delay slot) */
        !           552: void op_blikely (void)
        !           553: {
        !           554:     /* If the test is false, skip the delay slot */
        !           555:     if (T2 == 0) {
        !           556:         env->hflags = PARAM3;
        !           557:         JUMP_TB(blikely, PARAM1, 1, PARAM2);
        !           558:     }
        !           559:     RETURN();
        !           560: }
        !           561: 
        !           562: /* CP0 functions */
        !           563: void op_mfc0 (void)
        !           564: {
        !           565:     CALL_FROM_TB2(do_mfc0, PARAM1, PARAM2);
        !           566:     RETURN();
        !           567: }
        !           568: 
        !           569: void op_mtc0 (void)
        !           570: {
        !           571:     CALL_FROM_TB2(do_mtc0, PARAM1, PARAM2);
        !           572:     RETURN();
        !           573: }
        !           574: 
        !           575: #if defined(MIPS_USES_R4K_TLB)
        !           576: void op_tlbwi (void)
        !           577: {
        !           578:     CALL_FROM_TB0(do_tlbwi);
        !           579:     RETURN();
        !           580: }
        !           581: 
        !           582: void op_tlbwr (void)
        !           583: {
        !           584:     CALL_FROM_TB0(do_tlbwr);
        !           585:     RETURN();
        !           586: }
        !           587: 
        !           588: void op_tlbp (void)
        !           589: {
        !           590:     CALL_FROM_TB0(do_tlbp);
        !           591:     RETURN();
        !           592: }
        !           593: 
        !           594: void op_tlbr (void)
        !           595: {
        !           596:     CALL_FROM_TB0(do_tlbr);
        !           597:     RETURN();
        !           598: }
        !           599: #endif
        !           600: 
        !           601: /* Specials */
        !           602: void op_pmon (void)
        !           603: {
        !           604:     CALL_FROM_TB1(do_pmon, PARAM1);
        !           605: }
        !           606: 
        !           607: void op_trap (void)
        !           608: {
        !           609:     if (T0) {
        !           610:         CALL_FROM_TB1(do_raise_exception, EXCP_TRAP);
        !           611:     }
        !           612:     RETURN();
        !           613: }
        !           614: 
        !           615: void op_set_lladdr (void)
        !           616: {
        !           617:     env->CP0_LLAddr = T2;
        !           618: }
        !           619: 
        !           620: void debug_eret (void);
        !           621: void op_eret (void)
        !           622: {
        !           623:     CALL_FROM_TB0(debug_eret);
        !           624:     if (env->hflags & MIPS_HFLAG_ERL) {
        !           625:         env->PC = env->CP0_ErrorEPC;
        !           626:         env->hflags &= ~MIPS_HFLAG_ERL;
        !           627:     } else {
        !           628:         env->PC = env->CP0_EPC;
        !           629:         env->hflags &= ~MIPS_HFLAG_EXL;
        !           630:     }
        !           631:     env->CP0_LLAddr = 1;
        !           632: }
        !           633: 
        !           634: void op_deret (void)
        !           635: {
        !           636:     CALL_FROM_TB0(debug_eret);
        !           637:     env->PC = env->CP0_DEPC;
        !           638: }
        !           639: 
        !           640: void op_save_state (void)
        !           641: {
        !           642:     env->hflags = PARAM1;
        !           643:     RETURN();
        !           644: }
        !           645: 
        !           646: void op_save_pc (void)
        !           647: {
        !           648:     env->PC = PARAM1;
        !           649:     RETURN();
        !           650: }
        !           651: 
        !           652: void op_raise_exception (void)
        !           653: {
        !           654:     CALL_FROM_TB1(do_raise_exception, PARAM1);
        !           655:     RETURN();
        !           656: }
        !           657: 
        !           658: void op_raise_exception_err (void)
        !           659: {
        !           660:     CALL_FROM_TB2(do_raise_exception_err, PARAM1, PARAM2);
        !           661:     RETURN();
        !           662: }
        !           663: 
        !           664: void op_exit_tb (void)
        !           665: {
        !           666:     EXIT_TB();
        !           667: }
        !           668: 

unix.superglobalmegacorp.com

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