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