blob: fffae08adec63c38452fe4d0ffc74bbf25321f92 [file] [log] [blame]
Carl Shapirocd8f5e72011-04-20 16:12:46 -07001/*
2 * This file was generated automatically by gen-mterp.py for 'portable'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: c/header.cpp */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24/* common includes */
25#include "Dalvik.h"
26#include "interp/InterpDefs.h"
27#include "mterp/Mterp.h"
28#include <math.h> // needed for fmod, fmodf
29#include "mterp/common/FindInterface.h"
30
31/*
32 * Configuration defines. These affect the C implementations, i.e. the
33 * portable interpreter(s) and C stubs.
34 *
35 * Some defines are controlled by the Makefile, e.g.:
36 * WITH_INSTR_CHECKS
37 * WITH_TRACKREF_CHECKS
38 * EASY_GDB
39 * NDEBUG
40 */
41
42#ifdef WITH_INSTR_CHECKS /* instruction-level paranoia (slow!) */
43# define CHECK_BRANCH_OFFSETS
44# define CHECK_REGISTER_INDICES
45#endif
46
47/*
48 * Some architectures require 64-bit alignment for access to 64-bit data
49 * types. We can't just use pointers to copy 64-bit values out of our
50 * interpreted register set, because gcc may assume the pointer target is
51 * aligned and generate invalid code.
52 *
53 * There are two common approaches:
54 * (1) Use a union that defines a 32-bit pair and a 64-bit value.
55 * (2) Call memcpy().
56 *
57 * Depending upon what compiler you're using and what options are specified,
58 * one may be faster than the other. For example, the compiler might
59 * convert a memcpy() of 8 bytes into a series of instructions and omit
60 * the call. The union version could cause some strange side-effects,
61 * e.g. for a while ARM gcc thought it needed separate storage for each
62 * inlined instance, and generated instructions to zero out ~700 bytes of
63 * stack space at the top of the interpreter.
64 *
65 * The default is to use memcpy(). The current gcc for ARM seems to do
66 * better with the union.
67 */
68#if defined(__ARM_EABI__)
69# define NO_UNALIGN_64__UNION
70#endif
71
72
73//#define LOG_INSTR /* verbose debugging */
74/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
75
76/*
Carl Shapirocd8f5e72011-04-20 16:12:46 -070077 * Export another copy of the PC on every instruction; this is largely
78 * redundant with EXPORT_PC and the debugger code. This value can be
79 * compared against what we have stored on the stack with EXPORT_PC to
80 * help ensure that we aren't missing any export calls.
81 */
82#if WITH_EXTRA_GC_CHECKS > 1
83# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
84#else
85# define EXPORT_EXTRA_PC()
86#endif
87
88/*
89 * Adjust the program counter. "_offset" is a signed int, in 16-bit units.
90 *
91 * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
92 *
93 * We don't advance the program counter until we finish an instruction or
94 * branch, because we do want to have to unroll the PC if there's an
95 * exception.
96 */
97#ifdef CHECK_BRANCH_OFFSETS
98# define ADJUST_PC(_offset) do { \
99 int myoff = _offset; /* deref only once */ \
100 if (pc + myoff < curMethod->insns || \
101 pc + myoff >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) \
102 { \
103 char* desc; \
104 desc = dexProtoCopyMethodDescriptor(&curMethod->prototype); \
105 LOGE("Invalid branch %d at 0x%04x in %s.%s %s\n", \
106 myoff, (int) (pc - curMethod->insns), \
107 curMethod->clazz->descriptor, curMethod->name, desc); \
108 free(desc); \
109 dvmAbort(); \
110 } \
111 pc += myoff; \
112 EXPORT_EXTRA_PC(); \
113 } while (false)
114#else
115# define ADJUST_PC(_offset) do { \
116 pc += _offset; \
117 EXPORT_EXTRA_PC(); \
118 } while (false)
119#endif
120
121/*
122 * If enabled, log instructions as we execute them.
123 */
124#ifdef LOG_INSTR
125# define ILOGD(...) ILOG(LOG_DEBUG, __VA_ARGS__)
126# define ILOGV(...) ILOG(LOG_VERBOSE, __VA_ARGS__)
127# define ILOG(_level, ...) do { \
128 char debugStrBuf[128]; \
129 snprintf(debugStrBuf, sizeof(debugStrBuf), __VA_ARGS__); \
130 if (curMethod != NULL) \
131 LOG(_level, LOG_TAG"i", "%-2d|%04x%s\n", \
132 self->threadId, (int)(pc - curMethod->insns), debugStrBuf); \
133 else \
134 LOG(_level, LOG_TAG"i", "%-2d|####%s\n", \
135 self->threadId, debugStrBuf); \
136 } while(false)
137void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly);
138# define DUMP_REGS(_meth, _frame, _inOnly) dvmDumpRegs(_meth, _frame, _inOnly)
139static const char kSpacing[] = " ";
140#else
141# define ILOGD(...) ((void)0)
142# define ILOGV(...) ((void)0)
143# define DUMP_REGS(_meth, _frame, _inOnly) ((void)0)
144#endif
145
146/* get a long from an array of u4 */
147static inline s8 getLongFromArray(const u4* ptr, int idx)
148{
149#if defined(NO_UNALIGN_64__UNION)
150 union { s8 ll; u4 parts[2]; } conv;
151
152 ptr += idx;
153 conv.parts[0] = ptr[0];
154 conv.parts[1] = ptr[1];
155 return conv.ll;
156#else
157 s8 val;
158 memcpy(&val, &ptr[idx], 8);
159 return val;
160#endif
161}
162
163/* store a long into an array of u4 */
164static inline void putLongToArray(u4* ptr, int idx, s8 val)
165{
166#if defined(NO_UNALIGN_64__UNION)
167 union { s8 ll; u4 parts[2]; } conv;
168
169 ptr += idx;
170 conv.ll = val;
171 ptr[0] = conv.parts[0];
172 ptr[1] = conv.parts[1];
173#else
174 memcpy(&ptr[idx], &val, 8);
175#endif
176}
177
178/* get a double from an array of u4 */
179static inline double getDoubleFromArray(const u4* ptr, int idx)
180{
181#if defined(NO_UNALIGN_64__UNION)
182 union { double d; u4 parts[2]; } conv;
183
184 ptr += idx;
185 conv.parts[0] = ptr[0];
186 conv.parts[1] = ptr[1];
187 return conv.d;
188#else
189 double dval;
190 memcpy(&dval, &ptr[idx], 8);
191 return dval;
192#endif
193}
194
195/* store a double into an array of u4 */
196static inline void putDoubleToArray(u4* ptr, int idx, double dval)
197{
198#if defined(NO_UNALIGN_64__UNION)
199 union { double d; u4 parts[2]; } conv;
200
201 ptr += idx;
202 conv.d = dval;
203 ptr[0] = conv.parts[0];
204 ptr[1] = conv.parts[1];
205#else
206 memcpy(&ptr[idx], &dval, 8);
207#endif
208}
209
210/*
211 * If enabled, validate the register number on every access. Otherwise,
212 * just do an array access.
213 *
214 * Assumes the existence of "u4* fp".
215 *
216 * "_idx" may be referenced more than once.
217 */
218#ifdef CHECK_REGISTER_INDICES
219# define GET_REGISTER(_idx) \
220 ( (_idx) < curMethod->registersSize ? \
221 (fp[(_idx)]) : (assert(!"bad reg"),1969) )
222# define SET_REGISTER(_idx, _val) \
223 ( (_idx) < curMethod->registersSize ? \
224 (fp[(_idx)] = (u4)(_val)) : (assert(!"bad reg"),1969) )
225# define GET_REGISTER_AS_OBJECT(_idx) ((Object *)GET_REGISTER(_idx))
226# define SET_REGISTER_AS_OBJECT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
227# define GET_REGISTER_INT(_idx) ((s4) GET_REGISTER(_idx))
228# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
229# define GET_REGISTER_WIDE(_idx) \
230 ( (_idx) < curMethod->registersSize-1 ? \
231 getLongFromArray(fp, (_idx)) : (assert(!"bad reg"),1969) )
232# define SET_REGISTER_WIDE(_idx, _val) \
233 ( (_idx) < curMethod->registersSize-1 ? \
234 putLongToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969) )
235# define GET_REGISTER_FLOAT(_idx) \
236 ( (_idx) < curMethod->registersSize ? \
237 (*((float*) &fp[(_idx)])) : (assert(!"bad reg"),1969.0f) )
238# define SET_REGISTER_FLOAT(_idx, _val) \
239 ( (_idx) < curMethod->registersSize ? \
240 (*((float*) &fp[(_idx)]) = (_val)) : (assert(!"bad reg"),1969.0f) )
241# define GET_REGISTER_DOUBLE(_idx) \
242 ( (_idx) < curMethod->registersSize-1 ? \
243 getDoubleFromArray(fp, (_idx)) : (assert(!"bad reg"),1969.0) )
244# define SET_REGISTER_DOUBLE(_idx, _val) \
245 ( (_idx) < curMethod->registersSize-1 ? \
246 putDoubleToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969.0) )
247#else
248# define GET_REGISTER(_idx) (fp[(_idx)])
249# define SET_REGISTER(_idx, _val) (fp[(_idx)] = (_val))
250# define GET_REGISTER_AS_OBJECT(_idx) ((Object*) fp[(_idx)])
251# define SET_REGISTER_AS_OBJECT(_idx, _val) (fp[(_idx)] = (u4)(_val))
252# define GET_REGISTER_INT(_idx) ((s4)GET_REGISTER(_idx))
253# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
254# define GET_REGISTER_WIDE(_idx) getLongFromArray(fp, (_idx))
255# define SET_REGISTER_WIDE(_idx, _val) putLongToArray(fp, (_idx), (_val))
256# define GET_REGISTER_FLOAT(_idx) (*((float*) &fp[(_idx)]))
257# define SET_REGISTER_FLOAT(_idx, _val) (*((float*) &fp[(_idx)]) = (_val))
258# define GET_REGISTER_DOUBLE(_idx) getDoubleFromArray(fp, (_idx))
259# define SET_REGISTER_DOUBLE(_idx, _val) putDoubleToArray(fp, (_idx), (_val))
260#endif
261
262/*
263 * Get 16 bits from the specified offset of the program counter. We always
264 * want to load 16 bits at a time from the instruction stream -- it's more
265 * efficient than 8 and won't have the alignment problems that 32 might.
266 *
267 * Assumes existence of "const u2* pc".
268 */
269#define FETCH(_offset) (pc[(_offset)])
270
271/*
272 * Extract instruction byte from 16-bit fetch (_inst is a u2).
273 */
274#define INST_INST(_inst) ((_inst) & 0xff)
275
276/*
277 * Replace the opcode (used when handling breakpoints). _opcode is a u1.
278 */
279#define INST_REPLACE_OP(_inst, _opcode) (((_inst) & 0xff00) | _opcode)
280
281/*
282 * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2).
283 */
284#define INST_A(_inst) (((_inst) >> 8) & 0x0f)
285#define INST_B(_inst) ((_inst) >> 12)
286
287/*
288 * Get the 8-bit "vAA" 8-bit register index from the instruction word.
289 * (_inst is u2)
290 */
291#define INST_AA(_inst) ((_inst) >> 8)
292
293/*
294 * The current PC must be available to Throwable constructors, e.g.
295 * those created by the various exception throw routines, so that the
296 * exception stack trace can be generated correctly. If we don't do this,
297 * the offset within the current method won't be shown correctly. See the
298 * notes in Exception.c.
299 *
300 * This is also used to determine the address for precise GC.
301 *
302 * Assumes existence of "u4* fp" and "const u2* pc".
303 */
304#define EXPORT_PC() (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
305
306/*
307 * Check to see if "obj" is NULL. If so, throw an exception. Assumes the
308 * pc has already been exported to the stack.
309 *
310 * Perform additional checks on debug builds.
311 *
312 * Use this to check for NULL when the instruction handler calls into
313 * something that could throw an exception (so we have already called
314 * EXPORT_PC at the top).
315 */
316static inline bool checkForNull(Object* obj)
317{
318 if (obj == NULL) {
319 dvmThrowNullPointerException(NULL);
320 return false;
321 }
322#ifdef WITH_EXTRA_OBJECT_VALIDATION
323 if (!dvmIsValidObject(obj)) {
324 LOGE("Invalid object %p\n", obj);
325 dvmAbort();
326 }
327#endif
328#ifndef NDEBUG
329 if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
330 /* probable heap corruption */
331 LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
332 dvmAbort();
333 }
334#endif
335 return true;
336}
337
338/*
339 * Check to see if "obj" is NULL. If so, export the PC into the stack
340 * frame and throw an exception.
341 *
342 * Perform additional checks on debug builds.
343 *
344 * Use this to check for NULL when the instruction handler doesn't do
345 * anything else that can throw an exception.
346 */
347static inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc)
348{
349 if (obj == NULL) {
350 EXPORT_PC();
351 dvmThrowNullPointerException(NULL);
352 return false;
353 }
354#ifdef WITH_EXTRA_OBJECT_VALIDATION
355 if (!dvmIsValidObject(obj)) {
356 LOGE("Invalid object %p\n", obj);
357 dvmAbort();
358 }
359#endif
360#ifndef NDEBUG
361 if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
362 /* probable heap corruption */
363 LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
364 dvmAbort();
365 }
366#endif
367 return true;
368}
369
370/* File: portable/stubdefs.cpp */
371/*
372 * In the C mterp stubs, "goto" is a function call followed immediately
373 * by a return.
374 */
375
376#define GOTO_TARGET_DECL(_target, ...)
377
378#define GOTO_TARGET(_target, ...) _target:
379
380#define GOTO_TARGET_END
381
382/* ugh */
383#define STUB_HACK(x)
384#define JIT_STUB_HACK(x)
385
386/*
387 * InterpSave's pc and fp must be valid when breaking out to a
388 * "Reportxxx" routine. Because the portable interpreter uses local
389 * variables for these, we must flush prior. Stubs, however, use
390 * the interpSave vars directly, so this is a nop for stubs.
391 */
392#define PC_FP_TO_SELF() \
393 self->interpSave.pc = pc; \
buzbee30bc0d42011-04-22 10:27:14 -0700394 self->interpSave.curFrame = fp;
395#define PC_TO_SELF() self->interpSave.pc = pc;
Carl Shapirocd8f5e72011-04-20 16:12:46 -0700396
397/*
398 * Instruction framing. For a switch-oriented implementation this is
399 * case/break, for a threaded implementation it's a goto label and an
400 * instruction fetch/computed goto.
401 *
402 * Assumes the existence of "const u2* pc" and (for threaded operation)
403 * "u2 inst".
404 */
405# define H(_op) &&op_##_op
406# define HANDLE_OPCODE(_op) op_##_op:
407# define FINISH(_offset) { \
408 ADJUST_PC(_offset); \
409 inst = FETCH(0); \
410 if (self->interpBreak.ctl.subMode) { \
411 dvmCheckBefore(pc, fp, self); \
412 } \
413 goto *handlerTable[INST_INST(inst)]; \
414 }
415# define FINISH_BKPT(_opcode) { \
416 goto *handlerTable[_opcode]; \
417 }
418# define DISPATCH_EXTENDED(_opcode) { \
419 goto *handlerTable[0x100 + _opcode]; \
420 }
421
422#define OP_END
423
424/*
425 * The "goto" targets just turn into goto statements. The "arguments" are
426 * passed through local variables.
427 */
428
429#define GOTO_exceptionThrown() goto exceptionThrown;
430
431#define GOTO_returnFromMethod() goto returnFromMethod;
432
433#define GOTO_invoke(_target, _methodCallRange, _jumboFormat) \
434 do { \
435 methodCallRange = _methodCallRange; \
436 jumboFormat = _jumboFormat; \
437 goto _target; \
438 } while(false)
439
440/* for this, the "args" are already in the locals */
441#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst) goto invokeMethod;
442
443#define GOTO_bail() goto bail;
444
445/*
446 * Periodically check for thread suspension.
447 *
448 * While we're at it, see if a debugger has attached or the profiler has
449 * started. If so, switch to a different "goto" table.
450 */
451#define PERIODIC_CHECKS(_pcadj) { \
452 if (dvmCheckSuspendQuick(self)) { \
453 EXPORT_PC(); /* need for precise GC */ \
454 dvmCheckSuspendPending(self); \
455 } \
456 }
457
458/* File: c/opcommon.cpp */
459/* forward declarations of goto targets */
460GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat);
461GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat);
462GOTO_TARGET_DECL(invokeSuper, bool methodCallRange, bool jumboFormat);
463GOTO_TARGET_DECL(invokeInterface, bool methodCallRange, bool jumboFormat);
464GOTO_TARGET_DECL(invokeDirect, bool methodCallRange, bool jumboFormat);
465GOTO_TARGET_DECL(invokeStatic, bool methodCallRange, bool jumboFormat);
466GOTO_TARGET_DECL(invokeVirtualQuick, bool methodCallRange, bool jumboFormat);
467GOTO_TARGET_DECL(invokeSuperQuick, bool methodCallRange, bool jumboFormat);
468GOTO_TARGET_DECL(invokeMethod, bool methodCallRange, const Method* methodToCall,
469 u2 count, u2 regs);
470GOTO_TARGET_DECL(returnFromMethod);
471GOTO_TARGET_DECL(exceptionThrown);
472
473/*
474 * ===========================================================================
475 *
476 * What follows are opcode definitions shared between multiple opcodes with
477 * minor substitutions handled by the C pre-processor. These should probably
478 * use the mterp substitution mechanism instead, with the code here moved
479 * into common fragment files (like the asm "binop.S"), although it's hard
480 * to give up the C preprocessor in favor of the much simpler text subst.
481 *
482 * ===========================================================================
483 */
484
485#define HANDLE_NUMCONV(_opcode, _opname, _fromtype, _totype) \
486 HANDLE_OPCODE(_opcode /*vA, vB*/) \
487 vdst = INST_A(inst); \
488 vsrc1 = INST_B(inst); \
489 ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
490 SET_REGISTER##_totype(vdst, \
491 GET_REGISTER##_fromtype(vsrc1)); \
492 FINISH(1);
493
494#define HANDLE_FLOAT_TO_INT(_opcode, _opname, _fromvtype, _fromrtype, \
495 _tovtype, _tortype) \
496 HANDLE_OPCODE(_opcode /*vA, vB*/) \
497 { \
498 /* spec defines specific handling for +/- inf and NaN values */ \
499 _fromvtype val; \
500 _tovtype intMin, intMax, result; \
501 vdst = INST_A(inst); \
502 vsrc1 = INST_B(inst); \
503 ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
504 val = GET_REGISTER##_fromrtype(vsrc1); \
505 intMin = (_tovtype) 1 << (sizeof(_tovtype) * 8 -1); \
506 intMax = ~intMin; \
507 result = (_tovtype) val; \
508 if (val >= intMax) /* +inf */ \
509 result = intMax; \
510 else if (val <= intMin) /* -inf */ \
511 result = intMin; \
512 else if (val != val) /* NaN */ \
513 result = 0; \
514 else \
515 result = (_tovtype) val; \
516 SET_REGISTER##_tortype(vdst, result); \
517 } \
518 FINISH(1);
519
520#define HANDLE_INT_TO_SMALL(_opcode, _opname, _type) \
521 HANDLE_OPCODE(_opcode /*vA, vB*/) \
522 vdst = INST_A(inst); \
523 vsrc1 = INST_B(inst); \
524 ILOGV("|int-to-%s v%d,v%d", (_opname), vdst, vsrc1); \
525 SET_REGISTER(vdst, (_type) GET_REGISTER(vsrc1)); \
526 FINISH(1);
527
528/* NOTE: the comparison result is always a signed 4-byte integer */
529#define HANDLE_OP_CMPX(_opcode, _opname, _varType, _type, _nanVal) \
530 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
531 { \
532 int result; \
533 u2 regs; \
534 _varType val1, val2; \
535 vdst = INST_AA(inst); \
536 regs = FETCH(1); \
537 vsrc1 = regs & 0xff; \
538 vsrc2 = regs >> 8; \
539 ILOGV("|cmp%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
540 val1 = GET_REGISTER##_type(vsrc1); \
541 val2 = GET_REGISTER##_type(vsrc2); \
542 if (val1 == val2) \
543 result = 0; \
544 else if (val1 < val2) \
545 result = -1; \
546 else if (val1 > val2) \
547 result = 1; \
548 else \
549 result = (_nanVal); \
550 ILOGV("+ result=%d\n", result); \
551 SET_REGISTER(vdst, result); \
552 } \
553 FINISH(2);
554
555#define HANDLE_OP_IF_XX(_opcode, _opname, _cmp) \
556 HANDLE_OPCODE(_opcode /*vA, vB, +CCCC*/) \
557 vsrc1 = INST_A(inst); \
558 vsrc2 = INST_B(inst); \
559 if ((s4) GET_REGISTER(vsrc1) _cmp (s4) GET_REGISTER(vsrc2)) { \
560 int branchOffset = (s2)FETCH(1); /* sign-extended */ \
561 ILOGV("|if-%s v%d,v%d,+0x%04x", (_opname), vsrc1, vsrc2, \
562 branchOffset); \
563 ILOGV("> branch taken"); \
564 if (branchOffset < 0) \
565 PERIODIC_CHECKS(branchOffset); \
566 FINISH(branchOffset); \
567 } else { \
568 ILOGV("|if-%s v%d,v%d,-", (_opname), vsrc1, vsrc2); \
569 FINISH(2); \
570 }
571
572#define HANDLE_OP_IF_XXZ(_opcode, _opname, _cmp) \
573 HANDLE_OPCODE(_opcode /*vAA, +BBBB*/) \
574 vsrc1 = INST_AA(inst); \
575 if ((s4) GET_REGISTER(vsrc1) _cmp 0) { \
576 int branchOffset = (s2)FETCH(1); /* sign-extended */ \
577 ILOGV("|if-%s v%d,+0x%04x", (_opname), vsrc1, branchOffset); \
578 ILOGV("> branch taken"); \
579 if (branchOffset < 0) \
580 PERIODIC_CHECKS(branchOffset); \
581 FINISH(branchOffset); \
582 } else { \
583 ILOGV("|if-%s v%d,-", (_opname), vsrc1); \
584 FINISH(2); \
585 }
586
587#define HANDLE_UNOP(_opcode, _opname, _pfx, _sfx, _type) \
588 HANDLE_OPCODE(_opcode /*vA, vB*/) \
589 vdst = INST_A(inst); \
590 vsrc1 = INST_B(inst); \
591 ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \
592 SET_REGISTER##_type(vdst, _pfx GET_REGISTER##_type(vsrc1) _sfx); \
593 FINISH(1);
594
595#define HANDLE_OP_X_INT(_opcode, _opname, _op, _chkdiv) \
596 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
597 { \
598 u2 srcRegs; \
599 vdst = INST_AA(inst); \
600 srcRegs = FETCH(1); \
601 vsrc1 = srcRegs & 0xff; \
602 vsrc2 = srcRegs >> 8; \
603 ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \
604 if (_chkdiv != 0) { \
605 s4 firstVal, secondVal, result; \
606 firstVal = GET_REGISTER(vsrc1); \
607 secondVal = GET_REGISTER(vsrc2); \
608 if (secondVal == 0) { \
609 EXPORT_PC(); \
610 dvmThrowArithmeticException("divide by zero"); \
611 GOTO_exceptionThrown(); \
612 } \
613 if ((u4)firstVal == 0x80000000 && secondVal == -1) { \
614 if (_chkdiv == 1) \
615 result = firstVal; /* division */ \
616 else \
617 result = 0; /* remainder */ \
618 } else { \
619 result = firstVal _op secondVal; \
620 } \
621 SET_REGISTER(vdst, result); \
622 } else { \
623 /* non-div/rem case */ \
624 SET_REGISTER(vdst, \
625 (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2)); \
626 } \
627 } \
628 FINISH(2);
629
630#define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op) \
631 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
632 { \
633 u2 srcRegs; \
634 vdst = INST_AA(inst); \
635 srcRegs = FETCH(1); \
636 vsrc1 = srcRegs & 0xff; \
637 vsrc2 = srcRegs >> 8; \
638 ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \
639 SET_REGISTER(vdst, \
640 _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f)); \
641 } \
642 FINISH(2);
643
644#define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv) \
645 HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/) \
646 vdst = INST_A(inst); \
647 vsrc1 = INST_B(inst); \
648 vsrc2 = FETCH(1); \
649 ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x", \
650 (_opname), vdst, vsrc1, vsrc2); \
651 if (_chkdiv != 0) { \
652 s4 firstVal, result; \
653 firstVal = GET_REGISTER(vsrc1); \
654 if ((s2) vsrc2 == 0) { \
655 EXPORT_PC(); \
656 dvmThrowArithmeticException("divide by zero"); \
657 GOTO_exceptionThrown(); \
658 } \
659 if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) { \
660 /* won't generate /lit16 instr for this; check anyway */ \
661 if (_chkdiv == 1) \
662 result = firstVal; /* division */ \
663 else \
664 result = 0; /* remainder */ \
665 } else { \
666 result = firstVal _op (s2) vsrc2; \
667 } \
668 SET_REGISTER(vdst, result); \
669 } else { \
670 /* non-div/rem case */ \
671 SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2); \
672 } \
673 FINISH(2);
674
675#define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv) \
676 HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \
677 { \
678 u2 litInfo; \
679 vdst = INST_AA(inst); \
680 litInfo = FETCH(1); \
681 vsrc1 = litInfo & 0xff; \
682 vsrc2 = litInfo >> 8; /* constant */ \
683 ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \
684 (_opname), vdst, vsrc1, vsrc2); \
685 if (_chkdiv != 0) { \
686 s4 firstVal, result; \
687 firstVal = GET_REGISTER(vsrc1); \
688 if ((s1) vsrc2 == 0) { \
689 EXPORT_PC(); \
690 dvmThrowArithmeticException("divide by zero"); \
691 GOTO_exceptionThrown(); \
692 } \
693 if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) { \
694 if (_chkdiv == 1) \
695 result = firstVal; /* division */ \
696 else \
697 result = 0; /* remainder */ \
698 } else { \
699 result = firstVal _op ((s1) vsrc2); \
700 } \
701 SET_REGISTER(vdst, result); \
702 } else { \
703 SET_REGISTER(vdst, \
704 (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2); \
705 } \
706 } \
707 FINISH(2);
708
709#define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op) \
710 HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \
711 { \
712 u2 litInfo; \
713 vdst = INST_AA(inst); \
714 litInfo = FETCH(1); \
715 vsrc1 = litInfo & 0xff; \
716 vsrc2 = litInfo >> 8; /* constant */ \
717 ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \
718 (_opname), vdst, vsrc1, vsrc2); \
719 SET_REGISTER(vdst, \
720 _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f)); \
721 } \
722 FINISH(2);
723
724#define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv) \
725 HANDLE_OPCODE(_opcode /*vA, vB*/) \
726 vdst = INST_A(inst); \
727 vsrc1 = INST_B(inst); \
728 ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \
729 if (_chkdiv != 0) { \
730 s4 firstVal, secondVal, result; \
731 firstVal = GET_REGISTER(vdst); \
732 secondVal = GET_REGISTER(vsrc1); \
733 if (secondVal == 0) { \
734 EXPORT_PC(); \
735 dvmThrowArithmeticException("divide by zero"); \
736 GOTO_exceptionThrown(); \
737 } \
738 if ((u4)firstVal == 0x80000000 && secondVal == -1) { \
739 if (_chkdiv == 1) \
740 result = firstVal; /* division */ \
741 else \
742 result = 0; /* remainder */ \
743 } else { \
744 result = firstVal _op secondVal; \
745 } \
746 SET_REGISTER(vdst, result); \
747 } else { \
748 SET_REGISTER(vdst, \
749 (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1)); \
750 } \
751 FINISH(1);
752
753#define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op) \
754 HANDLE_OPCODE(_opcode /*vA, vB*/) \
755 vdst = INST_A(inst); \
756 vsrc1 = INST_B(inst); \
757 ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \
758 SET_REGISTER(vdst, \
759 _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f)); \
760 FINISH(1);
761
762#define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv) \
763 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
764 { \
765 u2 srcRegs; \
766 vdst = INST_AA(inst); \
767 srcRegs = FETCH(1); \
768 vsrc1 = srcRegs & 0xff; \
769 vsrc2 = srcRegs >> 8; \
770 ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
771 if (_chkdiv != 0) { \
772 s8 firstVal, secondVal, result; \
773 firstVal = GET_REGISTER_WIDE(vsrc1); \
774 secondVal = GET_REGISTER_WIDE(vsrc2); \
775 if (secondVal == 0LL) { \
776 EXPORT_PC(); \
777 dvmThrowArithmeticException("divide by zero"); \
778 GOTO_exceptionThrown(); \
779 } \
780 if ((u8)firstVal == 0x8000000000000000ULL && \
781 secondVal == -1LL) \
782 { \
783 if (_chkdiv == 1) \
784 result = firstVal; /* division */ \
785 else \
786 result = 0; /* remainder */ \
787 } else { \
788 result = firstVal _op secondVal; \
789 } \
790 SET_REGISTER_WIDE(vdst, result); \
791 } else { \
792 SET_REGISTER_WIDE(vdst, \
793 (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \
794 } \
795 } \
796 FINISH(2);
797
798#define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op) \
799 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
800 { \
801 u2 srcRegs; \
802 vdst = INST_AA(inst); \
803 srcRegs = FETCH(1); \
804 vsrc1 = srcRegs & 0xff; \
805 vsrc2 = srcRegs >> 8; \
806 ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
807 SET_REGISTER_WIDE(vdst, \
808 _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \
809 } \
810 FINISH(2);
811
812#define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv) \
813 HANDLE_OPCODE(_opcode /*vA, vB*/) \
814 vdst = INST_A(inst); \
815 vsrc1 = INST_B(inst); \
816 ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \
817 if (_chkdiv != 0) { \
818 s8 firstVal, secondVal, result; \
819 firstVal = GET_REGISTER_WIDE(vdst); \
820 secondVal = GET_REGISTER_WIDE(vsrc1); \
821 if (secondVal == 0LL) { \
822 EXPORT_PC(); \
823 dvmThrowArithmeticException("divide by zero"); \
824 GOTO_exceptionThrown(); \
825 } \
826 if ((u8)firstVal == 0x8000000000000000ULL && \
827 secondVal == -1LL) \
828 { \
829 if (_chkdiv == 1) \
830 result = firstVal; /* division */ \
831 else \
832 result = 0; /* remainder */ \
833 } else { \
834 result = firstVal _op secondVal; \
835 } \
836 SET_REGISTER_WIDE(vdst, result); \
837 } else { \
838 SET_REGISTER_WIDE(vdst, \
839 (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\
840 } \
841 FINISH(1);
842
843#define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op) \
844 HANDLE_OPCODE(_opcode /*vA, vB*/) \
845 vdst = INST_A(inst); \
846 vsrc1 = INST_B(inst); \
847 ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \
848 SET_REGISTER_WIDE(vdst, \
849 _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \
850 FINISH(1);
851
852#define HANDLE_OP_X_FLOAT(_opcode, _opname, _op) \
853 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
854 { \
855 u2 srcRegs; \
856 vdst = INST_AA(inst); \
857 srcRegs = FETCH(1); \
858 vsrc1 = srcRegs & 0xff; \
859 vsrc2 = srcRegs >> 8; \
860 ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
861 SET_REGISTER_FLOAT(vdst, \
862 GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2)); \
863 } \
864 FINISH(2);
865
866#define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op) \
867 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
868 { \
869 u2 srcRegs; \
870 vdst = INST_AA(inst); \
871 srcRegs = FETCH(1); \
872 vsrc1 = srcRegs & 0xff; \
873 vsrc2 = srcRegs >> 8; \
874 ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
875 SET_REGISTER_DOUBLE(vdst, \
876 GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2)); \
877 } \
878 FINISH(2);
879
880#define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op) \
881 HANDLE_OPCODE(_opcode /*vA, vB*/) \
882 vdst = INST_A(inst); \
883 vsrc1 = INST_B(inst); \
884 ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1); \
885 SET_REGISTER_FLOAT(vdst, \
886 GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1)); \
887 FINISH(1);
888
889#define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op) \
890 HANDLE_OPCODE(_opcode /*vA, vB*/) \
891 vdst = INST_A(inst); \
892 vsrc1 = INST_B(inst); \
893 ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1); \
894 SET_REGISTER_DOUBLE(vdst, \
895 GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1)); \
896 FINISH(1);
897
898#define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize) \
899 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
900 { \
901 ArrayObject* arrayObj; \
902 u2 arrayInfo; \
903 EXPORT_PC(); \
904 vdst = INST_AA(inst); \
905 arrayInfo = FETCH(1); \
906 vsrc1 = arrayInfo & 0xff; /* array ptr */ \
907 vsrc2 = arrayInfo >> 8; /* index */ \
908 ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
909 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \
910 if (!checkForNull((Object*) arrayObj)) \
911 GOTO_exceptionThrown(); \
912 if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
913 dvmThrowArrayIndexOutOfBoundsException( \
914 arrayObj->length, GET_REGISTER(vsrc2)); \
915 GOTO_exceptionThrown(); \
916 } \
917 SET_REGISTER##_regsize(vdst, \
918 ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]); \
919 ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \
920 } \
921 FINISH(2);
922
923#define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize) \
924 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \
925 { \
926 ArrayObject* arrayObj; \
927 u2 arrayInfo; \
928 EXPORT_PC(); \
929 vdst = INST_AA(inst); /* AA: source value */ \
930 arrayInfo = FETCH(1); \
931 vsrc1 = arrayInfo & 0xff; /* BB: array ptr */ \
932 vsrc2 = arrayInfo >> 8; /* CC: index */ \
933 ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \
934 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \
935 if (!checkForNull((Object*) arrayObj)) \
936 GOTO_exceptionThrown(); \
937 if (GET_REGISTER(vsrc2) >= arrayObj->length) { \
938 dvmThrowArrayIndexOutOfBoundsException( \
939 arrayObj->length, GET_REGISTER(vsrc2)); \
940 GOTO_exceptionThrown(); \
941 } \
942 ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
943 ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] = \
944 GET_REGISTER##_regsize(vdst); \
945 } \
946 FINISH(2);
947
948/*
949 * It's possible to get a bad value out of a field with sub-32-bit stores
950 * because the -quick versions always operate on 32 bits. Consider:
951 * short foo = -1 (sets a 32-bit register to 0xffffffff)
952 * iput-quick foo (writes all 32 bits to the field)
953 * short bar = 1 (sets a 32-bit register to 0x00000001)
954 * iput-short (writes the low 16 bits to the field)
955 * iget-quick foo (reads all 32 bits from the field, yielding 0xffff0001)
956 * This can only happen when optimized and non-optimized code has interleaved
957 * access to the same field. This is unlikely but possible.
958 *
959 * The easiest way to fix this is to always read/write 32 bits at a time. On
960 * a device with a 16-bit data bus this is sub-optimal. (The alternative
961 * approach is to have sub-int versions of iget-quick, but now we're wasting
962 * Dalvik instruction space and making it less likely that handler code will
963 * already be in the CPU i-cache.)
964 */
965#define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize) \
966 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
967 { \
968 InstField* ifield; \
969 Object* obj; \
970 EXPORT_PC(); \
971 vdst = INST_A(inst); \
972 vsrc1 = INST_B(inst); /* object ptr */ \
973 ref = FETCH(1); /* field ref */ \
974 ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
975 obj = (Object*) GET_REGISTER(vsrc1); \
976 if (!checkForNull(obj)) \
977 GOTO_exceptionThrown(); \
978 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
979 if (ifield == NULL) { \
980 ifield = dvmResolveInstField(curMethod->clazz, ref); \
981 if (ifield == NULL) \
982 GOTO_exceptionThrown(); \
983 } \
984 SET_REGISTER##_regsize(vdst, \
985 dvmGetField##_ftype(obj, ifield->byteOffset)); \
986 ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
987 (u8) GET_REGISTER##_regsize(vdst)); \
Carl Shapirocd8f5e72011-04-20 16:12:46 -0700988 } \
989 FINISH(2);
990
991#define HANDLE_IGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
992 HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \
993 { \
994 InstField* ifield; \
995 Object* obj; \
996 EXPORT_PC(); \
997 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
998 vdst = FETCH(3); \
999 vsrc1 = FETCH(4); /* object ptr */ \
1000 ILOGV("|iget%s/jumbo v%d,v%d,field@0x%08x", \
1001 (_opname), vdst, vsrc1, ref); \
1002 obj = (Object*) GET_REGISTER(vsrc1); \
1003 if (!checkForNull(obj)) \
1004 GOTO_exceptionThrown(); \
1005 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
1006 if (ifield == NULL) { \
1007 ifield = dvmResolveInstField(curMethod->clazz, ref); \
1008 if (ifield == NULL) \
1009 GOTO_exceptionThrown(); \
1010 } \
1011 SET_REGISTER##_regsize(vdst, \
1012 dvmGetField##_ftype(obj, ifield->byteOffset)); \
1013 ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name, \
1014 (u8) GET_REGISTER##_regsize(vdst)); \
Carl Shapirocd8f5e72011-04-20 16:12:46 -07001015 } \
1016 FINISH(5);
1017
1018#define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize) \
1019 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
1020 { \
1021 Object* obj; \
1022 vdst = INST_A(inst); \
1023 vsrc1 = INST_B(inst); /* object ptr */ \
1024 ref = FETCH(1); /* field offset */ \
1025 ILOGV("|iget%s-quick v%d,v%d,field@+%u", \
1026 (_opname), vdst, vsrc1, ref); \
1027 obj = (Object*) GET_REGISTER(vsrc1); \
1028 if (!checkForNullExportPC(obj, fp, pc)) \
1029 GOTO_exceptionThrown(); \
1030 SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref)); \
1031 ILOGV("+ IGETQ %d=0x%08llx", ref, \
1032 (u8) GET_REGISTER##_regsize(vdst)); \
1033 } \
1034 FINISH(2);
1035
1036#define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize) \
1037 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
1038 { \
1039 InstField* ifield; \
1040 Object* obj; \
1041 EXPORT_PC(); \
1042 vdst = INST_A(inst); \
1043 vsrc1 = INST_B(inst); /* object ptr */ \
1044 ref = FETCH(1); /* field ref */ \
1045 ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
1046 obj = (Object*) GET_REGISTER(vsrc1); \
1047 if (!checkForNull(obj)) \
1048 GOTO_exceptionThrown(); \
1049 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
1050 if (ifield == NULL) { \
1051 ifield = dvmResolveInstField(curMethod->clazz, ref); \
1052 if (ifield == NULL) \
1053 GOTO_exceptionThrown(); \
1054 } \
1055 dvmSetField##_ftype(obj, ifield->byteOffset, \
1056 GET_REGISTER##_regsize(vdst)); \
1057 ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
1058 (u8) GET_REGISTER##_regsize(vdst)); \
Carl Shapirocd8f5e72011-04-20 16:12:46 -07001059 } \
1060 FINISH(2);
1061
1062#define HANDLE_IPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
1063 HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \
1064 { \
1065 InstField* ifield; \
1066 Object* obj; \
1067 EXPORT_PC(); \
1068 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
1069 vdst = FETCH(3); \
1070 vsrc1 = FETCH(4); /* object ptr */ \
1071 ILOGV("|iput%s/jumbo v%d,v%d,field@0x%08x", \
1072 (_opname), vdst, vsrc1, ref); \
1073 obj = (Object*) GET_REGISTER(vsrc1); \
1074 if (!checkForNull(obj)) \
1075 GOTO_exceptionThrown(); \
1076 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \
1077 if (ifield == NULL) { \
1078 ifield = dvmResolveInstField(curMethod->clazz, ref); \
1079 if (ifield == NULL) \
1080 GOTO_exceptionThrown(); \
1081 } \
1082 dvmSetField##_ftype(obj, ifield->byteOffset, \
1083 GET_REGISTER##_regsize(vdst)); \
1084 ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name, \
1085 (u8) GET_REGISTER##_regsize(vdst)); \
Carl Shapirocd8f5e72011-04-20 16:12:46 -07001086 } \
1087 FINISH(5);
1088
1089#define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize) \
1090 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \
1091 { \
1092 Object* obj; \
1093 vdst = INST_A(inst); \
1094 vsrc1 = INST_B(inst); /* object ptr */ \
1095 ref = FETCH(1); /* field offset */ \
1096 ILOGV("|iput%s-quick v%d,v%d,field@0x%04x", \
1097 (_opname), vdst, vsrc1, ref); \
1098 obj = (Object*) GET_REGISTER(vsrc1); \
1099 if (!checkForNullExportPC(obj, fp, pc)) \
1100 GOTO_exceptionThrown(); \
1101 dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst)); \
1102 ILOGV("+ IPUTQ %d=0x%08llx", ref, \
1103 (u8) GET_REGISTER##_regsize(vdst)); \
1104 } \
1105 FINISH(2);
1106
1107/*
1108 * The JIT needs dvmDexGetResolvedField() to return non-null.
1109 * Because the portable interpreter is not involved with the JIT
1110 * and trace building, we only need the extra check here when this
1111 * code is massaged into a stub called from an assembly interpreter.
1112 * This is controlled by the JIT_STUB_HACK maco.
1113 */
1114
1115#define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize) \
1116 HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \
1117 { \
1118 StaticField* sfield; \
1119 vdst = INST_AA(inst); \
1120 ref = FETCH(1); /* field ref */ \
1121 ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref); \
1122 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
1123 if (sfield == NULL) { \
1124 EXPORT_PC(); \
1125 sfield = dvmResolveStaticField(curMethod->clazz, ref); \
1126 if (sfield == NULL) \
1127 GOTO_exceptionThrown(); \
1128 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
1129 JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
1130 } \
1131 } \
1132 SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
1133 ILOGV("+ SGET '%s'=0x%08llx", \
1134 sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
Carl Shapirocd8f5e72011-04-20 16:12:46 -07001135 } \
1136 FINISH(2);
1137
1138#define HANDLE_SGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
1139 HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \
1140 { \
1141 StaticField* sfield; \
1142 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
1143 vdst = FETCH(3); \
1144 ILOGV("|sget%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \
1145 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
1146 if (sfield == NULL) { \
1147 EXPORT_PC(); \
1148 sfield = dvmResolveStaticField(curMethod->clazz, ref); \
1149 if (sfield == NULL) \
1150 GOTO_exceptionThrown(); \
1151 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
1152 JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
1153 } \
1154 } \
1155 SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \
1156 ILOGV("+ SGET '%s'=0x%08llx", \
1157 sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
Carl Shapirocd8f5e72011-04-20 16:12:46 -07001158 } \
1159 FINISH(4);
1160
1161#define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize) \
1162 HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \
1163 { \
1164 StaticField* sfield; \
1165 vdst = INST_AA(inst); \
1166 ref = FETCH(1); /* field ref */ \
1167 ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref); \
1168 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
1169 if (sfield == NULL) { \
1170 EXPORT_PC(); \
1171 sfield = dvmResolveStaticField(curMethod->clazz, ref); \
1172 if (sfield == NULL) \
1173 GOTO_exceptionThrown(); \
1174 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
1175 JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
1176 } \
1177 } \
1178 dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
1179 ILOGV("+ SPUT '%s'=0x%08llx", \
1180 sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
Carl Shapirocd8f5e72011-04-20 16:12:46 -07001181 } \
1182 FINISH(2);
1183
1184#define HANDLE_SPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \
1185 HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \
1186 { \
1187 StaticField* sfield; \
1188 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \
1189 vdst = FETCH(3); \
1190 ILOGV("|sput%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \
1191 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
1192 if (sfield == NULL) { \
1193 EXPORT_PC(); \
1194 sfield = dvmResolveStaticField(curMethod->clazz, ref); \
1195 if (sfield == NULL) \
1196 GOTO_exceptionThrown(); \
1197 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \
1198 JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \
1199 } \
1200 } \
1201 dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \
1202 ILOGV("+ SPUT '%s'=0x%08llx", \
1203 sfield->field.name, (u8)GET_REGISTER##_regsize(vdst)); \
Carl Shapirocd8f5e72011-04-20 16:12:46 -07001204 } \
1205 FINISH(4);
1206
1207/* File: portable/entry.cpp */
1208/*
1209 * Main interpreter loop.
1210 *
1211 * This was written with an ARM implementation in mind.
1212 */
1213void dvmInterpretPortable(Thread* self)
1214{
1215#if defined(EASY_GDB)
buzbee30bc0d42011-04-22 10:27:14 -07001216 StackSaveArea* debugSaveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame);
Carl Shapirocd8f5e72011-04-20 16:12:46 -07001217#endif
1218#if defined(WITH_TRACKREF_CHECKS)
1219 int debugTrackedRefStart = self->interpSave.debugTrackedRefStart;
1220#endif
1221 DvmDex* methodClassDex; // curMethod->clazz->pDvmDex
1222 JValue retval;
1223
1224 /* core state */
1225 const Method* curMethod; // method we're interpreting
1226 const u2* pc; // program counter
1227 u4* fp; // frame pointer
1228 u2 inst; // current instruction
1229 /* instruction decoding */
1230 u4 ref; // 16 or 32-bit quantity fetched directly
1231 u2 vsrc1, vsrc2, vdst; // usually used for register indexes
1232 /* method call setup */
1233 const Method* methodToCall;
1234 bool methodCallRange;
1235 bool jumboFormat;
1236
1237
1238 /* static computed goto table */
1239 DEFINE_GOTO_TABLE(handlerTable);
1240
1241 /* copy state in */
1242 curMethod = self->interpSave.method;
1243 pc = self->interpSave.pc;
buzbee30bc0d42011-04-22 10:27:14 -07001244 fp = self->interpSave.curFrame;
buzbeecf4a20c2011-05-25 14:21:14 -07001245 retval = self->interpSave.retval; /* only need for kInterpEntryReturn? */
Carl Shapirocd8f5e72011-04-20 16:12:46 -07001246
1247 methodClassDex = curMethod->clazz->pDvmDex;
1248
1249 LOGVV("threadid=%d: %s.%s pc=0x%x fp=%p\n",
1250 self->threadId, curMethod->clazz->descriptor, curMethod->name,
1251 pc - curMethod->insns, fp);
1252
1253 /*
1254 * Handle any ongoing profiling and prep for debugging.
1255 */
1256 if (self->interpBreak.ctl.subMode != 0) {
1257 TRACE_METHOD_ENTER(self, curMethod);
1258 self->debugIsMethodEntry = true; // Always true on startup
1259 }
1260 /*
1261 * DEBUG: scramble this to ensure we're not relying on it.
1262 */
1263 methodToCall = (const Method*) -1;
1264
1265#if 0
1266 if (self->debugIsMethodEntry) {
1267 ILOGD("|-- Now interpreting %s.%s", curMethod->clazz->descriptor,
1268 curMethod->name);
buzbee30bc0d42011-04-22 10:27:14 -07001269 DUMP_REGS(curMethod, self->interpSave.curFrame, false);
Carl Shapirocd8f5e72011-04-20 16:12:46 -07001270 }
1271#endif
1272
1273 FINISH(0); /* fetch and execute first instruction */
1274
1275/*--- start of opcodes ---*/
1276
1277/* File: c/OP_NOP.cpp */
1278HANDLE_OPCODE(OP_NOP)
1279 FINISH(1);
1280OP_END
1281
1282/* File: c/OP_MOVE.cpp */
1283HANDLE_OPCODE(OP_MOVE /*vA, vB*/)
1284 vdst = INST_A(inst);
1285 vsrc1 = INST_B(inst);
1286 ILOGV("|move%s v%d,v%d %s(v%d=0x%08x)",
1287 (INST_INST(inst) == OP_MOVE) ? "" : "-object", vdst, vsrc1,
1288 kSpacing, vdst, GET_REGISTER(vsrc1));
1289 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1290 FINISH(1);
1291OP_END
1292
1293/* File: c/OP_MOVE_FROM16.cpp */
1294HANDLE_OPCODE(OP_MOVE_FROM16 /*vAA, vBBBB*/)
1295 vdst = INST_AA(inst);
1296 vsrc1 = FETCH(1);
1297 ILOGV("|move%s/from16 v%d,v%d %s(v%d=0x%08x)",
1298 (INST_INST(inst) == OP_MOVE_FROM16) ? "" : "-object", vdst, vsrc1,
1299 kSpacing, vdst, GET_REGISTER(vsrc1));
1300 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1301 FINISH(2);
1302OP_END
1303
1304/* File: c/OP_MOVE_16.cpp */
1305HANDLE_OPCODE(OP_MOVE_16 /*vAAAA, vBBBB*/)
1306 vdst = FETCH(1);
1307 vsrc1 = FETCH(2);
1308 ILOGV("|move%s/16 v%d,v%d %s(v%d=0x%08x)",
1309 (INST_INST(inst) == OP_MOVE_16) ? "" : "-object", vdst, vsrc1,
1310 kSpacing, vdst, GET_REGISTER(vsrc1));
1311 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1312 FINISH(3);
1313OP_END
1314
1315/* File: c/OP_MOVE_WIDE.cpp */
1316HANDLE_OPCODE(OP_MOVE_WIDE /*vA, vB*/)
1317 /* IMPORTANT: must correctly handle overlapping registers, e.g. both
1318 * "move-wide v6, v7" and "move-wide v7, v6" */
1319 vdst = INST_A(inst);
1320 vsrc1 = INST_B(inst);
1321 ILOGV("|move-wide v%d,v%d %s(v%d=0x%08llx)", vdst, vsrc1,
1322 kSpacing+5, vdst, GET_REGISTER_WIDE(vsrc1));
1323 SET_REGISTER_WIDE(vdst, GET_REGISTER_WIDE(vsrc1));
1324 FINISH(1);
1325OP_END
1326
1327/* File: c/OP_MOVE_WIDE_FROM16.cpp */
1328HANDLE_OPCODE(OP_MOVE_WIDE_FROM16 /*vAA, vBBBB*/)
1329 vdst = INST_AA(inst);
1330 vsrc1 = FETCH(1);
1331 ILOGV("|move-wide/from16 v%d,v%d (v%d=0x%08llx)", vdst, vsrc1,
1332 vdst, GET_REGISTER_WIDE(vsrc1));
1333 SET_REGISTER_WIDE(vdst, GET_REGISTER_WIDE(vsrc1));
1334 FINISH(2);
1335OP_END
1336
1337/* File: c/OP_MOVE_WIDE_16.cpp */
1338HANDLE_OPCODE(OP_MOVE_WIDE_16 /*vAAAA, vBBBB*/)
1339 vdst = FETCH(1);
1340 vsrc1 = FETCH(2);
1341 ILOGV("|move-wide/16 v%d,v%d %s(v%d=0x%08llx)", vdst, vsrc1,
1342 kSpacing+8, vdst, GET_REGISTER_WIDE(vsrc1));
1343 SET_REGISTER_WIDE(vdst, GET_REGISTER_WIDE(vsrc1));
1344 FINISH(3);
1345OP_END
1346
1347/* File: c/OP_MOVE_OBJECT.cpp */
1348/* File: c/OP_MOVE.cpp */
1349HANDLE_OPCODE(OP_MOVE_OBJECT /*vA, vB*/)
1350 vdst = INST_A(inst);
1351 vsrc1 = INST_B(inst);
1352 ILOGV("|move%s v%d,v%d %s(v%d=0x%08x)",
1353 (INST_INST(inst) == OP_MOVE) ? "" : "-object", vdst, vsrc1,
1354 kSpacing, vdst, GET_REGISTER(vsrc1));
1355 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1356 FINISH(1);
1357OP_END
1358
1359
1360/* File: c/OP_MOVE_OBJECT_FROM16.cpp */
1361/* File: c/OP_MOVE_FROM16.cpp */
1362HANDLE_OPCODE(OP_MOVE_OBJECT_FROM16 /*vAA, vBBBB*/)
1363 vdst = INST_AA(inst);
1364 vsrc1 = FETCH(1);
1365 ILOGV("|move%s/from16 v%d,v%d %s(v%d=0x%08x)",
1366 (INST_INST(inst) == OP_MOVE_FROM16) ? "" : "-object", vdst, vsrc1,
1367 kSpacing, vdst, GET_REGISTER(vsrc1));
1368 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1369 FINISH(2);
1370OP_END
1371
1372
1373/* File: c/OP_MOVE_OBJECT_16.cpp */
1374/* File: c/OP_MOVE_16.cpp */
1375HANDLE_OPCODE(OP_MOVE_OBJECT_16 /*vAAAA, vBBBB*/)
1376 vdst = FETCH(1);
1377 vsrc1 = FETCH(2);
1378 ILOGV("|move%s/16 v%d,v%d %s(v%d=0x%08x)",
1379 (INST_INST(inst) == OP_MOVE_16) ? "" : "-object", vdst, vsrc1,
1380 kSpacing, vdst, GET_REGISTER(vsrc1));
1381 SET_REGISTER(vdst, GET_REGISTER(vsrc1));
1382 FINISH(3);
1383OP_END
1384
1385
1386/* File: c/OP_MOVE_RESULT.cpp */
1387HANDLE_OPCODE(OP_MOVE_RESULT /*vAA*/)
1388 vdst = INST_AA(inst);
1389 ILOGV("|move-result%s v%d %s(v%d=0x%08x)",
1390 (INST_INST(inst) == OP_MOVE_RESULT) ? "" : "-object",
1391 vdst, kSpacing+4, vdst,retval.i);
1392 SET_REGISTER(vdst, retval.i);
1393 FINISH(1);
1394OP_END
1395
1396/* File: c/OP_MOVE_RESULT_WIDE.cpp */
1397HANDLE_OPCODE(OP_MOVE_RESULT_WIDE /*vAA*/)
1398 vdst = INST_AA(inst);
1399 ILOGV("|move-result-wide v%d %s(0x%08llx)", vdst, kSpacing, retval.j);
1400 SET_REGISTER_WIDE(vdst, retval.j);
1401 FINISH(1);
1402OP_END
1403
1404/* File: c/OP_MOVE_RESULT_OBJECT.cpp */
1405/* File: c/OP_MOVE_RESULT.cpp */
1406HANDLE_OPCODE(OP_MOVE_RESULT_OBJECT /*vAA*/)
1407 vdst = INST_AA(inst);
1408 ILOGV("|move-result%s v%d %s(v%d=0x%08x)",
1409 (INST_INST(inst) == OP_MOVE_RESULT) ? "" : "-object",
1410 vdst, kSpacing+4, vdst,retval.i);
1411 SET_REGISTER(vdst, retval.i);
1412 FINISH(1);
1413OP_END
1414
1415
1416/* File: c/OP_MOVE_EXCEPTION.cpp */
1417HANDLE_OPCODE(OP_MOVE_EXCEPTION /*vAA*/)
1418 vdst = INST_AA(inst);
1419 ILOGV("|move-exception v%d", vdst);
1420 assert(self->exception != NULL);
1421 SET_REGISTER(vdst, (u4)self->exception);
1422 dvmClearException(self);
1423 FINISH(1);
1424OP_END
1425
1426/* File: c/OP_RETURN_VOID.cpp */
1427HANDLE_OPCODE(OP_RETURN_VOID /**/)
1428 ILOGV("|return-void");
1429#ifndef NDEBUG
1430 retval.j = 0xababababULL; // placate valgrind
1431#endif
1432 GOTO_returnFromMethod();
1433OP_END
1434
1435/* File: c/OP_RETURN.cpp */
1436HANDLE_OPCODE(OP_RETURN /*vAA*/)
1437 vsrc1 = INST_AA(inst);
1438 ILOGV("|return%s v%d",
1439 (INST_INST(inst) == OP_RETURN) ? "" : "-object", vsrc1);
1440 retval.i = GET_REGISTER(vsrc1);
1441 GOTO_returnFromMethod();
1442OP_END
1443
1444/* File: c/OP_RETURN_WIDE.cpp */
1445HANDLE_OPCODE(OP_RETURN_WIDE /*vAA*/)
1446 vsrc1 = INST_AA(inst);
1447 ILOGV("|return-wide v%d", vsrc1);
1448 retval.j = GET_REGISTER_WIDE(vsrc1);
1449 GOTO_returnFromMethod();
1450OP_END
1451
1452/* File: c/OP_RETURN_OBJECT.cpp */
1453/* File: c/OP_RETURN.cpp */
1454HANDLE_OPCODE(OP_RETURN_OBJECT /*vAA*/)
1455 vsrc1 = INST_AA(inst);
1456 ILOGV("|return%s v%d",
1457 (INST_INST(inst) == OP_RETURN) ? "" : "-object", vsrc1);
1458 retval.i = GET_REGISTER(vsrc1);
1459 GOTO_returnFromMethod();
1460OP_END
1461
1462
1463/* File: c/OP_CONST_4.cpp */
1464HANDLE_OPCODE(OP_CONST_4 /*vA, #+B*/)
1465 {
1466 s4 tmp;
1467
1468 vdst = INST_A(inst);
1469 tmp = (s4) (INST_B(inst) << 28) >> 28; // sign extend 4-bit value
1470 ILOGV("|const/4 v%d,#0x%02x", vdst, (s4)tmp);
1471 SET_REGISTER(vdst, tmp);
1472 }
1473 FINISH(1);
1474OP_END
1475
1476/* File: c/OP_CONST_16.cpp */
1477HANDLE_OPCODE(OP_CONST_16 /*vAA, #+BBBB*/)
1478 vdst = INST_AA(inst);
1479 vsrc1 = FETCH(1);
1480 ILOGV("|const/16 v%d,#0x%04x", vdst, (s2)vsrc1);
1481 SET_REGISTER(vdst, (s2) vsrc1);
1482 FINISH(2);
1483OP_END
1484
1485/* File: c/OP_CONST.cpp */
1486HANDLE_OPCODE(OP_CONST /*vAA, #+BBBBBBBB*/)
1487 {
1488 u4 tmp;
1489
1490 vdst = INST_AA(inst);
1491 tmp = FETCH(1);
1492 tmp |= (u4)FETCH(2) << 16;
1493 ILOGV("|const v%d,#0x%08x", vdst, tmp);
1494 SET_REGISTER(vdst, tmp);
1495 }
1496 FINISH(3);
1497OP_END
1498
1499/* File: c/OP_CONST_HIGH16.cpp */
1500HANDLE_OPCODE(OP_CONST_HIGH16 /*vAA, #+BBBB0000*/)
1501 vdst = INST_AA(inst);
1502 vsrc1 = FETCH(1);
1503 ILOGV("|const/high16 v%d,#0x%04x0000", vdst, vsrc1);
1504 SET_REGISTER(vdst, vsrc1 << 16);
1505 FINISH(2);
1506OP_END
1507
1508/* File: c/OP_CONST_WIDE_16.cpp */
1509HANDLE_OPCODE(OP_CONST_WIDE_16 /*vAA, #+BBBB*/)
1510 vdst = INST_AA(inst);
1511 vsrc1 = FETCH(1);
1512 ILOGV("|const-wide/16 v%d,#0x%04x", vdst, (s2)vsrc1);
1513 SET_REGISTER_WIDE(vdst, (s2)vsrc1);
1514 FINISH(2);
1515OP_END
1516
1517/* File: c/OP_CONST_WIDE_32.cpp */
1518HANDLE_OPCODE(OP_CONST_WIDE_32 /*vAA, #+BBBBBBBB*/)
1519 {
1520 u4 tmp;
1521
1522 vdst = INST_AA(inst);
1523 tmp = FETCH(1);
1524 tmp |= (u4)FETCH(2) << 16;
1525 ILOGV("|const-wide/32 v%d,#0x%08x", vdst, tmp);
1526 SET_REGISTER_WIDE(vdst, (s4) tmp);
1527 }
1528 FINISH(3);
1529OP_END
1530
1531/* File: c/OP_CONST_WIDE.cpp */
1532HANDLE_OPCODE(OP_CONST_WIDE /*vAA, #+BBBBBBBBBBBBBBBB*/)
1533 {
1534 u8 tmp;
1535
1536 vdst = INST_AA(inst);
1537 tmp = FETCH(1);
1538 tmp |= (u8)FETCH(2) << 16;
1539 tmp |= (u8)FETCH(3) << 32;
1540 tmp |= (u8)FETCH(4) << 48;
1541 ILOGV("|const-wide v%d,#0x%08llx", vdst, tmp);
1542 SET_REGISTER_WIDE(vdst, tmp);
1543 }
1544 FINISH(5);
1545OP_END
1546
1547/* File: c/OP_CONST_WIDE_HIGH16.cpp */
1548HANDLE_OPCODE(OP_CONST_WIDE_HIGH16 /*vAA, #+BBBB000000000000*/)
1549 vdst = INST_AA(inst);
1550 vsrc1 = FETCH(1);
1551 ILOGV("|const-wide/high16 v%d,#0x%04x000000000000", vdst, vsrc1);
1552 SET_REGISTER_WIDE(vdst, ((u8) vsrc1) << 48);
1553 FINISH(2);
1554OP_END
1555
1556/* File: c/OP_CONST_STRING.cpp */
1557HANDLE_OPCODE(OP_CONST_STRING /*vAA, string@BBBB*/)
1558 {
1559 StringObject* strObj;
1560
1561 vdst = INST_AA(inst);
1562 ref = FETCH(1);
1563 ILOGV("|const-string v%d string@0x%04x", vdst, ref);
1564 strObj = dvmDexGetResolvedString(methodClassDex, ref);
1565 if (strObj == NULL) {
1566 EXPORT_PC();
1567 strObj = dvmResolveString(curMethod->clazz, ref);
1568 if (strObj == NULL)
1569 GOTO_exceptionThrown();
1570 }
1571 SET_REGISTER(vdst, (u4) strObj);
1572 }
1573 FINISH(2);
1574OP_END
1575
1576/* File: c/OP_CONST_STRING_JUMBO.cpp */
1577HANDLE_OPCODE(OP_CONST_STRING_JUMBO /*vAA, string@BBBBBBBB*/)
1578 {
1579 StringObject* strObj;
1580 u4 tmp;
1581
1582 vdst = INST_AA(inst);
1583 tmp = FETCH(1);
1584 tmp |= (u4)FETCH(2) << 16;
1585 ILOGV("|const-string/jumbo v%d string@0x%08x", vdst, tmp);
1586 strObj = dvmDexGetResolvedString(methodClassDex, tmp);
1587 if (strObj == NULL) {
1588 EXPORT_PC();
1589 strObj = dvmResolveString(curMethod->clazz, tmp);
1590 if (strObj == NULL)
1591 GOTO_exceptionThrown();
1592 }
1593 SET_REGISTER(vdst, (u4) strObj);
1594 }
1595 FINISH(3);
1596OP_END
1597
1598/* File: c/OP_CONST_CLASS.cpp */
1599HANDLE_OPCODE(OP_CONST_CLASS /*vAA, class@BBBB*/)
1600 {
1601 ClassObject* clazz;
1602
1603 vdst = INST_AA(inst);
1604 ref = FETCH(1);
1605 ILOGV("|const-class v%d class@0x%04x", vdst, ref);
1606 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
1607 if (clazz == NULL) {
1608 EXPORT_PC();
1609 clazz = dvmResolveClass(curMethod->clazz, ref, true);
1610 if (clazz == NULL)
1611 GOTO_exceptionThrown();
1612 }
1613 SET_REGISTER(vdst, (u4) clazz);
1614 }
1615 FINISH(2);
1616OP_END
1617
1618/* File: c/OP_MONITOR_ENTER.cpp */
1619HANDLE_OPCODE(OP_MONITOR_ENTER /*vAA*/)
1620 {
1621 Object* obj;
1622
1623 vsrc1 = INST_AA(inst);
1624 ILOGV("|monitor-enter v%d %s(0x%08x)",
1625 vsrc1, kSpacing+6, GET_REGISTER(vsrc1));
1626 obj = (Object*)GET_REGISTER(vsrc1);
1627 if (!checkForNullExportPC(obj, fp, pc))
1628 GOTO_exceptionThrown();
1629 ILOGV("+ locking %p %s\n", obj, obj->clazz->descriptor);
1630 EXPORT_PC(); /* need for precise GC */
1631 dvmLockObject(self, obj);
1632 }
1633 FINISH(1);
1634OP_END
1635
1636/* File: c/OP_MONITOR_EXIT.cpp */
1637HANDLE_OPCODE(OP_MONITOR_EXIT /*vAA*/)
1638 {
1639 Object* obj;
1640
1641 EXPORT_PC();
1642
1643 vsrc1 = INST_AA(inst);
1644 ILOGV("|monitor-exit v%d %s(0x%08x)",
1645 vsrc1, kSpacing+5, GET_REGISTER(vsrc1));
1646 obj = (Object*)GET_REGISTER(vsrc1);
1647 if (!checkForNull(obj)) {
1648 /*
1649 * The exception needs to be processed at the *following*
1650 * instruction, not the current instruction (see the Dalvik
1651 * spec). Because we're jumping to an exception handler,
1652 * we're not actually at risk of skipping an instruction
1653 * by doing so.
1654 */
1655 ADJUST_PC(1); /* monitor-exit width is 1 */
1656 GOTO_exceptionThrown();
1657 }
1658 ILOGV("+ unlocking %p %s\n", obj, obj->clazz->descriptor);
1659 if (!dvmUnlockObject(self, obj)) {
1660 assert(dvmCheckException(self));
1661 ADJUST_PC(1);
1662 GOTO_exceptionThrown();
1663 }
1664 }
1665 FINISH(1);
1666OP_END
1667
1668/* File: c/OP_CHECK_CAST.cpp */
1669HANDLE_OPCODE(OP_CHECK_CAST /*vAA, class@BBBB*/)
1670 {
1671 ClassObject* clazz;
1672 Object* obj;
1673
1674 EXPORT_PC();
1675
1676 vsrc1 = INST_AA(inst);
1677 ref = FETCH(1); /* class to check against */
1678 ILOGV("|check-cast v%d,class@0x%04x", vsrc1, ref);
1679
1680 obj = (Object*)GET_REGISTER(vsrc1);
1681 if (obj != NULL) {
1682#if defined(WITH_EXTRA_OBJECT_VALIDATION)
1683 if (!checkForNull(obj))
1684 GOTO_exceptionThrown();
1685#endif
1686 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
1687 if (clazz == NULL) {
1688 clazz = dvmResolveClass(curMethod->clazz, ref, false);
1689 if (clazz == NULL)
1690 GOTO_exceptionThrown();
1691 }
1692 if (!dvmInstanceof(obj->clazz, clazz)) {
1693 dvmThrowClassCastException(obj->clazz, clazz);
1694 GOTO_exceptionThrown();
1695 }
1696 }
1697 }
1698 FINISH(2);
1699OP_END
1700
1701/* File: c/OP_INSTANCE_OF.cpp */
1702HANDLE_OPCODE(OP_INSTANCE_OF /*vA, vB, class@CCCC*/)
1703 {
1704 ClassObject* clazz;
1705 Object* obj;
1706
1707 vdst = INST_A(inst);
1708 vsrc1 = INST_B(inst); /* object to check */
1709 ref = FETCH(1); /* class to check against */
1710 ILOGV("|instance-of v%d,v%d,class@0x%04x", vdst, vsrc1, ref);
1711
1712 obj = (Object*)GET_REGISTER(vsrc1);
1713 if (obj == NULL) {
1714 SET_REGISTER(vdst, 0);
1715 } else {
1716#if defined(WITH_EXTRA_OBJECT_VALIDATION)
1717 if (!checkForNullExportPC(obj, fp, pc))
1718 GOTO_exceptionThrown();
1719#endif
1720 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
1721 if (clazz == NULL) {
1722 EXPORT_PC();
1723 clazz = dvmResolveClass(curMethod->clazz, ref, true);
1724 if (clazz == NULL)
1725 GOTO_exceptionThrown();
1726 }
1727 SET_REGISTER(vdst, dvmInstanceof(obj->clazz, clazz));
1728 }
1729 }
1730 FINISH(2);
1731OP_END
1732
1733/* File: c/OP_ARRAY_LENGTH.cpp */
1734HANDLE_OPCODE(OP_ARRAY_LENGTH /*vA, vB*/)
1735 {
1736 ArrayObject* arrayObj;
1737
1738 vdst = INST_A(inst);
1739 vsrc1 = INST_B(inst);
1740 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);
1741 ILOGV("|array-length v%d,v%d (%p)", vdst, vsrc1, arrayObj);
1742 if (!checkForNullExportPC((Object*) arrayObj, fp, pc))
1743 GOTO_exceptionThrown();
1744 /* verifier guarantees this is an array reference */
1745 SET_REGISTER(vdst, arrayObj->length);
1746 }
1747 FINISH(1);
1748OP_END
1749
1750/* File: c/OP_NEW_INSTANCE.cpp */
1751HANDLE_OPCODE(OP_NEW_INSTANCE /*vAA, class@BBBB*/)
1752 {
1753 ClassObject* clazz;
1754 Object* newObj;
1755
1756 EXPORT_PC();
1757
1758 vdst = INST_AA(inst);
1759 ref = FETCH(1);
1760 ILOGV("|new-instance v%d,class@0x%04x", vdst, ref);
1761 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
1762 if (clazz == NULL) {
1763 clazz = dvmResolveClass(curMethod->clazz, ref, false);
1764 if (clazz == NULL)
1765 GOTO_exceptionThrown();
1766 }
1767
1768 if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz))
1769 GOTO_exceptionThrown();
1770
1771#if defined(WITH_JIT)
1772 /*
1773 * The JIT needs dvmDexGetResolvedClass() to return non-null.
1774 * Since we use the portable interpreter to build the trace, this extra
1775 * check is not needed for mterp.
1776 */
1777 if ((self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) &&
1778 (!dvmDexGetResolvedClass(methodClassDex, ref))) {
1779 /* Class initialization is still ongoing - end the trace */
1780 dvmJitEndTraceSelect(self,pc);
1781 }
1782#endif
1783
1784 /*
1785 * Verifier now tests for interface/abstract class.
1786 */
1787 //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
1788 // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError,
1789 // clazz->descriptor);
1790 // GOTO_exceptionThrown();
1791 //}
1792 newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
1793 if (newObj == NULL)
1794 GOTO_exceptionThrown();
1795 SET_REGISTER(vdst, (u4) newObj);
1796 }
1797 FINISH(2);
1798OP_END
1799
1800/* File: c/OP_NEW_ARRAY.cpp */
1801HANDLE_OPCODE(OP_NEW_ARRAY /*vA, vB, class@CCCC*/)
1802 {
1803 ClassObject* arrayClass;
1804 ArrayObject* newArray;
1805 s4 length;
1806
1807 EXPORT_PC();
1808
1809 vdst = INST_A(inst);
1810 vsrc1 = INST_B(inst); /* length reg */
1811 ref = FETCH(1);
1812 ILOGV("|new-array v%d,v%d,class@0x%04x (%d elements)",
1813 vdst, vsrc1, ref, (s4) GET_REGISTER(vsrc1));
1814 length = (s4) GET_REGISTER(vsrc1);
1815 if (length < 0) {
1816 dvmThrowNegativeArraySizeException(length);
1817 GOTO_exceptionThrown();
1818 }
1819 arrayClass = dvmDexGetResolvedClass(methodClassDex, ref);
1820 if (arrayClass == NULL) {
1821 arrayClass = dvmResolveClass(curMethod->clazz, ref, false);
1822 if (arrayClass == NULL)
1823 GOTO_exceptionThrown();
1824 }
1825 /* verifier guarantees this is an array class */
1826 assert(dvmIsArrayClass(arrayClass));
1827 assert(dvmIsClassInitialized(arrayClass));
1828
1829 newArray = dvmAllocArrayByClass(arrayClass, length, ALLOC_DONT_TRACK);
1830 if (newArray == NULL)
1831 GOTO_exceptionThrown();
1832 SET_REGISTER(vdst, (u4) newArray);
1833 }
1834 FINISH(2);
1835OP_END
1836
1837/* File: c/OP_FILLED_NEW_ARRAY.cpp */
1838HANDLE_OPCODE(OP_FILLED_NEW_ARRAY /*vB, {vD, vE, vF, vG, vA}, class@CCCC*/)
1839 GOTO_invoke(filledNewArray, false, false);
1840OP_END
1841
1842/* File: c/OP_FILLED_NEW_ARRAY_RANGE.cpp */
1843HANDLE_OPCODE(OP_FILLED_NEW_ARRAY_RANGE /*{vCCCC..v(CCCC+AA-1)}, class@BBBB*/)
1844 GOTO_invoke(filledNewArray, true, false);
1845OP_END
1846
1847/* File: c/OP_FILL_ARRAY_DATA.cpp */
1848HANDLE_OPCODE(OP_FILL_ARRAY_DATA) /*vAA, +BBBBBBBB*/
1849 {
1850 const u2* arrayData;
1851 s4 offset;
1852 ArrayObject* arrayObj;
1853
1854 EXPORT_PC();
1855 vsrc1 = INST_AA(inst);
1856 offset = FETCH(1) | (((s4) FETCH(2)) << 16);
1857 ILOGV("|fill-array-data v%d +0x%04x", vsrc1, offset);
1858 arrayData = pc + offset; // offset in 16-bit units
1859#ifndef NDEBUG
1860 if (arrayData < curMethod->insns ||
1861 arrayData >= curMethod->insns + dvmGetMethodInsnsSize(curMethod))
1862 {
1863 /* should have been caught in verifier */
1864 dvmThrowInternalError("bad fill array data");
1865 GOTO_exceptionThrown();
1866 }
1867#endif
1868 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);
1869 if (!dvmInterpHandleFillArrayData(arrayObj, arrayData)) {
1870 GOTO_exceptionThrown();
1871 }
1872 FINISH(3);
1873 }
1874OP_END
1875
1876/* File: c/OP_THROW.cpp */
1877HANDLE_OPCODE(OP_THROW /*vAA*/)
1878 {
1879 Object* obj;
1880
1881 /*
1882 * We don't create an exception here, but the process of searching
1883 * for a catch block can do class lookups and throw exceptions.
1884 * We need to update the saved PC.
1885 */
1886 EXPORT_PC();
1887
1888 vsrc1 = INST_AA(inst);
1889 ILOGV("|throw v%d (%p)", vsrc1, (void*)GET_REGISTER(vsrc1));
1890 obj = (Object*) GET_REGISTER(vsrc1);
1891 if (!checkForNull(obj)) {
1892 /* will throw a null pointer exception */
1893 LOGVV("Bad exception\n");
1894 } else {
1895 /* use the requested exception */
1896 dvmSetException(self, obj);
1897 }
1898 GOTO_exceptionThrown();
1899 }
1900OP_END
1901
1902/* File: c/OP_GOTO.cpp */
1903HANDLE_OPCODE(OP_GOTO /*+AA*/)
1904 vdst = INST_AA(inst);
1905 if ((s1)vdst < 0)
1906 ILOGV("|goto -0x%02x", -((s1)vdst));
1907 else
1908 ILOGV("|goto +0x%02x", ((s1)vdst));
1909 ILOGV("> branch taken");
1910 if ((s1)vdst < 0)
1911 PERIODIC_CHECKS((s1)vdst);
1912 FINISH((s1)vdst);
1913OP_END
1914
1915/* File: c/OP_GOTO_16.cpp */
1916HANDLE_OPCODE(OP_GOTO_16 /*+AAAA*/)
1917 {
1918 s4 offset = (s2) FETCH(1); /* sign-extend next code unit */
1919
1920 if (offset < 0)
1921 ILOGV("|goto/16 -0x%04x", -offset);
1922 else
1923 ILOGV("|goto/16 +0x%04x", offset);
1924 ILOGV("> branch taken");
1925 if (offset < 0)
1926 PERIODIC_CHECKS(offset);
1927 FINISH(offset);
1928 }
1929OP_END
1930
1931/* File: c/OP_GOTO_32.cpp */
1932HANDLE_OPCODE(OP_GOTO_32 /*+AAAAAAAA*/)
1933 {
1934 s4 offset = FETCH(1); /* low-order 16 bits */
1935 offset |= ((s4) FETCH(2)) << 16; /* high-order 16 bits */
1936
1937 if (offset < 0)
1938 ILOGV("|goto/32 -0x%08x", -offset);
1939 else
1940 ILOGV("|goto/32 +0x%08x", offset);
1941 ILOGV("> branch taken");
1942 if (offset <= 0) /* allowed to branch to self */
1943 PERIODIC_CHECKS(offset);
1944 FINISH(offset);
1945 }
1946OP_END
1947
1948/* File: c/OP_PACKED_SWITCH.cpp */
1949HANDLE_OPCODE(OP_PACKED_SWITCH /*vAA, +BBBB*/)
1950 {
1951 const u2* switchData;
1952 u4 testVal;
1953 s4 offset;
1954
1955 vsrc1 = INST_AA(inst);
1956 offset = FETCH(1) | (((s4) FETCH(2)) << 16);
1957 ILOGV("|packed-switch v%d +0x%04x", vsrc1, vsrc2);
1958 switchData = pc + offset; // offset in 16-bit units
1959#ifndef NDEBUG
1960 if (switchData < curMethod->insns ||
1961 switchData >= curMethod->insns + dvmGetMethodInsnsSize(curMethod))
1962 {
1963 /* should have been caught in verifier */
1964 EXPORT_PC();
1965 dvmThrowInternalError("bad packed switch");
1966 GOTO_exceptionThrown();
1967 }
1968#endif
1969 testVal = GET_REGISTER(vsrc1);
1970
1971 offset = dvmInterpHandlePackedSwitch(switchData, testVal);
1972 ILOGV("> branch taken (0x%04x)\n", offset);
1973 if (offset <= 0) /* uncommon */
1974 PERIODIC_CHECKS(offset);
1975 FINISH(offset);
1976 }
1977OP_END
1978
1979/* File: c/OP_SPARSE_SWITCH.cpp */
1980HANDLE_OPCODE(OP_SPARSE_SWITCH /*vAA, +BBBB*/)
1981 {
1982 const u2* switchData;
1983 u4 testVal;
1984 s4 offset;
1985
1986 vsrc1 = INST_AA(inst);
1987 offset = FETCH(1) | (((s4) FETCH(2)) << 16);
1988 ILOGV("|sparse-switch v%d +0x%04x", vsrc1, vsrc2);
1989 switchData = pc + offset; // offset in 16-bit units
1990#ifndef NDEBUG
1991 if (switchData < curMethod->insns ||
1992 switchData >= curMethod->insns + dvmGetMethodInsnsSize(curMethod))
1993 {
1994 /* should have been caught in verifier */
1995 EXPORT_PC();
1996 dvmThrowInternalError("bad sparse switch");
1997 GOTO_exceptionThrown();
1998 }
1999#endif
2000 testVal = GET_REGISTER(vsrc1);
2001
2002 offset = dvmInterpHandleSparseSwitch(switchData, testVal);
2003 ILOGV("> branch taken (0x%04x)\n", offset);
2004 if (offset <= 0) /* uncommon */
2005 PERIODIC_CHECKS(offset);
2006 FINISH(offset);
2007 }
2008OP_END
2009
2010/* File: c/OP_CMPL_FLOAT.cpp */
2011HANDLE_OP_CMPX(OP_CMPL_FLOAT, "l-float", float, _FLOAT, -1)
2012OP_END
2013
2014/* File: c/OP_CMPG_FLOAT.cpp */
2015HANDLE_OP_CMPX(OP_CMPG_FLOAT, "g-float", float, _FLOAT, 1)
2016OP_END
2017
2018/* File: c/OP_CMPL_DOUBLE.cpp */
2019HANDLE_OP_CMPX(OP_CMPL_DOUBLE, "l-double", double, _DOUBLE, -1)
2020OP_END
2021
2022/* File: c/OP_CMPG_DOUBLE.cpp */
2023HANDLE_OP_CMPX(OP_CMPG_DOUBLE, "g-double", double, _DOUBLE, 1)
2024OP_END
2025
2026/* File: c/OP_CMP_LONG.cpp */
2027HANDLE_OP_CMPX(OP_CMP_LONG, "-long", s8, _WIDE, 0)
2028OP_END
2029
2030/* File: c/OP_IF_EQ.cpp */
2031HANDLE_OP_IF_XX(OP_IF_EQ, "eq", ==)
2032OP_END
2033
2034/* File: c/OP_IF_NE.cpp */
2035HANDLE_OP_IF_XX(OP_IF_NE, "ne", !=)
2036OP_END
2037
2038/* File: c/OP_IF_LT.cpp */
2039HANDLE_OP_IF_XX(OP_IF_LT, "lt", <)
2040OP_END
2041
2042/* File: c/OP_IF_GE.cpp */
2043HANDLE_OP_IF_XX(OP_IF_GE, "ge", >=)
2044OP_END
2045
2046/* File: c/OP_IF_GT.cpp */
2047HANDLE_OP_IF_XX(OP_IF_GT, "gt", >)
2048OP_END
2049
2050/* File: c/OP_IF_LE.cpp */
2051HANDLE_OP_IF_XX(OP_IF_LE, "le", <=)
2052OP_END
2053
2054/* File: c/OP_IF_EQZ.cpp */
2055HANDLE_OP_IF_XXZ(OP_IF_EQZ, "eqz", ==)
2056OP_END
2057
2058/* File: c/OP_IF_NEZ.cpp */
2059HANDLE_OP_IF_XXZ(OP_IF_NEZ, "nez", !=)
2060OP_END
2061
2062/* File: c/OP_IF_LTZ.cpp */
2063HANDLE_OP_IF_XXZ(OP_IF_LTZ, "ltz", <)
2064OP_END
2065
2066/* File: c/OP_IF_GEZ.cpp */
2067HANDLE_OP_IF_XXZ(OP_IF_GEZ, "gez", >=)
2068OP_END
2069
2070/* File: c/OP_IF_GTZ.cpp */
2071HANDLE_OP_IF_XXZ(OP_IF_GTZ, "gtz", >)
2072OP_END
2073
2074/* File: c/OP_IF_LEZ.cpp */
2075HANDLE_OP_IF_XXZ(OP_IF_LEZ, "lez", <=)
2076OP_END
2077
2078/* File: c/OP_UNUSED_3E.cpp */
2079HANDLE_OPCODE(OP_UNUSED_3E)
2080OP_END
2081
2082/* File: c/OP_UNUSED_3F.cpp */
2083HANDLE_OPCODE(OP_UNUSED_3F)
2084OP_END
2085
2086/* File: c/OP_UNUSED_40.cpp */
2087HANDLE_OPCODE(OP_UNUSED_40)
2088OP_END
2089
2090/* File: c/OP_UNUSED_41.cpp */
2091HANDLE_OPCODE(OP_UNUSED_41)
2092OP_END
2093
2094/* File: c/OP_UNUSED_42.cpp */
2095HANDLE_OPCODE(OP_UNUSED_42)
2096OP_END
2097
2098/* File: c/OP_UNUSED_43.cpp */
2099HANDLE_OPCODE(OP_UNUSED_43)
2100OP_END
2101
2102/* File: c/OP_AGET.cpp */
2103HANDLE_OP_AGET(OP_AGET, "", u4, )
2104OP_END
2105
2106/* File: c/OP_AGET_WIDE.cpp */
2107HANDLE_OP_AGET(OP_AGET_WIDE, "-wide", s8, _WIDE)
2108OP_END
2109
2110/* File: c/OP_AGET_OBJECT.cpp */
2111HANDLE_OP_AGET(OP_AGET_OBJECT, "-object", u4, )
2112OP_END
2113
2114/* File: c/OP_AGET_BOOLEAN.cpp */
2115HANDLE_OP_AGET(OP_AGET_BOOLEAN, "-boolean", u1, )
2116OP_END
2117
2118/* File: c/OP_AGET_BYTE.cpp */
2119HANDLE_OP_AGET(OP_AGET_BYTE, "-byte", s1, )
2120OP_END
2121
2122/* File: c/OP_AGET_CHAR.cpp */
2123HANDLE_OP_AGET(OP_AGET_CHAR, "-char", u2, )
2124OP_END
2125
2126/* File: c/OP_AGET_SHORT.cpp */
2127HANDLE_OP_AGET(OP_AGET_SHORT, "-short", s2, )
2128OP_END
2129
2130/* File: c/OP_APUT.cpp */
2131HANDLE_OP_APUT(OP_APUT, "", u4, )
2132OP_END
2133
2134/* File: c/OP_APUT_WIDE.cpp */
2135HANDLE_OP_APUT(OP_APUT_WIDE, "-wide", s8, _WIDE)
2136OP_END
2137
2138/* File: c/OP_APUT_OBJECT.cpp */
2139HANDLE_OPCODE(OP_APUT_OBJECT /*vAA, vBB, vCC*/)
2140 {
2141 ArrayObject* arrayObj;
2142 Object* obj;
2143 u2 arrayInfo;
2144 EXPORT_PC();
2145 vdst = INST_AA(inst); /* AA: source value */
2146 arrayInfo = FETCH(1);
2147 vsrc1 = arrayInfo & 0xff; /* BB: array ptr */
2148 vsrc2 = arrayInfo >> 8; /* CC: index */
2149 ILOGV("|aput%s v%d,v%d,v%d", "-object", vdst, vsrc1, vsrc2);
2150 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);
2151 if (!checkForNull((Object*) arrayObj))
2152 GOTO_exceptionThrown();
2153 if (GET_REGISTER(vsrc2) >= arrayObj->length) {
2154 dvmThrowArrayIndexOutOfBoundsException(
2155 arrayObj->length, GET_REGISTER(vsrc2));
2156 GOTO_exceptionThrown();
2157 }
2158 obj = (Object*) GET_REGISTER(vdst);
2159 if (obj != NULL) {
2160 if (!checkForNull(obj))
2161 GOTO_exceptionThrown();
Carl Shapiroa62c3a02011-05-03 17:59:35 -07002162 if (!dvmCanPutArrayElement(obj->clazz, arrayObj->clazz)) {
Carl Shapirocd8f5e72011-04-20 16:12:46 -07002163 LOGV("Can't put a '%s'(%p) into array type='%s'(%p)\n",
2164 obj->clazz->descriptor, obj,
2165 arrayObj->obj.clazz->descriptor, arrayObj);
Carl Shapiroa62c3a02011-05-03 17:59:35 -07002166 dvmThrowArrayStoreExceptionIncompatibleElement(obj->clazz, arrayObj->clazz);
Carl Shapirocd8f5e72011-04-20 16:12:46 -07002167 GOTO_exceptionThrown();
2168 }
2169 }
2170 ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));
2171 dvmSetObjectArrayElement(arrayObj,
2172 GET_REGISTER(vsrc2),
2173 (Object *)GET_REGISTER(vdst));
2174 }
2175 FINISH(2);
2176OP_END
2177
2178/* File: c/OP_APUT_BOOLEAN.cpp */
2179HANDLE_OP_APUT(OP_APUT_BOOLEAN, "-boolean", u1, )
2180OP_END
2181
2182/* File: c/OP_APUT_BYTE.cpp */
2183HANDLE_OP_APUT(OP_APUT_BYTE, "-byte", s1, )
2184OP_END
2185
2186/* File: c/OP_APUT_CHAR.cpp */
2187HANDLE_OP_APUT(OP_APUT_CHAR, "-char", u2, )
2188OP_END
2189
2190/* File: c/OP_APUT_SHORT.cpp */
2191HANDLE_OP_APUT(OP_APUT_SHORT, "-short", s2, )
2192OP_END
2193
2194/* File: c/OP_IGET.cpp */
2195HANDLE_IGET_X(OP_IGET, "", Int, )
2196OP_END
2197
2198/* File: c/OP_IGET_WIDE.cpp */
2199HANDLE_IGET_X(OP_IGET_WIDE, "-wide", Long, _WIDE)
2200OP_END
2201
2202/* File: c/OP_IGET_OBJECT.cpp */
2203HANDLE_IGET_X(OP_IGET_OBJECT, "-object", Object, _AS_OBJECT)
2204OP_END
2205
2206/* File: c/OP_IGET_BOOLEAN.cpp */
2207HANDLE_IGET_X(OP_IGET_BOOLEAN, "", Int, )
2208OP_END
2209
2210/* File: c/OP_IGET_BYTE.cpp */
2211HANDLE_IGET_X(OP_IGET_BYTE, "", Int, )
2212OP_END
2213
2214/* File: c/OP_IGET_CHAR.cpp */
2215HANDLE_IGET_X(OP_IGET_CHAR, "", Int, )
2216OP_END
2217
2218/* File: c/OP_IGET_SHORT.cpp */
2219HANDLE_IGET_X(OP_IGET_SHORT, "", Int, )
2220OP_END
2221
2222/* File: c/OP_IPUT.cpp */
2223HANDLE_IPUT_X(OP_IPUT, "", Int, )
2224OP_END
2225
2226/* File: c/OP_IPUT_WIDE.cpp */
2227HANDLE_IPUT_X(OP_IPUT_WIDE, "-wide", Long, _WIDE)
2228OP_END
2229
2230/* File: c/OP_IPUT_OBJECT.cpp */
2231/*
2232 * The VM spec says we should verify that the reference being stored into
2233 * the field is assignment compatible. In practice, many popular VMs don't
2234 * do this because it slows down a very common operation. It's not so bad
2235 * for us, since "dexopt" quickens it whenever possible, but it's still an
2236 * issue.
2237 *
2238 * To make this spec-complaint, we'd need to add a ClassObject pointer to
2239 * the Field struct, resolve the field's type descriptor at link or class
2240 * init time, and then verify the type here.
2241 */
2242HANDLE_IPUT_X(OP_IPUT_OBJECT, "-object", Object, _AS_OBJECT)
2243OP_END
2244
2245/* File: c/OP_IPUT_BOOLEAN.cpp */
2246HANDLE_IPUT_X(OP_IPUT_BOOLEAN, "", Int, )
2247OP_END
2248
2249/* File: c/OP_IPUT_BYTE.cpp */
2250HANDLE_IPUT_X(OP_IPUT_BYTE, "", Int, )
2251OP_END
2252
2253/* File: c/OP_IPUT_CHAR.cpp */
2254HANDLE_IPUT_X(OP_IPUT_CHAR, "", Int, )
2255OP_END
2256
2257/* File: c/OP_IPUT_SHORT.cpp */
2258HANDLE_IPUT_X(OP_IPUT_SHORT, "", Int, )
2259OP_END
2260
2261/* File: c/OP_SGET.cpp */
2262HANDLE_SGET_X(OP_SGET, "", Int, )
2263OP_END
2264
2265/* File: c/OP_SGET_WIDE.cpp */
2266HANDLE_SGET_X(OP_SGET_WIDE, "-wide", Long, _WIDE)
2267OP_END
2268
2269/* File: c/OP_SGET_OBJECT.cpp */
2270HANDLE_SGET_X(OP_SGET_OBJECT, "-object", Object, _AS_OBJECT)
2271OP_END
2272
2273/* File: c/OP_SGET_BOOLEAN.cpp */
2274HANDLE_SGET_X(OP_SGET_BOOLEAN, "", Int, )
2275OP_END
2276
2277/* File: c/OP_SGET_BYTE.cpp */
2278HANDLE_SGET_X(OP_SGET_BYTE, "", Int, )
2279OP_END
2280
2281/* File: c/OP_SGET_CHAR.cpp */
2282HANDLE_SGET_X(OP_SGET_CHAR, "", Int, )
2283OP_END
2284
2285/* File: c/OP_SGET_SHORT.cpp */
2286HANDLE_SGET_X(OP_SGET_SHORT, "", Int, )
2287OP_END
2288
2289/* File: c/OP_SPUT.cpp */
2290HANDLE_SPUT_X(OP_SPUT, "", Int, )
2291OP_END
2292
2293/* File: c/OP_SPUT_WIDE.cpp */
2294HANDLE_SPUT_X(OP_SPUT_WIDE, "-wide", Long, _WIDE)
2295OP_END
2296
2297/* File: c/OP_SPUT_OBJECT.cpp */
2298HANDLE_SPUT_X(OP_SPUT_OBJECT, "-object", Object, _AS_OBJECT)
2299OP_END
2300
2301/* File: c/OP_SPUT_BOOLEAN.cpp */
2302HANDLE_SPUT_X(OP_SPUT_BOOLEAN, "", Int, )
2303OP_END
2304
2305/* File: c/OP_SPUT_BYTE.cpp */
2306HANDLE_SPUT_X(OP_SPUT_BYTE, "", Int, )
2307OP_END
2308
2309/* File: c/OP_SPUT_CHAR.cpp */
2310HANDLE_SPUT_X(OP_SPUT_CHAR, "", Int, )
2311OP_END
2312
2313/* File: c/OP_SPUT_SHORT.cpp */
2314HANDLE_SPUT_X(OP_SPUT_SHORT, "", Int, )
2315OP_END
2316
2317/* File: c/OP_INVOKE_VIRTUAL.cpp */
2318HANDLE_OPCODE(OP_INVOKE_VIRTUAL /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
2319 GOTO_invoke(invokeVirtual, false, false);
2320OP_END
2321
2322/* File: c/OP_INVOKE_SUPER.cpp */
2323HANDLE_OPCODE(OP_INVOKE_SUPER /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
2324 GOTO_invoke(invokeSuper, false, false);
2325OP_END
2326
2327/* File: c/OP_INVOKE_DIRECT.cpp */
2328HANDLE_OPCODE(OP_INVOKE_DIRECT /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
2329 GOTO_invoke(invokeDirect, false, false);
2330OP_END
2331
2332/* File: c/OP_INVOKE_STATIC.cpp */
2333HANDLE_OPCODE(OP_INVOKE_STATIC /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
2334 GOTO_invoke(invokeStatic, false, false);
2335OP_END
2336
2337/* File: c/OP_INVOKE_INTERFACE.cpp */
2338HANDLE_OPCODE(OP_INVOKE_INTERFACE /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
2339 GOTO_invoke(invokeInterface, false, false);
2340OP_END
2341
2342/* File: c/OP_UNUSED_73.cpp */
2343HANDLE_OPCODE(OP_UNUSED_73)
2344OP_END
2345
2346/* File: c/OP_INVOKE_VIRTUAL_RANGE.cpp */
2347HANDLE_OPCODE(OP_INVOKE_VIRTUAL_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
2348 GOTO_invoke(invokeVirtual, true, false);
2349OP_END
2350
2351/* File: c/OP_INVOKE_SUPER_RANGE.cpp */
2352HANDLE_OPCODE(OP_INVOKE_SUPER_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
2353 GOTO_invoke(invokeSuper, true, false);
2354OP_END
2355
2356/* File: c/OP_INVOKE_DIRECT_RANGE.cpp */
2357HANDLE_OPCODE(OP_INVOKE_DIRECT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
2358 GOTO_invoke(invokeDirect, true, false);
2359OP_END
2360
2361/* File: c/OP_INVOKE_STATIC_RANGE.cpp */
2362HANDLE_OPCODE(OP_INVOKE_STATIC_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
2363 GOTO_invoke(invokeStatic, true, false);
2364OP_END
2365
2366/* File: c/OP_INVOKE_INTERFACE_RANGE.cpp */
2367HANDLE_OPCODE(OP_INVOKE_INTERFACE_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
2368 GOTO_invoke(invokeInterface, true, false);
2369OP_END
2370
2371/* File: c/OP_UNUSED_79.cpp */
2372HANDLE_OPCODE(OP_UNUSED_79)
2373OP_END
2374
2375/* File: c/OP_UNUSED_7A.cpp */
2376HANDLE_OPCODE(OP_UNUSED_7A)
2377OP_END
2378
2379/* File: c/OP_NEG_INT.cpp */
2380HANDLE_UNOP(OP_NEG_INT, "neg-int", -, , )
2381OP_END
2382
2383/* File: c/OP_NOT_INT.cpp */
2384HANDLE_UNOP(OP_NOT_INT, "not-int", , ^ 0xffffffff, )
2385OP_END
2386
2387/* File: c/OP_NEG_LONG.cpp */
2388HANDLE_UNOP(OP_NEG_LONG, "neg-long", -, , _WIDE)
2389OP_END
2390
2391/* File: c/OP_NOT_LONG.cpp */
2392HANDLE_UNOP(OP_NOT_LONG, "not-long", , ^ 0xffffffffffffffffULL, _WIDE)
2393OP_END
2394
2395/* File: c/OP_NEG_FLOAT.cpp */
2396HANDLE_UNOP(OP_NEG_FLOAT, "neg-float", -, , _FLOAT)
2397OP_END
2398
2399/* File: c/OP_NEG_DOUBLE.cpp */
2400HANDLE_UNOP(OP_NEG_DOUBLE, "neg-double", -, , _DOUBLE)
2401OP_END
2402
2403/* File: c/OP_INT_TO_LONG.cpp */
2404HANDLE_NUMCONV(OP_INT_TO_LONG, "int-to-long", _INT, _WIDE)
2405OP_END
2406
2407/* File: c/OP_INT_TO_FLOAT.cpp */
2408HANDLE_NUMCONV(OP_INT_TO_FLOAT, "int-to-float", _INT, _FLOAT)
2409OP_END
2410
2411/* File: c/OP_INT_TO_DOUBLE.cpp */
2412HANDLE_NUMCONV(OP_INT_TO_DOUBLE, "int-to-double", _INT, _DOUBLE)
2413OP_END
2414
2415/* File: c/OP_LONG_TO_INT.cpp */
2416HANDLE_NUMCONV(OP_LONG_TO_INT, "long-to-int", _WIDE, _INT)
2417OP_END
2418
2419/* File: c/OP_LONG_TO_FLOAT.cpp */
2420HANDLE_NUMCONV(OP_LONG_TO_FLOAT, "long-to-float", _WIDE, _FLOAT)
2421OP_END
2422
2423/* File: c/OP_LONG_TO_DOUBLE.cpp */
2424HANDLE_NUMCONV(OP_LONG_TO_DOUBLE, "long-to-double", _WIDE, _DOUBLE)
2425OP_END
2426
2427/* File: c/OP_FLOAT_TO_INT.cpp */
2428HANDLE_FLOAT_TO_INT(OP_FLOAT_TO_INT, "float-to-int",
2429 float, _FLOAT, s4, _INT)
2430OP_END
2431
2432/* File: c/OP_FLOAT_TO_LONG.cpp */
2433HANDLE_FLOAT_TO_INT(OP_FLOAT_TO_LONG, "float-to-long",
2434 float, _FLOAT, s8, _WIDE)
2435OP_END
2436
2437/* File: c/OP_FLOAT_TO_DOUBLE.cpp */
2438HANDLE_NUMCONV(OP_FLOAT_TO_DOUBLE, "float-to-double", _FLOAT, _DOUBLE)
2439OP_END
2440
2441/* File: c/OP_DOUBLE_TO_INT.cpp */
2442HANDLE_FLOAT_TO_INT(OP_DOUBLE_TO_INT, "double-to-int",
2443 double, _DOUBLE, s4, _INT)
2444OP_END
2445
2446/* File: c/OP_DOUBLE_TO_LONG.cpp */
2447HANDLE_FLOAT_TO_INT(OP_DOUBLE_TO_LONG, "double-to-long",
2448 double, _DOUBLE, s8, _WIDE)
2449OP_END
2450
2451/* File: c/OP_DOUBLE_TO_FLOAT.cpp */
2452HANDLE_NUMCONV(OP_DOUBLE_TO_FLOAT, "double-to-float", _DOUBLE, _FLOAT)
2453OP_END
2454
2455/* File: c/OP_INT_TO_BYTE.cpp */
2456HANDLE_INT_TO_SMALL(OP_INT_TO_BYTE, "byte", s1)
2457OP_END
2458
2459/* File: c/OP_INT_TO_CHAR.cpp */
2460HANDLE_INT_TO_SMALL(OP_INT_TO_CHAR, "char", u2)
2461OP_END
2462
2463/* File: c/OP_INT_TO_SHORT.cpp */
2464HANDLE_INT_TO_SMALL(OP_INT_TO_SHORT, "short", s2) /* want sign bit */
2465OP_END
2466
2467/* File: c/OP_ADD_INT.cpp */
2468HANDLE_OP_X_INT(OP_ADD_INT, "add", +, 0)
2469OP_END
2470
2471/* File: c/OP_SUB_INT.cpp */
2472HANDLE_OP_X_INT(OP_SUB_INT, "sub", -, 0)
2473OP_END
2474
2475/* File: c/OP_MUL_INT.cpp */
2476HANDLE_OP_X_INT(OP_MUL_INT, "mul", *, 0)
2477OP_END
2478
2479/* File: c/OP_DIV_INT.cpp */
2480HANDLE_OP_X_INT(OP_DIV_INT, "div", /, 1)
2481OP_END
2482
2483/* File: c/OP_REM_INT.cpp */
2484HANDLE_OP_X_INT(OP_REM_INT, "rem", %, 2)
2485OP_END
2486
2487/* File: c/OP_AND_INT.cpp */
2488HANDLE_OP_X_INT(OP_AND_INT, "and", &, 0)
2489OP_END
2490
2491/* File: c/OP_OR_INT.cpp */
2492HANDLE_OP_X_INT(OP_OR_INT, "or", |, 0)
2493OP_END
2494
2495/* File: c/OP_XOR_INT.cpp */
2496HANDLE_OP_X_INT(OP_XOR_INT, "xor", ^, 0)
2497OP_END
2498
2499/* File: c/OP_SHL_INT.cpp */
2500HANDLE_OP_SHX_INT(OP_SHL_INT, "shl", (s4), <<)
2501OP_END
2502
2503/* File: c/OP_SHR_INT.cpp */
2504HANDLE_OP_SHX_INT(OP_SHR_INT, "shr", (s4), >>)
2505OP_END
2506
2507/* File: c/OP_USHR_INT.cpp */
2508HANDLE_OP_SHX_INT(OP_USHR_INT, "ushr", (u4), >>)
2509OP_END
2510
2511/* File: c/OP_ADD_LONG.cpp */
2512HANDLE_OP_X_LONG(OP_ADD_LONG, "add", +, 0)
2513OP_END
2514
2515/* File: c/OP_SUB_LONG.cpp */
2516HANDLE_OP_X_LONG(OP_SUB_LONG, "sub", -, 0)
2517OP_END
2518
2519/* File: c/OP_MUL_LONG.cpp */
2520HANDLE_OP_X_LONG(OP_MUL_LONG, "mul", *, 0)
2521OP_END
2522
2523/* File: c/OP_DIV_LONG.cpp */
2524HANDLE_OP_X_LONG(OP_DIV_LONG, "div", /, 1)
2525OP_END
2526
2527/* File: c/OP_REM_LONG.cpp */
2528HANDLE_OP_X_LONG(OP_REM_LONG, "rem", %, 2)
2529OP_END
2530
2531/* File: c/OP_AND_LONG.cpp */
2532HANDLE_OP_X_LONG(OP_AND_LONG, "and", &, 0)
2533OP_END
2534
2535/* File: c/OP_OR_LONG.cpp */
2536HANDLE_OP_X_LONG(OP_OR_LONG, "or", |, 0)
2537OP_END
2538
2539/* File: c/OP_XOR_LONG.cpp */
2540HANDLE_OP_X_LONG(OP_XOR_LONG, "xor", ^, 0)
2541OP_END
2542
2543/* File: c/OP_SHL_LONG.cpp */
2544HANDLE_OP_SHX_LONG(OP_SHL_LONG, "shl", (s8), <<)
2545OP_END
2546
2547/* File: c/OP_SHR_LONG.cpp */
2548HANDLE_OP_SHX_LONG(OP_SHR_LONG, "shr", (s8), >>)
2549OP_END
2550
2551/* File: c/OP_USHR_LONG.cpp */
2552HANDLE_OP_SHX_LONG(OP_USHR_LONG, "ushr", (u8), >>)
2553OP_END
2554
2555/* File: c/OP_ADD_FLOAT.cpp */
2556HANDLE_OP_X_FLOAT(OP_ADD_FLOAT, "add", +)
2557OP_END
2558
2559/* File: c/OP_SUB_FLOAT.cpp */
2560HANDLE_OP_X_FLOAT(OP_SUB_FLOAT, "sub", -)
2561OP_END
2562
2563/* File: c/OP_MUL_FLOAT.cpp */
2564HANDLE_OP_X_FLOAT(OP_MUL_FLOAT, "mul", *)
2565OP_END
2566
2567/* File: c/OP_DIV_FLOAT.cpp */
2568HANDLE_OP_X_FLOAT(OP_DIV_FLOAT, "div", /)
2569OP_END
2570
2571/* File: c/OP_REM_FLOAT.cpp */
2572HANDLE_OPCODE(OP_REM_FLOAT /*vAA, vBB, vCC*/)
2573 {
2574 u2 srcRegs;
2575 vdst = INST_AA(inst);
2576 srcRegs = FETCH(1);
2577 vsrc1 = srcRegs & 0xff;
2578 vsrc2 = srcRegs >> 8;
2579 ILOGV("|%s-float v%d,v%d,v%d", "mod", vdst, vsrc1, vsrc2);
2580 SET_REGISTER_FLOAT(vdst,
2581 fmodf(GET_REGISTER_FLOAT(vsrc1), GET_REGISTER_FLOAT(vsrc2)));
2582 }
2583 FINISH(2);
2584OP_END
2585
2586/* File: c/OP_ADD_DOUBLE.cpp */
2587HANDLE_OP_X_DOUBLE(OP_ADD_DOUBLE, "add", +)
2588OP_END
2589
2590/* File: c/OP_SUB_DOUBLE.cpp */
2591HANDLE_OP_X_DOUBLE(OP_SUB_DOUBLE, "sub", -)
2592OP_END
2593
2594/* File: c/OP_MUL_DOUBLE.cpp */
2595HANDLE_OP_X_DOUBLE(OP_MUL_DOUBLE, "mul", *)
2596OP_END
2597
2598/* File: c/OP_DIV_DOUBLE.cpp */
2599HANDLE_OP_X_DOUBLE(OP_DIV_DOUBLE, "div", /)
2600OP_END
2601
2602/* File: c/OP_REM_DOUBLE.cpp */
2603HANDLE_OPCODE(OP_REM_DOUBLE /*vAA, vBB, vCC*/)
2604 {
2605 u2 srcRegs;
2606 vdst = INST_AA(inst);
2607 srcRegs = FETCH(1);
2608 vsrc1 = srcRegs & 0xff;
2609 vsrc2 = srcRegs >> 8;
2610 ILOGV("|%s-double v%d,v%d,v%d", "mod", vdst, vsrc1, vsrc2);
2611 SET_REGISTER_DOUBLE(vdst,
2612 fmod(GET_REGISTER_DOUBLE(vsrc1), GET_REGISTER_DOUBLE(vsrc2)));
2613 }
2614 FINISH(2);
2615OP_END
2616
2617/* File: c/OP_ADD_INT_2ADDR.cpp */
2618HANDLE_OP_X_INT_2ADDR(OP_ADD_INT_2ADDR, "add", +, 0)
2619OP_END
2620
2621/* File: c/OP_SUB_INT_2ADDR.cpp */
2622HANDLE_OP_X_INT_2ADDR(OP_SUB_INT_2ADDR, "sub", -, 0)
2623OP_END
2624
2625/* File: c/OP_MUL_INT_2ADDR.cpp */
2626HANDLE_OP_X_INT_2ADDR(OP_MUL_INT_2ADDR, "mul", *, 0)
2627OP_END
2628
2629/* File: c/OP_DIV_INT_2ADDR.cpp */
2630HANDLE_OP_X_INT_2ADDR(OP_DIV_INT_2ADDR, "div", /, 1)
2631OP_END
2632
2633/* File: c/OP_REM_INT_2ADDR.cpp */
2634HANDLE_OP_X_INT_2ADDR(OP_REM_INT_2ADDR, "rem", %, 2)
2635OP_END
2636
2637/* File: c/OP_AND_INT_2ADDR.cpp */
2638HANDLE_OP_X_INT_2ADDR(OP_AND_INT_2ADDR, "and", &, 0)
2639OP_END
2640
2641/* File: c/OP_OR_INT_2ADDR.cpp */
2642HANDLE_OP_X_INT_2ADDR(OP_OR_INT_2ADDR, "or", |, 0)
2643OP_END
2644
2645/* File: c/OP_XOR_INT_2ADDR.cpp */
2646HANDLE_OP_X_INT_2ADDR(OP_XOR_INT_2ADDR, "xor", ^, 0)
2647OP_END
2648
2649/* File: c/OP_SHL_INT_2ADDR.cpp */
2650HANDLE_OP_SHX_INT_2ADDR(OP_SHL_INT_2ADDR, "shl", (s4), <<)
2651OP_END
2652
2653/* File: c/OP_SHR_INT_2ADDR.cpp */
2654HANDLE_OP_SHX_INT_2ADDR(OP_SHR_INT_2ADDR, "shr", (s4), >>)
2655OP_END
2656
2657/* File: c/OP_USHR_INT_2ADDR.cpp */
2658HANDLE_OP_SHX_INT_2ADDR(OP_USHR_INT_2ADDR, "ushr", (u4), >>)
2659OP_END
2660
2661/* File: c/OP_ADD_LONG_2ADDR.cpp */
2662HANDLE_OP_X_LONG_2ADDR(OP_ADD_LONG_2ADDR, "add", +, 0)
2663OP_END
2664
2665/* File: c/OP_SUB_LONG_2ADDR.cpp */
2666HANDLE_OP_X_LONG_2ADDR(OP_SUB_LONG_2ADDR, "sub", -, 0)
2667OP_END
2668
2669/* File: c/OP_MUL_LONG_2ADDR.cpp */
2670HANDLE_OP_X_LONG_2ADDR(OP_MUL_LONG_2ADDR, "mul", *, 0)
2671OP_END
2672
2673/* File: c/OP_DIV_LONG_2ADDR.cpp */
2674HANDLE_OP_X_LONG_2ADDR(OP_DIV_LONG_2ADDR, "div", /, 1)
2675OP_END
2676
2677/* File: c/OP_REM_LONG_2ADDR.cpp */
2678HANDLE_OP_X_LONG_2ADDR(OP_REM_LONG_2ADDR, "rem", %, 2)
2679OP_END
2680
2681/* File: c/OP_AND_LONG_2ADDR.cpp */
2682HANDLE_OP_X_LONG_2ADDR(OP_AND_LONG_2ADDR, "and", &, 0)
2683OP_END
2684
2685/* File: c/OP_OR_LONG_2ADDR.cpp */
2686HANDLE_OP_X_LONG_2ADDR(OP_OR_LONG_2ADDR, "or", |, 0)
2687OP_END
2688
2689/* File: c/OP_XOR_LONG_2ADDR.cpp */
2690HANDLE_OP_X_LONG_2ADDR(OP_XOR_LONG_2ADDR, "xor", ^, 0)
2691OP_END
2692
2693/* File: c/OP_SHL_LONG_2ADDR.cpp */
2694HANDLE_OP_SHX_LONG_2ADDR(OP_SHL_LONG_2ADDR, "shl", (s8), <<)
2695OP_END
2696
2697/* File: c/OP_SHR_LONG_2ADDR.cpp */
2698HANDLE_OP_SHX_LONG_2ADDR(OP_SHR_LONG_2ADDR, "shr", (s8), >>)
2699OP_END
2700
2701/* File: c/OP_USHR_LONG_2ADDR.cpp */
2702HANDLE_OP_SHX_LONG_2ADDR(OP_USHR_LONG_2ADDR, "ushr", (u8), >>)
2703OP_END
2704
2705/* File: c/OP_ADD_FLOAT_2ADDR.cpp */
2706HANDLE_OP_X_FLOAT_2ADDR(OP_ADD_FLOAT_2ADDR, "add", +)
2707OP_END
2708
2709/* File: c/OP_SUB_FLOAT_2ADDR.cpp */
2710HANDLE_OP_X_FLOAT_2ADDR(OP_SUB_FLOAT_2ADDR, "sub", -)
2711OP_END
2712
2713/* File: c/OP_MUL_FLOAT_2ADDR.cpp */
2714HANDLE_OP_X_FLOAT_2ADDR(OP_MUL_FLOAT_2ADDR, "mul", *)
2715OP_END
2716
2717/* File: c/OP_DIV_FLOAT_2ADDR.cpp */
2718HANDLE_OP_X_FLOAT_2ADDR(OP_DIV_FLOAT_2ADDR, "div", /)
2719OP_END
2720
2721/* File: c/OP_REM_FLOAT_2ADDR.cpp */
2722HANDLE_OPCODE(OP_REM_FLOAT_2ADDR /*vA, vB*/)
2723 vdst = INST_A(inst);
2724 vsrc1 = INST_B(inst);
2725 ILOGV("|%s-float-2addr v%d,v%d", "mod", vdst, vsrc1);
2726 SET_REGISTER_FLOAT(vdst,
2727 fmodf(GET_REGISTER_FLOAT(vdst), GET_REGISTER_FLOAT(vsrc1)));
2728 FINISH(1);
2729OP_END
2730
2731/* File: c/OP_ADD_DOUBLE_2ADDR.cpp */
2732HANDLE_OP_X_DOUBLE_2ADDR(OP_ADD_DOUBLE_2ADDR, "add", +)
2733OP_END
2734
2735/* File: c/OP_SUB_DOUBLE_2ADDR.cpp */
2736HANDLE_OP_X_DOUBLE_2ADDR(OP_SUB_DOUBLE_2ADDR, "sub", -)
2737OP_END
2738
2739/* File: c/OP_MUL_DOUBLE_2ADDR.cpp */
2740HANDLE_OP_X_DOUBLE_2ADDR(OP_MUL_DOUBLE_2ADDR, "mul", *)
2741OP_END
2742
2743/* File: c/OP_DIV_DOUBLE_2ADDR.cpp */
2744HANDLE_OP_X_DOUBLE_2ADDR(OP_DIV_DOUBLE_2ADDR, "div", /)
2745OP_END
2746
2747/* File: c/OP_REM_DOUBLE_2ADDR.cpp */
2748HANDLE_OPCODE(OP_REM_DOUBLE_2ADDR /*vA, vB*/)
2749 vdst = INST_A(inst);
2750 vsrc1 = INST_B(inst);
2751 ILOGV("|%s-double-2addr v%d,v%d", "mod", vdst, vsrc1);
2752 SET_REGISTER_DOUBLE(vdst,
2753 fmod(GET_REGISTER_DOUBLE(vdst), GET_REGISTER_DOUBLE(vsrc1)));
2754 FINISH(1);
2755OP_END
2756
2757/* File: c/OP_ADD_INT_LIT16.cpp */
2758HANDLE_OP_X_INT_LIT16(OP_ADD_INT_LIT16, "add", +, 0)
2759OP_END
2760
2761/* File: c/OP_RSUB_INT.cpp */
2762HANDLE_OPCODE(OP_RSUB_INT /*vA, vB, #+CCCC*/)
2763 {
2764 vdst = INST_A(inst);
2765 vsrc1 = INST_B(inst);
2766 vsrc2 = FETCH(1);
2767 ILOGV("|rsub-int v%d,v%d,#+0x%04x", vdst, vsrc1, vsrc2);
2768 SET_REGISTER(vdst, (s2) vsrc2 - (s4) GET_REGISTER(vsrc1));
2769 }
2770 FINISH(2);
2771OP_END
2772
2773/* File: c/OP_MUL_INT_LIT16.cpp */
2774HANDLE_OP_X_INT_LIT16(OP_MUL_INT_LIT16, "mul", *, 0)
2775OP_END
2776
2777/* File: c/OP_DIV_INT_LIT16.cpp */
2778HANDLE_OP_X_INT_LIT16(OP_DIV_INT_LIT16, "div", /, 1)
2779OP_END
2780
2781/* File: c/OP_REM_INT_LIT16.cpp */
2782HANDLE_OP_X_INT_LIT16(OP_REM_INT_LIT16, "rem", %, 2)
2783OP_END
2784
2785/* File: c/OP_AND_INT_LIT16.cpp */
2786HANDLE_OP_X_INT_LIT16(OP_AND_INT_LIT16, "and", &, 0)
2787OP_END
2788
2789/* File: c/OP_OR_INT_LIT16.cpp */
2790HANDLE_OP_X_INT_LIT16(OP_OR_INT_LIT16, "or", |, 0)
2791OP_END
2792
2793/* File: c/OP_XOR_INT_LIT16.cpp */
2794HANDLE_OP_X_INT_LIT16(OP_XOR_INT_LIT16, "xor", ^, 0)
2795OP_END
2796
2797/* File: c/OP_ADD_INT_LIT8.cpp */
2798HANDLE_OP_X_INT_LIT8(OP_ADD_INT_LIT8, "add", +, 0)
2799OP_END
2800
2801/* File: c/OP_RSUB_INT_LIT8.cpp */
2802HANDLE_OPCODE(OP_RSUB_INT_LIT8 /*vAA, vBB, #+CC*/)
2803 {
2804 u2 litInfo;
2805 vdst = INST_AA(inst);
2806 litInfo = FETCH(1);
2807 vsrc1 = litInfo & 0xff;
2808 vsrc2 = litInfo >> 8;
2809 ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", "rsub", vdst, vsrc1, vsrc2);
2810 SET_REGISTER(vdst, (s1) vsrc2 - (s4) GET_REGISTER(vsrc1));
2811 }
2812 FINISH(2);
2813OP_END
2814
2815/* File: c/OP_MUL_INT_LIT8.cpp */
2816HANDLE_OP_X_INT_LIT8(OP_MUL_INT_LIT8, "mul", *, 0)
2817OP_END
2818
2819/* File: c/OP_DIV_INT_LIT8.cpp */
2820HANDLE_OP_X_INT_LIT8(OP_DIV_INT_LIT8, "div", /, 1)
2821OP_END
2822
2823/* File: c/OP_REM_INT_LIT8.cpp */
2824HANDLE_OP_X_INT_LIT8(OP_REM_INT_LIT8, "rem", %, 2)
2825OP_END
2826
2827/* File: c/OP_AND_INT_LIT8.cpp */
2828HANDLE_OP_X_INT_LIT8(OP_AND_INT_LIT8, "and", &, 0)
2829OP_END
2830
2831/* File: c/OP_OR_INT_LIT8.cpp */
2832HANDLE_OP_X_INT_LIT8(OP_OR_INT_LIT8, "or", |, 0)
2833OP_END
2834
2835/* File: c/OP_XOR_INT_LIT8.cpp */
2836HANDLE_OP_X_INT_LIT8(OP_XOR_INT_LIT8, "xor", ^, 0)
2837OP_END
2838
2839/* File: c/OP_SHL_INT_LIT8.cpp */
2840HANDLE_OP_SHX_INT_LIT8(OP_SHL_INT_LIT8, "shl", (s4), <<)
2841OP_END
2842
2843/* File: c/OP_SHR_INT_LIT8.cpp */
2844HANDLE_OP_SHX_INT_LIT8(OP_SHR_INT_LIT8, "shr", (s4), >>)
2845OP_END
2846
2847/* File: c/OP_USHR_INT_LIT8.cpp */
2848HANDLE_OP_SHX_INT_LIT8(OP_USHR_INT_LIT8, "ushr", (u4), >>)
2849OP_END
2850
2851/* File: c/OP_IGET_VOLATILE.cpp */
2852HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, )
2853OP_END
2854
2855/* File: c/OP_IPUT_VOLATILE.cpp */
2856HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, )
2857OP_END
2858
2859/* File: c/OP_SGET_VOLATILE.cpp */
2860HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, )
2861OP_END
2862
2863/* File: c/OP_SPUT_VOLATILE.cpp */
2864HANDLE_SPUT_X(OP_SPUT_VOLATILE, "-volatile", IntVolatile, )
2865OP_END
2866
2867/* File: c/OP_IGET_OBJECT_VOLATILE.cpp */
2868HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
2869OP_END
2870
2871/* File: c/OP_IGET_WIDE_VOLATILE.cpp */
2872HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
2873OP_END
2874
2875/* File: c/OP_IPUT_WIDE_VOLATILE.cpp */
2876HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
2877OP_END
2878
2879/* File: c/OP_SGET_WIDE_VOLATILE.cpp */
2880HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
2881OP_END
2882
2883/* File: c/OP_SPUT_WIDE_VOLATILE.cpp */
2884HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE)
2885OP_END
2886
2887/* File: c/OP_BREAKPOINT.cpp */
2888HANDLE_OPCODE(OP_BREAKPOINT)
2889 {
2890 /*
2891 * Restart this instruction with the original opcode. We do
2892 * this by simply jumping to the handler.
2893 *
2894 * It's probably not necessary to update "inst", but we do it
2895 * for the sake of anything that needs to do disambiguation in a
2896 * common handler with INST_INST.
2897 *
2898 * The breakpoint itself is handled over in updateDebugger(),
2899 * because we need to detect other events (method entry, single
2900 * step) and report them in the same event packet, and we're not
2901 * yet handling those through breakpoint instructions. By the
2902 * time we get here, the breakpoint has already been handled and
2903 * the thread resumed.
2904 */
2905 u1 originalOpcode = dvmGetOriginalOpcode(pc);
2906 LOGV("+++ break 0x%02x (0x%04x -> 0x%04x)\n", originalOpcode, inst,
2907 INST_REPLACE_OP(inst, originalOpcode));
2908 inst = INST_REPLACE_OP(inst, originalOpcode);
2909 FINISH_BKPT(originalOpcode);
2910 }
2911OP_END
2912
2913/* File: c/OP_THROW_VERIFICATION_ERROR.cpp */
2914HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR)
2915 EXPORT_PC();
2916 vsrc1 = INST_AA(inst);
2917 ref = FETCH(1); /* class/field/method ref */
2918 dvmThrowVerificationError(curMethod, vsrc1, ref);
2919 GOTO_exceptionThrown();
2920OP_END
2921
2922/* File: c/OP_EXECUTE_INLINE.cpp */
2923HANDLE_OPCODE(OP_EXECUTE_INLINE /*vB, {vD, vE, vF, vG}, inline@CCCC*/)
2924 {
2925 /*
2926 * This has the same form as other method calls, but we ignore
2927 * the 5th argument (vA). This is chiefly because the first four
2928 * arguments to a function on ARM are in registers.
2929 *
2930 * We only set the arguments that are actually used, leaving
2931 * the rest uninitialized. We're assuming that, if the method
2932 * needs them, they'll be specified in the call.
2933 *
2934 * However, this annoys gcc when optimizations are enabled,
2935 * causing a "may be used uninitialized" warning. Quieting
2936 * the warnings incurs a slight penalty (5%: 373ns vs. 393ns
2937 * on empty method). Note that valgrind is perfectly happy
2938 * either way as the uninitialiezd values are never actually
2939 * used.
2940 */
2941 u4 arg0, arg1, arg2, arg3;
2942 arg0 = arg1 = arg2 = arg3 = 0;
2943
2944 EXPORT_PC();
2945
2946 vsrc1 = INST_B(inst); /* #of args */
2947 ref = FETCH(1); /* inline call "ref" */
2948 vdst = FETCH(2); /* 0-4 register indices */
2949 ILOGV("|execute-inline args=%d @%d {regs=0x%04x}",
2950 vsrc1, ref, vdst);
2951
2952 assert((vdst >> 16) == 0); // 16-bit type -or- high 16 bits clear
2953 assert(vsrc1 <= 4);
2954
2955 switch (vsrc1) {
2956 case 4:
2957 arg3 = GET_REGISTER(vdst >> 12);
2958 /* fall through */
2959 case 3:
2960 arg2 = GET_REGISTER((vdst & 0x0f00) >> 8);
2961 /* fall through */
2962 case 2:
2963 arg1 = GET_REGISTER((vdst & 0x00f0) >> 4);
2964 /* fall through */
2965 case 1:
2966 arg0 = GET_REGISTER(vdst & 0x0f);
2967 /* fall through */
2968 default: // case 0
2969 ;
2970 }
2971
2972 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
2973 if (!dvmPerformInlineOp4Dbg(arg0, arg1, arg2, arg3, &retval, ref))
2974 GOTO_exceptionThrown();
2975 } else {
2976 if (!dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref))
2977 GOTO_exceptionThrown();
2978 }
2979 }
2980 FINISH(3);
2981OP_END
2982
2983/* File: c/OP_EXECUTE_INLINE_RANGE.cpp */
2984HANDLE_OPCODE(OP_EXECUTE_INLINE_RANGE /*{vCCCC..v(CCCC+AA-1)}, inline@BBBB*/)
2985 {
2986 u4 arg0, arg1, arg2, arg3;
2987 arg0 = arg1 = arg2 = arg3 = 0; /* placate gcc */
2988
2989 EXPORT_PC();
2990
2991 vsrc1 = INST_AA(inst); /* #of args */
2992 ref = FETCH(1); /* inline call "ref" */
2993 vdst = FETCH(2); /* range base */
2994 ILOGV("|execute-inline-range args=%d @%d {regs=v%d-v%d}",
2995 vsrc1, ref, vdst, vdst+vsrc1-1);
2996
2997 assert((vdst >> 16) == 0); // 16-bit type -or- high 16 bits clear
2998 assert(vsrc1 <= 4);
2999
3000 switch (vsrc1) {
3001 case 4:
3002 arg3 = GET_REGISTER(vdst+3);
3003 /* fall through */
3004 case 3:
3005 arg2 = GET_REGISTER(vdst+2);
3006 /* fall through */
3007 case 2:
3008 arg1 = GET_REGISTER(vdst+1);
3009 /* fall through */
3010 case 1:
3011 arg0 = GET_REGISTER(vdst+0);
3012 /* fall through */
3013 default: // case 0
3014 ;
3015 }
3016
3017 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
3018 if (!dvmPerformInlineOp4Dbg(arg0, arg1, arg2, arg3, &retval, ref))
3019 GOTO_exceptionThrown();
3020 } else {
3021 if (!dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref))
3022 GOTO_exceptionThrown();
3023 }
3024 }
3025 FINISH(3);
3026OP_END
3027
3028/* File: c/OP_INVOKE_OBJECT_INIT_RANGE.cpp */
3029HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
3030 {
3031 Object* obj;
3032
3033 vsrc1 = FETCH(2); /* reg number of "this" pointer */
3034 obj = GET_REGISTER_AS_OBJECT(vsrc1);
3035
3036 if (!checkForNullExportPC(obj, fp, pc))
3037 GOTO_exceptionThrown();
3038
3039 /*
3040 * The object should be marked "finalizable" when Object.<init>
3041 * completes normally. We're going to assume it does complete
3042 * (by virtue of being nothing but a return-void) and set it now.
3043 */
3044 if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISFINALIZABLE)) {
3045 EXPORT_PC();
3046 dvmSetFinalizable(obj);
3047 if (dvmGetException(self))
3048 GOTO_exceptionThrown();
3049 }
3050
3051 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
3052 /* behave like OP_INVOKE_DIRECT_RANGE */
3053 GOTO_invoke(invokeDirect, true, false);
3054 }
3055 FINISH(3);
3056 }
3057OP_END
3058
3059/* File: c/OP_RETURN_VOID_BARRIER.cpp */
3060HANDLE_OPCODE(OP_RETURN_VOID_BARRIER /**/)
3061 ILOGV("|return-void");
3062#ifndef NDEBUG
3063 retval.j = 0xababababULL; /* placate valgrind */
3064#endif
3065 ANDROID_MEMBAR_STORE();
3066 GOTO_returnFromMethod();
3067OP_END
3068
3069/* File: c/OP_IGET_QUICK.cpp */
3070HANDLE_IGET_X_QUICK(OP_IGET_QUICK, "", Int, )
3071OP_END
3072
3073/* File: c/OP_IGET_WIDE_QUICK.cpp */
3074HANDLE_IGET_X_QUICK(OP_IGET_WIDE_QUICK, "-wide", Long, _WIDE)
3075OP_END
3076
3077/* File: c/OP_IGET_OBJECT_QUICK.cpp */
3078HANDLE_IGET_X_QUICK(OP_IGET_OBJECT_QUICK, "-object", Object, _AS_OBJECT)
3079OP_END
3080
3081/* File: c/OP_IPUT_QUICK.cpp */
3082HANDLE_IPUT_X_QUICK(OP_IPUT_QUICK, "", Int, )
3083OP_END
3084
3085/* File: c/OP_IPUT_WIDE_QUICK.cpp */
3086HANDLE_IPUT_X_QUICK(OP_IPUT_WIDE_QUICK, "-wide", Long, _WIDE)
3087OP_END
3088
3089/* File: c/OP_IPUT_OBJECT_QUICK.cpp */
3090HANDLE_IPUT_X_QUICK(OP_IPUT_OBJECT_QUICK, "-object", Object, _AS_OBJECT)
3091OP_END
3092
3093/* File: c/OP_INVOKE_VIRTUAL_QUICK.cpp */
3094HANDLE_OPCODE(OP_INVOKE_VIRTUAL_QUICK /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
3095 GOTO_invoke(invokeVirtualQuick, false, false);
3096OP_END
3097
3098/* File: c/OP_INVOKE_VIRTUAL_QUICK_RANGE.cpp */
3099HANDLE_OPCODE(OP_INVOKE_VIRTUAL_QUICK_RANGE/*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
3100 GOTO_invoke(invokeVirtualQuick, true, false);
3101OP_END
3102
3103/* File: c/OP_INVOKE_SUPER_QUICK.cpp */
3104HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/)
3105 GOTO_invoke(invokeSuperQuick, false, false);
3106OP_END
3107
3108/* File: c/OP_INVOKE_SUPER_QUICK_RANGE.cpp */
3109HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/)
3110 GOTO_invoke(invokeSuperQuick, true, false);
3111OP_END
3112
3113/* File: c/OP_IPUT_OBJECT_VOLATILE.cpp */
3114HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
3115OP_END
3116
3117/* File: c/OP_SGET_OBJECT_VOLATILE.cpp */
3118HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
3119OP_END
3120
3121/* File: c/OP_SPUT_OBJECT_VOLATILE.cpp */
3122HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT)
3123OP_END
3124
3125/* File: c/OP_DISPATCH_FF.cpp */
3126HANDLE_OPCODE(OP_DISPATCH_FF)
3127 /*
3128 * Indicates extended opcode. Use next 8 bits to choose where to branch.
3129 */
3130 DISPATCH_EXTENDED(INST_AA(inst));
3131OP_END
3132
3133/* File: c/OP_CONST_CLASS_JUMBO.cpp */
3134HANDLE_OPCODE(OP_CONST_CLASS_JUMBO /*vBBBB, class@AAAAAAAA*/)
3135 {
3136 ClassObject* clazz;
3137
3138 ref = FETCH(1) | (u4)FETCH(2) << 16;
3139 vdst = FETCH(3);
3140 ILOGV("|const-class/jumbo v%d class@0x%08x", vdst, ref);
3141 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
3142 if (clazz == NULL) {
3143 EXPORT_PC();
3144 clazz = dvmResolveClass(curMethod->clazz, ref, true);
3145 if (clazz == NULL)
3146 GOTO_exceptionThrown();
3147 }
3148 SET_REGISTER(vdst, (u4) clazz);
3149 }
3150 FINISH(4);
3151OP_END
3152
3153/* File: c/OP_CHECK_CAST_JUMBO.cpp */
3154HANDLE_OPCODE(OP_CHECK_CAST_JUMBO /*vBBBB, class@AAAAAAAA*/)
3155 {
3156 ClassObject* clazz;
3157 Object* obj;
3158
3159 EXPORT_PC();
3160
3161 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class to check against */
3162 vsrc1 = FETCH(3);
3163 ILOGV("|check-cast/jumbo v%d,class@0x%08x", vsrc1, ref);
3164
3165 obj = (Object*)GET_REGISTER(vsrc1);
3166 if (obj != NULL) {
3167#if defined(WITH_EXTRA_OBJECT_VALIDATION)
3168 if (!checkForNull(obj))
3169 GOTO_exceptionThrown();
3170#endif
3171 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
3172 if (clazz == NULL) {
3173 clazz = dvmResolveClass(curMethod->clazz, ref, false);
3174 if (clazz == NULL)
3175 GOTO_exceptionThrown();
3176 }
3177 if (!dvmInstanceof(obj->clazz, clazz)) {
3178 dvmThrowClassCastException(obj->clazz, clazz);
3179 GOTO_exceptionThrown();
3180 }
3181 }
3182 }
3183 FINISH(4);
3184OP_END
3185
3186/* File: c/OP_INSTANCE_OF_JUMBO.cpp */
3187HANDLE_OPCODE(OP_INSTANCE_OF_JUMBO /*vBBBB, vCCCC, class@AAAAAAAA*/)
3188 {
3189 ClassObject* clazz;
3190 Object* obj;
3191
3192 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class to check against */
3193 vdst = FETCH(3);
3194 vsrc1 = FETCH(4); /* object to check */
3195 ILOGV("|instance-of/jumbo v%d,v%d,class@0x%08x", vdst, vsrc1, ref);
3196
3197 obj = (Object*)GET_REGISTER(vsrc1);
3198 if (obj == NULL) {
3199 SET_REGISTER(vdst, 0);
3200 } else {
3201#if defined(WITH_EXTRA_OBJECT_VALIDATION)
3202 if (!checkForNullExportPC(obj, fp, pc))
3203 GOTO_exceptionThrown();
3204#endif
3205 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
3206 if (clazz == NULL) {
3207 EXPORT_PC();
3208 clazz = dvmResolveClass(curMethod->clazz, ref, true);
3209 if (clazz == NULL)
3210 GOTO_exceptionThrown();
3211 }
3212 SET_REGISTER(vdst, dvmInstanceof(obj->clazz, clazz));
3213 }
3214 }
3215 FINISH(5);
3216OP_END
3217
3218/* File: c/OP_NEW_INSTANCE_JUMBO.cpp */
3219HANDLE_OPCODE(OP_NEW_INSTANCE_JUMBO /*vBBBB, class@AAAAAAAA*/)
3220 {
3221 ClassObject* clazz;
3222 Object* newObj;
3223
3224 EXPORT_PC();
3225
3226 ref = FETCH(1) | (u4)FETCH(2) << 16;
3227 vdst = FETCH(3);
3228 ILOGV("|new-instance/jumbo v%d,class@0x%08x", vdst, ref);
3229 clazz = dvmDexGetResolvedClass(methodClassDex, ref);
3230 if (clazz == NULL) {
3231 clazz = dvmResolveClass(curMethod->clazz, ref, false);
3232 if (clazz == NULL)
3233 GOTO_exceptionThrown();
3234 }
3235
3236 if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz))
3237 GOTO_exceptionThrown();
3238
3239#if defined(WITH_JIT)
3240 /*
3241 * The JIT needs dvmDexGetResolvedClass() to return non-null.
3242 * Since we use the portable interpreter to build the trace, this extra
3243 * check is not needed for mterp.
3244 */
3245 if ((self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) &&
3246 (!dvmDexGetResolvedClass(methodClassDex, ref))) {
3247 /* Class initialization is still ongoing - end the trace */
3248 dvmJitEndTraceSelect(self,pc);
3249 }
3250#endif
3251
3252 /*
3253 * Verifier now tests for interface/abstract class.
3254 */
3255 //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
3256 // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError,
3257 // clazz->descriptor);
3258 // GOTO_exceptionThrown();
3259 //}
3260 newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
3261 if (newObj == NULL)
3262 GOTO_exceptionThrown();
3263 SET_REGISTER(vdst, (u4) newObj);
3264 }
3265 FINISH(4);
3266OP_END
3267
3268/* File: c/OP_NEW_ARRAY_JUMBO.cpp */
3269HANDLE_OPCODE(OP_NEW_ARRAY_JUMBO /*vBBBB, vCCCC, class@AAAAAAAA*/)
3270 {
3271 ClassObject* arrayClass;
3272 ArrayObject* newArray;
3273 s4 length;
3274
3275 EXPORT_PC();
3276
3277 ref = FETCH(1) | (u4)FETCH(2) << 16;
3278 vdst = FETCH(3);
3279 vsrc1 = FETCH(4); /* length reg */
3280 ILOGV("|new-array/jumbo v%d,v%d,class@0x%08x (%d elements)",
3281 vdst, vsrc1, ref, (s4) GET_REGISTER(vsrc1));
3282 length = (s4) GET_REGISTER(vsrc1);
3283 if (length < 0) {
3284 dvmThrowNegativeArraySizeException(length);
3285 GOTO_exceptionThrown();
3286 }
3287 arrayClass = dvmDexGetResolvedClass(methodClassDex, ref);
3288 if (arrayClass == NULL) {
3289 arrayClass = dvmResolveClass(curMethod->clazz, ref, false);
3290 if (arrayClass == NULL)
3291 GOTO_exceptionThrown();
3292 }
3293 /* verifier guarantees this is an array class */
3294 assert(dvmIsArrayClass(arrayClass));
3295 assert(dvmIsClassInitialized(arrayClass));
3296
3297 newArray = dvmAllocArrayByClass(arrayClass, length, ALLOC_DONT_TRACK);
3298 if (newArray == NULL)
3299 GOTO_exceptionThrown();
3300 SET_REGISTER(vdst, (u4) newArray);
3301 }
3302 FINISH(5);
3303OP_END
3304
3305/* File: c/OP_FILLED_NEW_ARRAY_JUMBO.cpp */
3306HANDLE_OPCODE(OP_FILLED_NEW_ARRAY_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, class@AAAAAAAA*/)
3307 GOTO_invoke(filledNewArray, true, true);
3308OP_END
3309
3310/* File: c/OP_IGET_JUMBO.cpp */
3311HANDLE_IGET_X_JUMBO(OP_IGET_JUMBO, "", Int, )
3312OP_END
3313
3314/* File: c/OP_IGET_WIDE_JUMBO.cpp */
3315HANDLE_IGET_X_JUMBO(OP_IGET_WIDE_JUMBO, "-wide", Long, _WIDE)
3316OP_END
3317
3318/* File: c/OP_IGET_OBJECT_JUMBO.cpp */
3319HANDLE_IGET_X_JUMBO(OP_IGET_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
3320OP_END
3321
3322/* File: c/OP_IGET_BOOLEAN_JUMBO.cpp */
3323HANDLE_IGET_X_JUMBO(OP_IGET_BOOLEAN_JUMBO, "", Int, )
3324OP_END
3325
3326/* File: c/OP_IGET_BYTE_JUMBO.cpp */
3327HANDLE_IGET_X_JUMBO(OP_IGET_BYTE_JUMBO, "", Int, )
3328OP_END
3329
3330/* File: c/OP_IGET_CHAR_JUMBO.cpp */
3331HANDLE_IGET_X_JUMBO(OP_IGET_CHAR_JUMBO, "", Int, )
3332OP_END
3333
3334/* File: c/OP_IGET_SHORT_JUMBO.cpp */
3335HANDLE_IGET_X_JUMBO(OP_IGET_SHORT_JUMBO, "", Int, )
3336OP_END
3337
3338/* File: c/OP_IPUT_JUMBO.cpp */
3339HANDLE_IPUT_X_JUMBO(OP_IPUT_JUMBO, "", Int, )
3340OP_END
3341
3342/* File: c/OP_IPUT_WIDE_JUMBO.cpp */
3343HANDLE_IPUT_X_JUMBO(OP_IPUT_WIDE_JUMBO, "-wide", Long, _WIDE)
3344OP_END
3345
3346/* File: c/OP_IPUT_OBJECT_JUMBO.cpp */
3347/*
3348 * The VM spec says we should verify that the reference being stored into
3349 * the field is assignment compatible. In practice, many popular VMs don't
3350 * do this because it slows down a very common operation. It's not so bad
3351 * for us, since "dexopt" quickens it whenever possible, but it's still an
3352 * issue.
3353 *
3354 * To make this spec-complaint, we'd need to add a ClassObject pointer to
3355 * the Field struct, resolve the field's type descriptor at link or class
3356 * init time, and then verify the type here.
3357 */
3358HANDLE_IPUT_X_JUMBO(OP_IPUT_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
3359OP_END
3360
3361/* File: c/OP_IPUT_BOOLEAN_JUMBO.cpp */
3362HANDLE_IPUT_X_JUMBO(OP_IPUT_BOOLEAN_JUMBO, "", Int, )
3363OP_END
3364
3365/* File: c/OP_IPUT_BYTE_JUMBO.cpp */
3366HANDLE_IPUT_X_JUMBO(OP_IPUT_BYTE_JUMBO, "", Int, )
3367OP_END
3368
3369/* File: c/OP_IPUT_CHAR_JUMBO.cpp */
3370HANDLE_IPUT_X_JUMBO(OP_IPUT_CHAR_JUMBO, "", Int, )
3371OP_END
3372
3373/* File: c/OP_IPUT_SHORT_JUMBO.cpp */
3374HANDLE_IPUT_X_JUMBO(OP_IPUT_SHORT_JUMBO, "", Int, )
3375OP_END
3376
3377/* File: c/OP_SGET_JUMBO.cpp */
3378HANDLE_SGET_X_JUMBO(OP_SGET_JUMBO, "", Int, )
3379OP_END
3380
3381/* File: c/OP_SGET_WIDE_JUMBO.cpp */
3382HANDLE_SGET_X_JUMBO(OP_SGET_WIDE_JUMBO, "-wide", Long, _WIDE)
3383OP_END
3384
3385/* File: c/OP_SGET_OBJECT_JUMBO.cpp */
3386HANDLE_SGET_X_JUMBO(OP_SGET_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
3387OP_END
3388
3389/* File: c/OP_SGET_BOOLEAN_JUMBO.cpp */
3390HANDLE_SGET_X_JUMBO(OP_SGET_BOOLEAN_JUMBO, "", Int, )
3391OP_END
3392
3393/* File: c/OP_SGET_BYTE_JUMBO.cpp */
3394HANDLE_SGET_X_JUMBO(OP_SGET_BYTE_JUMBO, "", Int, )
3395OP_END
3396
3397/* File: c/OP_SGET_CHAR_JUMBO.cpp */
3398HANDLE_SGET_X_JUMBO(OP_SGET_CHAR_JUMBO, "", Int, )
3399OP_END
3400
3401/* File: c/OP_SGET_SHORT_JUMBO.cpp */
3402HANDLE_SGET_X_JUMBO(OP_SGET_SHORT_JUMBO, "", Int, )
3403OP_END
3404
3405/* File: c/OP_SPUT_JUMBO.cpp */
3406HANDLE_SPUT_X_JUMBO(OP_SPUT_JUMBO, "", Int, )
3407OP_END
3408
3409/* File: c/OP_SPUT_WIDE_JUMBO.cpp */
3410HANDLE_SPUT_X_JUMBO(OP_SPUT_WIDE_JUMBO, "-wide", Long, _WIDE)
3411OP_END
3412
3413/* File: c/OP_SPUT_OBJECT_JUMBO.cpp */
3414HANDLE_SPUT_X_JUMBO(OP_SPUT_OBJECT_JUMBO, "-object", Object, _AS_OBJECT)
3415OP_END
3416
3417/* File: c/OP_SPUT_BOOLEAN_JUMBO.cpp */
3418HANDLE_SPUT_X_JUMBO(OP_SPUT_BOOLEAN_JUMBO, "", Int, )
3419OP_END
3420
3421/* File: c/OP_SPUT_BYTE_JUMBO.cpp */
3422HANDLE_SPUT_X_JUMBO(OP_SPUT_BYTE_JUMBO, "", Int, )
3423OP_END
3424
3425/* File: c/OP_SPUT_CHAR_JUMBO.cpp */
3426HANDLE_SPUT_X_JUMBO(OP_SPUT_CHAR_JUMBO, "", Int, )
3427OP_END
3428
3429/* File: c/OP_SPUT_SHORT_JUMBO.cpp */
3430HANDLE_SPUT_X_JUMBO(OP_SPUT_SHORT_JUMBO, "", Int, )
3431OP_END
3432
3433/* File: c/OP_INVOKE_VIRTUAL_JUMBO.cpp */
3434HANDLE_OPCODE(OP_INVOKE_VIRTUAL_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
3435 GOTO_invoke(invokeVirtual, true, true);
3436OP_END
3437
3438/* File: c/OP_INVOKE_SUPER_JUMBO.cpp */
3439HANDLE_OPCODE(OP_INVOKE_SUPER_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
3440 GOTO_invoke(invokeSuper, true, true);
3441OP_END
3442
3443/* File: c/OP_INVOKE_DIRECT_JUMBO.cpp */
3444HANDLE_OPCODE(OP_INVOKE_DIRECT_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
3445 GOTO_invoke(invokeDirect, true, true);
3446OP_END
3447
3448/* File: c/OP_INVOKE_STATIC_JUMBO.cpp */
3449HANDLE_OPCODE(OP_INVOKE_STATIC_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
3450 GOTO_invoke(invokeStatic, true, true);
3451OP_END
3452
3453/* File: c/OP_INVOKE_INTERFACE_JUMBO.cpp */
3454HANDLE_OPCODE(OP_INVOKE_INTERFACE_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/)
3455 GOTO_invoke(invokeInterface, true, true);
3456OP_END
3457
3458/* File: c/OP_UNUSED_27FF.cpp */
3459HANDLE_OPCODE(OP_UNUSED_27FF)
3460OP_END
3461
3462/* File: c/OP_UNUSED_28FF.cpp */
3463HANDLE_OPCODE(OP_UNUSED_28FF)
3464OP_END
3465
3466/* File: c/OP_UNUSED_29FF.cpp */
3467HANDLE_OPCODE(OP_UNUSED_29FF)
3468OP_END
3469
3470/* File: c/OP_UNUSED_2AFF.cpp */
3471HANDLE_OPCODE(OP_UNUSED_2AFF)
3472OP_END
3473
3474/* File: c/OP_UNUSED_2BFF.cpp */
3475HANDLE_OPCODE(OP_UNUSED_2BFF)
3476OP_END
3477
3478/* File: c/OP_UNUSED_2CFF.cpp */
3479HANDLE_OPCODE(OP_UNUSED_2CFF)
3480OP_END
3481
3482/* File: c/OP_UNUSED_2DFF.cpp */
3483HANDLE_OPCODE(OP_UNUSED_2DFF)
3484OP_END
3485
3486/* File: c/OP_UNUSED_2EFF.cpp */
3487HANDLE_OPCODE(OP_UNUSED_2EFF)
3488OP_END
3489
3490/* File: c/OP_UNUSED_2FFF.cpp */
3491HANDLE_OPCODE(OP_UNUSED_2FFF)
3492OP_END
3493
3494/* File: c/OP_UNUSED_30FF.cpp */
3495HANDLE_OPCODE(OP_UNUSED_30FF)
3496OP_END
3497
3498/* File: c/OP_UNUSED_31FF.cpp */
3499HANDLE_OPCODE(OP_UNUSED_31FF)
3500OP_END
3501
3502/* File: c/OP_UNUSED_32FF.cpp */
3503HANDLE_OPCODE(OP_UNUSED_32FF)
3504OP_END
3505
3506/* File: c/OP_UNUSED_33FF.cpp */
3507HANDLE_OPCODE(OP_UNUSED_33FF)
3508OP_END
3509
3510/* File: c/OP_UNUSED_34FF.cpp */
3511HANDLE_OPCODE(OP_UNUSED_34FF)
3512OP_END
3513
3514/* File: c/OP_UNUSED_35FF.cpp */
3515HANDLE_OPCODE(OP_UNUSED_35FF)
3516OP_END
3517
3518/* File: c/OP_UNUSED_36FF.cpp */
3519HANDLE_OPCODE(OP_UNUSED_36FF)
3520OP_END
3521
3522/* File: c/OP_UNUSED_37FF.cpp */
3523HANDLE_OPCODE(OP_UNUSED_37FF)
3524OP_END
3525
3526/* File: c/OP_UNUSED_38FF.cpp */
3527HANDLE_OPCODE(OP_UNUSED_38FF)
3528OP_END
3529
3530/* File: c/OP_UNUSED_39FF.cpp */
3531HANDLE_OPCODE(OP_UNUSED_39FF)
3532OP_END
3533
3534/* File: c/OP_UNUSED_3AFF.cpp */
3535HANDLE_OPCODE(OP_UNUSED_3AFF)
3536OP_END
3537
3538/* File: c/OP_UNUSED_3BFF.cpp */
3539HANDLE_OPCODE(OP_UNUSED_3BFF)
3540OP_END
3541
3542/* File: c/OP_UNUSED_3CFF.cpp */
3543HANDLE_OPCODE(OP_UNUSED_3CFF)
3544OP_END
3545
3546/* File: c/OP_UNUSED_3DFF.cpp */
3547HANDLE_OPCODE(OP_UNUSED_3DFF)
3548OP_END
3549
3550/* File: c/OP_UNUSED_3EFF.cpp */
3551HANDLE_OPCODE(OP_UNUSED_3EFF)
3552OP_END
3553
3554/* File: c/OP_UNUSED_3FFF.cpp */
3555HANDLE_OPCODE(OP_UNUSED_3FFF)
3556OP_END
3557
3558/* File: c/OP_UNUSED_40FF.cpp */
3559HANDLE_OPCODE(OP_UNUSED_40FF)
3560OP_END
3561
3562/* File: c/OP_UNUSED_41FF.cpp */
3563HANDLE_OPCODE(OP_UNUSED_41FF)
3564OP_END
3565
3566/* File: c/OP_UNUSED_42FF.cpp */
3567HANDLE_OPCODE(OP_UNUSED_42FF)
3568OP_END
3569
3570/* File: c/OP_UNUSED_43FF.cpp */
3571HANDLE_OPCODE(OP_UNUSED_43FF)
3572OP_END
3573
3574/* File: c/OP_UNUSED_44FF.cpp */
3575HANDLE_OPCODE(OP_UNUSED_44FF)
3576OP_END
3577
3578/* File: c/OP_UNUSED_45FF.cpp */
3579HANDLE_OPCODE(OP_UNUSED_45FF)
3580OP_END
3581
3582/* File: c/OP_UNUSED_46FF.cpp */
3583HANDLE_OPCODE(OP_UNUSED_46FF)
3584OP_END
3585
3586/* File: c/OP_UNUSED_47FF.cpp */
3587HANDLE_OPCODE(OP_UNUSED_47FF)
3588OP_END
3589
3590/* File: c/OP_UNUSED_48FF.cpp */
3591HANDLE_OPCODE(OP_UNUSED_48FF)
3592OP_END
3593
3594/* File: c/OP_UNUSED_49FF.cpp */
3595HANDLE_OPCODE(OP_UNUSED_49FF)
3596OP_END
3597
3598/* File: c/OP_UNUSED_4AFF.cpp */
3599HANDLE_OPCODE(OP_UNUSED_4AFF)
3600OP_END
3601
3602/* File: c/OP_UNUSED_4BFF.cpp */
3603HANDLE_OPCODE(OP_UNUSED_4BFF)
3604OP_END
3605
3606/* File: c/OP_UNUSED_4CFF.cpp */
3607HANDLE_OPCODE(OP_UNUSED_4CFF)
3608OP_END
3609
3610/* File: c/OP_UNUSED_4DFF.cpp */
3611HANDLE_OPCODE(OP_UNUSED_4DFF)
3612OP_END
3613
3614/* File: c/OP_UNUSED_4EFF.cpp */
3615HANDLE_OPCODE(OP_UNUSED_4EFF)
3616OP_END
3617
3618/* File: c/OP_UNUSED_4FFF.cpp */
3619HANDLE_OPCODE(OP_UNUSED_4FFF)
3620OP_END
3621
3622/* File: c/OP_UNUSED_50FF.cpp */
3623HANDLE_OPCODE(OP_UNUSED_50FF)
3624OP_END
3625
3626/* File: c/OP_UNUSED_51FF.cpp */
3627HANDLE_OPCODE(OP_UNUSED_51FF)
3628OP_END
3629
3630/* File: c/OP_UNUSED_52FF.cpp */
3631HANDLE_OPCODE(OP_UNUSED_52FF)
3632OP_END
3633
3634/* File: c/OP_UNUSED_53FF.cpp */
3635HANDLE_OPCODE(OP_UNUSED_53FF)
3636OP_END
3637
3638/* File: c/OP_UNUSED_54FF.cpp */
3639HANDLE_OPCODE(OP_UNUSED_54FF)
3640OP_END
3641
3642/* File: c/OP_UNUSED_55FF.cpp */
3643HANDLE_OPCODE(OP_UNUSED_55FF)
3644OP_END
3645
3646/* File: c/OP_UNUSED_56FF.cpp */
3647HANDLE_OPCODE(OP_UNUSED_56FF)
3648OP_END
3649
3650/* File: c/OP_UNUSED_57FF.cpp */
3651HANDLE_OPCODE(OP_UNUSED_57FF)
3652OP_END
3653
3654/* File: c/OP_UNUSED_58FF.cpp */
3655HANDLE_OPCODE(OP_UNUSED_58FF)
3656OP_END
3657
3658/* File: c/OP_UNUSED_59FF.cpp */
3659HANDLE_OPCODE(OP_UNUSED_59FF)
3660OP_END
3661
3662/* File: c/OP_UNUSED_5AFF.cpp */
3663HANDLE_OPCODE(OP_UNUSED_5AFF)
3664OP_END
3665
3666/* File: c/OP_UNUSED_5BFF.cpp */
3667HANDLE_OPCODE(OP_UNUSED_5BFF)
3668OP_END
3669
3670/* File: c/OP_UNUSED_5CFF.cpp */
3671HANDLE_OPCODE(OP_UNUSED_5CFF)
3672OP_END
3673
3674/* File: c/OP_UNUSED_5DFF.cpp */
3675HANDLE_OPCODE(OP_UNUSED_5DFF)
3676OP_END
3677
3678/* File: c/OP_UNUSED_5EFF.cpp */
3679HANDLE_OPCODE(OP_UNUSED_5EFF)
3680OP_END
3681
3682/* File: c/OP_UNUSED_5FFF.cpp */
3683HANDLE_OPCODE(OP_UNUSED_5FFF)
3684OP_END
3685
3686/* File: c/OP_UNUSED_60FF.cpp */
3687HANDLE_OPCODE(OP_UNUSED_60FF)
3688OP_END
3689
3690/* File: c/OP_UNUSED_61FF.cpp */
3691HANDLE_OPCODE(OP_UNUSED_61FF)
3692OP_END
3693
3694/* File: c/OP_UNUSED_62FF.cpp */
3695HANDLE_OPCODE(OP_UNUSED_62FF)
3696OP_END
3697
3698/* File: c/OP_UNUSED_63FF.cpp */
3699HANDLE_OPCODE(OP_UNUSED_63FF)
3700OP_END
3701
3702/* File: c/OP_UNUSED_64FF.cpp */
3703HANDLE_OPCODE(OP_UNUSED_64FF)
3704OP_END
3705
3706/* File: c/OP_UNUSED_65FF.cpp */
3707HANDLE_OPCODE(OP_UNUSED_65FF)
3708OP_END
3709
3710/* File: c/OP_UNUSED_66FF.cpp */
3711HANDLE_OPCODE(OP_UNUSED_66FF)
3712OP_END
3713
3714/* File: c/OP_UNUSED_67FF.cpp */
3715HANDLE_OPCODE(OP_UNUSED_67FF)
3716OP_END
3717
3718/* File: c/OP_UNUSED_68FF.cpp */
3719HANDLE_OPCODE(OP_UNUSED_68FF)
3720OP_END
3721
3722/* File: c/OP_UNUSED_69FF.cpp */
3723HANDLE_OPCODE(OP_UNUSED_69FF)
3724OP_END
3725
3726/* File: c/OP_UNUSED_6AFF.cpp */
3727HANDLE_OPCODE(OP_UNUSED_6AFF)
3728OP_END
3729
3730/* File: c/OP_UNUSED_6BFF.cpp */
3731HANDLE_OPCODE(OP_UNUSED_6BFF)
3732OP_END
3733
3734/* File: c/OP_UNUSED_6CFF.cpp */
3735HANDLE_OPCODE(OP_UNUSED_6CFF)
3736OP_END
3737
3738/* File: c/OP_UNUSED_6DFF.cpp */
3739HANDLE_OPCODE(OP_UNUSED_6DFF)
3740OP_END
3741
3742/* File: c/OP_UNUSED_6EFF.cpp */
3743HANDLE_OPCODE(OP_UNUSED_6EFF)
3744OP_END
3745
3746/* File: c/OP_UNUSED_6FFF.cpp */
3747HANDLE_OPCODE(OP_UNUSED_6FFF)
3748OP_END
3749
3750/* File: c/OP_UNUSED_70FF.cpp */
3751HANDLE_OPCODE(OP_UNUSED_70FF)
3752OP_END
3753
3754/* File: c/OP_UNUSED_71FF.cpp */
3755HANDLE_OPCODE(OP_UNUSED_71FF)
3756OP_END
3757
3758/* File: c/OP_UNUSED_72FF.cpp */
3759HANDLE_OPCODE(OP_UNUSED_72FF)
3760OP_END
3761
3762/* File: c/OP_UNUSED_73FF.cpp */
3763HANDLE_OPCODE(OP_UNUSED_73FF)
3764OP_END
3765
3766/* File: c/OP_UNUSED_74FF.cpp */
3767HANDLE_OPCODE(OP_UNUSED_74FF)
3768OP_END
3769
3770/* File: c/OP_UNUSED_75FF.cpp */
3771HANDLE_OPCODE(OP_UNUSED_75FF)
3772OP_END
3773
3774/* File: c/OP_UNUSED_76FF.cpp */
3775HANDLE_OPCODE(OP_UNUSED_76FF)
3776OP_END
3777
3778/* File: c/OP_UNUSED_77FF.cpp */
3779HANDLE_OPCODE(OP_UNUSED_77FF)
3780OP_END
3781
3782/* File: c/OP_UNUSED_78FF.cpp */
3783HANDLE_OPCODE(OP_UNUSED_78FF)
3784OP_END
3785
3786/* File: c/OP_UNUSED_79FF.cpp */
3787HANDLE_OPCODE(OP_UNUSED_79FF)
3788OP_END
3789
3790/* File: c/OP_UNUSED_7AFF.cpp */
3791HANDLE_OPCODE(OP_UNUSED_7AFF)
3792OP_END
3793
3794/* File: c/OP_UNUSED_7BFF.cpp */
3795HANDLE_OPCODE(OP_UNUSED_7BFF)
3796OP_END
3797
3798/* File: c/OP_UNUSED_7CFF.cpp */
3799HANDLE_OPCODE(OP_UNUSED_7CFF)
3800OP_END
3801
3802/* File: c/OP_UNUSED_7DFF.cpp */
3803HANDLE_OPCODE(OP_UNUSED_7DFF)
3804OP_END
3805
3806/* File: c/OP_UNUSED_7EFF.cpp */
3807HANDLE_OPCODE(OP_UNUSED_7EFF)
3808OP_END
3809
3810/* File: c/OP_UNUSED_7FFF.cpp */
3811HANDLE_OPCODE(OP_UNUSED_7FFF)
3812OP_END
3813
3814/* File: c/OP_UNUSED_80FF.cpp */
3815HANDLE_OPCODE(OP_UNUSED_80FF)
3816OP_END
3817
3818/* File: c/OP_UNUSED_81FF.cpp */
3819HANDLE_OPCODE(OP_UNUSED_81FF)
3820OP_END
3821
3822/* File: c/OP_UNUSED_82FF.cpp */
3823HANDLE_OPCODE(OP_UNUSED_82FF)
3824OP_END
3825
3826/* File: c/OP_UNUSED_83FF.cpp */
3827HANDLE_OPCODE(OP_UNUSED_83FF)
3828OP_END
3829
3830/* File: c/OP_UNUSED_84FF.cpp */
3831HANDLE_OPCODE(OP_UNUSED_84FF)
3832OP_END
3833
3834/* File: c/OP_UNUSED_85FF.cpp */
3835HANDLE_OPCODE(OP_UNUSED_85FF)
3836OP_END
3837
3838/* File: c/OP_UNUSED_86FF.cpp */
3839HANDLE_OPCODE(OP_UNUSED_86FF)
3840OP_END
3841
3842/* File: c/OP_UNUSED_87FF.cpp */
3843HANDLE_OPCODE(OP_UNUSED_87FF)
3844OP_END
3845
3846/* File: c/OP_UNUSED_88FF.cpp */
3847HANDLE_OPCODE(OP_UNUSED_88FF)
3848OP_END
3849
3850/* File: c/OP_UNUSED_89FF.cpp */
3851HANDLE_OPCODE(OP_UNUSED_89FF)
3852OP_END
3853
3854/* File: c/OP_UNUSED_8AFF.cpp */
3855HANDLE_OPCODE(OP_UNUSED_8AFF)
3856OP_END
3857
3858/* File: c/OP_UNUSED_8BFF.cpp */
3859HANDLE_OPCODE(OP_UNUSED_8BFF)
3860OP_END
3861
3862/* File: c/OP_UNUSED_8CFF.cpp */
3863HANDLE_OPCODE(OP_UNUSED_8CFF)
3864OP_END
3865
3866/* File: c/OP_UNUSED_8DFF.cpp */
3867HANDLE_OPCODE(OP_UNUSED_8DFF)
3868OP_END
3869
3870/* File: c/OP_UNUSED_8EFF.cpp */
3871HANDLE_OPCODE(OP_UNUSED_8EFF)
3872OP_END
3873
3874/* File: c/OP_UNUSED_8FFF.cpp */
3875HANDLE_OPCODE(OP_UNUSED_8FFF)
3876OP_END
3877
3878/* File: c/OP_UNUSED_90FF.cpp */
3879HANDLE_OPCODE(OP_UNUSED_90FF)
3880OP_END
3881
3882/* File: c/OP_UNUSED_91FF.cpp */
3883HANDLE_OPCODE(OP_UNUSED_91FF)
3884OP_END
3885
3886/* File: c/OP_UNUSED_92FF.cpp */
3887HANDLE_OPCODE(OP_UNUSED_92FF)
3888OP_END
3889
3890/* File: c/OP_UNUSED_93FF.cpp */
3891HANDLE_OPCODE(OP_UNUSED_93FF)
3892OP_END
3893
3894/* File: c/OP_UNUSED_94FF.cpp */
3895HANDLE_OPCODE(OP_UNUSED_94FF)
3896OP_END
3897
3898/* File: c/OP_UNUSED_95FF.cpp */
3899HANDLE_OPCODE(OP_UNUSED_95FF)
3900OP_END
3901
3902/* File: c/OP_UNUSED_96FF.cpp */
3903HANDLE_OPCODE(OP_UNUSED_96FF)
3904OP_END
3905
3906/* File: c/OP_UNUSED_97FF.cpp */
3907HANDLE_OPCODE(OP_UNUSED_97FF)
3908OP_END
3909
3910/* File: c/OP_UNUSED_98FF.cpp */
3911HANDLE_OPCODE(OP_UNUSED_98FF)
3912OP_END
3913
3914/* File: c/OP_UNUSED_99FF.cpp */
3915HANDLE_OPCODE(OP_UNUSED_99FF)
3916OP_END
3917
3918/* File: c/OP_UNUSED_9AFF.cpp */
3919HANDLE_OPCODE(OP_UNUSED_9AFF)
3920OP_END
3921
3922/* File: c/OP_UNUSED_9BFF.cpp */
3923HANDLE_OPCODE(OP_UNUSED_9BFF)
3924OP_END
3925
3926/* File: c/OP_UNUSED_9CFF.cpp */
3927HANDLE_OPCODE(OP_UNUSED_9CFF)
3928OP_END
3929
3930/* File: c/OP_UNUSED_9DFF.cpp */
3931HANDLE_OPCODE(OP_UNUSED_9DFF)
3932OP_END
3933
3934/* File: c/OP_UNUSED_9EFF.cpp */
3935HANDLE_OPCODE(OP_UNUSED_9EFF)
3936OP_END
3937
3938/* File: c/OP_UNUSED_9FFF.cpp */
3939HANDLE_OPCODE(OP_UNUSED_9FFF)
3940OP_END
3941
3942/* File: c/OP_UNUSED_A0FF.cpp */
3943HANDLE_OPCODE(OP_UNUSED_A0FF)
3944OP_END
3945
3946/* File: c/OP_UNUSED_A1FF.cpp */
3947HANDLE_OPCODE(OP_UNUSED_A1FF)
3948OP_END
3949
3950/* File: c/OP_UNUSED_A2FF.cpp */
3951HANDLE_OPCODE(OP_UNUSED_A2FF)
3952OP_END
3953
3954/* File: c/OP_UNUSED_A3FF.cpp */
3955HANDLE_OPCODE(OP_UNUSED_A3FF)
3956OP_END
3957
3958/* File: c/OP_UNUSED_A4FF.cpp */
3959HANDLE_OPCODE(OP_UNUSED_A4FF)
3960OP_END
3961
3962/* File: c/OP_UNUSED_A5FF.cpp */
3963HANDLE_OPCODE(OP_UNUSED_A5FF)
3964OP_END
3965
3966/* File: c/OP_UNUSED_A6FF.cpp */
3967HANDLE_OPCODE(OP_UNUSED_A6FF)
3968OP_END
3969
3970/* File: c/OP_UNUSED_A7FF.cpp */
3971HANDLE_OPCODE(OP_UNUSED_A7FF)
3972OP_END
3973
3974/* File: c/OP_UNUSED_A8FF.cpp */
3975HANDLE_OPCODE(OP_UNUSED_A8FF)
3976OP_END
3977
3978/* File: c/OP_UNUSED_A9FF.cpp */
3979HANDLE_OPCODE(OP_UNUSED_A9FF)
3980OP_END
3981
3982/* File: c/OP_UNUSED_AAFF.cpp */
3983HANDLE_OPCODE(OP_UNUSED_AAFF)
3984OP_END
3985
3986/* File: c/OP_UNUSED_ABFF.cpp */
3987HANDLE_OPCODE(OP_UNUSED_ABFF)
3988OP_END
3989
3990/* File: c/OP_UNUSED_ACFF.cpp */
3991HANDLE_OPCODE(OP_UNUSED_ACFF)
3992OP_END
3993
3994/* File: c/OP_UNUSED_ADFF.cpp */
3995HANDLE_OPCODE(OP_UNUSED_ADFF)
3996OP_END
3997
3998/* File: c/OP_UNUSED_AEFF.cpp */
3999HANDLE_OPCODE(OP_UNUSED_AEFF)
4000OP_END
4001
4002/* File: c/OP_UNUSED_AFFF.cpp */
4003HANDLE_OPCODE(OP_UNUSED_AFFF)
4004OP_END
4005
4006/* File: c/OP_UNUSED_B0FF.cpp */
4007HANDLE_OPCODE(OP_UNUSED_B0FF)
4008OP_END
4009
4010/* File: c/OP_UNUSED_B1FF.cpp */
4011HANDLE_OPCODE(OP_UNUSED_B1FF)
4012OP_END
4013
4014/* File: c/OP_UNUSED_B2FF.cpp */
4015HANDLE_OPCODE(OP_UNUSED_B2FF)
4016OP_END
4017
4018/* File: c/OP_UNUSED_B3FF.cpp */
4019HANDLE_OPCODE(OP_UNUSED_B3FF)
4020OP_END
4021
4022/* File: c/OP_UNUSED_B4FF.cpp */
4023HANDLE_OPCODE(OP_UNUSED_B4FF)
4024OP_END
4025
4026/* File: c/OP_UNUSED_B5FF.cpp */
4027HANDLE_OPCODE(OP_UNUSED_B5FF)
4028OP_END
4029
4030/* File: c/OP_UNUSED_B6FF.cpp */
4031HANDLE_OPCODE(OP_UNUSED_B6FF)
4032OP_END
4033
4034/* File: c/OP_UNUSED_B7FF.cpp */
4035HANDLE_OPCODE(OP_UNUSED_B7FF)
4036OP_END
4037
4038/* File: c/OP_UNUSED_B8FF.cpp */
4039HANDLE_OPCODE(OP_UNUSED_B8FF)
4040OP_END
4041
4042/* File: c/OP_UNUSED_B9FF.cpp */
4043HANDLE_OPCODE(OP_UNUSED_B9FF)
4044OP_END
4045
4046/* File: c/OP_UNUSED_BAFF.cpp */
4047HANDLE_OPCODE(OP_UNUSED_BAFF)
4048OP_END
4049
4050/* File: c/OP_UNUSED_BBFF.cpp */
4051HANDLE_OPCODE(OP_UNUSED_BBFF)
4052OP_END
4053
4054/* File: c/OP_UNUSED_BCFF.cpp */
4055HANDLE_OPCODE(OP_UNUSED_BCFF)
4056OP_END
4057
4058/* File: c/OP_UNUSED_BDFF.cpp */
4059HANDLE_OPCODE(OP_UNUSED_BDFF)
4060OP_END
4061
4062/* File: c/OP_UNUSED_BEFF.cpp */
4063HANDLE_OPCODE(OP_UNUSED_BEFF)
4064OP_END
4065
4066/* File: c/OP_UNUSED_BFFF.cpp */
4067HANDLE_OPCODE(OP_UNUSED_BFFF)
4068OP_END
4069
4070/* File: c/OP_UNUSED_C0FF.cpp */
4071HANDLE_OPCODE(OP_UNUSED_C0FF)
4072OP_END
4073
4074/* File: c/OP_UNUSED_C1FF.cpp */
4075HANDLE_OPCODE(OP_UNUSED_C1FF)
4076OP_END
4077
4078/* File: c/OP_UNUSED_C2FF.cpp */
4079HANDLE_OPCODE(OP_UNUSED_C2FF)
4080OP_END
4081
4082/* File: c/OP_UNUSED_C3FF.cpp */
4083HANDLE_OPCODE(OP_UNUSED_C3FF)
4084OP_END
4085
4086/* File: c/OP_UNUSED_C4FF.cpp */
4087HANDLE_OPCODE(OP_UNUSED_C4FF)
4088OP_END
4089
4090/* File: c/OP_UNUSED_C5FF.cpp */
4091HANDLE_OPCODE(OP_UNUSED_C5FF)
4092OP_END
4093
4094/* File: c/OP_UNUSED_C6FF.cpp */
4095HANDLE_OPCODE(OP_UNUSED_C6FF)
4096OP_END
4097
4098/* File: c/OP_UNUSED_C7FF.cpp */
4099HANDLE_OPCODE(OP_UNUSED_C7FF)
4100OP_END
4101
4102/* File: c/OP_UNUSED_C8FF.cpp */
4103HANDLE_OPCODE(OP_UNUSED_C8FF)
4104OP_END
4105
4106/* File: c/OP_UNUSED_C9FF.cpp */
4107HANDLE_OPCODE(OP_UNUSED_C9FF)
4108OP_END
4109
4110/* File: c/OP_UNUSED_CAFF.cpp */
4111HANDLE_OPCODE(OP_UNUSED_CAFF)
4112OP_END
4113
4114/* File: c/OP_UNUSED_CBFF.cpp */
4115HANDLE_OPCODE(OP_UNUSED_CBFF)
4116OP_END
4117
4118/* File: c/OP_UNUSED_CCFF.cpp */
4119HANDLE_OPCODE(OP_UNUSED_CCFF)
4120OP_END
4121
4122/* File: c/OP_UNUSED_CDFF.cpp */
4123HANDLE_OPCODE(OP_UNUSED_CDFF)
4124OP_END
4125
4126/* File: c/OP_UNUSED_CEFF.cpp */
4127HANDLE_OPCODE(OP_UNUSED_CEFF)
4128OP_END
4129
4130/* File: c/OP_UNUSED_CFFF.cpp */
4131HANDLE_OPCODE(OP_UNUSED_CFFF)
4132OP_END
4133
4134/* File: c/OP_UNUSED_D0FF.cpp */
4135HANDLE_OPCODE(OP_UNUSED_D0FF)
4136OP_END
4137
4138/* File: c/OP_UNUSED_D1FF.cpp */
4139HANDLE_OPCODE(OP_UNUSED_D1FF)
4140OP_END
4141
4142/* File: c/OP_UNUSED_D2FF.cpp */
4143HANDLE_OPCODE(OP_UNUSED_D2FF)
4144OP_END
4145
4146/* File: c/OP_UNUSED_D3FF.cpp */
4147HANDLE_OPCODE(OP_UNUSED_D3FF)
4148OP_END
4149
4150/* File: c/OP_UNUSED_D4FF.cpp */
4151HANDLE_OPCODE(OP_UNUSED_D4FF)
4152OP_END
4153
4154/* File: c/OP_UNUSED_D5FF.cpp */
4155HANDLE_OPCODE(OP_UNUSED_D5FF)
4156OP_END
4157
4158/* File: c/OP_UNUSED_D6FF.cpp */
4159HANDLE_OPCODE(OP_UNUSED_D6FF)
4160OP_END
4161
4162/* File: c/OP_UNUSED_D7FF.cpp */
4163HANDLE_OPCODE(OP_UNUSED_D7FF)
4164OP_END
4165
4166/* File: c/OP_UNUSED_D8FF.cpp */
4167HANDLE_OPCODE(OP_UNUSED_D8FF)
4168OP_END
4169
4170/* File: c/OP_UNUSED_D9FF.cpp */
4171HANDLE_OPCODE(OP_UNUSED_D9FF)
4172OP_END
4173
4174/* File: c/OP_UNUSED_DAFF.cpp */
4175HANDLE_OPCODE(OP_UNUSED_DAFF)
4176OP_END
4177
4178/* File: c/OP_UNUSED_DBFF.cpp */
4179HANDLE_OPCODE(OP_UNUSED_DBFF)
4180OP_END
4181
4182/* File: c/OP_UNUSED_DCFF.cpp */
4183HANDLE_OPCODE(OP_UNUSED_DCFF)
4184OP_END
4185
4186/* File: c/OP_UNUSED_DDFF.cpp */
4187HANDLE_OPCODE(OP_UNUSED_DDFF)
4188OP_END
4189
4190/* File: c/OP_UNUSED_DEFF.cpp */
4191HANDLE_OPCODE(OP_UNUSED_DEFF)
4192OP_END
4193
4194/* File: c/OP_UNUSED_DFFF.cpp */
4195HANDLE_OPCODE(OP_UNUSED_DFFF)
4196OP_END
4197
4198/* File: c/OP_UNUSED_E0FF.cpp */
4199HANDLE_OPCODE(OP_UNUSED_E0FF)
4200OP_END
4201
4202/* File: c/OP_UNUSED_E1FF.cpp */
4203HANDLE_OPCODE(OP_UNUSED_E1FF)
4204OP_END
4205
4206/* File: c/OP_UNUSED_E2FF.cpp */
4207HANDLE_OPCODE(OP_UNUSED_E2FF)
4208OP_END
4209
4210/* File: c/OP_UNUSED_E3FF.cpp */
4211HANDLE_OPCODE(OP_UNUSED_E3FF)
4212OP_END
4213
4214/* File: c/OP_UNUSED_E4FF.cpp */
4215HANDLE_OPCODE(OP_UNUSED_E4FF)
4216OP_END
4217
4218/* File: c/OP_UNUSED_E5FF.cpp */
4219HANDLE_OPCODE(OP_UNUSED_E5FF)
4220OP_END
4221
4222/* File: c/OP_UNUSED_E6FF.cpp */
4223HANDLE_OPCODE(OP_UNUSED_E6FF)
4224OP_END
4225
4226/* File: c/OP_UNUSED_E7FF.cpp */
4227HANDLE_OPCODE(OP_UNUSED_E7FF)
4228OP_END
4229
4230/* File: c/OP_UNUSED_E8FF.cpp */
4231HANDLE_OPCODE(OP_UNUSED_E8FF)
4232OP_END
4233
4234/* File: c/OP_UNUSED_E9FF.cpp */
4235HANDLE_OPCODE(OP_UNUSED_E9FF)
4236OP_END
4237
4238/* File: c/OP_UNUSED_EAFF.cpp */
4239HANDLE_OPCODE(OP_UNUSED_EAFF)
4240OP_END
4241
4242/* File: c/OP_UNUSED_EBFF.cpp */
4243HANDLE_OPCODE(OP_UNUSED_EBFF)
4244OP_END
4245
4246/* File: c/OP_UNUSED_ECFF.cpp */
4247HANDLE_OPCODE(OP_UNUSED_ECFF)
4248OP_END
4249
4250/* File: c/OP_UNUSED_EDFF.cpp */
4251HANDLE_OPCODE(OP_UNUSED_EDFF)
4252OP_END
4253
4254/* File: c/OP_UNUSED_EEFF.cpp */
4255HANDLE_OPCODE(OP_UNUSED_EEFF)
4256OP_END
4257
4258/* File: c/OP_UNUSED_EFFF.cpp */
4259HANDLE_OPCODE(OP_UNUSED_EFFF)
4260OP_END
4261
4262/* File: c/OP_UNUSED_F0FF.cpp */
4263HANDLE_OPCODE(OP_UNUSED_F0FF)
4264OP_END
4265
4266/* File: c/OP_UNUSED_F1FF.cpp */
4267HANDLE_OPCODE(OP_UNUSED_F1FF)
4268 /*
4269 * In portable interp, most unused opcodes will fall through to here.
4270 */
4271 LOGE("unknown opcode 0x%04x\n", inst);
4272 dvmAbort();
4273 FINISH(1);
4274OP_END
4275
4276/* File: c/OP_INVOKE_OBJECT_INIT_JUMBO.cpp */
4277HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_JUMBO /*{vCCCC..vNNNN}, meth@AAAAAAAA*/)
4278 {
4279 Object* obj;
4280
4281 vsrc1 = FETCH(4); /* reg number of "this" pointer */
4282 obj = GET_REGISTER_AS_OBJECT(vsrc1);
4283
4284 if (!checkForNullExportPC(obj, fp, pc))
4285 GOTO_exceptionThrown();
4286
4287 /*
4288 * The object should be marked "finalizable" when Object.<init>
4289 * completes normally. We're going to assume it does complete
4290 * (by virtue of being nothing but a return-void) and set it now.
4291 */
4292 if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISFINALIZABLE)) {
4293 EXPORT_PC();
4294 dvmSetFinalizable(obj);
4295 if (dvmGetException(self))
4296 GOTO_exceptionThrown();
4297 }
4298
4299 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
4300 /* behave like OP_INVOKE_DIRECT_RANGE */
4301 GOTO_invoke(invokeDirect, true, true);
4302 }
4303 FINISH(5);
4304 }
4305OP_END
4306
4307/* File: c/OP_IGET_VOLATILE_JUMBO.cpp */
4308HANDLE_IGET_X_JUMBO(OP_IGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
4309OP_END
4310
4311/* File: c/OP_IGET_WIDE_VOLATILE_JUMBO.cpp */
4312HANDLE_IGET_X_JUMBO(OP_IGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
4313OP_END
4314
4315/* File: c/OP_IGET_OBJECT_VOLATILE_JUMBO.cpp */
4316HANDLE_IGET_X_JUMBO(OP_IGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
4317OP_END
4318
4319/* File: c/OP_IPUT_VOLATILE_JUMBO.cpp */
4320HANDLE_IPUT_X_JUMBO(OP_IPUT_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
4321OP_END
4322
4323/* File: c/OP_IPUT_WIDE_VOLATILE_JUMBO.cpp */
4324HANDLE_IPUT_X_JUMBO(OP_IPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
4325OP_END
4326
4327/* File: c/OP_IPUT_OBJECT_VOLATILE_JUMBO.cpp */
4328HANDLE_IPUT_X_JUMBO(OP_IPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
4329OP_END
4330
4331/* File: c/OP_SGET_VOLATILE_JUMBO.cpp */
4332HANDLE_SGET_X_JUMBO(OP_SGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, )
4333OP_END
4334
4335/* File: c/OP_SGET_WIDE_VOLATILE_JUMBO.cpp */
4336HANDLE_SGET_X_JUMBO(OP_SGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
4337OP_END
4338
4339/* File: c/OP_SGET_OBJECT_VOLATILE_JUMBO.cpp */
4340HANDLE_SGET_X_JUMBO(OP_SGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
4341OP_END
4342
4343/* File: c/OP_SPUT_VOLATILE_JUMBO.cpp */
4344HANDLE_SPUT_X_JUMBO(OP_SPUT_VOLATILE_JUMBO, "-volatile", IntVolatile, )
4345OP_END
4346
4347/* File: c/OP_SPUT_WIDE_VOLATILE_JUMBO.cpp */
4348HANDLE_SPUT_X_JUMBO(OP_SPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE)
4349OP_END
4350
4351/* File: c/OP_SPUT_OBJECT_VOLATILE_JUMBO.cpp */
4352HANDLE_SPUT_X_JUMBO(OP_SPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT)
4353OP_END
4354
4355/* File: c/OP_THROW_VERIFICATION_ERROR_JUMBO.cpp */
4356HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR_JUMBO)
4357 EXPORT_PC();
4358 vsrc1 = FETCH(3);
4359 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class/field/method ref */
4360 dvmThrowVerificationError(curMethod, vsrc1, ref);
4361 GOTO_exceptionThrown();
4362OP_END
4363
4364/* File: c/gotoTargets.cpp */
4365/*
4366 * C footer. This has some common code shared by the various targets.
4367 */
4368
4369/*
4370 * Everything from here on is a "goto target". In the basic interpreter
4371 * we jump into these targets and then jump directly to the handler for
4372 * next instruction. Here, these are subroutines that return to the caller.
4373 */
4374
4375GOTO_TARGET(filledNewArray, bool methodCallRange, bool jumboFormat)
4376 {
4377 ClassObject* arrayClass;
4378 ArrayObject* newArray;
4379 u4* contents;
4380 char typeCh;
4381 int i;
4382 u4 arg5;
4383
4384 EXPORT_PC();
4385
4386 if (jumboFormat) {
4387 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class ref */
4388 vsrc1 = FETCH(3); /* #of elements */
4389 vdst = FETCH(4); /* range base */
4390 arg5 = -1; /* silence compiler warning */
4391 ILOGV("|filled-new-array/jumbo args=%d @0x%08x {regs=v%d-v%d}",
4392 vsrc1, ref, vdst, vdst+vsrc1-1);
4393 } else {
4394 ref = FETCH(1); /* class ref */
4395 vdst = FETCH(2); /* first 4 regs -or- range base */
4396
4397 if (methodCallRange) {
4398 vsrc1 = INST_AA(inst); /* #of elements */
4399 arg5 = -1; /* silence compiler warning */
4400 ILOGV("|filled-new-array-range args=%d @0x%04x {regs=v%d-v%d}",
4401 vsrc1, ref, vdst, vdst+vsrc1-1);
4402 } else {
4403 arg5 = INST_A(inst);
4404 vsrc1 = INST_B(inst); /* #of elements */
4405 ILOGV("|filled-new-array args=%d @0x%04x {regs=0x%04x %x}",
4406 vsrc1, ref, vdst, arg5);
4407 }
4408 }
4409
4410 /*
4411 * Resolve the array class.
4412 */
4413 arrayClass = dvmDexGetResolvedClass(methodClassDex, ref);
4414 if (arrayClass == NULL) {
4415 arrayClass = dvmResolveClass(curMethod->clazz, ref, false);
4416 if (arrayClass == NULL)
4417 GOTO_exceptionThrown();
4418 }
4419 /*
4420 if (!dvmIsArrayClass(arrayClass)) {
4421 dvmThrowRuntimeException(
4422 "filled-new-array needs array class");
4423 GOTO_exceptionThrown();
4424 }
4425 */
4426 /* verifier guarantees this is an array class */
4427 assert(dvmIsArrayClass(arrayClass));
4428 assert(dvmIsClassInitialized(arrayClass));
4429
4430 /*
4431 * Create an array of the specified type.
4432 */
4433 LOGVV("+++ filled-new-array type is '%s'\n", arrayClass->descriptor);
4434 typeCh = arrayClass->descriptor[1];
4435 if (typeCh == 'D' || typeCh == 'J') {
4436 /* category 2 primitives not allowed */
4437 dvmThrowRuntimeException("bad filled array req");
4438 GOTO_exceptionThrown();
4439 } else if (typeCh != 'L' && typeCh != '[' && typeCh != 'I') {
4440 /* TODO: requires multiple "fill in" loops with different widths */
4441 LOGE("non-int primitives not implemented\n");
4442 dvmThrowInternalError(
4443 "filled-new-array not implemented for anything but 'int'");
4444 GOTO_exceptionThrown();
4445 }
4446
4447 newArray = dvmAllocArrayByClass(arrayClass, vsrc1, ALLOC_DONT_TRACK);
4448 if (newArray == NULL)
4449 GOTO_exceptionThrown();
4450
4451 /*
4452 * Fill in the elements. It's legal for vsrc1 to be zero.
4453 */
4454 contents = (u4*)(void*)newArray->contents;
4455 if (methodCallRange) {
4456 for (i = 0; i < vsrc1; i++)
4457 contents[i] = GET_REGISTER(vdst+i);
4458 } else {
4459 assert(vsrc1 <= 5);
4460 if (vsrc1 == 5) {
4461 contents[4] = GET_REGISTER(arg5);
4462 vsrc1--;
4463 }
4464 for (i = 0; i < vsrc1; i++) {
4465 contents[i] = GET_REGISTER(vdst & 0x0f);
4466 vdst >>= 4;
4467 }
4468 }
4469 if (typeCh == 'L' || typeCh == '[') {
4470 dvmWriteBarrierArray(newArray, 0, newArray->length);
4471 }
4472
Carl Shapiro92a3b692011-04-29 19:19:46 -07004473 retval.l = (Object*)newArray;
Carl Shapirocd8f5e72011-04-20 16:12:46 -07004474 }
4475 if (jumboFormat) {
4476 FINISH(5);
4477 } else {
4478 FINISH(3);
4479 }
4480GOTO_TARGET_END
4481
4482
4483GOTO_TARGET(invokeVirtual, bool methodCallRange, bool jumboFormat)
4484 {
4485 Method* baseMethod;
4486 Object* thisPtr;
4487
4488 EXPORT_PC();
4489
4490 if (jumboFormat) {
4491 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
4492 vsrc1 = FETCH(3); /* count */
4493 vdst = FETCH(4); /* first reg */
4494 ADJUST_PC(2); /* advance pc partially to make returns easier */
4495 ILOGV("|invoke-virtual/jumbo args=%d @0x%08x {regs=v%d-v%d}",
4496 vsrc1, ref, vdst, vdst+vsrc1-1);
4497 thisPtr = (Object*) GET_REGISTER(vdst);
4498 } else {
4499 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4500 ref = FETCH(1); /* method ref */
4501 vdst = FETCH(2); /* 4 regs -or- first reg */
4502
4503 /*
4504 * The object against which we are executing a method is always
4505 * in the first argument.
4506 */
4507 if (methodCallRange) {
4508 assert(vsrc1 > 0);
4509 ILOGV("|invoke-virtual-range args=%d @0x%04x {regs=v%d-v%d}",
4510 vsrc1, ref, vdst, vdst+vsrc1-1);
4511 thisPtr = (Object*) GET_REGISTER(vdst);
4512 } else {
4513 assert((vsrc1>>4) > 0);
4514 ILOGV("|invoke-virtual args=%d @0x%04x {regs=0x%04x %x}",
4515 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4516 thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
4517 }
4518 }
4519
4520 if (!checkForNull(thisPtr))
4521 GOTO_exceptionThrown();
4522
4523 /*
4524 * Resolve the method. This is the correct method for the static
4525 * type of the object. We also verify access permissions here.
4526 */
4527 baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
4528 if (baseMethod == NULL) {
4529 baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
4530 if (baseMethod == NULL) {
4531 ILOGV("+ unknown method or access denied\n");
4532 GOTO_exceptionThrown();
4533 }
4534 }
4535
4536 /*
4537 * Combine the object we found with the vtable offset in the
4538 * method.
4539 */
4540 assert(baseMethod->methodIndex < thisPtr->clazz->vtableCount);
4541 methodToCall = thisPtr->clazz->vtable[baseMethod->methodIndex];
4542
4543#if defined(WITH_JIT) && defined(MTERP_STUB)
4544 self->methodToCall = methodToCall;
4545 self->callsiteClass = thisPtr->clazz;
4546#endif
4547
4548#if 0
4549 if (dvmIsAbstractMethod(methodToCall)) {
4550 /*
4551 * This can happen if you create two classes, Base and Sub, where
4552 * Sub is a sub-class of Base. Declare a protected abstract
4553 * method foo() in Base, and invoke foo() from a method in Base.
4554 * Base is an "abstract base class" and is never instantiated
4555 * directly. Now, Override foo() in Sub, and use Sub. This
4556 * Works fine unless Sub stops providing an implementation of
4557 * the method.
4558 */
4559 dvmThrowAbstractMethodError("abstract method not implemented");
4560 GOTO_exceptionThrown();
4561 }
4562#else
4563 assert(!dvmIsAbstractMethod(methodToCall) ||
4564 methodToCall->nativeFunc != NULL);
4565#endif
4566
4567 LOGVV("+++ base=%s.%s virtual[%d]=%s.%s\n",
4568 baseMethod->clazz->descriptor, baseMethod->name,
4569 (u4) baseMethod->methodIndex,
4570 methodToCall->clazz->descriptor, methodToCall->name);
4571 assert(methodToCall != NULL);
4572
4573#if 0
4574 if (vsrc1 != methodToCall->insSize) {
4575 LOGW("WRONG METHOD: base=%s.%s virtual[%d]=%s.%s\n",
4576 baseMethod->clazz->descriptor, baseMethod->name,
4577 (u4) baseMethod->methodIndex,
4578 methodToCall->clazz->descriptor, methodToCall->name);
4579 //dvmDumpClass(baseMethod->clazz);
4580 //dvmDumpClass(methodToCall->clazz);
4581 dvmDumpAllClasses(0);
4582 }
4583#endif
4584
4585 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4586 }
4587GOTO_TARGET_END
4588
4589GOTO_TARGET(invokeSuper, bool methodCallRange, bool jumboFormat)
4590 {
4591 Method* baseMethod;
4592 u2 thisReg;
4593
4594 EXPORT_PC();
4595
4596 if (jumboFormat) {
4597 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
4598 vsrc1 = FETCH(3); /* count */
4599 vdst = FETCH(4); /* first reg */
4600 ADJUST_PC(2); /* advance pc partially to make returns easier */
4601 ILOGV("|invoke-super/jumbo args=%d @0x%08x {regs=v%d-v%d}",
4602 vsrc1, ref, vdst, vdst+vsrc1-1);
4603 thisReg = vdst;
4604 } else {
4605 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4606 ref = FETCH(1); /* method ref */
4607 vdst = FETCH(2); /* 4 regs -or- first reg */
4608
4609 if (methodCallRange) {
4610 ILOGV("|invoke-super-range args=%d @0x%04x {regs=v%d-v%d}",
4611 vsrc1, ref, vdst, vdst+vsrc1-1);
4612 thisReg = vdst;
4613 } else {
4614 ILOGV("|invoke-super args=%d @0x%04x {regs=0x%04x %x}",
4615 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4616 thisReg = vdst & 0x0f;
4617 }
4618 }
4619
4620 /* impossible in well-formed code, but we must check nevertheless */
4621 if (!checkForNull((Object*) GET_REGISTER(thisReg)))
4622 GOTO_exceptionThrown();
4623
4624 /*
4625 * Resolve the method. This is the correct method for the static
4626 * type of the object. We also verify access permissions here.
4627 * The first arg to dvmResolveMethod() is just the referring class
4628 * (used for class loaders and such), so we don't want to pass
4629 * the superclass into the resolution call.
4630 */
4631 baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
4632 if (baseMethod == NULL) {
4633 baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
4634 if (baseMethod == NULL) {
4635 ILOGV("+ unknown method or access denied\n");
4636 GOTO_exceptionThrown();
4637 }
4638 }
4639
4640 /*
4641 * Combine the object we found with the vtable offset in the
4642 * method's class.
4643 *
4644 * We're using the current method's class' superclass, not the
4645 * superclass of "this". This is because we might be executing
4646 * in a method inherited from a superclass, and we want to run
4647 * in that class' superclass.
4648 */
4649 if (baseMethod->methodIndex >= curMethod->clazz->super->vtableCount) {
4650 /*
4651 * Method does not exist in the superclass. Could happen if
4652 * superclass gets updated.
4653 */
4654 dvmThrowNoSuchMethodError(baseMethod->name);
4655 GOTO_exceptionThrown();
4656 }
4657 methodToCall = curMethod->clazz->super->vtable[baseMethod->methodIndex];
4658
4659#if 0
4660 if (dvmIsAbstractMethod(methodToCall)) {
4661 dvmThrowAbstractMethodError("abstract method not implemented");
4662 GOTO_exceptionThrown();
4663 }
4664#else
4665 assert(!dvmIsAbstractMethod(methodToCall) ||
4666 methodToCall->nativeFunc != NULL);
4667#endif
4668 LOGVV("+++ base=%s.%s super-virtual=%s.%s\n",
4669 baseMethod->clazz->descriptor, baseMethod->name,
4670 methodToCall->clazz->descriptor, methodToCall->name);
4671 assert(methodToCall != NULL);
4672
4673 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4674 }
4675GOTO_TARGET_END
4676
4677GOTO_TARGET(invokeInterface, bool methodCallRange, bool jumboFormat)
4678 {
4679 Object* thisPtr;
4680 ClassObject* thisClass;
4681
4682 EXPORT_PC();
4683
4684 if (jumboFormat) {
4685 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
4686 vsrc1 = FETCH(3); /* count */
4687 vdst = FETCH(4); /* first reg */
4688 ADJUST_PC(2); /* advance pc partially to make returns easier */
4689 ILOGV("|invoke-interface/jumbo args=%d @0x%08x {regs=v%d-v%d}",
4690 vsrc1, ref, vdst, vdst+vsrc1-1);
4691 thisPtr = (Object*) GET_REGISTER(vdst);
4692 } else {
4693 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4694 ref = FETCH(1); /* method ref */
4695 vdst = FETCH(2); /* 4 regs -or- first reg */
4696
4697 /*
4698 * The object against which we are executing a method is always
4699 * in the first argument.
4700 */
4701 if (methodCallRange) {
4702 assert(vsrc1 > 0);
4703 ILOGV("|invoke-interface-range args=%d @0x%04x {regs=v%d-v%d}",
4704 vsrc1, ref, vdst, vdst+vsrc1-1);
4705 thisPtr = (Object*) GET_REGISTER(vdst);
4706 } else {
4707 assert((vsrc1>>4) > 0);
4708 ILOGV("|invoke-interface args=%d @0x%04x {regs=0x%04x %x}",
4709 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4710 thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
4711 }
4712 }
4713
4714 if (!checkForNull(thisPtr))
4715 GOTO_exceptionThrown();
4716
4717 thisClass = thisPtr->clazz;
4718
4719
4720 /*
4721 * Given a class and a method index, find the Method* with the
4722 * actual code we want to execute.
4723 */
4724 methodToCall = dvmFindInterfaceMethodInCache(thisClass, ref, curMethod,
4725 methodClassDex);
4726#if defined(WITH_JIT) && defined(MTERP_STUB)
4727 self->callsiteClass = thisClass;
4728 self->methodToCall = methodToCall;
4729#endif
4730 if (methodToCall == NULL) {
4731 assert(dvmCheckException(self));
4732 GOTO_exceptionThrown();
4733 }
4734
4735 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4736 }
4737GOTO_TARGET_END
4738
4739GOTO_TARGET(invokeDirect, bool methodCallRange, bool jumboFormat)
4740 {
4741 u2 thisReg;
4742
4743 EXPORT_PC();
4744
4745 if (jumboFormat) {
4746 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
4747 vsrc1 = FETCH(3); /* count */
4748 vdst = FETCH(4); /* first reg */
4749 ADJUST_PC(2); /* advance pc partially to make returns easier */
4750 ILOGV("|invoke-direct/jumbo args=%d @0x%08x {regs=v%d-v%d}",
4751 vsrc1, ref, vdst, vdst+vsrc1-1);
4752 thisReg = vdst;
4753 } else {
4754 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4755 ref = FETCH(1); /* method ref */
4756 vdst = FETCH(2); /* 4 regs -or- first reg */
4757
4758 if (methodCallRange) {
4759 ILOGV("|invoke-direct-range args=%d @0x%04x {regs=v%d-v%d}",
4760 vsrc1, ref, vdst, vdst+vsrc1-1);
4761 thisReg = vdst;
4762 } else {
4763 ILOGV("|invoke-direct args=%d @0x%04x {regs=0x%04x %x}",
4764 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4765 thisReg = vdst & 0x0f;
4766 }
4767 }
4768
4769 if (!checkForNull((Object*) GET_REGISTER(thisReg)))
4770 GOTO_exceptionThrown();
4771
4772 methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
4773 if (methodToCall == NULL) {
4774 methodToCall = dvmResolveMethod(curMethod->clazz, ref,
4775 METHOD_DIRECT);
4776 if (methodToCall == NULL) {
4777 ILOGV("+ unknown direct method\n"); // should be impossible
4778 GOTO_exceptionThrown();
4779 }
4780 }
4781 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4782 }
4783GOTO_TARGET_END
4784
4785GOTO_TARGET(invokeStatic, bool methodCallRange, bool jumboFormat)
4786 EXPORT_PC();
4787
4788 if (jumboFormat) {
4789 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */
4790 vsrc1 = FETCH(3); /* count */
4791 vdst = FETCH(4); /* first reg */
4792 ADJUST_PC(2); /* advance pc partially to make returns easier */
4793 ILOGV("|invoke-static/jumbo args=%d @0x%08x {regs=v%d-v%d}",
4794 vsrc1, ref, vdst, vdst+vsrc1-1);
4795 } else {
4796 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4797 ref = FETCH(1); /* method ref */
4798 vdst = FETCH(2); /* 4 regs -or- first reg */
4799
4800 if (methodCallRange)
4801 ILOGV("|invoke-static-range args=%d @0x%04x {regs=v%d-v%d}",
4802 vsrc1, ref, vdst, vdst+vsrc1-1);
4803 else
4804 ILOGV("|invoke-static args=%d @0x%04x {regs=0x%04x %x}",
4805 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4806 }
4807
4808 methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
4809 if (methodToCall == NULL) {
4810 methodToCall = dvmResolveMethod(curMethod->clazz, ref, METHOD_STATIC);
4811 if (methodToCall == NULL) {
4812 ILOGV("+ unknown method\n");
4813 GOTO_exceptionThrown();
4814 }
4815
4816#if defined(WITH_JIT) && defined(MTERP_STUB)
4817 /*
4818 * The JIT needs dvmDexGetResolvedMethod() to return non-null.
4819 * Include the check if this code is being used as a stub
4820 * called from the assembly interpreter.
4821 */
4822 if ((self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) &&
4823 (dvmDexGetResolvedMethod(methodClassDex, ref) == NULL)) {
4824 /* Class initialization is still ongoing */
4825 dvmJitEndTraceSelect(self,pc);
4826 }
4827#endif
4828 }
4829 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4830GOTO_TARGET_END
4831
4832GOTO_TARGET(invokeVirtualQuick, bool methodCallRange, bool jumboFormat)
4833 {
4834 Object* thisPtr;
4835
4836 EXPORT_PC();
4837
4838 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4839 ref = FETCH(1); /* vtable index */
4840 vdst = FETCH(2); /* 4 regs -or- first reg */
4841
4842 /*
4843 * The object against which we are executing a method is always
4844 * in the first argument.
4845 */
4846 if (methodCallRange) {
4847 assert(vsrc1 > 0);
4848 ILOGV("|invoke-virtual-quick-range args=%d @0x%04x {regs=v%d-v%d}",
4849 vsrc1, ref, vdst, vdst+vsrc1-1);
4850 thisPtr = (Object*) GET_REGISTER(vdst);
4851 } else {
4852 assert((vsrc1>>4) > 0);
4853 ILOGV("|invoke-virtual-quick args=%d @0x%04x {regs=0x%04x %x}",
4854 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4855 thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
4856 }
4857
4858 if (!checkForNull(thisPtr))
4859 GOTO_exceptionThrown();
4860
4861
4862 /*
4863 * Combine the object we found with the vtable offset in the
4864 * method.
4865 */
4866 assert(ref < (unsigned int) thisPtr->clazz->vtableCount);
4867 methodToCall = thisPtr->clazz->vtable[ref];
4868#if defined(WITH_JIT) && defined(MTERP_STUB)
4869 self->callsiteClass = thisPtr->clazz;
4870 self->methodToCall = methodToCall;
4871#endif
4872
4873#if 0
4874 if (dvmIsAbstractMethod(methodToCall)) {
4875 dvmThrowAbstractMethodError("abstract method not implemented");
4876 GOTO_exceptionThrown();
4877 }
4878#else
4879 assert(!dvmIsAbstractMethod(methodToCall) ||
4880 methodToCall->nativeFunc != NULL);
4881#endif
4882
4883 LOGVV("+++ virtual[%d]=%s.%s\n",
4884 ref, methodToCall->clazz->descriptor, methodToCall->name);
4885 assert(methodToCall != NULL);
4886
4887 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4888 }
4889GOTO_TARGET_END
4890
4891GOTO_TARGET(invokeSuperQuick, bool methodCallRange, bool jumboFormat)
4892 {
4893 u2 thisReg;
4894
4895 EXPORT_PC();
4896
4897 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */
4898 ref = FETCH(1); /* vtable index */
4899 vdst = FETCH(2); /* 4 regs -or- first reg */
4900
4901 if (methodCallRange) {
4902 ILOGV("|invoke-super-quick-range args=%d @0x%04x {regs=v%d-v%d}",
4903 vsrc1, ref, vdst, vdst+vsrc1-1);
4904 thisReg = vdst;
4905 } else {
4906 ILOGV("|invoke-super-quick args=%d @0x%04x {regs=0x%04x %x}",
4907 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
4908 thisReg = vdst & 0x0f;
4909 }
4910 /* impossible in well-formed code, but we must check nevertheless */
4911 if (!checkForNull((Object*) GET_REGISTER(thisReg)))
4912 GOTO_exceptionThrown();
4913
4914#if 0 /* impossible in optimized + verified code */
4915 if (ref >= curMethod->clazz->super->vtableCount) {
4916 dvmThrowNoSuchMethodError(NULL);
4917 GOTO_exceptionThrown();
4918 }
4919#else
4920 assert(ref < (unsigned int) curMethod->clazz->super->vtableCount);
4921#endif
4922
4923 /*
4924 * Combine the object we found with the vtable offset in the
4925 * method's class.
4926 *
4927 * We're using the current method's class' superclass, not the
4928 * superclass of "this". This is because we might be executing
4929 * in a method inherited from a superclass, and we want to run
4930 * in the method's class' superclass.
4931 */
4932 methodToCall = curMethod->clazz->super->vtable[ref];
4933
4934#if 0
4935 if (dvmIsAbstractMethod(methodToCall)) {
4936 dvmThrowAbstractMethodError("abstract method not implemented");
4937 GOTO_exceptionThrown();
4938 }
4939#else
4940 assert(!dvmIsAbstractMethod(methodToCall) ||
4941 methodToCall->nativeFunc != NULL);
4942#endif
4943 LOGVV("+++ super-virtual[%d]=%s.%s\n",
4944 ref, methodToCall->clazz->descriptor, methodToCall->name);
4945 assert(methodToCall != NULL);
4946 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
4947 }
4948GOTO_TARGET_END
4949
4950
4951 /*
4952 * General handling for return-void, return, and return-wide. Put the
4953 * return value in "retval" before jumping here.
4954 */
4955GOTO_TARGET(returnFromMethod)
4956 {
4957 StackSaveArea* saveArea;
4958
4959 /*
4960 * We must do this BEFORE we pop the previous stack frame off, so
4961 * that the GC can see the return value (if any) in the local vars.
4962 *
4963 * Since this is now an interpreter switch point, we must do it before
4964 * we do anything at all.
4965 */
4966 PERIODIC_CHECKS(0);
4967
4968 ILOGV("> retval=0x%llx (leaving %s.%s %s)",
4969 retval.j, curMethod->clazz->descriptor, curMethod->name,
4970 curMethod->shorty);
4971 //DUMP_REGS(curMethod, fp);
4972
4973 saveArea = SAVEAREA_FROM_FP(fp);
4974
4975#ifdef EASY_GDB
4976 debugSaveArea = saveArea;
4977#endif
4978
4979 /* back up to previous frame and see if we hit a break */
4980 fp = (u4*)saveArea->prevFrame;
4981 assert(fp != NULL);
4982
4983 /* Handle any special subMode requirements */
4984 if (self->interpBreak.ctl.subMode != 0) {
4985 PC_FP_TO_SELF();
4986 dvmReportReturn(self);
4987 }
4988
4989 if (dvmIsBreakFrame(fp)) {
4990 /* bail without popping the method frame from stack */
4991 LOGVV("+++ returned into break frame\n");
4992 GOTO_bail();
4993 }
4994
4995 /* update thread FP, and reset local variables */
buzbee30bc0d42011-04-22 10:27:14 -07004996 self->interpSave.curFrame = fp;
Carl Shapirocd8f5e72011-04-20 16:12:46 -07004997 curMethod = SAVEAREA_FROM_FP(fp)->method;
4998 self->interpSave.method = curMethod;
4999 //methodClass = curMethod->clazz;
5000 methodClassDex = curMethod->clazz->pDvmDex;
5001 pc = saveArea->savedPc;
5002 ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor,
5003 curMethod->name, curMethod->shorty);
5004
5005 /* use FINISH on the caller's invoke instruction */
5006 //u2 invokeInstr = INST_INST(FETCH(0));
5007 if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
5008 invokeInstr <= OP_INVOKE_INTERFACE*/)
5009 {
5010 FINISH(3);
5011 } else {
5012 //LOGE("Unknown invoke instr %02x at %d\n",
5013 // invokeInstr, (int) (pc - curMethod->insns));
5014 assert(false);
5015 }
5016 }
5017GOTO_TARGET_END
5018
5019
5020 /*
5021 * Jump here when the code throws an exception.
5022 *
5023 * By the time we get here, the Throwable has been created and the stack
5024 * trace has been saved off.
5025 */
5026GOTO_TARGET(exceptionThrown)
5027 {
5028 Object* exception;
5029 int catchRelPc;
5030
5031 PERIODIC_CHECKS(0);
5032
5033 /*
5034 * We save off the exception and clear the exception status. While
5035 * processing the exception we might need to load some Throwable
5036 * classes, and we don't want class loader exceptions to get
5037 * confused with this one.
5038 */
5039 assert(dvmCheckException(self));
5040 exception = dvmGetException(self);
5041 dvmAddTrackedAlloc(exception, self);
5042 dvmClearException(self);
5043
5044 LOGV("Handling exception %s at %s:%d\n",
5045 exception->clazz->descriptor, curMethod->name,
5046 dvmLineNumFromPC(curMethod, pc - curMethod->insns));
5047
5048 /*
5049 * Report the exception throw to any "subMode" watchers.
5050 *
5051 * TODO: if the exception was thrown by interpreted code, control
5052 * fell through native, and then back to us, we will report the
5053 * exception at the point of the throw and again here. We can avoid
5054 * this by not reporting exceptions when we jump here directly from
5055 * the native call code above, but then we won't report exceptions
5056 * that were thrown *from* the JNI code (as opposed to *through* it).
5057 *
5058 * The correct solution is probably to ignore from-native exceptions
5059 * here, and have the JNI exception code do the reporting to the
5060 * debugger.
5061 */
5062 if (self->interpBreak.ctl.subMode != 0) {
5063 PC_FP_TO_SELF();
5064 dvmReportExceptionThrow(self, exception);
5065 }
5066
5067 /*
5068 * We need to unroll to the catch block or the nearest "break"
5069 * frame.
5070 *
5071 * A break frame could indicate that we have reached an intermediate
5072 * native call, or have gone off the top of the stack and the thread
5073 * needs to exit. Either way, we return from here, leaving the
5074 * exception raised.
5075 *
5076 * If we do find a catch block, we want to transfer execution to
5077 * that point.
5078 *
5079 * Note this can cause an exception while resolving classes in
5080 * the "catch" blocks.
5081 */
5082 catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns,
5083 exception, false, (void**)(void*)&fp);
5084
5085 /*
5086 * Restore the stack bounds after an overflow. This isn't going to
5087 * be correct in all circumstances, e.g. if JNI code devours the
5088 * exception this won't happen until some other exception gets
5089 * thrown. If the code keeps pushing the stack bounds we'll end
5090 * up aborting the VM.
5091 *
5092 * Note we want to do this *after* the call to dvmFindCatchBlock,
5093 * because that may need extra stack space to resolve exception
5094 * classes (e.g. through a class loader).
5095 *
5096 * It's possible for the stack overflow handling to cause an
5097 * exception (specifically, class resolution in a "catch" block
5098 * during the call above), so we could see the thread's overflow
5099 * flag raised but actually be running in a "nested" interpreter
5100 * frame. We don't allow doubled-up StackOverflowErrors, so
5101 * we can check for this by just looking at the exception type
5102 * in the cleanup function. Also, we won't unroll past the SOE
5103 * point because the more-recent exception will hit a break frame
5104 * as it unrolls to here.
5105 */
5106 if (self->stackOverflowed)
5107 dvmCleanupStackOverflow(self, exception);
5108
5109 if (catchRelPc < 0) {
5110 /* falling through to JNI code or off the bottom of the stack */
5111#if DVM_SHOW_EXCEPTION >= 2
5112 LOGD("Exception %s from %s:%d not caught locally\n",
5113 exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod),
5114 dvmLineNumFromPC(curMethod, pc - curMethod->insns));
5115#endif
5116 dvmSetException(self, exception);
5117 dvmReleaseTrackedAlloc(exception, self);
5118 GOTO_bail();
5119 }
5120
5121#if DVM_SHOW_EXCEPTION >= 3
5122 {
5123 const Method* catchMethod = SAVEAREA_FROM_FP(fp)->method;
5124 LOGD("Exception %s thrown from %s:%d to %s:%d\n",
5125 exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod),
5126 dvmLineNumFromPC(curMethod, pc - curMethod->insns),
5127 dvmGetMethodSourceFile(catchMethod),
5128 dvmLineNumFromPC(catchMethod, catchRelPc));
5129 }
5130#endif
5131
5132 /*
buzbee30bc0d42011-04-22 10:27:14 -07005133 * Adjust local variables to match self->interpSave.curFrame and the
Carl Shapirocd8f5e72011-04-20 16:12:46 -07005134 * updated PC.
5135 */
buzbee30bc0d42011-04-22 10:27:14 -07005136 //fp = (u4*) self->interpSave.curFrame;
Carl Shapirocd8f5e72011-04-20 16:12:46 -07005137 curMethod = SAVEAREA_FROM_FP(fp)->method;
5138 self->interpSave.method = curMethod;
5139 //methodClass = curMethod->clazz;
5140 methodClassDex = curMethod->clazz->pDvmDex;
5141 pc = curMethod->insns + catchRelPc;
5142 ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
5143 curMethod->name, curMethod->shorty);
5144 DUMP_REGS(curMethod, fp, false); // show all regs
5145
5146 /*
5147 * Restore the exception if the handler wants it.
5148 *
5149 * The Dalvik spec mandates that, if an exception handler wants to
5150 * do something with the exception, the first instruction executed
5151 * must be "move-exception". We can pass the exception along
5152 * through the thread struct, and let the move-exception instruction
5153 * clear it for us.
5154 *
5155 * If the handler doesn't call move-exception, we don't want to
5156 * finish here with an exception still pending.
5157 */
5158 if (INST_INST(FETCH(0)) == OP_MOVE_EXCEPTION)
5159 dvmSetException(self, exception);
5160
5161 dvmReleaseTrackedAlloc(exception, self);
5162 FINISH(0);
5163 }
5164GOTO_TARGET_END
5165
5166
5167
5168 /*
5169 * General handling for invoke-{virtual,super,direct,static,interface},
5170 * including "quick" variants.
5171 *
5172 * Set "methodToCall" to the Method we're calling, and "methodCallRange"
5173 * depending on whether this is a "/range" instruction.
5174 *
5175 * For a range call:
5176 * "vsrc1" holds the argument count (8 bits)
5177 * "vdst" holds the first argument in the range
5178 * For a non-range call:
5179 * "vsrc1" holds the argument count (4 bits) and the 5th argument index
5180 * "vdst" holds four 4-bit register indices
5181 *
5182 * The caller must EXPORT_PC before jumping here, because any method
5183 * call can throw a stack overflow exception.
5184 */
5185GOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall,
5186 u2 count, u2 regs)
5187 {
5188 STUB_HACK(vsrc1 = count; vdst = regs; methodToCall = _methodToCall;);
5189
5190 //printf("range=%d call=%p count=%d regs=0x%04x\n",
5191 // methodCallRange, methodToCall, count, regs);
5192 //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor,
5193 // methodToCall->name, methodToCall->shorty);
5194
5195 u4* outs;
5196 int i;
5197
5198 /*
5199 * Copy args. This may corrupt vsrc1/vdst.
5200 */
5201 if (methodCallRange) {
5202 // could use memcpy or a "Duff's device"; most functions have
5203 // so few args it won't matter much
5204 assert(vsrc1 <= curMethod->outsSize);
5205 assert(vsrc1 == methodToCall->insSize);
5206 outs = OUTS_FROM_FP(fp, vsrc1);
5207 for (i = 0; i < vsrc1; i++)
5208 outs[i] = GET_REGISTER(vdst+i);
5209 } else {
5210 u4 count = vsrc1 >> 4;
5211
5212 assert(count <= curMethod->outsSize);
5213 assert(count == methodToCall->insSize);
5214 assert(count <= 5);
5215
5216 outs = OUTS_FROM_FP(fp, count);
5217#if 0
5218 if (count == 5) {
5219 outs[4] = GET_REGISTER(vsrc1 & 0x0f);
5220 count--;
5221 }
5222 for (i = 0; i < (int) count; i++) {
5223 outs[i] = GET_REGISTER(vdst & 0x0f);
5224 vdst >>= 4;
5225 }
5226#else
5227 // This version executes fewer instructions but is larger
5228 // overall. Seems to be a teensy bit faster.
5229 assert((vdst >> 16) == 0); // 16 bits -or- high 16 bits clear
5230 switch (count) {
5231 case 5:
5232 outs[4] = GET_REGISTER(vsrc1 & 0x0f);
5233 case 4:
5234 outs[3] = GET_REGISTER(vdst >> 12);
5235 case 3:
5236 outs[2] = GET_REGISTER((vdst & 0x0f00) >> 8);
5237 case 2:
5238 outs[1] = GET_REGISTER((vdst & 0x00f0) >> 4);
5239 case 1:
5240 outs[0] = GET_REGISTER(vdst & 0x0f);
5241 default:
5242 ;
5243 }
5244#endif
5245 }
5246 }
5247
5248 /*
5249 * (This was originally a "goto" target; I've kept it separate from the
5250 * stuff above in case we want to refactor things again.)
5251 *
5252 * At this point, we have the arguments stored in the "outs" area of
5253 * the current method's stack frame, and the method to call in
5254 * "methodToCall". Push a new stack frame.
5255 */
5256 {
5257 StackSaveArea* newSaveArea;
5258 u4* newFp;
5259
5260 ILOGV("> %s%s.%s %s",
5261 dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "",
5262 methodToCall->clazz->descriptor, methodToCall->name,
5263 methodToCall->shorty);
5264
5265 newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize;
5266 newSaveArea = SAVEAREA_FROM_FP(newFp);
5267
5268 /* verify that we have enough space */
5269 if (true) {
5270 u1* bottom;
5271 bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
5272 if (bottom < self->interpStackEnd) {
5273 /* stack overflow */
5274 LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n",
5275 self->interpStackStart, self->interpStackEnd, bottom,
5276 (u1*) fp - bottom, self->interpStackSize,
5277 methodToCall->name);
5278 dvmHandleStackOverflow(self, methodToCall);
5279 assert(dvmCheckException(self));
5280 GOTO_exceptionThrown();
5281 }
5282 //LOGD("+++ fp=%p newFp=%p newSave=%p bottom=%p\n",
5283 // fp, newFp, newSaveArea, bottom);
5284 }
5285
5286#ifdef LOG_INSTR
5287 if (methodToCall->registersSize > methodToCall->insSize) {
5288 /*
5289 * This makes valgrind quiet when we print registers that
5290 * haven't been initialized. Turn it off when the debug
5291 * messages are disabled -- we want valgrind to report any
5292 * used-before-initialized issues.
5293 */
5294 memset(newFp, 0xcc,
5295 (methodToCall->registersSize - methodToCall->insSize) * 4);
5296 }
5297#endif
5298
5299#ifdef EASY_GDB
5300 newSaveArea->prevSave = SAVEAREA_FROM_FP(fp);
5301#endif
5302 newSaveArea->prevFrame = fp;
5303 newSaveArea->savedPc = pc;
5304#if defined(WITH_JIT) && defined(MTERP_STUB)
5305 newSaveArea->returnAddr = 0;
5306#endif
5307 newSaveArea->method = methodToCall;
5308
5309 if (self->interpBreak.ctl.subMode != 0) {
5310 /*
5311 * We mark ENTER here for both native and non-native
5312 * calls. For native calls, we'll mark EXIT on return.
5313 * For non-native calls, EXIT is marked in the RETURN op.
5314 */
buzbee30bc0d42011-04-22 10:27:14 -07005315 PC_TO_SELF();
Carl Shapirocd8f5e72011-04-20 16:12:46 -07005316 dvmReportInvoke(self, methodToCall);
5317 }
5318
5319 if (!dvmIsNativeMethod(methodToCall)) {
5320 /*
5321 * "Call" interpreted code. Reposition the PC, update the
5322 * frame pointer and other local state, and continue.
5323 */
5324 curMethod = methodToCall;
5325 self->interpSave.method = curMethod;
5326 methodClassDex = curMethod->clazz->pDvmDex;
5327 pc = methodToCall->insns;
buzbee30bc0d42011-04-22 10:27:14 -07005328 self->interpSave.curFrame = fp = newFp;
Carl Shapirocd8f5e72011-04-20 16:12:46 -07005329#ifdef EASY_GDB
5330 debugSaveArea = SAVEAREA_FROM_FP(newFp);
5331#endif
5332 self->debugIsMethodEntry = true; // profiling, debugging
5333 ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
5334 curMethod->name, curMethod->shorty);
5335 DUMP_REGS(curMethod, fp, true); // show input args
5336 FINISH(0); // jump to method start
5337 } else {
5338 /* set this up for JNI locals, even if not a JNI native */
5339 newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
5340
buzbee30bc0d42011-04-22 10:27:14 -07005341 self->interpSave.curFrame = newFp;
Carl Shapirocd8f5e72011-04-20 16:12:46 -07005342
5343 DUMP_REGS(methodToCall, newFp, true); // show input args
5344
5345 if (self->interpBreak.ctl.subMode != 0) {
buzbee30bc0d42011-04-22 10:27:14 -07005346 dvmReportPreNativeInvoke(methodToCall, self, fp);
Carl Shapirocd8f5e72011-04-20 16:12:46 -07005347 }
5348
5349 ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
5350 methodToCall->name, methodToCall->shorty);
5351
5352 /*
5353 * Jump through native call bridge. Because we leave no
5354 * space for locals on native calls, "newFp" points directly
5355 * to the method arguments.
5356 */
5357 (*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self);
5358
5359 if (self->interpBreak.ctl.subMode != 0) {
buzbee30bc0d42011-04-22 10:27:14 -07005360 dvmReportPostNativeInvoke(methodToCall, self, fp);
Carl Shapirocd8f5e72011-04-20 16:12:46 -07005361 }
5362
5363 /* pop frame off */
5364 dvmPopJniLocals(self, newSaveArea);
buzbee30bc0d42011-04-22 10:27:14 -07005365 self->interpSave.curFrame = fp;
Carl Shapirocd8f5e72011-04-20 16:12:46 -07005366
5367 /*
5368 * If the native code threw an exception, or interpreted code
5369 * invoked by the native call threw one and nobody has cleared
5370 * it, jump to our local exception handling.
5371 */
5372 if (dvmCheckException(self)) {
5373 LOGV("Exception thrown by/below native code\n");
5374 GOTO_exceptionThrown();
5375 }
5376
5377 ILOGD("> retval=0x%llx (leaving native)", retval.j);
5378 ILOGD("> (return from native %s.%s to %s.%s %s)",
5379 methodToCall->clazz->descriptor, methodToCall->name,
5380 curMethod->clazz->descriptor, curMethod->name,
5381 curMethod->shorty);
5382
5383 //u2 invokeInstr = INST_INST(FETCH(0));
5384 if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
5385 invokeInstr <= OP_INVOKE_INTERFACE*/)
5386 {
5387 FINISH(3);
5388 } else {
5389 //LOGE("Unknown invoke instr %02x at %d\n",
5390 // invokeInstr, (int) (pc - curMethod->insns));
5391 assert(false);
5392 }
5393 }
5394 }
5395 assert(false); // should not get here
5396GOTO_TARGET_END
5397
5398/* File: portable/enddefs.cpp */
5399/*--- end of opcodes ---*/
5400
5401bail:
5402 ILOGD("|-- Leaving interpreter loop"); // note "curMethod" may be NULL
5403
buzbeecf4a20c2011-05-25 14:21:14 -07005404 self->interpSave.retval = retval;
Carl Shapirocd8f5e72011-04-20 16:12:46 -07005405}
5406