|  | /* forward declarations of goto targets */ | 
|  | GOTO_TARGET_DECL(filledNewArray, bool methodCallRange); | 
|  | GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange); | 
|  | GOTO_TARGET_DECL(invokeSuper, bool methodCallRange); | 
|  | GOTO_TARGET_DECL(invokeInterface, bool methodCallRange); | 
|  | GOTO_TARGET_DECL(invokeDirect, bool methodCallRange); | 
|  | GOTO_TARGET_DECL(invokeStatic, bool methodCallRange); | 
|  | GOTO_TARGET_DECL(invokeVirtualQuick, bool methodCallRange); | 
|  | GOTO_TARGET_DECL(invokeSuperQuick, bool methodCallRange); | 
|  | GOTO_TARGET_DECL(invokeMethod, bool methodCallRange, const Method* methodToCall, | 
|  | u2 count, u2 regs); | 
|  | GOTO_TARGET_DECL(returnFromMethod); | 
|  | GOTO_TARGET_DECL(exceptionThrown); | 
|  |  | 
|  | /* | 
|  | * =========================================================================== | 
|  | * | 
|  | * What follows are opcode definitions shared between multiple opcodes with | 
|  | * minor substitutions handled by the C pre-processor.  These should probably | 
|  | * use the mterp substitution mechanism instead, with the code here moved | 
|  | * into common fragment files (like the asm "binop.S"), although it's hard | 
|  | * to give up the C preprocessor in favor of the much simpler text subst. | 
|  | * | 
|  | * =========================================================================== | 
|  | */ | 
|  |  | 
|  | #define HANDLE_NUMCONV(_opcode, _opname, _fromtype, _totype)                \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \ | 
|  | vdst = INST_A(inst);                                                \ | 
|  | vsrc1 = INST_B(inst);                                               \ | 
|  | ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \ | 
|  | SET_REGISTER##_totype(vdst,                                         \ | 
|  | GET_REGISTER##_fromtype(vsrc1));                                \ | 
|  | FINISH(1); | 
|  |  | 
|  | #define HANDLE_FLOAT_TO_INT(_opcode, _opname, _fromvtype, _fromrtype,       \ | 
|  | _tovtype, _tortype)                                                 \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \ | 
|  | {                                                                       \ | 
|  | /* spec defines specific handling for +/- inf and NaN values */     \ | 
|  | _fromvtype val;                                                     \ | 
|  | _tovtype intMin, intMax, result;                                    \ | 
|  | vdst = INST_A(inst);                                                \ | 
|  | vsrc1 = INST_B(inst);                                               \ | 
|  | ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \ | 
|  | val = GET_REGISTER##_fromrtype(vsrc1);                              \ | 
|  | intMin = (_tovtype) 1 << (sizeof(_tovtype) * 8 -1);                 \ | 
|  | intMax = ~intMin;                                                   \ | 
|  | result = (_tovtype) val;                                            \ | 
|  | if (val >= intMax)          /* +inf */                              \ | 
|  | result = intMax;                                                \ | 
|  | else if (val <= intMin)     /* -inf */                              \ | 
|  | result = intMin;                                                \ | 
|  | else if (val != val)        /* NaN */                               \ | 
|  | result = 0;                                                     \ | 
|  | else                                                                \ | 
|  | result = (_tovtype) val;                                        \ | 
|  | SET_REGISTER##_tortype(vdst, result);                               \ | 
|  | }                                                                       \ | 
|  | FINISH(1); | 
|  |  | 
|  | #define HANDLE_INT_TO_SMALL(_opcode, _opname, _type)                        \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \ | 
|  | vdst = INST_A(inst);                                                \ | 
|  | vsrc1 = INST_B(inst);                                               \ | 
|  | ILOGV("|int-to-%s v%d,v%d", (_opname), vdst, vsrc1);                \ | 
|  | SET_REGISTER(vdst, (_type) GET_REGISTER(vsrc1));                    \ | 
|  | FINISH(1); | 
|  |  | 
|  | /* NOTE: the comparison result is always a signed 4-byte integer */ | 
|  | #define HANDLE_OP_CMPX(_opcode, _opname, _varType, _type, _nanVal)          \ | 
|  | HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \ | 
|  | {                                                                       \ | 
|  | int result;                                                         \ | 
|  | u2 regs;                                                            \ | 
|  | _varType val1, val2;                                                \ | 
|  | vdst = INST_AA(inst);                                               \ | 
|  | regs = FETCH(1);                                                    \ | 
|  | vsrc1 = regs & 0xff;                                                \ | 
|  | vsrc2 = regs >> 8;                                                  \ | 
|  | ILOGV("|cmp%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);         \ | 
|  | val1 = GET_REGISTER##_type(vsrc1);                                  \ | 
|  | val2 = GET_REGISTER##_type(vsrc2);                                  \ | 
|  | if (val1 == val2)                                                   \ | 
|  | result = 0;                                                     \ | 
|  | else if (val1 < val2)                                               \ | 
|  | result = -1;                                                    \ | 
|  | else if (val1 > val2)                                               \ | 
|  | result = 1;                                                     \ | 
|  | else                                                                \ | 
|  | result = (_nanVal);                                             \ | 
|  | ILOGV("+ result=%d", result);                                       \ | 
|  | SET_REGISTER(vdst, result);                                         \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | #define HANDLE_OP_IF_XX(_opcode, _opname, _cmp)                             \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB, +CCCC*/)                                \ | 
|  | vsrc1 = INST_A(inst);                                               \ | 
|  | vsrc2 = INST_B(inst);                                               \ | 
|  | if ((s4) GET_REGISTER(vsrc1) _cmp (s4) GET_REGISTER(vsrc2)) {       \ | 
|  | int branchOffset = (s2)FETCH(1);    /* sign-extended */         \ | 
|  | ILOGV("|if-%s v%d,v%d,+0x%04x", (_opname), vsrc1, vsrc2,        \ | 
|  | branchOffset);                                              \ | 
|  | ILOGV("> branch taken");                                        \ | 
|  | if (branchOffset < 0)                                           \ | 
|  | PERIODIC_CHECKS(branchOffset);                              \ | 
|  | FINISH(branchOffset);                                           \ | 
|  | } else {                                                            \ | 
|  | ILOGV("|if-%s v%d,v%d,-", (_opname), vsrc1, vsrc2);             \ | 
|  | FINISH(2);                                                      \ | 
|  | } | 
|  |  | 
|  | #define HANDLE_OP_IF_XXZ(_opcode, _opname, _cmp)                            \ | 
|  | HANDLE_OPCODE(_opcode /*vAA, +BBBB*/)                                   \ | 
|  | vsrc1 = INST_AA(inst);                                              \ | 
|  | if ((s4) GET_REGISTER(vsrc1) _cmp 0) {                              \ | 
|  | int branchOffset = (s2)FETCH(1);    /* sign-extended */         \ | 
|  | ILOGV("|if-%s v%d,+0x%04x", (_opname), vsrc1, branchOffset);    \ | 
|  | ILOGV("> branch taken");                                        \ | 
|  | if (branchOffset < 0)                                           \ | 
|  | PERIODIC_CHECKS(branchOffset);                              \ | 
|  | FINISH(branchOffset);                                           \ | 
|  | } else {                                                            \ | 
|  | ILOGV("|if-%s v%d,-", (_opname), vsrc1);                        \ | 
|  | FINISH(2);                                                      \ | 
|  | } | 
|  |  | 
|  | #define HANDLE_UNOP(_opcode, _opname, _pfx, _sfx, _type)                    \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \ | 
|  | vdst = INST_A(inst);                                                \ | 
|  | vsrc1 = INST_B(inst);                                               \ | 
|  | ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \ | 
|  | SET_REGISTER##_type(vdst, _pfx GET_REGISTER##_type(vsrc1) _sfx);    \ | 
|  | FINISH(1); | 
|  |  | 
|  | #define HANDLE_OP_X_INT(_opcode, _opname, _op, _chkdiv)                     \ | 
|  | HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \ | 
|  | {                                                                       \ | 
|  | u2 srcRegs;                                                         \ | 
|  | vdst = INST_AA(inst);                                               \ | 
|  | srcRegs = FETCH(1);                                                 \ | 
|  | vsrc1 = srcRegs & 0xff;                                             \ | 
|  | vsrc2 = srcRegs >> 8;                                               \ | 
|  | ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1);                   \ | 
|  | if (_chkdiv != 0) {                                                 \ | 
|  | s4 firstVal, secondVal, result;                                 \ | 
|  | firstVal = GET_REGISTER(vsrc1);                                 \ | 
|  | secondVal = GET_REGISTER(vsrc2);                                \ | 
|  | if (secondVal == 0) {                                           \ | 
|  | EXPORT_PC();                                                \ | 
|  | dvmThrowArithmeticException("divide by zero");              \ | 
|  | GOTO_exceptionThrown();                                     \ | 
|  | }                                                               \ | 
|  | if ((u4)firstVal == 0x80000000 && secondVal == -1) {            \ | 
|  | if (_chkdiv == 1)                                           \ | 
|  | result = firstVal;  /* division */                      \ | 
|  | else                                                        \ | 
|  | result = 0;         /* remainder */                     \ | 
|  | } else {                                                        \ | 
|  | result = firstVal _op secondVal;                            \ | 
|  | }                                                               \ | 
|  | SET_REGISTER(vdst, result);                                     \ | 
|  | } else {                                                            \ | 
|  | /* non-div/rem case */                                          \ | 
|  | SET_REGISTER(vdst,                                              \ | 
|  | (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2));     \ | 
|  | }                                                                   \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | #define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op)                     \ | 
|  | HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \ | 
|  | {                                                                       \ | 
|  | u2 srcRegs;                                                         \ | 
|  | vdst = INST_AA(inst);                                               \ | 
|  | srcRegs = FETCH(1);                                                 \ | 
|  | vsrc1 = srcRegs & 0xff;                                             \ | 
|  | vsrc2 = srcRegs >> 8;                                               \ | 
|  | ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1);                   \ | 
|  | SET_REGISTER(vdst,                                                  \ | 
|  | _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f));    \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | #define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv)               \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/)                               \ | 
|  | vdst = INST_A(inst);                                                \ | 
|  | vsrc1 = INST_B(inst);                                               \ | 
|  | vsrc2 = FETCH(1);                                                   \ | 
|  | ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x",                             \ | 
|  | (_opname), vdst, vsrc1, vsrc2);                                 \ | 
|  | if (_chkdiv != 0) {                                                 \ | 
|  | s4 firstVal, result;                                            \ | 
|  | firstVal = GET_REGISTER(vsrc1);                                 \ | 
|  | if ((s2) vsrc2 == 0) {                                          \ | 
|  | EXPORT_PC();                                                \ | 
|  | dvmThrowArithmeticException("divide by zero");              \ | 
|  | GOTO_exceptionThrown();                                     \ | 
|  | }                                                               \ | 
|  | if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) {         \ | 
|  | /* won't generate /lit16 instr for this; check anyway */    \ | 
|  | if (_chkdiv == 1)                                           \ | 
|  | result = firstVal;  /* division */                      \ | 
|  | else                                                        \ | 
|  | result = 0;         /* remainder */                     \ | 
|  | } else {                                                        \ | 
|  | result = firstVal _op (s2) vsrc2;                           \ | 
|  | }                                                               \ | 
|  | SET_REGISTER(vdst, result);                                     \ | 
|  | } else {                                                            \ | 
|  | /* non-div/rem case */                                          \ | 
|  | SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2);         \ | 
|  | }                                                                   \ | 
|  | FINISH(2); | 
|  |  | 
|  | #define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv)                \ | 
|  | HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/)                               \ | 
|  | {                                                                       \ | 
|  | u2 litInfo;                                                         \ | 
|  | vdst = INST_AA(inst);                                               \ | 
|  | litInfo = FETCH(1);                                                 \ | 
|  | vsrc1 = litInfo & 0xff;                                             \ | 
|  | vsrc2 = litInfo >> 8;       /* constant */                          \ | 
|  | ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x",                              \ | 
|  | (_opname), vdst, vsrc1, vsrc2);                                 \ | 
|  | if (_chkdiv != 0) {                                                 \ | 
|  | s4 firstVal, result;                                            \ | 
|  | firstVal = GET_REGISTER(vsrc1);                                 \ | 
|  | if ((s1) vsrc2 == 0) {                                          \ | 
|  | EXPORT_PC();                                                \ | 
|  | dvmThrowArithmeticException("divide by zero");              \ | 
|  | GOTO_exceptionThrown();                                     \ | 
|  | }                                                               \ | 
|  | if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) {         \ | 
|  | if (_chkdiv == 1)                                           \ | 
|  | result = firstVal;  /* division */                      \ | 
|  | else                                                        \ | 
|  | result = 0;         /* remainder */                     \ | 
|  | } else {                                                        \ | 
|  | result = firstVal _op ((s1) vsrc2);                         \ | 
|  | }                                                               \ | 
|  | SET_REGISTER(vdst, result);                                     \ | 
|  | } else {                                                            \ | 
|  | SET_REGISTER(vdst,                                              \ | 
|  | (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2);                   \ | 
|  | }                                                                   \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | #define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op)                \ | 
|  | HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/)                               \ | 
|  | {                                                                       \ | 
|  | u2 litInfo;                                                         \ | 
|  | vdst = INST_AA(inst);                                               \ | 
|  | litInfo = FETCH(1);                                                 \ | 
|  | vsrc1 = litInfo & 0xff;                                             \ | 
|  | vsrc2 = litInfo >> 8;       /* constant */                          \ | 
|  | ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x",                              \ | 
|  | (_opname), vdst, vsrc1, vsrc2);                                 \ | 
|  | SET_REGISTER(vdst,                                                  \ | 
|  | _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f));                  \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | #define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv)               \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \ | 
|  | vdst = INST_A(inst);                                                \ | 
|  | vsrc1 = INST_B(inst);                                               \ | 
|  | ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1);             \ | 
|  | if (_chkdiv != 0) {                                                 \ | 
|  | s4 firstVal, secondVal, result;                                 \ | 
|  | firstVal = GET_REGISTER(vdst);                                  \ | 
|  | secondVal = GET_REGISTER(vsrc1);                                \ | 
|  | if (secondVal == 0) {                                           \ | 
|  | EXPORT_PC();                                                \ | 
|  | dvmThrowArithmeticException("divide by zero");              \ | 
|  | GOTO_exceptionThrown();                                     \ | 
|  | }                                                               \ | 
|  | if ((u4)firstVal == 0x80000000 && secondVal == -1) {            \ | 
|  | if (_chkdiv == 1)                                           \ | 
|  | result = firstVal;  /* division */                      \ | 
|  | else                                                        \ | 
|  | result = 0;         /* remainder */                     \ | 
|  | } else {                                                        \ | 
|  | result = firstVal _op secondVal;                            \ | 
|  | }                                                               \ | 
|  | SET_REGISTER(vdst, result);                                     \ | 
|  | } else {                                                            \ | 
|  | SET_REGISTER(vdst,                                              \ | 
|  | (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1));      \ | 
|  | }                                                                   \ | 
|  | FINISH(1); | 
|  |  | 
|  | #define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op)               \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \ | 
|  | vdst = INST_A(inst);                                                \ | 
|  | vsrc1 = INST_B(inst);                                               \ | 
|  | ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1);             \ | 
|  | SET_REGISTER(vdst,                                                  \ | 
|  | _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f));     \ | 
|  | FINISH(1); | 
|  |  | 
|  | #define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv)                    \ | 
|  | HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \ | 
|  | {                                                                       \ | 
|  | u2 srcRegs;                                                         \ | 
|  | vdst = INST_AA(inst);                                               \ | 
|  | srcRegs = FETCH(1);                                                 \ | 
|  | vsrc1 = srcRegs & 0xff;                                             \ | 
|  | vsrc2 = srcRegs >> 8;                                               \ | 
|  | ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);       \ | 
|  | if (_chkdiv != 0) {                                                 \ | 
|  | s8 firstVal, secondVal, result;                                 \ | 
|  | firstVal = GET_REGISTER_WIDE(vsrc1);                            \ | 
|  | secondVal = GET_REGISTER_WIDE(vsrc2);                           \ | 
|  | if (secondVal == 0LL) {                                         \ | 
|  | EXPORT_PC();                                                \ | 
|  | dvmThrowArithmeticException("divide by zero");              \ | 
|  | GOTO_exceptionThrown();                                     \ | 
|  | }                                                               \ | 
|  | if ((u8)firstVal == 0x8000000000000000ULL &&                    \ | 
|  | secondVal == -1LL)                                          \ | 
|  | {                                                               \ | 
|  | if (_chkdiv == 1)                                           \ | 
|  | result = firstVal;  /* division */                      \ | 
|  | else                                                        \ | 
|  | result = 0;         /* remainder */                     \ | 
|  | } else {                                                        \ | 
|  | result = firstVal _op secondVal;                            \ | 
|  | }                                                               \ | 
|  | SET_REGISTER_WIDE(vdst, result);                                \ | 
|  | } else {                                                            \ | 
|  | SET_REGISTER_WIDE(vdst,                                         \ | 
|  | (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \ | 
|  | }                                                                   \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | #define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op)                    \ | 
|  | HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \ | 
|  | {                                                                       \ | 
|  | u2 srcRegs;                                                         \ | 
|  | vdst = INST_AA(inst);                                               \ | 
|  | srcRegs = FETCH(1);                                                 \ | 
|  | vsrc1 = srcRegs & 0xff;                                             \ | 
|  | vsrc2 = srcRegs >> 8;                                               \ | 
|  | ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);       \ | 
|  | SET_REGISTER_WIDE(vdst,                                             \ | 
|  | _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | #define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv)              \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \ | 
|  | vdst = INST_A(inst);                                                \ | 
|  | vsrc1 = INST_B(inst);                                               \ | 
|  | ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1);            \ | 
|  | if (_chkdiv != 0) {                                                 \ | 
|  | s8 firstVal, secondVal, result;                                 \ | 
|  | firstVal = GET_REGISTER_WIDE(vdst);                             \ | 
|  | secondVal = GET_REGISTER_WIDE(vsrc1);                           \ | 
|  | if (secondVal == 0LL) {                                         \ | 
|  | EXPORT_PC();                                                \ | 
|  | dvmThrowArithmeticException("divide by zero");              \ | 
|  | GOTO_exceptionThrown();                                     \ | 
|  | }                                                               \ | 
|  | if ((u8)firstVal == 0x8000000000000000ULL &&                    \ | 
|  | secondVal == -1LL)                                          \ | 
|  | {                                                               \ | 
|  | if (_chkdiv == 1)                                           \ | 
|  | result = firstVal;  /* division */                      \ | 
|  | else                                                        \ | 
|  | result = 0;         /* remainder */                     \ | 
|  | } else {                                                        \ | 
|  | result = firstVal _op secondVal;                            \ | 
|  | }                                                               \ | 
|  | SET_REGISTER_WIDE(vdst, result);                                \ | 
|  | } else {                                                            \ | 
|  | SET_REGISTER_WIDE(vdst,                                         \ | 
|  | (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\ | 
|  | }                                                                   \ | 
|  | FINISH(1); | 
|  |  | 
|  | #define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op)              \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \ | 
|  | vdst = INST_A(inst);                                                \ | 
|  | vsrc1 = INST_B(inst);                                               \ | 
|  | ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1);            \ | 
|  | SET_REGISTER_WIDE(vdst,                                             \ | 
|  | _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \ | 
|  | FINISH(1); | 
|  |  | 
|  | #define HANDLE_OP_X_FLOAT(_opcode, _opname, _op)                            \ | 
|  | HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \ | 
|  | {                                                                       \ | 
|  | u2 srcRegs;                                                         \ | 
|  | vdst = INST_AA(inst);                                               \ | 
|  | srcRegs = FETCH(1);                                                 \ | 
|  | vsrc1 = srcRegs & 0xff;                                             \ | 
|  | vsrc2 = srcRegs >> 8;                                               \ | 
|  | ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);      \ | 
|  | SET_REGISTER_FLOAT(vdst,                                            \ | 
|  | GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2));       \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | #define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op)                           \ | 
|  | HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \ | 
|  | {                                                                       \ | 
|  | u2 srcRegs;                                                         \ | 
|  | vdst = INST_AA(inst);                                               \ | 
|  | srcRegs = FETCH(1);                                                 \ | 
|  | vsrc1 = srcRegs & 0xff;                                             \ | 
|  | vsrc2 = srcRegs >> 8;                                               \ | 
|  | ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);     \ | 
|  | SET_REGISTER_DOUBLE(vdst,                                           \ | 
|  | GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2));     \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | #define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op)                      \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \ | 
|  | vdst = INST_A(inst);                                                \ | 
|  | vsrc1 = INST_B(inst);                                               \ | 
|  | ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1);           \ | 
|  | SET_REGISTER_FLOAT(vdst,                                            \ | 
|  | GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1));        \ | 
|  | FINISH(1); | 
|  |  | 
|  | #define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op)                     \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \ | 
|  | vdst = INST_A(inst);                                                \ | 
|  | vsrc1 = INST_B(inst);                                               \ | 
|  | ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1);          \ | 
|  | SET_REGISTER_DOUBLE(vdst,                                           \ | 
|  | GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1));      \ | 
|  | FINISH(1); | 
|  |  | 
|  | #define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize)                   \ | 
|  | HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \ | 
|  | {                                                                       \ | 
|  | ArrayObject* arrayObj;                                              \ | 
|  | u2 arrayInfo;                                                       \ | 
|  | EXPORT_PC();                                                        \ | 
|  | vdst = INST_AA(inst);                                               \ | 
|  | arrayInfo = FETCH(1);                                               \ | 
|  | vsrc1 = arrayInfo & 0xff;    /* array ptr */                        \ | 
|  | vsrc2 = arrayInfo >> 8;      /* index */                            \ | 
|  | ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);        \ | 
|  | arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);                      \ | 
|  | if (!checkForNull((Object*) arrayObj))                              \ | 
|  | GOTO_exceptionThrown();                                         \ | 
|  | if (GET_REGISTER(vsrc2) >= arrayObj->length) {                      \ | 
|  | dvmThrowArrayIndexOutOfBoundsException(                         \ | 
|  | arrayObj->length, GET_REGISTER(vsrc2));                     \ | 
|  | GOTO_exceptionThrown();                                         \ | 
|  | }                                                                   \ | 
|  | SET_REGISTER##_regsize(vdst,                                        \ | 
|  | ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]);      \ | 
|  | ILOGV("+ AGET[%d]=%#x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));   \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | #define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize)                   \ | 
|  | HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \ | 
|  | {                                                                       \ | 
|  | ArrayObject* arrayObj;                                              \ | 
|  | u2 arrayInfo;                                                       \ | 
|  | EXPORT_PC();                                                        \ | 
|  | vdst = INST_AA(inst);       /* AA: source value */                  \ | 
|  | arrayInfo = FETCH(1);                                               \ | 
|  | vsrc1 = arrayInfo & 0xff;   /* BB: array ptr */                     \ | 
|  | vsrc2 = arrayInfo >> 8;     /* CC: index */                         \ | 
|  | ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);        \ | 
|  | arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);                      \ | 
|  | if (!checkForNull((Object*) arrayObj))                              \ | 
|  | GOTO_exceptionThrown();                                         \ | 
|  | if (GET_REGISTER(vsrc2) >= arrayObj->length) {                      \ | 
|  | dvmThrowArrayIndexOutOfBoundsException(                         \ | 
|  | arrayObj->length, GET_REGISTER(vsrc2));                     \ | 
|  | GOTO_exceptionThrown();                                         \ | 
|  | }                                                                   \ | 
|  | ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\ | 
|  | ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] =          \ | 
|  | GET_REGISTER##_regsize(vdst);                                   \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | /* | 
|  | * It's possible to get a bad value out of a field with sub-32-bit stores | 
|  | * because the -quick versions always operate on 32 bits.  Consider: | 
|  | *   short foo = -1  (sets a 32-bit register to 0xffffffff) | 
|  | *   iput-quick foo  (writes all 32 bits to the field) | 
|  | *   short bar = 1   (sets a 32-bit register to 0x00000001) | 
|  | *   iput-short      (writes the low 16 bits to the field) | 
|  | *   iget-quick foo  (reads all 32 bits from the field, yielding 0xffff0001) | 
|  | * This can only happen when optimized and non-optimized code has interleaved | 
|  | * access to the same field.  This is unlikely but possible. | 
|  | * | 
|  | * The easiest way to fix this is to always read/write 32 bits at a time.  On | 
|  | * a device with a 16-bit data bus this is sub-optimal.  (The alternative | 
|  | * approach is to have sub-int versions of iget-quick, but now we're wasting | 
|  | * Dalvik instruction space and making it less likely that handler code will | 
|  | * already be in the CPU i-cache.) | 
|  | */ | 
|  | #define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize)                   \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \ | 
|  | {                                                                       \ | 
|  | InstField* ifield;                                                  \ | 
|  | Object* obj;                                                        \ | 
|  | EXPORT_PC();                                                        \ | 
|  | vdst = INST_A(inst);                                                \ | 
|  | vsrc1 = INST_B(inst);   /* object ptr */                            \ | 
|  | ref = FETCH(1);         /* field ref */                             \ | 
|  | ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \ | 
|  | obj = (Object*) GET_REGISTER(vsrc1);                                \ | 
|  | if (!checkForNull(obj))                                             \ | 
|  | GOTO_exceptionThrown();                                         \ | 
|  | ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref);  \ | 
|  | if (ifield == NULL) {                                               \ | 
|  | ifield = dvmResolveInstField(curMethod->clazz, ref);            \ | 
|  | if (ifield == NULL)                                             \ | 
|  | GOTO_exceptionThrown();                                     \ | 
|  | }                                                                   \ | 
|  | SET_REGISTER##_regsize(vdst,                                        \ | 
|  | dvmGetField##_ftype(obj, ifield->byteOffset));                  \ | 
|  | ILOGV("+ IGET '%s'=0x%08llx", ifield->name,                         \ | 
|  | (u8) GET_REGISTER##_regsize(vdst));                             \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | #define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize)             \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \ | 
|  | {                                                                       \ | 
|  | Object* obj;                                                        \ | 
|  | vdst = INST_A(inst);                                                \ | 
|  | vsrc1 = INST_B(inst);   /* object ptr */                            \ | 
|  | ref = FETCH(1);         /* field offset */                          \ | 
|  | ILOGV("|iget%s-quick v%d,v%d,field@+%u",                            \ | 
|  | (_opname), vdst, vsrc1, ref);                                   \ | 
|  | obj = (Object*) GET_REGISTER(vsrc1);                                \ | 
|  | if (!checkForNullExportPC(obj, fp, pc))                             \ | 
|  | GOTO_exceptionThrown();                                         \ | 
|  | SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref));        \ | 
|  | ILOGV("+ IGETQ %d=0x%08llx", ref,                                   \ | 
|  | (u8) GET_REGISTER##_regsize(vdst));                             \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | #define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize)                   \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \ | 
|  | {                                                                       \ | 
|  | InstField* ifield;                                                  \ | 
|  | Object* obj;                                                        \ | 
|  | EXPORT_PC();                                                        \ | 
|  | vdst = INST_A(inst);                                                \ | 
|  | vsrc1 = INST_B(inst);   /* object ptr */                            \ | 
|  | ref = FETCH(1);         /* field ref */                             \ | 
|  | ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \ | 
|  | obj = (Object*) GET_REGISTER(vsrc1);                                \ | 
|  | if (!checkForNull(obj))                                             \ | 
|  | GOTO_exceptionThrown();                                         \ | 
|  | ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref);  \ | 
|  | if (ifield == NULL) {                                               \ | 
|  | ifield = dvmResolveInstField(curMethod->clazz, ref);            \ | 
|  | if (ifield == NULL)                                             \ | 
|  | GOTO_exceptionThrown();                                     \ | 
|  | }                                                                   \ | 
|  | dvmSetField##_ftype(obj, ifield->byteOffset,                        \ | 
|  | GET_REGISTER##_regsize(vdst));                                  \ | 
|  | ILOGV("+ IPUT '%s'=0x%08llx", ifield->name,                         \ | 
|  | (u8) GET_REGISTER##_regsize(vdst));                             \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | #define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize)             \ | 
|  | HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \ | 
|  | {                                                                       \ | 
|  | Object* obj;                                                        \ | 
|  | vdst = INST_A(inst);                                                \ | 
|  | vsrc1 = INST_B(inst);   /* object ptr */                            \ | 
|  | ref = FETCH(1);         /* field offset */                          \ | 
|  | ILOGV("|iput%s-quick v%d,v%d,field@0x%04x",                         \ | 
|  | (_opname), vdst, vsrc1, ref);                                   \ | 
|  | obj = (Object*) GET_REGISTER(vsrc1);                                \ | 
|  | if (!checkForNullExportPC(obj, fp, pc))                             \ | 
|  | GOTO_exceptionThrown();                                         \ | 
|  | dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst));        \ | 
|  | ILOGV("+ IPUTQ %d=0x%08llx", ref,                                   \ | 
|  | (u8) GET_REGISTER##_regsize(vdst));                             \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | /* | 
|  | * The JIT needs dvmDexGetResolvedField() to return non-null. | 
|  | * Because the portable interpreter is not involved with the JIT | 
|  | * and trace building, we only need the extra check here when this | 
|  | * code is massaged into a stub called from an assembly interpreter. | 
|  | * This is controlled by the JIT_STUB_HACK maco. | 
|  | */ | 
|  |  | 
|  | #define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize)                   \ | 
|  | HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/)                              \ | 
|  | {                                                                       \ | 
|  | StaticField* sfield;                                                \ | 
|  | vdst = INST_AA(inst);                                               \ | 
|  | ref = FETCH(1);         /* field ref */                             \ | 
|  | ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref);           \ | 
|  | sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \ | 
|  | if (sfield == NULL) {                                               \ | 
|  | EXPORT_PC();                                                    \ | 
|  | sfield = dvmResolveStaticField(curMethod->clazz, ref);          \ | 
|  | if (sfield == NULL)                                             \ | 
|  | GOTO_exceptionThrown();                                     \ | 
|  | if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) {      \ | 
|  | JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc));               \ | 
|  | }                                                               \ | 
|  | }                                                                   \ | 
|  | SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield));    \ | 
|  | ILOGV("+ SGET '%s'=0x%08llx",                                       \ | 
|  | sfield->name, (u8)GET_REGISTER##_regsize(vdst));                \ | 
|  | }                                                                       \ | 
|  | FINISH(2); | 
|  |  | 
|  | #define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize)                   \ | 
|  | HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/)                              \ | 
|  | {                                                                       \ | 
|  | StaticField* sfield;                                                \ | 
|  | vdst = INST_AA(inst);                                               \ | 
|  | ref = FETCH(1);         /* field ref */                             \ | 
|  | ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref);           \ | 
|  | sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \ | 
|  | if (sfield == NULL) {                                               \ | 
|  | EXPORT_PC();                                                    \ | 
|  | sfield = dvmResolveStaticField(curMethod->clazz, ref);          \ | 
|  | if (sfield == NULL)                                             \ | 
|  | GOTO_exceptionThrown();                                     \ | 
|  | if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) {      \ | 
|  | JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc));               \ | 
|  | }                                                               \ | 
|  | }                                                                   \ | 
|  | dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst));    \ | 
|  | ILOGV("+ SPUT '%s'=0x%08llx",                                       \ | 
|  | sfield->name, (u8)GET_REGISTER##_regsize(vdst));                \ | 
|  | }                                                                       \ | 
|  | FINISH(2); |