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