Annotation of qemu/target-arm/op.c, revision 1.1.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.