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