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