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

1.1     ! root        1: /*
        !             2:  *  ARM micro operations
        !             3:  * 
        !             4:  *  Copyright (c) 2003 Fabrice Bellard
        !             5:  *  Copyright (c) 2005 CodeSourcery, LLC
        !             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: #include "exec.h"
        !            22: 
        !            23: #define REGNAME r0
        !            24: #define REG (env->regs[0])
        !            25: #include "op_template.h"
        !            26: 
        !            27: #define REGNAME r1
        !            28: #define REG (env->regs[1])
        !            29: #include "op_template.h"
        !            30: 
        !            31: #define REGNAME r2
        !            32: #define REG (env->regs[2])
        !            33: #include "op_template.h"
        !            34: 
        !            35: #define REGNAME r3
        !            36: #define REG (env->regs[3])
        !            37: #include "op_template.h"
        !            38: 
        !            39: #define REGNAME r4
        !            40: #define REG (env->regs[4])
        !            41: #include "op_template.h"
        !            42: 
        !            43: #define REGNAME r5
        !            44: #define REG (env->regs[5])
        !            45: #include "op_template.h"
        !            46: 
        !            47: #define REGNAME r6
        !            48: #define REG (env->regs[6])
        !            49: #include "op_template.h"
        !            50: 
        !            51: #define REGNAME r7
        !            52: #define REG (env->regs[7])
        !            53: #include "op_template.h"
        !            54: 
        !            55: #define REGNAME r8
        !            56: #define REG (env->regs[8])
        !            57: #include "op_template.h"
        !            58: 
        !            59: #define REGNAME r9
        !            60: #define REG (env->regs[9])
        !            61: #include "op_template.h"
        !            62: 
        !            63: #define REGNAME r10
        !            64: #define REG (env->regs[10])
        !            65: #include "op_template.h"
        !            66: 
        !            67: #define REGNAME r11
        !            68: #define REG (env->regs[11])
        !            69: #include "op_template.h"
        !            70: 
        !            71: #define REGNAME r12
        !            72: #define REG (env->regs[12])
        !            73: #include "op_template.h"
        !            74: 
        !            75: #define REGNAME r13
        !            76: #define REG (env->regs[13])
        !            77: #include "op_template.h"
        !            78: 
        !            79: #define REGNAME r14
        !            80: #define REG (env->regs[14])
        !            81: #include "op_template.h"
        !            82: 
        !            83: #define REGNAME r15
        !            84: #define REG (env->regs[15])
        !            85: #define SET_REG(x) REG = x & ~(uint32_t)1
        !            86: #include "op_template.h"
        !            87: 
        !            88: void OPPROTO op_bx_T0(void)
        !            89: {
        !            90:   env->regs[15] = T0 & ~(uint32_t)1;
        !            91:   env->thumb = (T0 & 1) != 0;
        !            92: }
        !            93: 
        !            94: void OPPROTO op_movl_T0_0(void)
        !            95: {
        !            96:     T0 = 0;
        !            97: }
        !            98: 
        !            99: void OPPROTO op_movl_T0_im(void)
        !           100: {
        !           101:     T0 = PARAM1;
        !           102: }
        !           103: 
        !           104: void OPPROTO op_movl_T1_im(void)
        !           105: {
        !           106:     T1 = PARAM1;
        !           107: }
        !           108: 
        !           109: void OPPROTO op_mov_CF_T1(void)
        !           110: {
        !           111:     env->CF = ((uint32_t)T1) >> 31;
        !           112: }
        !           113: 
        !           114: void OPPROTO op_movl_T2_im(void)
        !           115: {
        !           116:     T2 = PARAM1;
        !           117: }
        !           118: 
        !           119: void OPPROTO op_addl_T1_im(void)
        !           120: {
        !           121:     T1 += PARAM1;
        !           122: }
        !           123: 
        !           124: void OPPROTO op_addl_T1_T2(void)
        !           125: {
        !           126:     T1 += T2;
        !           127: }
        !           128: 
        !           129: void OPPROTO op_subl_T1_T2(void)
        !           130: {
        !           131:     T1 -= T2;
        !           132: }
        !           133: 
        !           134: void OPPROTO op_addl_T0_T1(void)
        !           135: {
        !           136:     T0 += T1;
        !           137: }
        !           138: 
        !           139: void OPPROTO op_addl_T0_T1_cc(void)
        !           140: {
        !           141:     unsigned int src1;
        !           142:     src1 = T0;
        !           143:     T0 += T1;
        !           144:     env->NZF = T0;
        !           145:     env->CF = T0 < src1;
        !           146:     env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
        !           147: }
        !           148: 
        !           149: void OPPROTO op_adcl_T0_T1(void)
        !           150: {
        !           151:     T0 += T1 + env->CF;
        !           152: }
        !           153: 
        !           154: void OPPROTO op_adcl_T0_T1_cc(void)
        !           155: {
        !           156:     unsigned int src1;
        !           157:     src1 = T0;
        !           158:     if (!env->CF) {
        !           159:         T0 += T1;
        !           160:         env->CF = T0 < src1;
        !           161:     } else {
        !           162:         T0 += T1 + 1;
        !           163:         env->CF = T0 <= src1;
        !           164:     }
        !           165:     env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
        !           166:     env->NZF = T0;
        !           167:     FORCE_RET();
        !           168: }
        !           169: 
        !           170: #define OPSUB(sub, sbc, res, T0, T1)            \
        !           171:                                                 \
        !           172: void OPPROTO op_ ## sub ## l_T0_T1(void)        \
        !           173: {                                               \
        !           174:     res = T0 - T1;                              \
        !           175: }                                               \
        !           176:                                                 \
        !           177: void OPPROTO op_ ## sub ## l_T0_T1_cc(void)     \
        !           178: {                                               \
        !           179:     unsigned int src1;                          \
        !           180:     src1 = T0;                                  \
        !           181:     T0 -= T1;                                   \
        !           182:     env->NZF = T0;                              \
        !           183:     env->CF = src1 >= T1;                       \
        !           184:     env->VF = (src1 ^ T1) & (src1 ^ T0);        \
        !           185:     res = T0;                                   \
        !           186: }                                               \
        !           187:                                                 \
        !           188: void OPPROTO op_ ## sbc ## l_T0_T1(void)        \
        !           189: {                                               \
        !           190:     res = T0 - T1 + env->CF - 1;                \
        !           191: }                                               \
        !           192:                                                 \
        !           193: void OPPROTO op_ ## sbc ## l_T0_T1_cc(void)     \
        !           194: {                                               \
        !           195:     unsigned int src1;                          \
        !           196:     src1 = T0;                                  \
        !           197:     if (!env->CF) {                             \
        !           198:         T0 = T0 - T1 - 1;                       \
        !           199:         env->CF = src1 > T1;                    \
        !           200:     } else {                                    \
        !           201:         T0 = T0 - T1;                           \
        !           202:         env->CF = src1 >= T1;                   \
        !           203:     }                                           \
        !           204:     env->VF = (src1 ^ T1) & (src1 ^ T0);        \
        !           205:     env->NZF = T0;                              \
        !           206:     res = T0;                                   \
        !           207:     FORCE_RET();                                \
        !           208: }
        !           209: 
        !           210: OPSUB(sub, sbc, T0, T0, T1)
        !           211: 
        !           212: OPSUB(rsb, rsc, T0, T1, T0)
        !           213: 
        !           214: void OPPROTO op_andl_T0_T1(void)
        !           215: {
        !           216:     T0 &= T1;
        !           217: }
        !           218: 
        !           219: void OPPROTO op_xorl_T0_T1(void)
        !           220: {
        !           221:     T0 ^= T1;
        !           222: }
        !           223: 
        !           224: void OPPROTO op_orl_T0_T1(void)
        !           225: {
        !           226:     T0 |= T1;
        !           227: }
        !           228: 
        !           229: void OPPROTO op_bicl_T0_T1(void)
        !           230: {
        !           231:     T0 &= ~T1;
        !           232: }
        !           233: 
        !           234: void OPPROTO op_notl_T1(void)
        !           235: {
        !           236:     T1 = ~T1;
        !           237: }
        !           238: 
        !           239: void OPPROTO op_logic_T0_cc(void)
        !           240: {
        !           241:     env->NZF = T0;
        !           242: }
        !           243: 
        !           244: void OPPROTO op_logic_T1_cc(void)
        !           245: {
        !           246:     env->NZF = T1;
        !           247: }
        !           248: 
        !           249: #define EIP (env->regs[15])
        !           250: 
        !           251: void OPPROTO op_test_eq(void)
        !           252: {
        !           253:     if (env->NZF == 0)
        !           254:         GOTO_LABEL_PARAM(1);;
        !           255:     FORCE_RET();
        !           256: }
        !           257: 
        !           258: void OPPROTO op_test_ne(void)
        !           259: {
        !           260:     if (env->NZF != 0)
        !           261:         GOTO_LABEL_PARAM(1);;
        !           262:     FORCE_RET();
        !           263: }
        !           264: 
        !           265: void OPPROTO op_test_cs(void)
        !           266: {
        !           267:     if (env->CF != 0)
        !           268:         GOTO_LABEL_PARAM(1);
        !           269:     FORCE_RET();
        !           270: }
        !           271: 
        !           272: void OPPROTO op_test_cc(void)
        !           273: {
        !           274:     if (env->CF == 0)
        !           275:         GOTO_LABEL_PARAM(1);
        !           276:     FORCE_RET();
        !           277: }
        !           278: 
        !           279: void OPPROTO op_test_mi(void)
        !           280: {
        !           281:     if ((env->NZF & 0x80000000) != 0)
        !           282:         GOTO_LABEL_PARAM(1);
        !           283:     FORCE_RET();
        !           284: }
        !           285: 
        !           286: void OPPROTO op_test_pl(void)
        !           287: {
        !           288:     if ((env->NZF & 0x80000000) == 0)
        !           289:         GOTO_LABEL_PARAM(1);
        !           290:     FORCE_RET();
        !           291: }
        !           292: 
        !           293: void OPPROTO op_test_vs(void)
        !           294: {
        !           295:     if ((env->VF & 0x80000000) != 0)
        !           296:         GOTO_LABEL_PARAM(1);
        !           297:     FORCE_RET();
        !           298: }
        !           299: 
        !           300: void OPPROTO op_test_vc(void)
        !           301: {
        !           302:     if ((env->VF & 0x80000000) == 0)
        !           303:         GOTO_LABEL_PARAM(1);
        !           304:     FORCE_RET();
        !           305: }
        !           306: 
        !           307: void OPPROTO op_test_hi(void)
        !           308: {
        !           309:     if (env->CF != 0 && env->NZF != 0)
        !           310:         GOTO_LABEL_PARAM(1);
        !           311:     FORCE_RET();
        !           312: }
        !           313: 
        !           314: void OPPROTO op_test_ls(void)
        !           315: {
        !           316:     if (env->CF == 0 || env->NZF == 0)
        !           317:         GOTO_LABEL_PARAM(1);
        !           318:     FORCE_RET();
        !           319: }
        !           320: 
        !           321: void OPPROTO op_test_ge(void)
        !           322: {
        !           323:     if (((env->VF ^ env->NZF) & 0x80000000) == 0)
        !           324:         GOTO_LABEL_PARAM(1);
        !           325:     FORCE_RET();
        !           326: }
        !           327: 
        !           328: void OPPROTO op_test_lt(void)
        !           329: {
        !           330:     if (((env->VF ^ env->NZF) & 0x80000000) != 0)
        !           331:         GOTO_LABEL_PARAM(1);
        !           332:     FORCE_RET();
        !           333: }
        !           334: 
        !           335: void OPPROTO op_test_gt(void)
        !           336: {
        !           337:     if (env->NZF != 0 && ((env->VF ^ env->NZF) & 0x80000000) == 0)
        !           338:         GOTO_LABEL_PARAM(1);
        !           339:     FORCE_RET();
        !           340: }
        !           341: 
        !           342: void OPPROTO op_test_le(void)
        !           343: {
        !           344:     if (env->NZF == 0 || ((env->VF ^ env->NZF) & 0x80000000) != 0)
        !           345:         GOTO_LABEL_PARAM(1);
        !           346:     FORCE_RET();
        !           347: }
        !           348: 
        !           349: void OPPROTO op_jmp0(void)
        !           350: {
        !           351:     JUMP_TB(op_jmp0, PARAM1, 0, PARAM2);
        !           352: }
        !           353: 
        !           354: void OPPROTO op_jmp1(void)
        !           355: {
        !           356:     JUMP_TB(op_jmp1, PARAM1, 1, PARAM2);
        !           357: }
        !           358: 
        !           359: void OPPROTO op_exit_tb(void)
        !           360: {
        !           361:     EXIT_TB();
        !           362: }
        !           363: 
        !           364: void OPPROTO op_movl_T0_psr(void)
        !           365: {
        !           366:     T0 = compute_cpsr();
        !           367: }
        !           368: 
        !           369: /* NOTE: N = 1 and Z = 1 cannot be stored currently */
        !           370: void OPPROTO op_movl_psr_T0(void)
        !           371: {
        !           372:     unsigned int psr;
        !           373:     psr = T0;
        !           374:     env->CF = (psr >> 29) & 1;
        !           375:     env->NZF = (psr & 0xc0000000) ^ 0x40000000;
        !           376:     env->VF = (psr << 3) & 0x80000000;
        !           377:     /* for user mode we do not update other state info */
        !           378: }
        !           379: 
        !           380: void OPPROTO op_mul_T0_T1(void)
        !           381: {
        !           382:     T0 = T0 * T1;
        !           383: }
        !           384: 
        !           385: /* 64 bit unsigned mul */
        !           386: void OPPROTO op_mull_T0_T1(void)
        !           387: {
        !           388:     uint64_t res;
        !           389:     res = (uint64_t)T0 * (uint64_t)T1;
        !           390:     T1 = res >> 32;
        !           391:     T0 = res;
        !           392: }
        !           393: 
        !           394: /* 64 bit signed mul */
        !           395: void OPPROTO op_imull_T0_T1(void)
        !           396: {
        !           397:     uint64_t res;
        !           398:     res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
        !           399:     T1 = res >> 32;
        !           400:     T0 = res;
        !           401: }
        !           402: 
        !           403: /* 48 bit signed mul, top 32 bits */
        !           404: void OPPROTO op_imulw_T0_T1(void)
        !           405: {
        !           406:   uint64_t res;
        !           407:   res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1);
        !           408:   T0 = res >> 16;
        !           409: }
        !           410: 
        !           411: void OPPROTO op_addq_T0_T1(void)
        !           412: {
        !           413:     uint64_t res;
        !           414:     res = ((uint64_t)T1 << 32) | T0;
        !           415:     res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
        !           416:     T1 = res >> 32;
        !           417:     T0 = res;
        !           418: }
        !           419: 
        !           420: void OPPROTO op_addq_lo_T0_T1(void)
        !           421: {
        !           422:     uint64_t res;
        !           423:     res = ((uint64_t)T1 << 32) | T0;
        !           424:     res += (uint64_t)(env->regs[PARAM1]);
        !           425:     T1 = res >> 32;
        !           426:     T0 = res;
        !           427: }
        !           428: 
        !           429: void OPPROTO op_logicq_cc(void)
        !           430: {
        !           431:     env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0);
        !           432: }
        !           433: 
        !           434: /* memory access */
        !           435: 
        !           436: void OPPROTO op_ldub_T0_T1(void)
        !           437: {
        !           438:     T0 = ldub((void *)T1);
        !           439: }
        !           440: 
        !           441: void OPPROTO op_ldsb_T0_T1(void)
        !           442: {
        !           443:     T0 = ldsb((void *)T1);
        !           444: }
        !           445: 
        !           446: void OPPROTO op_lduw_T0_T1(void)
        !           447: {
        !           448:     T0 = lduw((void *)T1);
        !           449: }
        !           450: 
        !           451: void OPPROTO op_ldsw_T0_T1(void)
        !           452: {
        !           453:     T0 = ldsw((void *)T1);
        !           454: }
        !           455: 
        !           456: void OPPROTO op_ldl_T0_T1(void)
        !           457: {
        !           458:     T0 = ldl((void *)T1);
        !           459: }
        !           460: 
        !           461: void OPPROTO op_stb_T0_T1(void)
        !           462: {
        !           463:     stb((void *)T1, T0);
        !           464: }
        !           465: 
        !           466: void OPPROTO op_stw_T0_T1(void)
        !           467: {
        !           468:     stw((void *)T1, T0);
        !           469: }
        !           470: 
        !           471: void OPPROTO op_stl_T0_T1(void)
        !           472: {
        !           473:     stl((void *)T1, T0);
        !           474: }
        !           475: 
        !           476: void OPPROTO op_swpb_T0_T1(void)
        !           477: {
        !           478:     int tmp;
        !           479: 
        !           480:     cpu_lock();
        !           481:     tmp = ldub((void *)T1);
        !           482:     stb((void *)T1, T0);
        !           483:     T0 = tmp;
        !           484:     cpu_unlock();
        !           485: }
        !           486: 
        !           487: void OPPROTO op_swpl_T0_T1(void)
        !           488: {
        !           489:     int tmp;
        !           490: 
        !           491:     cpu_lock();
        !           492:     tmp = ldl((void *)T1);
        !           493:     stl((void *)T1, T0);
        !           494:     T0 = tmp;
        !           495:     cpu_unlock();
        !           496: }
        !           497: 
        !           498: /* shifts */
        !           499: 
        !           500: /* T1 based */
        !           501: 
        !           502: void OPPROTO op_shll_T1_im(void)
        !           503: {
        !           504:     T1 = T1 << PARAM1;
        !           505: }
        !           506: 
        !           507: void OPPROTO op_shrl_T1_im(void)
        !           508: {
        !           509:     T1 = (uint32_t)T1 >> PARAM1;
        !           510: }
        !           511: 
        !           512: void OPPROTO op_shrl_T1_0(void)
        !           513: {
        !           514:     T1 = 0;
        !           515: }
        !           516: 
        !           517: void OPPROTO op_sarl_T1_im(void)
        !           518: {
        !           519:     T1 = (int32_t)T1 >> PARAM1;
        !           520: }
        !           521: 
        !           522: void OPPROTO op_sarl_T1_0(void)
        !           523: {
        !           524:     T1 = (int32_t)T1 >> 31;
        !           525: }
        !           526: 
        !           527: void OPPROTO op_rorl_T1_im(void)
        !           528: {
        !           529:     int shift;
        !           530:     shift = PARAM1;
        !           531:     T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
        !           532: }
        !           533: 
        !           534: void OPPROTO op_rrxl_T1(void)
        !           535: {
        !           536:     T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31);
        !           537: }
        !           538: 
        !           539: /* T1 based, set C flag */
        !           540: void OPPROTO op_shll_T1_im_cc(void)
        !           541: {
        !           542:     env->CF = (T1 >> (32 - PARAM1)) & 1;
        !           543:     T1 = T1 << PARAM1;
        !           544: }
        !           545: 
        !           546: void OPPROTO op_shrl_T1_im_cc(void)
        !           547: {
        !           548:     env->CF = (T1 >> (PARAM1 - 1)) & 1;
        !           549:     T1 = (uint32_t)T1 >> PARAM1;
        !           550: }
        !           551: 
        !           552: void OPPROTO op_shrl_T1_0_cc(void)
        !           553: {
        !           554:     env->CF = (T1 >> 31) & 1;
        !           555:     T1 = 0;
        !           556: }
        !           557: 
        !           558: void OPPROTO op_sarl_T1_im_cc(void)
        !           559: {
        !           560:     env->CF = (T1 >> (PARAM1 - 1)) & 1;
        !           561:     T1 = (int32_t)T1 >> PARAM1;
        !           562: }
        !           563: 
        !           564: void OPPROTO op_sarl_T1_0_cc(void)
        !           565: {
        !           566:     env->CF = (T1 >> 31) & 1;
        !           567:     T1 = (int32_t)T1 >> 31;
        !           568: }
        !           569: 
        !           570: void OPPROTO op_rorl_T1_im_cc(void)
        !           571: {
        !           572:     int shift;
        !           573:     shift = PARAM1;
        !           574:     env->CF = (T1 >> (shift - 1)) & 1;
        !           575:     T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
        !           576: }
        !           577: 
        !           578: void OPPROTO op_rrxl_T1_cc(void)
        !           579: {
        !           580:     uint32_t c;
        !           581:     c = T1 & 1;
        !           582:     T1 = ((uint32_t)T1 >> 1) | ((uint32_t)env->CF << 31);
        !           583:     env->CF = c;
        !           584: }
        !           585: 
        !           586: /* T2 based */
        !           587: void OPPROTO op_shll_T2_im(void)
        !           588: {
        !           589:     T2 = T2 << PARAM1;
        !           590: }
        !           591: 
        !           592: void OPPROTO op_shrl_T2_im(void)
        !           593: {
        !           594:     T2 = (uint32_t)T2 >> PARAM1;
        !           595: }
        !           596: 
        !           597: void OPPROTO op_shrl_T2_0(void)
        !           598: {
        !           599:     T2 = 0;
        !           600: }
        !           601: 
        !           602: void OPPROTO op_sarl_T2_im(void)
        !           603: {
        !           604:     T2 = (int32_t)T2 >> PARAM1;
        !           605: }
        !           606: 
        !           607: void OPPROTO op_sarl_T2_0(void)
        !           608: {
        !           609:     T2 = (int32_t)T2 >> 31;
        !           610: }
        !           611: 
        !           612: void OPPROTO op_rorl_T2_im(void)
        !           613: {
        !           614:     int shift;
        !           615:     shift = PARAM1;
        !           616:     T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift));
        !           617: }
        !           618: 
        !           619: void OPPROTO op_rrxl_T2(void)
        !           620: {
        !           621:     T2 = ((uint32_t)T2 >> 1) | ((uint32_t)env->CF << 31);
        !           622: }
        !           623: 
        !           624: /* T1 based, use T0 as shift count */
        !           625: 
        !           626: void OPPROTO op_shll_T1_T0(void)
        !           627: {
        !           628:     int shift;
        !           629:     shift = T0 & 0xff;
        !           630:     if (shift >= 32)
        !           631:         T1 = 0;
        !           632:     else
        !           633:         T1 = T1 << shift;
        !           634:     FORCE_RET();
        !           635: }
        !           636: 
        !           637: void OPPROTO op_shrl_T1_T0(void)
        !           638: {
        !           639:     int shift;
        !           640:     shift = T0 & 0xff;
        !           641:     if (shift >= 32)
        !           642:         T1 = 0;
        !           643:     else
        !           644:         T1 = (uint32_t)T1 >> shift;
        !           645:     FORCE_RET();
        !           646: }
        !           647: 
        !           648: void OPPROTO op_sarl_T1_T0(void)
        !           649: {
        !           650:     int shift;
        !           651:     shift = T0 & 0xff;
        !           652:     if (shift >= 32)
        !           653:         shift = 31;
        !           654:     T1 = (int32_t)T1 >> shift;
        !           655: }
        !           656: 
        !           657: void OPPROTO op_rorl_T1_T0(void)
        !           658: {
        !           659:     int shift;
        !           660:     shift = T0 & 0x1f;
        !           661:     if (shift) {
        !           662:         T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
        !           663:     }
        !           664:     FORCE_RET();
        !           665: }
        !           666: 
        !           667: /* T1 based, use T0 as shift count and compute CF */
        !           668: 
        !           669: void OPPROTO op_shll_T1_T0_cc(void)
        !           670: {
        !           671:     int shift;
        !           672:     shift = T0 & 0xff;
        !           673:     if (shift >= 32) {
        !           674:         if (shift == 32)
        !           675:             env->CF = T1 & 1;
        !           676:         else
        !           677:             env->CF = 0;
        !           678:         T1 = 0;
        !           679:     } else if (shift != 0) {
        !           680:         env->CF = (T1 >> (32 - shift)) & 1;
        !           681:         T1 = T1 << shift;
        !           682:     }
        !           683:     FORCE_RET();
        !           684: }
        !           685: 
        !           686: void OPPROTO op_shrl_T1_T0_cc(void)
        !           687: {
        !           688:     int shift;
        !           689:     shift = T0 & 0xff;
        !           690:     if (shift >= 32) {
        !           691:         if (shift == 32)
        !           692:             env->CF = (T1 >> 31) & 1;
        !           693:         else
        !           694:             env->CF = 0;
        !           695:         T1 = 0;
        !           696:     } else if (shift != 0) {
        !           697:         env->CF = (T1 >> (shift - 1)) & 1;
        !           698:         T1 = (uint32_t)T1 >> shift;
        !           699:     }
        !           700:     FORCE_RET();
        !           701: }
        !           702: 
        !           703: void OPPROTO op_sarl_T1_T0_cc(void)
        !           704: {
        !           705:     int shift;
        !           706:     shift = T0 & 0xff;
        !           707:     if (shift >= 32) {
        !           708:         env->CF = (T1 >> 31) & 1;
        !           709:         T1 = (int32_t)T1 >> 31;
        !           710:     } else {
        !           711:         env->CF = (T1 >> (shift - 1)) & 1;
        !           712:         T1 = (int32_t)T1 >> shift;
        !           713:     }
        !           714:     FORCE_RET();
        !           715: }
        !           716: 
        !           717: void OPPROTO op_rorl_T1_T0_cc(void)
        !           718: {
        !           719:     int shift1, shift;
        !           720:     shift1 = T0 & 0xff;
        !           721:     shift = shift1 & 0x1f;
        !           722:     if (shift == 0) {
        !           723:         if (shift1 != 0)
        !           724:             env->CF = (T1 >> 31) & 1;
        !           725:     } else {
        !           726:         env->CF = (T1 >> (shift - 1)) & 1;
        !           727:         T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
        !           728:     }
        !           729:     FORCE_RET();
        !           730: }
        !           731: 
        !           732: /* misc */
        !           733: void OPPROTO op_clz_T0(void)
        !           734: {
        !           735:     int count;
        !           736:     for (count = 32; T0 > 0; count--)
        !           737:         T0 = T0 >> 1;
        !           738:     T0 = count;
        !           739:     FORCE_RET();
        !           740: }
        !           741: 
        !           742: void OPPROTO op_sarl_T0_im(void)
        !           743: {
        !           744:     T0 = (int32_t)T0 >> PARAM1;
        !           745: }
        !           746: 
        !           747: /* 16->32 Sign extend */
        !           748: void OPPROTO op_sxl_T0(void)
        !           749: {
        !           750:   T0 = (int16_t)T0;
        !           751: }
        !           752: 
        !           753: void OPPROTO op_sxl_T1(void)
        !           754: {
        !           755:   T1 = (int16_t)T1;
        !           756: }
        !           757: 
        !           758: #define SIGNBIT (uint32_t)0x80000000
        !           759: /* saturating arithmetic  */
        !           760: void OPPROTO op_addl_T0_T1_setq(void)
        !           761: {
        !           762:   uint32_t res;
        !           763: 
        !           764:   res = T0 + T1;
        !           765:   if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT))
        !           766:       env->QF = 1;
        !           767: 
        !           768:   T0 = res;
        !           769:   FORCE_RET();
        !           770: }
        !           771: 
        !           772: void OPPROTO op_addl_T0_T1_saturate(void)
        !           773: {
        !           774:   uint32_t res;
        !           775: 
        !           776:   res = T0 + T1;
        !           777:   if (((res ^ T0) & SIGNBIT) && !((T0 ^ T1) & SIGNBIT)) {
        !           778:       env->QF = 1;
        !           779:       if (T0 & SIGNBIT)
        !           780:           T0 = 0x80000000;
        !           781:       else
        !           782:           T0 = 0x7fffffff;
        !           783:   }
        !           784:   else
        !           785:     T0 = res;
        !           786:   
        !           787:   FORCE_RET();
        !           788: }
        !           789: 
        !           790: void OPPROTO op_subl_T0_T1_saturate(void)
        !           791: {
        !           792:   uint32_t res;
        !           793: 
        !           794:   res = T0 - T1;
        !           795:   if (((res ^ T0) & SIGNBIT) && ((T0 ^ T1) & SIGNBIT)) {
        !           796:       env->QF = 1;
        !           797:       if (T0 & SIGNBIT)
        !           798:           T0 = 0x8000000;
        !           799:       else
        !           800:           T0 = 0x7fffffff;
        !           801:   }
        !           802:   else
        !           803:     T0 = res;
        !           804:   
        !           805:   FORCE_RET();
        !           806: }
        !           807: 
        !           808: void OPPROTO op_double_T1_saturate(void)
        !           809: {
        !           810:   int32_t val;
        !           811: 
        !           812:   val = T1;
        !           813:   if (val >= 0x40000000) {
        !           814:       T1 = 0x7fffffff;
        !           815:       env->QF = 1;
        !           816:   } else if (val <= (int32_t)0xc0000000) {
        !           817:       T1 = 0x80000000;
        !           818:       env->QF = 1;
        !           819:   } else {
        !           820:       T1 = val << 1;
        !           821:   }
        !           822:   FORCE_RET();
        !           823: }
        !           824: 
        !           825: /* thumb shift by immediate */
        !           826: void OPPROTO op_shll_T0_im_thumb(void)
        !           827: {
        !           828:     int shift;
        !           829:     shift = PARAM1;
        !           830:     if (shift != 0) {
        !           831:        env->CF = (T1 >> (32 - shift)) & 1;
        !           832:        T0 = T0 << shift;
        !           833:     }
        !           834:     env->NZF = T0;
        !           835:     FORCE_RET();
        !           836: }
        !           837: 
        !           838: void OPPROTO op_shrl_T0_im_thumb(void)
        !           839: {
        !           840:     int shift;
        !           841: 
        !           842:     shift = PARAM1;
        !           843:     if (shift == 0) {
        !           844:        env->CF = ((uint32_t)shift) >> 31;
        !           845:        T0 = 0;
        !           846:     } else {
        !           847:        env->CF = (T0 >> (shift - 1)) & 1;
        !           848:        T0 = T0 >> shift;
        !           849:     }
        !           850:     env->NZF = T0;
        !           851:     FORCE_RET();
        !           852: }
        !           853: 
        !           854: void OPPROTO op_sarl_T0_im_thumb(void)
        !           855: {
        !           856:     int shift;
        !           857: 
        !           858:     shift = PARAM1;
        !           859:     if (shift == 0) {
        !           860:        T0 = ((int32_t)T0) >> 31;
        !           861:        env->CF = T0 & 1;
        !           862:     } else {
        !           863:        env->CF = (T0 >> (shift - 1)) & 1;
        !           864:        T0 = ((int32_t)T0) >> shift;
        !           865:     }
        !           866:     env->NZF = T0;
        !           867:     FORCE_RET();
        !           868: }
        !           869: 
        !           870: /* exceptions */
        !           871: 
        !           872: void OPPROTO op_swi(void)
        !           873: {
        !           874:     env->exception_index = EXCP_SWI;
        !           875:     cpu_loop_exit();
        !           876: }
        !           877: 
        !           878: void OPPROTO op_undef_insn(void)
        !           879: {
        !           880:     env->exception_index = EXCP_UDEF;
        !           881:     cpu_loop_exit();
        !           882: }
        !           883: 
        !           884: void OPPROTO op_debug(void)
        !           885: {
        !           886:     env->exception_index = EXCP_DEBUG;
        !           887:     cpu_loop_exit();
        !           888: }
        !           889: 
        !           890: /* VFP support.  We follow the convention used for VFP instrunctions:
        !           891:    Single precition routines have a "s" suffix, double precision a
        !           892:    "d" suffix.  */
        !           893: 
        !           894: #define VFP_OP(name, p) void OPPROTO op_vfp_##name##p(void)
        !           895: 
        !           896: #define VFP_BINOP(name) \
        !           897: VFP_OP(name, s)             \
        !           898: {                           \
        !           899:     FT0s = float32_ ## name (FT0s, FT1s, &env->vfp.fp_status);    \
        !           900: }                           \
        !           901: VFP_OP(name, d)             \
        !           902: {                           \
        !           903:     FT0d = float64_ ## name (FT0d, FT1d, &env->vfp.fp_status);    \
        !           904: }
        !           905: VFP_BINOP(add)
        !           906: VFP_BINOP(sub)
        !           907: VFP_BINOP(mul)
        !           908: VFP_BINOP(div)
        !           909: #undef VFP_BINOP
        !           910: 
        !           911: #define VFP_HELPER(name)  \
        !           912: VFP_OP(name, s)           \
        !           913: {                         \
        !           914:     do_vfp_##name##s();    \
        !           915: }                         \
        !           916: VFP_OP(name, d)           \
        !           917: {                         \
        !           918:     do_vfp_##name##d();    \
        !           919: }
        !           920: VFP_HELPER(abs)
        !           921: VFP_HELPER(sqrt)
        !           922: VFP_HELPER(cmp)
        !           923: VFP_HELPER(cmpe)
        !           924: #undef VFP_HELPER
        !           925: 
        !           926: /* XXX: Will this do the right thing for NANs.  Should invert the signbit
        !           927:    without looking at the rest of the value.  */
        !           928: VFP_OP(neg, s)
        !           929: {
        !           930:     FT0s = float32_chs(FT0s);
        !           931: }
        !           932: 
        !           933: VFP_OP(neg, d)
        !           934: {
        !           935:     FT0d = float64_chs(FT0d);
        !           936: }
        !           937: 
        !           938: VFP_OP(F1_ld0, s)
        !           939: {
        !           940:     union {
        !           941:         uint32_t i;
        !           942:         float32 s;
        !           943:     } v;
        !           944:     v.i = 0;
        !           945:     FT1s = v.s;
        !           946: }
        !           947: 
        !           948: VFP_OP(F1_ld0, d)
        !           949: {
        !           950:     union {
        !           951:         uint64_t i;
        !           952:         float64 d;
        !           953:     } v;
        !           954:     v.i = 0;
        !           955:     FT1d = v.d;
        !           956: }
        !           957: 
        !           958: /* Helper routines to perform bitwise copies between float and int.  */
        !           959: static inline float32 vfp_itos(uint32_t i)
        !           960: {
        !           961:     union {
        !           962:         uint32_t i;
        !           963:         float32 s;
        !           964:     } v;
        !           965: 
        !           966:     v.i = i;
        !           967:     return v.s;
        !           968: }
        !           969: 
        !           970: static inline uint32_t vfp_stoi(float32 s)
        !           971: {
        !           972:     union {
        !           973:         uint32_t i;
        !           974:         float32 s;
        !           975:     } v;
        !           976: 
        !           977:     v.s = s;
        !           978:     return v.i;
        !           979: }
        !           980: 
        !           981: /* Integer to float conversion.  */
        !           982: VFP_OP(uito, s)
        !           983: {
        !           984:     FT0s = uint32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status);
        !           985: }
        !           986: 
        !           987: VFP_OP(uito, d)
        !           988: {
        !           989:     FT0d = uint32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status);
        !           990: }
        !           991: 
        !           992: VFP_OP(sito, s)
        !           993: {
        !           994:     FT0s = int32_to_float32(vfp_stoi(FT0s), &env->vfp.fp_status);
        !           995: }
        !           996: 
        !           997: VFP_OP(sito, d)
        !           998: {
        !           999:     FT0d = int32_to_float64(vfp_stoi(FT0s), &env->vfp.fp_status);
        !          1000: }
        !          1001: 
        !          1002: /* Float to integer conversion.  */
        !          1003: VFP_OP(toui, s)
        !          1004: {
        !          1005:     FT0s = vfp_itos(float32_to_uint32(FT0s, &env->vfp.fp_status));
        !          1006: }
        !          1007: 
        !          1008: VFP_OP(toui, d)
        !          1009: {
        !          1010:     FT0s = vfp_itos(float64_to_uint32(FT0d, &env->vfp.fp_status));
        !          1011: }
        !          1012: 
        !          1013: VFP_OP(tosi, s)
        !          1014: {
        !          1015:     FT0s = vfp_itos(float32_to_int32(FT0s, &env->vfp.fp_status));
        !          1016: }
        !          1017: 
        !          1018: VFP_OP(tosi, d)
        !          1019: {
        !          1020:     FT0s = vfp_itos(float64_to_int32(FT0d, &env->vfp.fp_status));
        !          1021: }
        !          1022: 
        !          1023: /* TODO: Set rounding mode properly.  */
        !          1024: VFP_OP(touiz, s)
        !          1025: {
        !          1026:     FT0s = vfp_itos(float32_to_uint32_round_to_zero(FT0s, &env->vfp.fp_status));
        !          1027: }
        !          1028: 
        !          1029: VFP_OP(touiz, d)
        !          1030: {
        !          1031:     FT0s = vfp_itos(float64_to_uint32_round_to_zero(FT0d, &env->vfp.fp_status));
        !          1032: }
        !          1033: 
        !          1034: VFP_OP(tosiz, s)
        !          1035: {
        !          1036:     FT0s = vfp_itos(float32_to_int32_round_to_zero(FT0s, &env->vfp.fp_status));
        !          1037: }
        !          1038: 
        !          1039: VFP_OP(tosiz, d)
        !          1040: {
        !          1041:     FT0s = vfp_itos(float64_to_int32_round_to_zero(FT0d, &env->vfp.fp_status));
        !          1042: }
        !          1043: 
        !          1044: /* floating point conversion */
        !          1045: VFP_OP(fcvtd, s)
        !          1046: {
        !          1047:     FT0d = float32_to_float64(FT0s, &env->vfp.fp_status);
        !          1048: }
        !          1049: 
        !          1050: VFP_OP(fcvts, d)
        !          1051: {
        !          1052:     FT0s = float64_to_float32(FT0d, &env->vfp.fp_status);
        !          1053: }
        !          1054: 
        !          1055: /* Get and Put values from registers.  */
        !          1056: VFP_OP(getreg_F0, d)
        !          1057: {
        !          1058:   FT0d = *(float64 *)((char *) env + PARAM1);
        !          1059: }
        !          1060: 
        !          1061: VFP_OP(getreg_F0, s)
        !          1062: {
        !          1063:   FT0s = *(float32 *)((char *) env + PARAM1);
        !          1064: }
        !          1065: 
        !          1066: VFP_OP(getreg_F1, d)
        !          1067: {
        !          1068:   FT1d = *(float64 *)((char *) env + PARAM1);
        !          1069: }
        !          1070: 
        !          1071: VFP_OP(getreg_F1, s)
        !          1072: {
        !          1073:   FT1s = *(float32 *)((char *) env + PARAM1);
        !          1074: }
        !          1075: 
        !          1076: VFP_OP(setreg_F0, d)
        !          1077: {
        !          1078:   *(float64 *)((char *) env + PARAM1) = FT0d;
        !          1079: }
        !          1080: 
        !          1081: VFP_OP(setreg_F0, s)
        !          1082: {
        !          1083:   *(float32 *)((char *) env + PARAM1) = FT0s;
        !          1084: }
        !          1085: 
        !          1086: void OPPROTO op_vfp_movl_T0_fpscr(void)
        !          1087: {
        !          1088:     do_vfp_get_fpscr ();
        !          1089: }
        !          1090: 
        !          1091: void OPPROTO op_vfp_movl_T0_fpscr_flags(void)
        !          1092: {
        !          1093:     T0 = env->vfp.fpscr & (0xf << 28);
        !          1094: }
        !          1095: 
        !          1096: void OPPROTO op_vfp_movl_fpscr_T0(void)
        !          1097: {
        !          1098:     do_vfp_set_fpscr();
        !          1099: }
        !          1100: 
        !          1101: /* Move between FT0s to T0  */
        !          1102: void OPPROTO op_vfp_mrs(void)
        !          1103: {
        !          1104:     T0 = vfp_stoi(FT0s);
        !          1105: }
        !          1106: 
        !          1107: void OPPROTO op_vfp_msr(void)
        !          1108: {
        !          1109:     FT0s = vfp_itos(T0);
        !          1110: }
        !          1111: 
        !          1112: /* Move between FT0d and {T0,T1} */
        !          1113: void OPPROTO op_vfp_mrrd(void)
        !          1114: {
        !          1115:     CPU_DoubleU u;
        !          1116:     
        !          1117:     u.d = FT0d;
        !          1118:     T0 = u.l.lower;
        !          1119:     T1 = u.l.upper;
        !          1120: }
        !          1121: 
        !          1122: void OPPROTO op_vfp_mdrr(void)
        !          1123: {
        !          1124:     CPU_DoubleU u;
        !          1125:     
        !          1126:     u.l.lower = T0;
        !          1127:     u.l.upper = T1;
        !          1128:     FT0d = u.d;
        !          1129: }
        !          1130: 
        !          1131: /* Floating point load/store.  Address is in T1 */
        !          1132: void OPPROTO op_vfp_lds(void)
        !          1133: {
        !          1134:     FT0s = ldfl((void *)T1);
        !          1135: }
        !          1136: 
        !          1137: void OPPROTO op_vfp_ldd(void)
        !          1138: {
        !          1139:     FT0d = ldfq((void *)T1);
        !          1140: }
        !          1141: 
        !          1142: void OPPROTO op_vfp_sts(void)
        !          1143: {
        !          1144:     stfl((void *)T1, FT0s);
        !          1145: }
        !          1146: 
        !          1147: void OPPROTO op_vfp_std(void)
        !          1148: {
        !          1149:     stfq((void *)T1, FT0d);
        !          1150: }

unix.superglobalmegacorp.com

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