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