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", 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(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(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                 dvmThrowArithmeticException("divide by zero");              \
    153                 GOTO_exceptionThrown();                                     \
    154             }                                                               \
    155             if ((u4)firstVal == 0x80000000 && secondVal == -1) {            \
    156                 if (_chkdiv == 1)                                           \
    157                     result = firstVal;  /* division */                      \
    158                 else                                                        \
    159                     result = 0;         /* remainder */                     \
    160             } else {                                                        \
    161                 result = firstVal _op secondVal;                            \
    162             }                                                               \
    163             SET_REGISTER(vdst, result);                                     \
    164         } else {                                                            \
    165             /* non-div/rem case */                                          \
    166             SET_REGISTER(vdst,                                              \
    167                 (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2));     \
    168         }                                                                   \
    169     }                                                                       \
    170     FINISH(2);
    171 
    172 #define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op)                     \
    173     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
    174     {                                                                       \
    175         u2 srcRegs;                                                         \
    176         vdst = INST_AA(inst);                                               \
    177         srcRegs = FETCH(1);                                                 \
    178         vsrc1 = srcRegs & 0xff;                                             \
    179         vsrc2 = srcRegs >> 8;                                               \
    180         ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1);                   \
    181         SET_REGISTER(vdst,                                                  \
    182             _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f));    \
    183     }                                                                       \
    184     FINISH(2);
    185 
    186 #define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv)               \
    187     HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/)                               \
    188         vdst = INST_A(inst);                                                \
    189         vsrc1 = INST_B(inst);                                               \
    190         vsrc2 = FETCH(1);                                                   \
    191         ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x",                             \
    192             (_opname), vdst, vsrc1, vsrc2);                                 \
    193         if (_chkdiv != 0) {                                                 \
    194             s4 firstVal, result;                                            \
    195             firstVal = GET_REGISTER(vsrc1);                                 \
    196             if ((s2) vsrc2 == 0) {                                          \
    197                 EXPORT_PC();                                                \
    198                 dvmThrowArithmeticException("divide by zero");              \
    199                 GOTO_exceptionThrown();                                     \
    200             }                                                               \
    201             if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) {         \
    202                 /* won't generate /lit16 instr for this; check anyway */    \
    203                 if (_chkdiv == 1)                                           \
    204                     result = firstVal;  /* division */                      \
    205                 else                                                        \
    206                     result = 0;         /* remainder */                     \
    207             } else {                                                        \
    208                 result = firstVal _op (s2) vsrc2;                           \
    209             }                                                               \
    210             SET_REGISTER(vdst, result);                                     \
    211         } else {                                                            \
    212             /* non-div/rem case */                                          \
    213             SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2);         \
    214         }                                                                   \
    215         FINISH(2);
    216 
    217 #define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv)                \
    218     HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/)                               \
    219     {                                                                       \
    220         u2 litInfo;                                                         \
    221         vdst = INST_AA(inst);                                               \
    222         litInfo = FETCH(1);                                                 \
    223         vsrc1 = litInfo & 0xff;                                             \
    224         vsrc2 = litInfo >> 8;       /* constant */                          \
    225         ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x",                              \
    226             (_opname), vdst, vsrc1, vsrc2);                                 \
    227         if (_chkdiv != 0) {                                                 \
    228             s4 firstVal, result;                                            \
    229             firstVal = GET_REGISTER(vsrc1);                                 \
    230             if ((s1) vsrc2 == 0) {                                          \
    231                 EXPORT_PC();                                                \
    232                 dvmThrowArithmeticException("divide by zero");              \
    233                 GOTO_exceptionThrown();                                     \
    234             }                                                               \
    235             if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) {         \
    236                 if (_chkdiv == 1)                                           \
    237                     result = firstVal;  /* division */                      \
    238                 else                                                        \
    239                     result = 0;         /* remainder */                     \
    240             } else {                                                        \
    241                 result = firstVal _op ((s1) vsrc2);                         \
    242             }                                                               \
    243             SET_REGISTER(vdst, result);                                     \
    244         } else {                                                            \
    245             SET_REGISTER(vdst,                                              \
    246                 (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2);                   \
    247         }                                                                   \
    248     }                                                                       \
    249     FINISH(2);
    250 
    251 #define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op)                \
    252     HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/)                               \
    253     {                                                                       \
    254         u2 litInfo;                                                         \
    255         vdst = INST_AA(inst);                                               \
    256         litInfo = FETCH(1);                                                 \
    257         vsrc1 = litInfo & 0xff;                                             \
    258         vsrc2 = litInfo >> 8;       /* constant */                          \
    259         ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x",                              \
    260             (_opname), vdst, vsrc1, vsrc2);                                 \
    261         SET_REGISTER(vdst,                                                  \
    262             _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f));                  \
    263     }                                                                       \
    264     FINISH(2);
    265 
    266 #define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv)               \
    267     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
    268         vdst = INST_A(inst);                                                \
    269         vsrc1 = INST_B(inst);                                               \
    270         ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1);             \
    271         if (_chkdiv != 0) {                                                 \
    272             s4 firstVal, secondVal, result;                                 \
    273             firstVal = GET_REGISTER(vdst);                                  \
    274             secondVal = GET_REGISTER(vsrc1);                                \
    275             if (secondVal == 0) {                                           \
    276                 EXPORT_PC();                                                \
    277                 dvmThrowArithmeticException("divide by zero");              \
    278                 GOTO_exceptionThrown();                                     \
    279             }                                                               \
    280             if ((u4)firstVal == 0x80000000 && secondVal == -1) {            \
    281                 if (_chkdiv == 1)                                           \
    282                     result = firstVal;  /* division */                      \
    283                 else                                                        \
    284                     result = 0;         /* remainder */                     \
    285             } else {                                                        \
    286                 result = firstVal _op secondVal;                            \
    287             }                                                               \
    288             SET_REGISTER(vdst, result);                                     \
    289         } else {                                                            \
    290             SET_REGISTER(vdst,                                              \
    291                 (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1));      \
    292         }                                                                   \
    293         FINISH(1);
    294 
    295 #define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op)               \
    296     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
    297         vdst = INST_A(inst);                                                \
    298         vsrc1 = INST_B(inst);                                               \
    299         ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1);             \
    300         SET_REGISTER(vdst,                                                  \
    301             _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f));     \
    302         FINISH(1);
    303 
    304 #define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv)                    \
    305     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
    306     {                                                                       \
    307         u2 srcRegs;                                                         \
    308         vdst = INST_AA(inst);                                               \
    309         srcRegs = FETCH(1);                                                 \
    310         vsrc1 = srcRegs & 0xff;                                             \
    311         vsrc2 = srcRegs >> 8;                                               \
    312         ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);       \
    313         if (_chkdiv != 0) {                                                 \
    314             s8 firstVal, secondVal, result;                                 \
    315             firstVal = GET_REGISTER_WIDE(vsrc1);                            \
    316             secondVal = GET_REGISTER_WIDE(vsrc2);                           \
    317             if (secondVal == 0LL) {                                         \
    318                 EXPORT_PC();                                                \
    319                 dvmThrowArithmeticException("divide by zero");              \
    320                 GOTO_exceptionThrown();                                     \
    321             }                                                               \
    322             if ((u8)firstVal == 0x8000000000000000ULL &&                    \
    323                 secondVal == -1LL)                                          \
    324             {                                                               \
    325                 if (_chkdiv == 1)                                           \
    326                     result = firstVal;  /* division */                      \
    327                 else                                                        \
    328                     result = 0;         /* remainder */                     \
    329             } else {                                                        \
    330                 result = firstVal _op secondVal;                            \
    331             }                                                               \
    332             SET_REGISTER_WIDE(vdst, result);                                \
    333         } else {                                                            \
    334             SET_REGISTER_WIDE(vdst,                                         \
    335                 (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \
    336         }                                                                   \
    337     }                                                                       \
    338     FINISH(2);
    339 
    340 #define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op)                    \
    341     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
    342     {                                                                       \
    343         u2 srcRegs;                                                         \
    344         vdst = INST_AA(inst);                                               \
    345         srcRegs = FETCH(1);                                                 \
    346         vsrc1 = srcRegs & 0xff;                                             \
    347         vsrc2 = srcRegs >> 8;                                               \
    348         ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);       \
    349         SET_REGISTER_WIDE(vdst,                                             \
    350             _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \
    351     }                                                                       \
    352     FINISH(2);
    353 
    354 #define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv)              \
    355     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
    356         vdst = INST_A(inst);                                                \
    357         vsrc1 = INST_B(inst);                                               \
    358         ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1);            \
    359         if (_chkdiv != 0) {                                                 \
    360             s8 firstVal, secondVal, result;                                 \
    361             firstVal = GET_REGISTER_WIDE(vdst);                             \
    362             secondVal = GET_REGISTER_WIDE(vsrc1);                           \
    363             if (secondVal == 0LL) {                                         \
    364                 EXPORT_PC();                                                \
    365                 dvmThrowArithmeticException("divide by zero");              \
    366                 GOTO_exceptionThrown();                                     \
    367             }                                                               \
    368             if ((u8)firstVal == 0x8000000000000000ULL &&                    \
    369                 secondVal == -1LL)                                          \
    370             {                                                               \
    371                 if (_chkdiv == 1)                                           \
    372                     result = firstVal;  /* division */                      \
    373                 else                                                        \
    374                     result = 0;         /* remainder */                     \
    375             } else {                                                        \
    376                 result = firstVal _op secondVal;                            \
    377             }                                                               \
    378             SET_REGISTER_WIDE(vdst, result);                                \
    379         } else {                                                            \
    380             SET_REGISTER_WIDE(vdst,                                         \
    381                 (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\
    382         }                                                                   \
    383         FINISH(1);
    384 
    385 #define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op)              \
    386     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
    387         vdst = INST_A(inst);                                                \
    388         vsrc1 = INST_B(inst);                                               \
    389         ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1);            \
    390         SET_REGISTER_WIDE(vdst,                                             \
    391             _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \
    392         FINISH(1);
    393 
    394 #define HANDLE_OP_X_FLOAT(_opcode, _opname, _op)                            \
    395     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
    396     {                                                                       \
    397         u2 srcRegs;                                                         \
    398         vdst = INST_AA(inst);                                               \
    399         srcRegs = FETCH(1);                                                 \
    400         vsrc1 = srcRegs & 0xff;                                             \
    401         vsrc2 = srcRegs >> 8;                                               \
    402         ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);      \
    403         SET_REGISTER_FLOAT(vdst,                                            \
    404             GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2));       \
    405     }                                                                       \
    406     FINISH(2);
    407 
    408 #define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op)                           \
    409     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
    410     {                                                                       \
    411         u2 srcRegs;                                                         \
    412         vdst = INST_AA(inst);                                               \
    413         srcRegs = FETCH(1);                                                 \
    414         vsrc1 = srcRegs & 0xff;                                             \
    415         vsrc2 = srcRegs >> 8;                                               \
    416         ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);     \
    417         SET_REGISTER_DOUBLE(vdst,                                           \
    418             GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2));     \
    419     }                                                                       \
    420     FINISH(2);
    421 
    422 #define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op)                      \
    423     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
    424         vdst = INST_A(inst);                                                \
    425         vsrc1 = INST_B(inst);                                               \
    426         ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1);           \
    427         SET_REGISTER_FLOAT(vdst,                                            \
    428             GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1));        \
    429         FINISH(1);
    430 
    431 #define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op)                     \
    432     HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
    433         vdst = INST_A(inst);                                                \
    434         vsrc1 = INST_B(inst);                                               \
    435         ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1);          \
    436         SET_REGISTER_DOUBLE(vdst,                                           \
    437             GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1));      \
    438         FINISH(1);
    439 
    440 #define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize)                   \
    441     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
    442     {                                                                       \
    443         ArrayObject* arrayObj;                                              \
    444         u2 arrayInfo;                                                       \
    445         EXPORT_PC();                                                        \
    446         vdst = INST_AA(inst);                                               \
    447         arrayInfo = FETCH(1);                                               \
    448         vsrc1 = arrayInfo & 0xff;    /* array ptr */                        \
    449         vsrc2 = arrayInfo >> 8;      /* index */                            \
    450         ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);        \
    451         arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);                      \
    452         if (!checkForNull((Object*) arrayObj))                              \
    453             GOTO_exceptionThrown();                                         \
    454         if (GET_REGISTER(vsrc2) >= arrayObj->length) {                      \
    455             dvmThrowArrayIndexOutOfBoundsException(                         \
    456                 arrayObj->length, GET_REGISTER(vsrc2));                     \
    457             GOTO_exceptionThrown();                                         \
    458         }                                                                   \
    459         SET_REGISTER##_regsize(vdst,                                        \
    460             ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]);      \
    461         ILOGV("+ AGET[%d]=%#x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));   \
    462     }                                                                       \
    463     FINISH(2);
    464 
    465 #define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize)                   \
    466     HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
    467     {                                                                       \
    468         ArrayObject* arrayObj;                                              \
    469         u2 arrayInfo;                                                       \
    470         EXPORT_PC();                                                        \
    471         vdst = INST_AA(inst);       /* AA: source value */                  \
    472         arrayInfo = FETCH(1);                                               \
    473         vsrc1 = arrayInfo & 0xff;   /* BB: array ptr */                     \
    474         vsrc2 = arrayInfo >> 8;     /* CC: index */                         \
    475         ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);        \
    476         arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);                      \
    477         if (!checkForNull((Object*) arrayObj))                              \
    478             GOTO_exceptionThrown();                                         \
    479         if (GET_REGISTER(vsrc2) >= arrayObj->length) {                      \
    480             dvmThrowArrayIndexOutOfBoundsException(                         \
    481                 arrayObj->length, GET_REGISTER(vsrc2));                     \
    482             GOTO_exceptionThrown();                                         \
    483         }                                                                   \
    484         ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
    485         ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] =          \
    486             GET_REGISTER##_regsize(vdst);                                   \
    487     }                                                                       \
    488     FINISH(2);
    489 
    490 /*
    491  * It's possible to get a bad value out of a field with sub-32-bit stores
    492  * because the -quick versions always operate on 32 bits.  Consider:
    493  *   short foo = -1  (sets a 32-bit register to 0xffffffff)
    494  *   iput-quick foo  (writes all 32 bits to the field)
    495  *   short bar = 1   (sets a 32-bit register to 0x00000001)
    496  *   iput-short      (writes the low 16 bits to the field)
    497  *   iget-quick foo  (reads all 32 bits from the field, yielding 0xffff0001)
    498  * This can only happen when optimized and non-optimized code has interleaved
    499  * access to the same field.  This is unlikely but possible.
    500  *
    501  * The easiest way to fix this is to always read/write 32 bits at a time.  On
    502  * a device with a 16-bit data bus this is sub-optimal.  (The alternative
    503  * approach is to have sub-int versions of iget-quick, but now we're wasting
    504  * Dalvik instruction space and making it less likely that handler code will
    505  * already be in the CPU i-cache.)
    506  */
    507 #define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize)                   \
    508     HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
    509     {                                                                       \
    510         InstField* ifield;                                                  \
    511         Object* obj;                                                        \
    512         EXPORT_PC();                                                        \
    513         vdst = INST_A(inst);                                                \
    514         vsrc1 = INST_B(inst);   /* object ptr */                            \
    515         ref = FETCH(1);         /* field ref */                             \
    516         ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
    517         obj = (Object*) GET_REGISTER(vsrc1);                                \
    518         if (!checkForNull(obj))                                             \
    519             GOTO_exceptionThrown();                                         \
    520         ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref);  \
    521         if (ifield == NULL) {                                               \
    522             ifield = dvmResolveInstField(curMethod->clazz, ref);            \
    523             if (ifield == NULL)                                             \
    524                 GOTO_exceptionThrown();                                     \
    525         }                                                                   \
    526         SET_REGISTER##_regsize(vdst,                                        \
    527             dvmGetField##_ftype(obj, ifield->byteOffset));                  \
    528         ILOGV("+ IGET '%s'=0x%08llx", ifield->name,                         \
    529             (u8) GET_REGISTER##_regsize(vdst));                             \
    530     }                                                                       \
    531     FINISH(2);
    532 
    533 #define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize)             \
    534     HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
    535     {                                                                       \
    536         Object* obj;                                                        \
    537         vdst = INST_A(inst);                                                \
    538         vsrc1 = INST_B(inst);   /* object ptr */                            \
    539         ref = FETCH(1);         /* field offset */                          \
    540         ILOGV("|iget%s-quick v%d,v%d,field@+%u",                            \
    541             (_opname), vdst, vsrc1, ref);                                   \
    542         obj = (Object*) GET_REGISTER(vsrc1);                                \
    543         if (!checkForNullExportPC(obj, fp, pc))                             \
    544             GOTO_exceptionThrown();                                         \
    545         SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref));        \
    546         ILOGV("+ IGETQ %d=0x%08llx", ref,                                   \
    547             (u8) GET_REGISTER##_regsize(vdst));                             \
    548     }                                                                       \
    549     FINISH(2);
    550 
    551 #define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize)                   \
    552     HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
    553     {                                                                       \
    554         InstField* ifield;                                                  \
    555         Object* obj;                                                        \
    556         EXPORT_PC();                                                        \
    557         vdst = INST_A(inst);                                                \
    558         vsrc1 = INST_B(inst);   /* object ptr */                            \
    559         ref = FETCH(1);         /* field ref */                             \
    560         ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
    561         obj = (Object*) GET_REGISTER(vsrc1);                                \
    562         if (!checkForNull(obj))                                             \
    563             GOTO_exceptionThrown();                                         \
    564         ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref);  \
    565         if (ifield == NULL) {                                               \
    566             ifield = dvmResolveInstField(curMethod->clazz, ref);            \
    567             if (ifield == NULL)                                             \
    568                 GOTO_exceptionThrown();                                     \
    569         }                                                                   \
    570         dvmSetField##_ftype(obj, ifield->byteOffset,                        \
    571             GET_REGISTER##_regsize(vdst));                                  \
    572         ILOGV("+ IPUT '%s'=0x%08llx", ifield->name,                         \
    573             (u8) GET_REGISTER##_regsize(vdst));                             \
    574     }                                                                       \
    575     FINISH(2);
    576 
    577 #define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize)             \
    578     HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
    579     {                                                                       \
    580         Object* obj;                                                        \
    581         vdst = INST_A(inst);                                                \
    582         vsrc1 = INST_B(inst);   /* object ptr */                            \
    583         ref = FETCH(1);         /* field offset */                          \
    584         ILOGV("|iput%s-quick v%d,v%d,field@0x%04x",                         \
    585             (_opname), vdst, vsrc1, ref);                                   \
    586         obj = (Object*) GET_REGISTER(vsrc1);                                \
    587         if (!checkForNullExportPC(obj, fp, pc))                             \
    588             GOTO_exceptionThrown();                                         \
    589         dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst));        \
    590         ILOGV("+ IPUTQ %d=0x%08llx", ref,                                   \
    591             (u8) GET_REGISTER##_regsize(vdst));                             \
    592     }                                                                       \
    593     FINISH(2);
    594 
    595 /*
    596  * The JIT needs dvmDexGetResolvedField() to return non-null.
    597  * Because the portable interpreter is not involved with the JIT
    598  * and trace building, we only need the extra check here when this
    599  * code is massaged into a stub called from an assembly interpreter.
    600  * This is controlled by the JIT_STUB_HACK maco.
    601  */
    602 
    603 #define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize)                   \
    604     HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/)                              \
    605     {                                                                       \
    606         StaticField* sfield;                                                \
    607         vdst = INST_AA(inst);                                               \
    608         ref = FETCH(1);         /* field ref */                             \
    609         ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref);           \
    610         sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
    611         if (sfield == NULL) {                                               \
    612             EXPORT_PC();                                                    \
    613             sfield = dvmResolveStaticField(curMethod->clazz, ref);          \
    614             if (sfield == NULL)                                             \
    615                 GOTO_exceptionThrown();                                     \
    616             if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) {      \
    617                 JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc));               \
    618             }                                                               \
    619         }                                                                   \
    620         SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield));    \
    621         ILOGV("+ SGET '%s'=0x%08llx",                                       \
    622             sfield->name, (u8)GET_REGISTER##_regsize(vdst));                \
    623     }                                                                       \
    624     FINISH(2);
    625 
    626 #define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize)                   \
    627     HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/)                              \
    628     {                                                                       \
    629         StaticField* sfield;                                                \
    630         vdst = INST_AA(inst);                                               \
    631         ref = FETCH(1);         /* field ref */                             \
    632         ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref);           \
    633         sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
    634         if (sfield == NULL) {                                               \
    635             EXPORT_PC();                                                    \
    636             sfield = dvmResolveStaticField(curMethod->clazz, ref);          \
    637             if (sfield == NULL)                                             \
    638                 GOTO_exceptionThrown();                                     \
    639             if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) {      \
    640                 JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc));               \
    641             }                                                               \
    642         }                                                                   \
    643         dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst));    \
    644         ILOGV("+ SPUT '%s'=0x%08llx",                                       \
    645             sfield->name, (u8)GET_REGISTER##_regsize(vdst));                \
    646     }                                                                       \
    647     FINISH(2);
    648