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

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

unix.superglobalmegacorp.com

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