Home | History | Annotate | Download | only in c
      1 /* forward declarations of goto targets */
      2 GOTO_TARGET_DECL(filledNewArray, bool methodCallRange);
      3 GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange);
      4 GOTO_TARGET_DECL(invokeSuper, bool methodCallRange);
      5 GOTO_TARGET_DECL(invokeInterface, bool methodCallRange);
      6 GOTO_TARGET_DECL(invokeDirect, bool methodCallRange);
      7 GOTO_TARGET_DECL(invokeStatic, bool methodCallRange);
      8 GOTO_TARGET_DECL(invokeVirtualQuick, bool methodCallRange);
      9 GOTO_TARGET_DECL(invokeSuperQuick, bool methodCallRange);
     10 GOTO_TARGET_DECL(invokeMethod, bool methodCallRange, const Method* methodToCall,
     11     u2 count, u2 regs);
     12 GOTO_TARGET_DECL(returnFromMethod);
     13 GOTO_TARGET_DECL(exceptionThrown);
     14 
     15 /*
     16  * ===========================================================================
     17  *
     18  * What follows are opcode definitions shared between multiple opcodes with
     19  * minor substitutions handled by the C pre-processor.  These should probably
     20  * use the mterp substitution mechanism instead, with the code here moved
     21  * into common fragment files (like the asm "binop.S"), although it's hard
     22  * to give up the C preprocessor in favor of the much simpler text subst.
     23  *
     24  * ===========================================================================
     25  */
     26 
     27 #define HANDLE_NUMCONV(_opcode, _opname, _fromtype, _totype)                \
     28     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
     29         vdst = INST_A(inst);                                                \
     30         vsrc1 = INST_B(inst);                                               \
     31         ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \
     32         SET_REGISTER##_totype(vdst,                                         \
     33             GET_REGISTER##_fromtype(vsrc1));                                \
     34         FINISH(1);
     35 
     36 #define HANDLE_FLOAT_TO_INT(_opcode, _opname, _fromvtype, _fromrtype,       \
     37         _tovtype, _tortype)                                                 \
     38     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
     39     {                                                                       \
     40         /* spec defines specific handling for +/- inf and NaN values */     \
     41         _fromvtype val;                                                     \
     42         _tovtype intMin, intMax, result;                                    \
     43         vdst = INST_A(inst);                                                \
     44         vsrc1 = INST_B(inst);                                               \
     45         ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \
     46         val = GET_REGISTER##_fromrtype(vsrc1);                              \
     47         intMin = (_tovtype) 1 << (sizeof(_tovtype) * 8 -1);                 \
     48         intMax = ~intMin;                                                   \
     49         result = (_tovtype) val;                                            \
     50         if (val >= intMax)          /* +inf */                              \
     51             result = intMax;                                                \
     52         else if (val <= intMin)     /* -inf */                              \
     53             result = intMin;                                                \
     54         else if (val != val)        /* NaN */                               \
     55             result = 0;                                                     \
     56         else                                                                \
     57             result = (_tovtype) val;                                        \
     58         SET_REGISTER##_tortype(vdst, result);                               \
     59     }                                                                       \
     60     FINISH(1);
     61 
     62 #define HANDLE_INT_TO_SMALL(_opcode, _opname, _type)                        \
     63     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
     64         vdst = INST_A(inst);                                                \
     65         vsrc1 = INST_B(inst);                                               \
     66         ILOGV("|int-to-%s v%d,v%d", (_opname), vdst, vsrc1);                \
     67         SET_REGISTER(vdst, (_type) GET_REGISTER(vsrc1));                    \
     68         FINISH(1);
     69 
     70 /* NOTE: the comparison result is always a signed 4-byte integer */
     71 #define HANDLE_OP_CMPX(_opcode, _opname, _varType, _type, _nanVal)          \
     72     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
     73     {                                                                       \
     74         int result;                                                         \
     75         u2 regs;                                                            \
     76         _varType val1, val2;                                                \
     77         vdst = INST_AA(inst);                                               \
     78         regs = FETCH(1);                                                    \
     79         vsrc1 = regs & 0xff;                                                \
     80         vsrc2 = regs >> 8;                                                  \
     81         ILOGV("|cmp%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);         \
     82         val1 = GET_REGISTER##_type(vsrc1);                                  \
     83         val2 = GET_REGISTER##_type(vsrc2);                                  \
     84         if (val1 == val2)                                                   \
     85             result = 0;                                                     \
     86         else if (val1 < val2)                                               \
     87             result = -1;                                                    \
     88         else if (val1 > val2)                                               \
     89             result = 1;                                                     \
     90         else                                                                \
     91             result = (_nanVal);                                             \
     92         ILOGV("+ result=%d\n", result);                                     \
     93         SET_REGISTER(vdst, result);                                         \
     94     }                                                                       \
     95     FINISH(2);
     96 
     97 #define HANDLE_OP_IF_XX(_opcode, _opname, _cmp)                             \
     98     HANDLE_OPCODE(_opcode /*vA, vB, +CCCC*/)                                \
     99         vsrc1 = INST_A(inst);                                               \
    100         vsrc2 = INST_B(inst);                                               \
    101         if ((s4) GET_REGISTER(vsrc1) _cmp (s4) GET_REGISTER(vsrc2)) {       \
    102             int branchOffset = (s2)FETCH(1);    /* sign-extended */         \
    103             ILOGV("|if-%s v%d,v%d,+0x%04x", (_opname), vsrc1, vsrc2,        \
    104                 branchOffset);                                              \
    105             ILOGV("> branch taken");                                        \
    106             if (branchOffset < 0)                                           \
    107                 PERIODIC_CHECKS(kInterpEntryInstr, branchOffset);           \
    108             FINISH(branchOffset);                                           \
    109         } else {                                                            \
    110             ILOGV("|if-%s v%d,v%d,-", (_opname), vsrc1, vsrc2);             \
    111             FINISH(2);                                                      \
    112         }
    113 
    114 #define HANDLE_OP_IF_XXZ(_opcode, _opname, _cmp)                            \
    115     HANDLE_OPCODE(_opcode /*vAA, +BBBB*/)                                   \
    116         vsrc1 = INST_AA(inst);                                              \
    117         if ((s4) GET_REGISTER(vsrc1) _cmp 0) {                              \
    118             int branchOffset = (s2)FETCH(1);    /* sign-extended */         \
    119             ILOGV("|if-%s v%d,+0x%04x", (_opname), vsrc1, branchOffset);    \
    120             ILOGV("> branch taken");                                        \
    121             if (branchOffset < 0)                                           \
    122                 PERIODIC_CHECKS(kInterpEntryInstr, branchOffset);           \
    123             FINISH(branchOffset);                                           \
    124         } else {                                                            \
    125             ILOGV("|if-%s v%d,-", (_opname), vsrc1);                        \
    126             FINISH(2);                                                      \
    127         }
    128 
    129 #define HANDLE_UNOP(_opcode, _opname, _pfx, _sfx, _type)                    \
    130     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
    131         vdst = INST_A(inst);                                                \
    132         vsrc1 = INST_B(inst);                                               \
    133         ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \
    134         SET_REGISTER##_type(vdst, _pfx GET_REGISTER##_type(vsrc1) _sfx);    \
    135         FINISH(1);
    136 
    137 #define HANDLE_OP_X_INT(_opcode, _opname, _op, _chkdiv)                     \
    138     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
    139     {                                                                       \
    140         u2 srcRegs;                                                         \
    141         vdst = INST_AA(inst);                                               \
    142         srcRegs = FETCH(1);                                                 \
    143         vsrc1 = srcRegs & 0xff;                                             \
    144         vsrc2 = srcRegs >> 8;                                               \
    145         ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1);                   \
    146         if (_chkdiv != 0) {                                                 \
    147             s4 firstVal, secondVal, result;                                 \
    148             firstVal = GET_REGISTER(vsrc1);                                 \
    149             secondVal = GET_REGISTER(vsrc2);                                \
    150             if (secondVal == 0) {                                           \
    151                 EXPORT_PC();                                                \
    152                 dvmThrowException("Ljava/lang/ArithmeticException;",        \
    153                     "divide by zero");                                      \
    154                 GOTO_exceptionThrown();                                     \
    155             }                                                               \
    156             if ((u4)firstVal == 0x80000000 && secondVal == -1) {            \
    157                 if (_chkdiv == 1)                                           \
    158                     result = firstVal;  /* division */                      \
    159                 else                                                        \
    160                     result = 0;         /* remainder */                     \
    161             } else {                                                        \
    162                 result = firstVal _op secondVal;                            \
    163             }                                                               \
    164             SET_REGISTER(vdst, result);                                     \
    165         } else {                                                            \
    166             /* non-div/rem case */                                          \
    167             SET_REGISTER(vdst,                                              \
    168                 (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2));     \
    169         }                                                                   \
    170     }                                                                       \
    171     FINISH(2);
    172 
    173 #define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op)                     \
    174     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
    175     {                                                                       \
    176         u2 srcRegs;                                                         \
    177         vdst = INST_AA(inst);                                               \
    178         srcRegs = FETCH(1);                                                 \
    179         vsrc1 = srcRegs & 0xff;                                             \
    180         vsrc2 = srcRegs >> 8;                                               \
    181         ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1);                   \
    182         SET_REGISTER(vdst,                                                  \
    183             _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f));    \
    184     }                                                                       \
    185     FINISH(2);
    186 
    187 #define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv)               \
    188     HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/)                               \
    189         vdst = INST_A(inst);                                                \
    190         vsrc1 = INST_B(inst);                                               \
    191         vsrc2 = FETCH(1);                                                   \
    192         ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x",                             \
    193             (_opname), vdst, vsrc1, vsrc2);                                 \
    194         if (_chkdiv != 0) {                                                 \
    195             s4 firstVal, result;                                            \
    196             firstVal = GET_REGISTER(vsrc1);                                 \
    197             if ((s2) vsrc2 == 0) {                                          \
    198                 EXPORT_PC();                                                \
    199                 dvmThrowException("Ljava/lang/ArithmeticException;",        \
    200                     "divide by zero");                                      \
    201                 GOTO_exceptionThrown();                                      \
    202             }                                                               \
    203             if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) {         \
    204                 /* won't generate /lit16 instr for this; check anyway */    \
    205                 if (_chkdiv == 1)                                           \
    206                     result = firstVal;  /* division */                      \
    207                 else                                                        \
    208                     result = 0;         /* remainder */                     \
    209             } else {                                                        \
    210                 result = firstVal _op (s2) vsrc2;                           \
    211             }                                                               \
    212             SET_REGISTER(vdst, result);                                     \
    213         } else {                                                            \
    214             /* non-div/rem case */                                          \
    215             SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2);         \
    216         }                                                                   \
    217         FINISH(2);
    218 
    219 #define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv)                \
    220     HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/)                               \
    221     {                                                                       \
    222         u2 litInfo;                                                         \
    223         vdst = INST_AA(inst);                                               \
    224         litInfo = FETCH(1);                                                 \
    225         vsrc1 = litInfo & 0xff;                                             \
    226         vsrc2 = litInfo >> 8;       /* constant */                          \
    227         ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x",                              \
    228             (_opname), vdst, vsrc1, vsrc2);                                 \
    229         if (_chkdiv != 0) {                                                 \
    230             s4 firstVal, result;                                            \
    231             firstVal = GET_REGISTER(vsrc1);                                 \
    232             if ((s1) vsrc2 == 0) {                                          \
    233                 EXPORT_PC();                                                \
    234                 dvmThrowException("Ljava/lang/ArithmeticException;",        \
    235                     "divide by zero");                                      \
    236                 GOTO_exceptionThrown();                                     \
    237             }                                                               \
    238             if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) {         \
    239                 if (_chkdiv == 1)                                           \
    240                     result = firstVal;  /* division */                      \
    241                 else                                                        \
    242                     result = 0;         /* remainder */                     \
    243             } else {                                                        \
    244                 result = firstVal _op ((s1) vsrc2);                         \
    245             }                                                               \
    246             SET_REGISTER(vdst, result);                                     \
    247         } else {                                                            \
    248             SET_REGISTER(vdst,                                              \
    249                 (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2);                   \
    250         }                                                                   \
    251     }                                                                       \
    252     FINISH(2);
    253 
    254 #define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op)                \
    255     HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/)                               \
    256     {                                                                       \
    257         u2 litInfo;                                                         \
    258         vdst = INST_AA(inst);                                               \
    259         litInfo = FETCH(1);                                                 \
    260         vsrc1 = litInfo & 0xff;                                             \
    261         vsrc2 = litInfo >> 8;       /* constant */                          \
    262         ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x",                              \
    263             (_opname), vdst, vsrc1, vsrc2);                                 \
    264         SET_REGISTER(vdst,                                                  \
    265             _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f));                  \
    266     }                                                                       \
    267     FINISH(2);
    268 
    269 #define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv)               \
    270     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
    271         vdst = INST_A(inst);                                                \
    272         vsrc1 = INST_B(inst);                                               \
    273         ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1);             \
    274         if (_chkdiv != 0) {                                                 \
    275             s4 firstVal, secondVal, result;                                 \
    276             firstVal = GET_REGISTER(vdst);                                  \
    277             secondVal = GET_REGISTER(vsrc1);                                \
    278             if (secondVal == 0) {                                           \
    279                 EXPORT_PC();                                                \
    280                 dvmThrowException("Ljava/lang/ArithmeticException;",        \
    281                     "divide by zero");                                      \
    282                 GOTO_exceptionThrown();                                     \
    283             }                                                               \
    284             if ((u4)firstVal == 0x80000000 && secondVal == -1) {            \
    285                 if (_chkdiv == 1)                                           \
    286                     result = firstVal;  /* division */                      \
    287                 else                                                        \
    288                     result = 0;         /* remainder */                     \
    289             } else {                                                        \
    290                 result = firstVal _op secondVal;                            \
    291             }                                                               \
    292             SET_REGISTER(vdst, result);                                     \
    293         } else {                                                            \
    294             SET_REGISTER(vdst,                                              \
    295                 (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1));      \
    296         }                                                                   \
    297         FINISH(1);
    298 
    299 #define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op)               \
    300     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
    301         vdst = INST_A(inst);                                                \
    302         vsrc1 = INST_B(inst);                                               \
    303         ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1);             \
    304         SET_REGISTER(vdst,                                                  \
    305             _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f));     \
    306         FINISH(1);
    307 
    308 #define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv)                    \
    309     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
    310     {                                                                       \
    311         u2 srcRegs;                                                         \
    312         vdst = INST_AA(inst);                                               \
    313         srcRegs = FETCH(1);                                                 \
    314         vsrc1 = srcRegs & 0xff;                                             \
    315         vsrc2 = srcRegs >> 8;                                               \
    316         ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);       \
    317         if (_chkdiv != 0) {                                                 \
    318             s8 firstVal, secondVal, result;                                 \
    319             firstVal = GET_REGISTER_WIDE(vsrc1);                            \
    320             secondVal = GET_REGISTER_WIDE(vsrc2);                           \
    321             if (secondVal == 0LL) {                                         \
    322                 EXPORT_PC();                                                \
    323                 dvmThrowException("Ljava/lang/ArithmeticException;",        \
    324                     "divide by zero");                                      \
    325                 GOTO_exceptionThrown();                                     \
    326             }                                                               \
    327             if ((u8)firstVal == 0x8000000000000000ULL &&                    \
    328                 secondVal == -1LL)                                          \
    329             {                                                               \
    330                 if (_chkdiv == 1)                                           \
    331                     result = firstVal;  /* division */                      \
    332                 else                                                        \
    333                     result = 0;         /* remainder */                     \
    334             } else {                                                        \
    335                 result = firstVal _op secondVal;                            \
    336             }                                                               \
    337             SET_REGISTER_WIDE(vdst, result);                                \
    338         } else {                                                            \
    339             SET_REGISTER_WIDE(vdst,                                         \
    340                 (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \
    341         }                                                                   \
    342     }                                                                       \
    343     FINISH(2);
    344 
    345 #define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op)                    \
    346     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
    347     {                                                                       \
    348         u2 srcRegs;                                                         \
    349         vdst = INST_AA(inst);                                               \
    350         srcRegs = FETCH(1);                                                 \
    351         vsrc1 = srcRegs & 0xff;                                             \
    352         vsrc2 = srcRegs >> 8;                                               \
    353         ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);       \
    354         SET_REGISTER_WIDE(vdst,                                             \
    355             _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \
    356     }                                                                       \
    357     FINISH(2);
    358 
    359 #define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv)              \
    360     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
    361         vdst = INST_A(inst);                                                \
    362         vsrc1 = INST_B(inst);                                               \
    363         ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1);            \
    364         if (_chkdiv != 0) {                                                 \
    365             s8 firstVal, secondVal, result;                                 \
    366             firstVal = GET_REGISTER_WIDE(vdst);                             \
    367             secondVal = GET_REGISTER_WIDE(vsrc1);                           \
    368             if (secondVal == 0LL) {                                         \
    369                 EXPORT_PC();                                                \
    370                 dvmThrowException("Ljava/lang/ArithmeticException;",        \
    371                     "divide by zero");                                      \
    372                 GOTO_exceptionThrown();                                     \
    373             }                                                               \
    374             if ((u8)firstVal == 0x8000000000000000ULL &&                    \
    375                 secondVal == -1LL)                                          \
    376             {                                                               \
    377                 if (_chkdiv == 1)                                           \
    378                     result = firstVal;  /* division */                      \
    379                 else                                                        \
    380                     result = 0;         /* remainder */                     \
    381             } else {                                                        \
    382                 result = firstVal _op secondVal;                            \
    383             }                                                               \
    384             SET_REGISTER_WIDE(vdst, result);                                \
    385         } else {                                                            \
    386             SET_REGISTER_WIDE(vdst,                                         \
    387                 (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\
    388         }                                                                   \
    389         FINISH(1);
    390 
    391 #define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op)              \
    392     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
    393         vdst = INST_A(inst);                                                \
    394         vsrc1 = INST_B(inst);                                               \
    395         ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1);            \
    396         SET_REGISTER_WIDE(vdst,                                             \
    397             _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \
    398         FINISH(1);
    399 
    400 #define HANDLE_OP_X_FLOAT(_opcode, _opname, _op)                            \
    401     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
    402     {                                                                       \
    403         u2 srcRegs;                                                         \
    404         vdst = INST_AA(inst);                                               \
    405         srcRegs = FETCH(1);                                                 \
    406         vsrc1 = srcRegs & 0xff;                                             \
    407         vsrc2 = srcRegs >> 8;                                               \
    408         ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);      \
    409         SET_REGISTER_FLOAT(vdst,                                            \
    410             GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2));       \
    411     }                                                                       \
    412     FINISH(2);
    413 
    414 #define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op)                           \
    415     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
    416     {                                                                       \
    417         u2 srcRegs;                                                         \
    418         vdst = INST_AA(inst);                                               \
    419         srcRegs = FETCH(1);                                                 \
    420         vsrc1 = srcRegs & 0xff;                                             \
    421         vsrc2 = srcRegs >> 8;                                               \
    422         ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);     \
    423         SET_REGISTER_DOUBLE(vdst,                                           \
    424             GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2));     \
    425     }                                                                       \
    426     FINISH(2);
    427 
    428 #define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op)                      \
    429     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
    430         vdst = INST_A(inst);                                                \
    431         vsrc1 = INST_B(inst);                                               \
    432         ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1);           \
    433         SET_REGISTER_FLOAT(vdst,                                            \
    434             GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1));        \
    435         FINISH(1);
    436 
    437 #define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op)                     \
    438     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
    439         vdst = INST_A(inst);                                                \
    440         vsrc1 = INST_B(inst);                                               \
    441         ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1);          \
    442         SET_REGISTER_DOUBLE(vdst,                                           \
    443             GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1));      \
    444         FINISH(1);
    445 
    446 #define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize)                   \
    447     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
    448     {                                                                       \
    449         ArrayObject* arrayObj;                                              \
    450         u2 arrayInfo;                                                       \
    451         EXPORT_PC();                                                        \
    452         vdst = INST_AA(inst);                                               \
    453         arrayInfo = FETCH(1);                                               \
    454         vsrc1 = arrayInfo & 0xff;    /* array ptr */                        \
    455         vsrc2 = arrayInfo >> 8;      /* index */                            \
    456         ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);        \
    457         arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);                      \
    458         if (!checkForNull((Object*) arrayObj))                              \
    459             GOTO_exceptionThrown();                                         \
    460         if (GET_REGISTER(vsrc2) >= arrayObj->length) {                      \
    461             LOGV("Invalid array access: %p %d (len=%d)\n",                  \
    462                 arrayObj, vsrc2, arrayObj->length);                         \
    463             dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", \
    464                 NULL);                                                      \
    465             GOTO_exceptionThrown();                                         \
    466         }                                                                   \
    467         SET_REGISTER##_regsize(vdst,                                        \
    468             ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]);            \
    469         ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));  \
    470     }                                                                       \
    471     FINISH(2);
    472 
    473 #define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize)                   \
    474     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
    475     {                                                                       \
    476         ArrayObject* arrayObj;                                              \
    477         u2 arrayInfo;                                                       \
    478         EXPORT_PC();                                                        \
    479         vdst = INST_AA(inst);       /* AA: source value */                  \
    480         arrayInfo = FETCH(1);                                               \
    481         vsrc1 = arrayInfo & 0xff;   /* BB: array ptr */                     \
    482         vsrc2 = arrayInfo >> 8;     /* CC: index */                         \
    483         ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);        \
    484         arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);                      \
    485         if (!checkForNull((Object*) arrayObj))                              \
    486             GOTO_exceptionThrown();                                         \
    487         if (GET_REGISTER(vsrc2) >= arrayObj->length) {                      \
    488             dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", \
    489                 NULL);                                                      \
    490             GOTO_exceptionThrown();                                         \
    491         }                                                                   \
    492         ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
    493         ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] =                \
    494             GET_REGISTER##_regsize(vdst);                                   \
    495     }                                                                       \
    496     FINISH(2);
    497 
    498 /*
    499  * It's possible to get a bad value out of a field with sub-32-bit stores
    500  * because the -quick versions always operate on 32 bits.  Consider:
    501  *   short foo = -1  (sets a 32-bit register to 0xffffffff)
    502  *   iput-quick foo  (writes all 32 bits to the field)
    503  *   short bar = 1   (sets a 32-bit register to 0x00000001)
    504  *   iput-short      (writes the low 16 bits to the field)
    505  *   iget-quick foo  (reads all 32 bits from the field, yielding 0xffff0001)
    506  * This can only happen when optimized and non-optimized code has interleaved
    507  * access to the same field.  This is unlikely but possible.
    508  *
    509  * The easiest way to fix this is to always read/write 32 bits at a time.  On
    510  * a device with a 16-bit data bus this is sub-optimal.  (The alternative
    511  * approach is to have sub-int versions of iget-quick, but now we're wasting
    512  * Dalvik instruction space and making it less likely that handler code will
    513  * already be in the CPU i-cache.)
    514  */
    515 #define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize)                   \
    516     HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
    517     {                                                                       \
    518         InstField* ifield;                                                  \
    519         Object* obj;                                                        \
    520         EXPORT_PC();                                                        \
    521         vdst = INST_A(inst);                                                \
    522         vsrc1 = INST_B(inst);   /* object ptr */                            \
    523         ref = FETCH(1);         /* field ref */                             \
    524         ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
    525         obj = (Object*) GET_REGISTER(vsrc1);                                \
    526         if (!checkForNull(obj))                                             \
    527             GOTO_exceptionThrown();                                         \
    528         ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref);  \
    529         if (ifield == NULL) {                                               \
    530             ifield = dvmResolveInstField(curMethod->clazz, ref);            \
    531             if (ifield == NULL)                                             \
    532                 GOTO_exceptionThrown();                                     \
    533         }                                                                   \
    534         SET_REGISTER##_regsize(vdst,                                        \
    535             dvmGetField##_ftype(obj, ifield->byteOffset));                  \
    536         ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name,                   \
    537             (u8) GET_REGISTER##_regsize(vdst));                             \
    538         UPDATE_FIELD_GET(&ifield->field);                                   \
    539     }                                                                       \
    540     FINISH(2);
    541 
    542 #define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize)             \
    543     HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
    544     {                                                                       \
    545         Object* obj;                                                        \
    546         vdst = INST_A(inst);                                                \
    547         vsrc1 = INST_B(inst);   /* object ptr */                            \
    548         ref = FETCH(1);         /* field offset */                          \
    549         ILOGV("|iget%s-quick v%d,v%d,field@+%u",                            \
    550             (_opname), vdst, vsrc1, ref);                                   \
    551         obj = (Object*) GET_REGISTER(vsrc1);                                \
    552         if (!checkForNullExportPC(obj, fp, pc))                             \
    553             GOTO_exceptionThrown();                                         \
    554         SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref));        \
    555         ILOGV("+ IGETQ %d=0x%08llx", ref,                                   \
    556             (u8) GET_REGISTER##_regsize(vdst));                             \
    557     }                                                                       \
    558     FINISH(2);
    559 
    560 #define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize)                   \
    561     HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
    562     {                                                                       \
    563         InstField* ifield;                                                  \
    564         Object* obj;                                                        \
    565         EXPORT_PC();                                                        \
    566         vdst = INST_A(inst);                                                \
    567         vsrc1 = INST_B(inst);   /* object ptr */                            \
    568         ref = FETCH(1);         /* field ref */                             \
    569         ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
    570         obj = (Object*) GET_REGISTER(vsrc1);                                \
    571         if (!checkForNull(obj))                                             \
    572             GOTO_exceptionThrown();                                         \
    573         ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref);  \
    574         if (ifield == NULL) {                                               \
    575             ifield = dvmResolveInstField(curMethod->clazz, ref);            \
    576             if (ifield == NULL)                                             \
    577                 GOTO_exceptionThrown();                                     \
    578         }                                                                   \
    579         dvmSetField##_ftype(obj, ifield->byteOffset,                        \
    580             GET_REGISTER##_regsize(vdst));                                  \
    581         ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name,                   \
    582             (u8) GET_REGISTER##_regsize(vdst));                             \
    583         UPDATE_FIELD_PUT(&ifield->field);                                   \
    584     }                                                                       \
    585     FINISH(2);
    586 
    587 #define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize)             \
    588     HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
    589     {                                                                       \
    590         Object* obj;                                                        \
    591         vdst = INST_A(inst);                                                \
    592         vsrc1 = INST_B(inst);   /* object ptr */                            \
    593         ref = FETCH(1);         /* field offset */                          \
    594         ILOGV("|iput%s-quick v%d,v%d,field@0x%04x",                         \
    595             (_opname), vdst, vsrc1, ref);                                   \
    596         obj = (Object*) GET_REGISTER(vsrc1);                                \
    597         if (!checkForNullExportPC(obj, fp, pc))                             \
    598             GOTO_exceptionThrown();                                         \
    599         dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst));        \
    600         ILOGV("+ IPUTQ %d=0x%08llx", ref,                                   \
    601             (u8) GET_REGISTER##_regsize(vdst));                             \
    602     }                                                                       \
    603     FINISH(2);
    604 
    605 /*
    606  * The JIT needs dvmDexGetResolvedField() to return non-null.
    607  * Since we use the portable interpreter to build the trace, the extra
    608  * checks in HANDLE_SGET_X and HANDLE_SPUT_X are not needed for mterp.
    609  */
    610 #define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize)                   \
    611     HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/)                              \
    612     {                                                                       \
    613         StaticField* sfield;                                                \
    614         vdst = INST_AA(inst);                                               \
    615         ref = FETCH(1);         /* field ref */                             \
    616         ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref);           \
    617         sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
    618         if (sfield == NULL) {                                               \
    619             EXPORT_PC();                                                    \
    620             sfield = dvmResolveStaticField(curMethod->clazz, ref);          \
    621             if (sfield == NULL)                                             \
    622                 GOTO_exceptionThrown();                                     \
    623             if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) {      \
    624                 ABORT_JIT_TSELECT();                                        \
    625             }                                                               \
    626         }                                                                   \
    627         SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield));    \
    628         ILOGV("+ SGET '%s'=0x%08llx",                                       \
    629             sfield->field.name, (u8)GET_REGISTER##_regsize(vdst));          \
    630         UPDATE_FIELD_GET(&sfield->field);                                   \
    631     }                                                                       \
    632     FINISH(2);
    633 
    634 #define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize)                   \
    635     HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/)                              \
    636     {                                                                       \
    637         StaticField* sfield;                                                \
    638         vdst = INST_AA(inst);                                               \
    639         ref = FETCH(1);         /* field ref */                             \
    640         ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref);           \
    641         sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
    642         if (sfield == NULL) {                                               \
    643             EXPORT_PC();                                                    \
    644             sfield = dvmResolveStaticField(curMethod->clazz, ref);          \
    645             if (sfield == NULL)                                             \
    646                 GOTO_exceptionThrown();                                     \
    647             if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) {      \
    648                 ABORT_JIT_TSELECT();                                        \
    649             }                                                               \
    650         }                                                                   \
    651         dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst));    \
    652         ILOGV("+ SPUT '%s'=0x%08llx",                                       \
    653             sfield->field.name, (u8)GET_REGISTER##_regsize(vdst));          \
    654         UPDATE_FIELD_PUT(&sfield->field);                                   \
    655     }                                                                       \
    656     FINISH(2);
    657