122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * This file was generated automatically by gen-mterp.py for 'x86-atom'.
322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * --> DO NOT EDIT <--
522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* File: c/header.c */
822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Copyright (C) 2008 The Android Open Source Project
1022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
1122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Licensed under the Apache License, Version 2.0 (the "License");
1222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * you may not use this file except in compliance with the License.
1322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * You may obtain a copy of the License at
1422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
1522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *      http://www.apache.org/licenses/LICENSE-2.0
1622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
1722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Unless required by applicable law or agreed to in writing, software
1822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * distributed under the License is distributed on an "AS IS" BASIS,
1922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * See the License for the specific language governing permissions and
2122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * limitations under the License.
2222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
2322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
2422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* common includes */
2522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#include "Dalvik.h"
2622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#include "interp/InterpDefs.h"
2722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#include "mterp/Mterp.h"
2822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#include <math.h>                   // needed for fmod, fmodf
2922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#include "mterp/common/FindInterface.h"
3022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
3122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
3222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Configuration defines.  These affect the C implementations, i.e. the
3322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * portable interpreter(s) and C stubs.
3422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
3522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Some defines are controlled by the Makefile, e.g.:
3622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *   WITH_PROFILER
3722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *   WITH_DEBUGGER
3822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *   WITH_INSTR_CHECKS
3922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *   WITH_TRACKREF_CHECKS
4022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *   EASY_GDB
4122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *   NDEBUG
4222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
4322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * If THREADED_INTERP is not defined, we use a classic "while true / switch"
4422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * interpreter.  If it is defined, then the tail end of each instruction
4522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * handler fetches the next instruction and jumps directly to the handler.
4622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * This increases the size of the "Std" interpreter by about 10%, but
4722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * provides a speedup of about the same magnitude.
4822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
4922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * There's a "hybrid" approach that uses a goto table instead of a switch
5022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * statement, avoiding the "is the opcode in range" tests required for switch.
5122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * The performance is close to the threaded version, and without the 10%
5222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * size increase, but the benchmark results are off enough that it's not
5322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * worth adding as a third option.
5422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
5522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define THREADED_INTERP             /* threaded vs. while-loop interpreter */
5622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
5722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia (slow!) */
5822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define CHECK_BRANCH_OFFSETS
5922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define CHECK_REGISTER_INDICES
6022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
6122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
6222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
6322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * ARM EABI requires 64-bit alignment for access to 64-bit data types.  We
6422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * can't just use pointers to copy 64-bit values out of our interpreted
6522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * register set, because gcc will generate ldrd/strd.
6622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
6722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * The __UNION version copies data in and out of a union.  The __MEMCPY
6822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * version uses a memcpy() call to do the transfer; gcc is smart enough to
6922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * not actually call memcpy().  The __UNION version is very bad on ARM;
7022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * it only uses one more instruction than __MEMCPY, but for some reason
7122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * gcc thinks it needs separate storage for every instance of the union.
7222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * On top of that, it feels the need to zero them out at the start of the
7322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * method.  Net result is we zero out ~700 bytes of stack space at the top
7422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * of the interpreter using ARM STM instructions.
7522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
7622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if defined(__ARM_EABI__)
7722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch//# define NO_UNALIGN_64__UNION
7822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define NO_UNALIGN_64__MEMCPY
7922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
8022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
8122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch//#define LOG_INSTR                   /* verbose debugging */
8222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
8322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
8422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
8522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Keep a tally of accesses to fields.  Currently only works if full DEX
8622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * optimization is disabled.
8722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
8822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#ifdef PROFILE_FIELD_ACCESS
8922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
9022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
9122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
9222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define UPDATE_FIELD_GET(_field) ((void)0)
9322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define UPDATE_FIELD_PUT(_field) ((void)0)
9422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
9522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
9622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
9722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Export another copy of the PC on every instruction; this is largely
9822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * redundant with EXPORT_PC and the debugger code.  This value can be
9922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * compared against what we have stored on the stack with EXPORT_PC to
10022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * help ensure that we aren't missing any export calls.
10122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
10222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if WITH_EXTRA_GC_CHECKS > 1
10322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
10422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
10522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define EXPORT_EXTRA_PC()
10622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
10722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
10822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
10922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Adjust the program counter.  "_offset" is a signed int, in 16-bit units.
11022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
11122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
11222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
11322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * We don't advance the program counter until we finish an instruction or
11422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * branch, because we do want to have to unroll the PC if there's an
11522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * exception.
11622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
11722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#ifdef CHECK_BRANCH_OFFSETS
11822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define ADJUST_PC(_offset) do {                                            \
11922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        int myoff = _offset;        /* deref only once */                   \
12022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (pc + myoff < curMethod->insns ||                                \
12122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            pc + myoff >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) \
12222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        {                                                                   \
12322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            char* desc;                                                     \
12422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            desc = dexProtoCopyMethodDescriptor(&curMethod->prototype);     \
12522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            LOGE("Invalid branch %d at 0x%04x in %s.%s %s\n",               \
12622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                myoff, (int) (pc - curMethod->insns),                       \
12722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                curMethod->clazz->descriptor, curMethod->name, desc);       \
12822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            free(desc);                                                     \
12922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmAbort();                                                     \
13022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }                                                                   \
13122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        pc += myoff;                                                        \
13222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        EXPORT_EXTRA_PC();                                                  \
13322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    } while (false)
13422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
13522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define ADJUST_PC(_offset) do {                                            \
13622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        pc += _offset;                                                      \
13722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        EXPORT_EXTRA_PC();                                                  \
13822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    } while (false)
13922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
14022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
14122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
14222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * If enabled, log instructions as we execute them.
14322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
14422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#ifdef LOG_INSTR
14522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define ILOGD(...) ILOG(LOG_DEBUG, __VA_ARGS__)
14622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define ILOGV(...) ILOG(LOG_VERBOSE, __VA_ARGS__)
14722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define ILOG(_level, ...) do {                                             \
14822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        char debugStrBuf[128];                                              \
14922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        snprintf(debugStrBuf, sizeof(debugStrBuf), __VA_ARGS__);            \
15022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (curMethod != NULL)                                                 \
15122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            LOG(_level, LOG_TAG"i", "%-2d|%04x%s\n",                        \
15222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                self->threadId, (int)(pc - curMethod->insns), debugStrBuf); \
15322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        else                                                                \
15422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            LOG(_level, LOG_TAG"i", "%-2d|####%s\n",                        \
15522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                self->threadId, debugStrBuf);                               \
15622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    } while(false)
15722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birchvoid dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly);
15822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define DUMP_REGS(_meth, _frame, _inOnly) dvmDumpRegs(_meth, _frame, _inOnly)
15922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birchstatic const char kSpacing[] = "            ";
16022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
16122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define ILOGD(...) ((void)0)
16222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define ILOGV(...) ((void)0)
16322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define DUMP_REGS(_meth, _frame, _inOnly) ((void)0)
16422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
16522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
16622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* get a long from an array of u4 */
16722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birchstatic inline s8 getLongFromArray(const u4* ptr, int idx)
16822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch{
16922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if defined(NO_UNALIGN_64__UNION)
17022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    union { s8 ll; u4 parts[2]; } conv;
17122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
17222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ptr += idx;
17322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    conv.parts[0] = ptr[0];
17422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    conv.parts[1] = ptr[1];
17522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    return conv.ll;
17622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#elif defined(NO_UNALIGN_64__MEMCPY)
17722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    s8 val;
17822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    memcpy(&val, &ptr[idx], 8);
17922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    return val;
18022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
18122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    return *((s8*) &ptr[idx]);
18222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
18322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch}
18422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
18522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* store a long into an array of u4 */
18622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birchstatic inline void putLongToArray(u4* ptr, int idx, s8 val)
18722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch{
18822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if defined(NO_UNALIGN_64__UNION)
18922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    union { s8 ll; u4 parts[2]; } conv;
19022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
19122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ptr += idx;
19222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    conv.ll = val;
19322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ptr[0] = conv.parts[0];
19422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ptr[1] = conv.parts[1];
19522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#elif defined(NO_UNALIGN_64__MEMCPY)
19622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    memcpy(&ptr[idx], &val, 8);
19722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
19822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *((s8*) &ptr[idx]) = val;
19922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
20022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch}
20122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
20222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* get a double from an array of u4 */
20322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birchstatic inline double getDoubleFromArray(const u4* ptr, int idx)
20422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch{
20522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if defined(NO_UNALIGN_64__UNION)
20622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    union { double d; u4 parts[2]; } conv;
20722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
20822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ptr += idx;
20922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    conv.parts[0] = ptr[0];
21022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    conv.parts[1] = ptr[1];
21122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    return conv.d;
21222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#elif defined(NO_UNALIGN_64__MEMCPY)
21322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    double dval;
21422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    memcpy(&dval, &ptr[idx], 8);
21522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    return dval;
21622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
21722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    return *((double*) &ptr[idx]);
21822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
21922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch}
22022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
22122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* store a double into an array of u4 */
22222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birchstatic inline void putDoubleToArray(u4* ptr, int idx, double dval)
22322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch{
22422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if defined(NO_UNALIGN_64__UNION)
22522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    union { double d; u4 parts[2]; } conv;
22622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
22722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ptr += idx;
22822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    conv.d = dval;
22922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ptr[0] = conv.parts[0];
23022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ptr[1] = conv.parts[1];
23122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#elif defined(NO_UNALIGN_64__MEMCPY)
23222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    memcpy(&ptr[idx], &dval, 8);
23322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
23422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    *((double*) &ptr[idx]) = dval;
23522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
23622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch}
23722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
23822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
23922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * If enabled, validate the register number on every access.  Otherwise,
24022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * just do an array access.
24122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
24222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Assumes the existence of "u4* fp".
24322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
24422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * "_idx" may be referenced more than once.
24522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
24622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#ifdef CHECK_REGISTER_INDICES
24722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define GET_REGISTER(_idx) \
24822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ( (_idx) < curMethod->registersSize ? \
24922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        (fp[(_idx)]) : (assert(!"bad reg"),1969) )
25022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define SET_REGISTER(_idx, _val) \
25122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ( (_idx) < curMethod->registersSize ? \
25222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        (fp[(_idx)] = (u4)(_val)) : (assert(!"bad reg"),1969) )
25322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define GET_REGISTER_AS_OBJECT(_idx)       ((Object *)GET_REGISTER(_idx))
25422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define SET_REGISTER_AS_OBJECT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
25522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define GET_REGISTER_INT(_idx) ((s4) GET_REGISTER(_idx))
25622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
25722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define GET_REGISTER_WIDE(_idx) \
25822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ( (_idx) < curMethod->registersSize-1 ? \
25922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        getLongFromArray(fp, (_idx)) : (assert(!"bad reg"),1969) )
26022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define SET_REGISTER_WIDE(_idx, _val) \
26122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ( (_idx) < curMethod->registersSize-1 ? \
26222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        putLongToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969) )
26322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define GET_REGISTER_FLOAT(_idx) \
26422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ( (_idx) < curMethod->registersSize ? \
26522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        (*((float*) &fp[(_idx)])) : (assert(!"bad reg"),1969.0f) )
26622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define SET_REGISTER_FLOAT(_idx, _val) \
26722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ( (_idx) < curMethod->registersSize ? \
26822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        (*((float*) &fp[(_idx)]) = (_val)) : (assert(!"bad reg"),1969.0f) )
26922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define GET_REGISTER_DOUBLE(_idx) \
27022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ( (_idx) < curMethod->registersSize-1 ? \
27122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        getDoubleFromArray(fp, (_idx)) : (assert(!"bad reg"),1969.0) )
27222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define SET_REGISTER_DOUBLE(_idx, _val) \
27322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ( (_idx) < curMethod->registersSize-1 ? \
27422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        putDoubleToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969.0) )
27522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
27622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define GET_REGISTER(_idx)                 (fp[(_idx)])
27722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define SET_REGISTER(_idx, _val)           (fp[(_idx)] = (_val))
27822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define GET_REGISTER_AS_OBJECT(_idx)       ((Object*) fp[(_idx)])
27922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define SET_REGISTER_AS_OBJECT(_idx, _val) (fp[(_idx)] = (u4)(_val))
28022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define GET_REGISTER_INT(_idx)             ((s4)GET_REGISTER(_idx))
28122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define SET_REGISTER_INT(_idx, _val)       SET_REGISTER(_idx, (s4)_val)
28222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define GET_REGISTER_WIDE(_idx)            getLongFromArray(fp, (_idx))
28322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define SET_REGISTER_WIDE(_idx, _val)      putLongToArray(fp, (_idx), (_val))
28422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define GET_REGISTER_FLOAT(_idx)           (*((float*) &fp[(_idx)]))
28522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define SET_REGISTER_FLOAT(_idx, _val)     (*((float*) &fp[(_idx)]) = (_val))
28622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define GET_REGISTER_DOUBLE(_idx)          getDoubleFromArray(fp, (_idx))
28722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define SET_REGISTER_DOUBLE(_idx, _val)    putDoubleToArray(fp, (_idx), (_val))
28822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
28922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
29022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
29122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Get 16 bits from the specified offset of the program counter.  We always
29222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * want to load 16 bits at a time from the instruction stream -- it's more
29322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * efficient than 8 and won't have the alignment problems that 32 might.
29422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
29522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Assumes existence of "const u2* pc".
29622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
29722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define FETCH(_offset)     (pc[(_offset)])
29822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
29922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
30022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Extract instruction byte from 16-bit fetch (_inst is a u2).
30122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
30222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define INST_INST(_inst)    ((_inst) & 0xff)
30322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
30422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
3054abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden * Replace the opcode (used when handling breakpoints).  _opcode is a u1.
3064abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden */
3074abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#define INST_REPLACE_OP(_inst, _opcode) (((_inst) & 0xff00) | _opcode)
3084abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden
3094abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden/*
31022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2).
31122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
31222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define INST_A(_inst)       (((_inst) >> 8) & 0x0f)
31322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define INST_B(_inst)       ((_inst) >> 12)
31422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
31522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
31622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Get the 8-bit "vAA" 8-bit register index from the instruction word.
31722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * (_inst is u2)
31822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
31922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define INST_AA(_inst)      ((_inst) >> 8)
32022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
32122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
32222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * The current PC must be available to Throwable constructors, e.g.
32322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * those created by dvmThrowException(), so that the exception stack
32422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * trace can be generated correctly.  If we don't do this, the offset
32522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * within the current method won't be shown correctly.  See the notes
32622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * in Exception.c.
32722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
32822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * This is also used to determine the address for precise GC.
32922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
33022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Assumes existence of "u4* fp" and "const u2* pc".
33122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
33222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define EXPORT_PC()         (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
33322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
33422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
33522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Determine if we need to switch to a different interpreter.  "_current"
33622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * is either INTERP_STD or INTERP_DBG.  It should be fixed for a given
33722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * interpreter generation file, which should remove the outer conditional
33822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * from the following.
33922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
34022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * If we're building without debug and profiling support, we never switch.
34122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
34222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
34322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if defined(WITH_JIT)
34422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define NEED_INTERP_SWITCH(_current) (                                     \
34522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    (_current == INTERP_STD) ?                                              \
3464abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        dvmJitDebuggerOrProfilerActive() : !dvmJitDebuggerOrProfilerActive() )
34722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
34822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define NEED_INTERP_SWITCH(_current) (                                     \
34922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    (_current == INTERP_STD) ?                                              \
35022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmDebuggerOrProfilerActive() : !dvmDebuggerOrProfilerActive() )
35122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
35222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
35322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define NEED_INTERP_SWITCH(_current) (false)
35422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
35522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
35622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
35722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Check to see if "obj" is NULL.  If so, throw an exception.  Assumes the
35822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * pc has already been exported to the stack.
35922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
36022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Perform additional checks on debug builds.
36122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
36222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Use this to check for NULL when the instruction handler calls into
36322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * something that could throw an exception (so we have already called
36422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * EXPORT_PC at the top).
36522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
36622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birchstatic inline bool checkForNull(Object* obj)
36722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch{
36822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    if (obj == NULL) {
36922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmThrowException("Ljava/lang/NullPointerException;", NULL);
37022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        return false;
37122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
37222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#ifdef WITH_EXTRA_OBJECT_VALIDATION
37322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    if (!dvmIsValidObject(obj)) {
37422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        LOGE("Invalid object %p\n", obj);
37522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmAbort();
37622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
37722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
37822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#ifndef NDEBUG
37922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
38022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /* probable heap corruption */
38122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
38222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmAbort();
38322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
38422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
38522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    return true;
38622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch}
38722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
38822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
38922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Check to see if "obj" is NULL.  If so, export the PC into the stack
39022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * frame and throw an exception.
39122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
39222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Perform additional checks on debug builds.
39322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
39422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Use this to check for NULL when the instruction handler doesn't do
39522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * anything else that can throw an exception.
39622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
39722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birchstatic inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc)
39822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch{
39922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    if (obj == NULL) {
40022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        EXPORT_PC();
40122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmThrowException("Ljava/lang/NullPointerException;", NULL);
40222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        return false;
40322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
40422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#ifdef WITH_EXTRA_OBJECT_VALIDATION
40522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    if (!dvmIsValidObject(obj)) {
40622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        LOGE("Invalid object %p\n", obj);
40722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmAbort();
40822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
40922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
41022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#ifndef NDEBUG
41122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
41222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /* probable heap corruption */
41322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
41422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmAbort();
41522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
41622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
41722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    return true;
41822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch}
41922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
42022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* File: cstubs/stubdefs.c */
42122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* this is a standard (no debug support) interpreter */
42222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define INTERP_TYPE INTERP_STD
42322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define CHECK_DEBUG_AND_PROF() ((void)0)
42422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch# define CHECK_TRACKED_REFS() ((void)0)
4254abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#if defined(WITH_JIT)
4264abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#define CHECK_JIT() (0)
4274abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#define ABORT_JIT_TSELECT() ((void)0)
4284abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#endif
42922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
43022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
43122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * In the C mterp stubs, "goto" is a function call followed immediately
43222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * by a return.
43322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
43422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
43522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define GOTO_TARGET_DECL(_target, ...)                                      \
43622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    void dvmMterp_##_target(MterpGlue* glue, ## __VA_ARGS__);
43722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
43822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define GOTO_TARGET(_target, ...)                                           \
43922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    void dvmMterp_##_target(MterpGlue* glue, ## __VA_ARGS__) {              \
44022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 ref, vsrc1, vsrc2, vdst;                                         \
44122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 inst = FETCH(0);                                                 \
44222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        const Method* methodToCall;                                         \
44322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        StackSaveArea* debugSaveArea;
44422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
44522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define GOTO_TARGET_END }
44622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
44722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
44822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Redefine what used to be local variable accesses into MterpGlue struct
44922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * references.  (These are undefined down in "footer.c".)
45022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
45122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define retval                  glue->retval
45222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define pc                      glue->pc
45322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define fp                      glue->fp
45422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define curMethod               glue->method
45522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define methodClassDex          glue->methodClassDex
45622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define self                    glue->self
45722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define debugTrackedRefStart    glue->debugTrackedRefStart
45822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
45922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* ugh */
46022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define STUB_HACK(x) x
46122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
46222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
46322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
46422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Opcode handler framing macros.  Here, each opcode is a separate function
46522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * that takes a "glue" argument and returns void.  We can't declare
46622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * these "static" because they may be called from an assembly stub.
46722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
46822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OPCODE(_op)                                                  \
46922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    void dvmMterp_##_op(MterpGlue* glue) {                                  \
47022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 ref, vsrc1, vsrc2, vdst;                                         \
47122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 inst = FETCH(0);
47222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
47322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define OP_END }
47422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
47522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
47622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Like the "portable" FINISH, but don't reload "inst", and return to caller
47722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * when done.
47822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
47922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define FINISH(_offset) {                                                   \
48022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ADJUST_PC(_offset);                                                 \
48122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        CHECK_DEBUG_AND_PROF();                                             \
48222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        CHECK_TRACKED_REFS();                                               \
48322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        return;                                                             \
48422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
48522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
48622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
48722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
48822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * The "goto label" statements turn into function calls followed by
48922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * return statements.  Some of the functions take arguments, which in the
49022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * portable interpreter are handled by assigning values to globals.
49122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
49222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
49322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define GOTO_exceptionThrown()                                              \
49422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    do {                                                                    \
49522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmMterp_exceptionThrown(glue);                                     \
49622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        return;                                                             \
49722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    } while(false)
49822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
49922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define GOTO_returnFromMethod()                                             \
50022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    do {                                                                    \
50122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmMterp_returnFromMethod(glue);                                    \
50222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        return;                                                             \
50322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    } while(false)
50422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
50522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define GOTO_invoke(_target, _methodCallRange)                              \
50622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    do {                                                                    \
50722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmMterp_##_target(glue, _methodCallRange);                         \
50822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        return;                                                             \
50922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    } while(false)
51022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
51122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst)   \
51222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    do {                                                                    \
51322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmMterp_invokeMethod(glue, _methodCallRange, _methodToCall,        \
51422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            _vsrc1, _vdst);                                                 \
51522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        return;                                                             \
51622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    } while(false)
51722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
51822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
51922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * As a special case, "goto bail" turns into a longjmp.  Use "bail_switch"
52022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * if we need to switch to the other interpreter upon our return.
52122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
52222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define GOTO_bail()                                                         \
52322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    dvmMterpStdBail(glue, false);
52422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define GOTO_bail_switch()                                                  \
52522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    dvmMterpStdBail(glue, true);
52622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
52722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
52822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Periodically check for thread suspension.
52922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
53022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * While we're at it, see if a debugger has attached or the profiler has
53122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * started.  If so, switch to a different "goto" table.
53222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
53322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define PERIODIC_CHECKS(_entryPoint, _pcadj) {                              \
53422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (dvmCheckSuspendQuick(self)) {                                   \
53522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            EXPORT_PC();  /* need for precise GC */                         \
53622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmCheckSuspendPending(self);                                   \
53722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }                                                                   \
53822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (NEED_INTERP_SWITCH(INTERP_TYPE)) {                              \
53922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ADJUST_PC(_pcadj);                                              \
54022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            glue->entryPoint = _entryPoint;                                 \
54122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            LOGVV("threadid=%d: switch to STD ep=%d adj=%d\n",              \
54222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                self->threadId, (_entryPoint), (_pcadj));                   \
54322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_bail_switch();                                             \
54422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }                                                                   \
54522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
54622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
54722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* File: c/opcommon.c */
54822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* forward declarations of goto targets */
54922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_DECL(filledNewArray, bool methodCallRange);
55022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_DECL(invokeVirtual, bool methodCallRange);
55122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_DECL(invokeSuper, bool methodCallRange);
55222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_DECL(invokeInterface, bool methodCallRange);
55322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_DECL(invokeDirect, bool methodCallRange);
55422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_DECL(invokeStatic, bool methodCallRange);
55522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_DECL(invokeVirtualQuick, bool methodCallRange);
55622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_DECL(invokeSuperQuick, bool methodCallRange);
55722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_DECL(invokeMethod, bool methodCallRange, const Method* methodToCall,
55822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    u2 count, u2 regs);
55922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_DECL(returnFromMethod);
56022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_DECL(exceptionThrown);
56122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
56222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
56322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * ===========================================================================
56422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
56522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * What follows are opcode definitions shared between multiple opcodes with
56622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * minor substitutions handled by the C pre-processor.  These should probably
56722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * use the mterp substitution mechanism instead, with the code here moved
56822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * into common fragment files (like the asm "binop.S"), although it's hard
56922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * to give up the C preprocessor in favor of the much simpler text subst.
57022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
57122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * ===========================================================================
57222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
57322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
57422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_NUMCONV(_opcode, _opname, _fromtype, _totype)                \
57522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
57622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_A(inst);                                                \
57722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_B(inst);                                               \
57822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \
57922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER##_totype(vdst,                                         \
58022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GET_REGISTER##_fromtype(vsrc1));                                \
58122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        FINISH(1);
58222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
58322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_FLOAT_TO_INT(_opcode, _opname, _fromvtype, _fromrtype,       \
58422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        _tovtype, _tortype)                                                 \
58522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
58622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
58722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /* spec defines specific handling for +/- inf and NaN values */     \
58822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        _fromvtype val;                                                     \
58922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        _tovtype intMin, intMax, result;                                    \
59022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_A(inst);                                                \
59122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_B(inst);                                               \
59222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \
59322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        val = GET_REGISTER##_fromrtype(vsrc1);                              \
59422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        intMin = (_tovtype) 1 << (sizeof(_tovtype) * 8 -1);                 \
59522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        intMax = ~intMin;                                                   \
59622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        result = (_tovtype) val;                                            \
59722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (val >= intMax)          /* +inf */                              \
59822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            result = intMax;                                                \
59922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        else if (val <= intMin)     /* -inf */                              \
60022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            result = intMin;                                                \
60122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        else if (val != val)        /* NaN */                               \
60222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            result = 0;                                                     \
60322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        else                                                                \
60422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            result = (_tovtype) val;                                        \
60522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER##_tortype(vdst, result);                               \
60622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
60722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(1);
60822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
60922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_INT_TO_SMALL(_opcode, _opname, _type)                        \
61022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
61122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_A(inst);                                                \
61222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_B(inst);                                               \
61322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|int-to-%s v%d,v%d", (_opname), vdst, vsrc1);                \
61422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER(vdst, (_type) GET_REGISTER(vsrc1));                    \
61522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        FINISH(1);
61622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
61722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* NOTE: the comparison result is always a signed 4-byte integer */
61822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_CMPX(_opcode, _opname, _varType, _type, _nanVal)          \
61922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
62022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
62122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        int result;                                                         \
62222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 regs;                                                            \
62322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        _varType val1, val2;                                                \
62422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_AA(inst);                                               \
62522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        regs = FETCH(1);                                                    \
62622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = regs & 0xff;                                                \
62722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc2 = regs >> 8;                                                  \
62822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|cmp%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);         \
62922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        val1 = GET_REGISTER##_type(vsrc1);                                  \
63022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        val2 = GET_REGISTER##_type(vsrc2);                                  \
63122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (val1 == val2)                                                   \
63222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            result = 0;                                                     \
63322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        else if (val1 < val2)                                               \
63422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            result = -1;                                                    \
63522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        else if (val1 > val2)                                               \
63622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            result = 1;                                                     \
63722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        else                                                                \
63822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            result = (_nanVal);                                             \
63922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("+ result=%d\n", result);                                     \
64022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER(vdst, result);                                         \
64122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
64222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
64322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
64422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_IF_XX(_opcode, _opname, _cmp)                             \
64522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB, +CCCC*/)                                \
64622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_A(inst);                                               \
64722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc2 = INST_B(inst);                                               \
64822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if ((s4) GET_REGISTER(vsrc1) _cmp (s4) GET_REGISTER(vsrc2)) {       \
64922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            int branchOffset = (s2)FETCH(1);    /* sign-extended */         \
65022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|if-%s v%d,v%d,+0x%04x", (_opname), vsrc1, vsrc2,        \
65122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                branchOffset);                                              \
65222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("> branch taken");                                        \
65322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (branchOffset < 0)                                           \
65422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                PERIODIC_CHECKS(kInterpEntryInstr, branchOffset);           \
65522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            FINISH(branchOffset);                                           \
65622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {                                                            \
65722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|if-%s v%d,v%d,-", (_opname), vsrc1, vsrc2);             \
65822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            FINISH(2);                                                      \
65922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
66022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
66122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_IF_XXZ(_opcode, _opname, _cmp)                            \
66222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vAA, +BBBB*/)                                   \
66322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_AA(inst);                                              \
66422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if ((s4) GET_REGISTER(vsrc1) _cmp 0) {                              \
66522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            int branchOffset = (s2)FETCH(1);    /* sign-extended */         \
66622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|if-%s v%d,+0x%04x", (_opname), vsrc1, branchOffset);    \
66722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("> branch taken");                                        \
66822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (branchOffset < 0)                                           \
66922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                PERIODIC_CHECKS(kInterpEntryInstr, branchOffset);           \
67022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            FINISH(branchOffset);                                           \
67122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {                                                            \
67222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|if-%s v%d,-", (_opname), vsrc1);                        \
67322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            FINISH(2);                                                      \
67422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
67522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
67622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_UNOP(_opcode, _opname, _pfx, _sfx, _type)                    \
67722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
67822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_A(inst);                                                \
67922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_B(inst);                                               \
68022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \
68122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER##_type(vdst, _pfx GET_REGISTER##_type(vsrc1) _sfx);    \
68222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        FINISH(1);
68322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
68422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_X_INT(_opcode, _opname, _op, _chkdiv)                     \
68522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
68622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
68722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 srcRegs;                                                         \
68822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_AA(inst);                                               \
68922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        srcRegs = FETCH(1);                                                 \
69022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = srcRegs & 0xff;                                             \
69122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc2 = srcRegs >> 8;                                               \
69222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1);                   \
69322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (_chkdiv != 0) {                                                 \
69422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            s4 firstVal, secondVal, result;                                 \
69522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            firstVal = GET_REGISTER(vsrc1);                                 \
69622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            secondVal = GET_REGISTER(vsrc2);                                \
69722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (secondVal == 0) {                                           \
69822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                EXPORT_PC();                                                \
69922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                dvmThrowException("Ljava/lang/ArithmeticException;",        \
70022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    "divide by zero");                                      \
70122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();                                     \
70222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }                                                               \
70322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if ((u4)firstVal == 0x80000000 && secondVal == -1) {            \
70422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                if (_chkdiv == 1)                                           \
70522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    result = firstVal;  /* division */                      \
70622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                else                                                        \
70722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    result = 0;         /* remainder */                     \
70822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            } else {                                                        \
70922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                result = firstVal _op secondVal;                            \
71022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }                                                               \
71122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            SET_REGISTER(vdst, result);                                     \
71222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {                                                            \
71322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            /* non-div/rem case */                                          \
71422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            SET_REGISTER(vdst,                                              \
71522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2));     \
71622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }                                                                   \
71722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
71822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
71922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
72022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op)                     \
72122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
72222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
72322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 srcRegs;                                                         \
72422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_AA(inst);                                               \
72522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        srcRegs = FETCH(1);                                                 \
72622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = srcRegs & 0xff;                                             \
72722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc2 = srcRegs >> 8;                                               \
72822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1);                   \
72922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER(vdst,                                                  \
73022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f));    \
73122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
73222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
73322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
73422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv)               \
73522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/)                               \
73622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_A(inst);                                                \
73722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_B(inst);                                               \
73822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc2 = FETCH(1);                                                   \
73922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x",                             \
74022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            (_opname), vdst, vsrc1, vsrc2);                                 \
74122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (_chkdiv != 0) {                                                 \
74222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            s4 firstVal, result;                                            \
74322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            firstVal = GET_REGISTER(vsrc1);                                 \
74422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if ((s2) vsrc2 == 0) {                                          \
74522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                EXPORT_PC();                                                \
74622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                dvmThrowException("Ljava/lang/ArithmeticException;",        \
74722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    "divide by zero");                                      \
74822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();                                      \
74922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }                                                               \
75022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) {         \
75122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                /* won't generate /lit16 instr for this; check anyway */    \
75222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                if (_chkdiv == 1)                                           \
75322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    result = firstVal;  /* division */                      \
75422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                else                                                        \
75522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    result = 0;         /* remainder */                     \
75622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            } else {                                                        \
75722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                result = firstVal _op (s2) vsrc2;                           \
75822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }                                                               \
75922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            SET_REGISTER(vdst, result);                                     \
76022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {                                                            \
76122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            /* non-div/rem case */                                          \
76222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2);         \
76322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }                                                                   \
76422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        FINISH(2);
76522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
76622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv)                \
76722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/)                               \
76822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
76922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 litInfo;                                                         \
77022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_AA(inst);                                               \
77122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        litInfo = FETCH(1);                                                 \
77222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = litInfo & 0xff;                                             \
77322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc2 = litInfo >> 8;       /* constant */                          \
77422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x",                              \
77522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            (_opname), vdst, vsrc1, vsrc2);                                 \
77622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (_chkdiv != 0) {                                                 \
77722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            s4 firstVal, result;                                            \
77822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            firstVal = GET_REGISTER(vsrc1);                                 \
77922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if ((s1) vsrc2 == 0) {                                          \
78022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                EXPORT_PC();                                                \
78122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                dvmThrowException("Ljava/lang/ArithmeticException;",        \
78222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    "divide by zero");                                      \
78322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();                                     \
78422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }                                                               \
78522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) {         \
78622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                if (_chkdiv == 1)                                           \
78722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    result = firstVal;  /* division */                      \
78822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                else                                                        \
78922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    result = 0;         /* remainder */                     \
79022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            } else {                                                        \
79122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                result = firstVal _op ((s1) vsrc2);                         \
79222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }                                                               \
79322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            SET_REGISTER(vdst, result);                                     \
79422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {                                                            \
79522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            SET_REGISTER(vdst,                                              \
79622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2);                   \
79722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }                                                                   \
79822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
79922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
80022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
80122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op)                \
80222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/)                               \
80322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
80422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 litInfo;                                                         \
80522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_AA(inst);                                               \
80622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        litInfo = FETCH(1);                                                 \
80722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = litInfo & 0xff;                                             \
80822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc2 = litInfo >> 8;       /* constant */                          \
80922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x",                              \
81022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            (_opname), vdst, vsrc1, vsrc2);                                 \
81122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER(vdst,                                                  \
81222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f));                  \
81322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
81422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
81522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
81622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv)               \
81722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
81822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_A(inst);                                                \
81922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_B(inst);                                               \
82022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1);             \
82122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (_chkdiv != 0) {                                                 \
82222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            s4 firstVal, secondVal, result;                                 \
82322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            firstVal = GET_REGISTER(vdst);                                  \
82422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            secondVal = GET_REGISTER(vsrc1);                                \
82522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (secondVal == 0) {                                           \
82622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                EXPORT_PC();                                                \
82722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                dvmThrowException("Ljava/lang/ArithmeticException;",        \
82822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    "divide by zero");                                      \
82922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();                                     \
83022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }                                                               \
83122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if ((u4)firstVal == 0x80000000 && secondVal == -1) {            \
83222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                if (_chkdiv == 1)                                           \
83322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    result = firstVal;  /* division */                      \
83422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                else                                                        \
83522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    result = 0;         /* remainder */                     \
83622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            } else {                                                        \
83722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                result = firstVal _op secondVal;                            \
83822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }                                                               \
83922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            SET_REGISTER(vdst, result);                                     \
84022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {                                                            \
84122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            SET_REGISTER(vdst,                                              \
84222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1));      \
84322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }                                                                   \
84422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        FINISH(1);
84522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
84622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op)               \
84722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
84822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_A(inst);                                                \
84922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_B(inst);                                               \
85022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1);             \
85122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER(vdst,                                                  \
85222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f));     \
85322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        FINISH(1);
85422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
85522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv)                    \
85622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
85722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
85822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 srcRegs;                                                         \
85922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_AA(inst);                                               \
86022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        srcRegs = FETCH(1);                                                 \
86122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = srcRegs & 0xff;                                             \
86222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc2 = srcRegs >> 8;                                               \
86322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);       \
86422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (_chkdiv != 0) {                                                 \
86522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            s8 firstVal, secondVal, result;                                 \
86622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            firstVal = GET_REGISTER_WIDE(vsrc1);                            \
86722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            secondVal = GET_REGISTER_WIDE(vsrc2);                           \
86822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (secondVal == 0LL) {                                         \
86922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                EXPORT_PC();                                                \
87022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                dvmThrowException("Ljava/lang/ArithmeticException;",        \
87122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    "divide by zero");                                      \
87222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();                                     \
87322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }                                                               \
87422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if ((u8)firstVal == 0x8000000000000000ULL &&                    \
87522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                secondVal == -1LL)                                          \
87622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            {                                                               \
87722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                if (_chkdiv == 1)                                           \
87822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    result = firstVal;  /* division */                      \
87922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                else                                                        \
88022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    result = 0;         /* remainder */                     \
88122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            } else {                                                        \
88222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                result = firstVal _op secondVal;                            \
88322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }                                                               \
88422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            SET_REGISTER_WIDE(vdst, result);                                \
88522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {                                                            \
88622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            SET_REGISTER_WIDE(vdst,                                         \
88722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \
88822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }                                                                   \
88922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
89022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
89122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
89222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op)                    \
89322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
89422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
89522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 srcRegs;                                                         \
89622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_AA(inst);                                               \
89722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        srcRegs = FETCH(1);                                                 \
89822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = srcRegs & 0xff;                                             \
89922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc2 = srcRegs >> 8;                                               \
90022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);       \
90122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER_WIDE(vdst,                                             \
90222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \
90322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
90422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
90522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
90622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv)              \
90722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
90822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_A(inst);                                                \
90922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_B(inst);                                               \
91022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1);            \
91122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (_chkdiv != 0) {                                                 \
91222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            s8 firstVal, secondVal, result;                                 \
91322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            firstVal = GET_REGISTER_WIDE(vdst);                             \
91422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            secondVal = GET_REGISTER_WIDE(vsrc1);                           \
91522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (secondVal == 0LL) {                                         \
91622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                EXPORT_PC();                                                \
91722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                dvmThrowException("Ljava/lang/ArithmeticException;",        \
91822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    "divide by zero");                                      \
91922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();                                     \
92022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }                                                               \
92122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if ((u8)firstVal == 0x8000000000000000ULL &&                    \
92222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                secondVal == -1LL)                                          \
92322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            {                                                               \
92422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                if (_chkdiv == 1)                                           \
92522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    result = firstVal;  /* division */                      \
92622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                else                                                        \
92722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    result = 0;         /* remainder */                     \
92822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            } else {                                                        \
92922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                result = firstVal _op secondVal;                            \
93022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }                                                               \
93122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            SET_REGISTER_WIDE(vdst, result);                                \
93222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {                                                            \
93322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            SET_REGISTER_WIDE(vdst,                                         \
93422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\
93522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }                                                                   \
93622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        FINISH(1);
93722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
93822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op)              \
93922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
94022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_A(inst);                                                \
94122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_B(inst);                                               \
94222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1);            \
94322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER_WIDE(vdst,                                             \
94422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \
94522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        FINISH(1);
94622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
94722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_X_FLOAT(_opcode, _opname, _op)                            \
94822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
94922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
95022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 srcRegs;                                                         \
95122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_AA(inst);                                               \
95222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        srcRegs = FETCH(1);                                                 \
95322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = srcRegs & 0xff;                                             \
95422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc2 = srcRegs >> 8;                                               \
95522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);      \
95622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER_FLOAT(vdst,                                            \
95722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2));       \
95822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
95922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
96022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
96122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op)                           \
96222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
96322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
96422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 srcRegs;                                                         \
96522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_AA(inst);                                               \
96622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        srcRegs = FETCH(1);                                                 \
96722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = srcRegs & 0xff;                                             \
96822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc2 = srcRegs >> 8;                                               \
96922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);     \
97022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER_DOUBLE(vdst,                                           \
97122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2));     \
97222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
97322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
97422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
97522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op)                      \
97622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
97722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_A(inst);                                                \
97822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_B(inst);                                               \
97922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1);           \
98022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER_FLOAT(vdst,                                            \
98122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1));        \
98222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        FINISH(1);
98322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
98422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op)                     \
98522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
98622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_A(inst);                                                \
98722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_B(inst);                                               \
98822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1);          \
98922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER_DOUBLE(vdst,                                           \
99022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1));      \
99122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        FINISH(1);
99222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
99322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize)                   \
99422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
99522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
99622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ArrayObject* arrayObj;                                              \
99722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 arrayInfo;                                                       \
99822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        EXPORT_PC();                                                        \
99922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_AA(inst);                                               \
100022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        arrayInfo = FETCH(1);                                               \
100122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = arrayInfo & 0xff;    /* array ptr */                        \
100222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc2 = arrayInfo >> 8;      /* index */                            \
100322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);        \
100422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);                      \
100522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (!checkForNull((Object*) arrayObj))                              \
100622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();                                         \
100722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (GET_REGISTER(vsrc2) >= arrayObj->length) {                      \
100822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            LOGV("Invalid array access: %p %d (len=%d)\n",                  \
100922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                arrayObj, vsrc2, arrayObj->length);                         \
101022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", \
101122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                NULL);                                                      \
101222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();                                         \
101322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }                                                                   \
101422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER##_regsize(vdst,                                        \
101522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]);            \
101622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));  \
101722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
101822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
101922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
102022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize)                   \
102122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
102222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
102322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ArrayObject* arrayObj;                                              \
102422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 arrayInfo;                                                       \
102522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        EXPORT_PC();                                                        \
102622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_AA(inst);       /* AA: source value */                  \
102722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        arrayInfo = FETCH(1);                                               \
102822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = arrayInfo & 0xff;   /* BB: array ptr */                     \
102922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc2 = arrayInfo >> 8;     /* CC: index */                         \
103022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);        \
103122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);                      \
103222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (!checkForNull((Object*) arrayObj))                              \
103322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();                                         \
103422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (GET_REGISTER(vsrc2) >= arrayObj->length) {                      \
103522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", \
103622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                NULL);                                                      \
103722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();                                         \
103822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }                                                                   \
103922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
104022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] =                \
104122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GET_REGISTER##_regsize(vdst);                                   \
104222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
104322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
104422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
104522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
104622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * It's possible to get a bad value out of a field with sub-32-bit stores
104722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * because the -quick versions always operate on 32 bits.  Consider:
104822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *   short foo = -1  (sets a 32-bit register to 0xffffffff)
104922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *   iput-quick foo  (writes all 32 bits to the field)
105022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *   short bar = 1   (sets a 32-bit register to 0x00000001)
105122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *   iput-short      (writes the low 16 bits to the field)
105222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *   iget-quick foo  (reads all 32 bits from the field, yielding 0xffff0001)
105322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * This can only happen when optimized and non-optimized code has interleaved
105422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * access to the same field.  This is unlikely but possible.
105522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch *
105622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * The easiest way to fix this is to always read/write 32 bits at a time.  On
105722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * a device with a 16-bit data bus this is sub-optimal.  (The alternative
105822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * approach is to have sub-int versions of iget-quick, but now we're wasting
105922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Dalvik instruction space and making it less likely that handler code will
106022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * already be in the CPU i-cache.)
106122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
106222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize)                   \
106322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
106422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
106522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        InstField* ifield;                                                  \
106622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        Object* obj;                                                        \
106722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        EXPORT_PC();                                                        \
106822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_A(inst);                                                \
106922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_B(inst);   /* object ptr */                            \
107022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ref = FETCH(1);         /* field ref */                             \
107122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
107222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        obj = (Object*) GET_REGISTER(vsrc1);                                \
107322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (!checkForNull(obj))                                             \
107422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();                                         \
107522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref);  \
107622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (ifield == NULL) {                                               \
107722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ifield = dvmResolveInstField(curMethod->clazz, ref);            \
107822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (ifield == NULL)                                             \
107922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();                                     \
108022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }                                                                   \
108122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER##_regsize(vdst,                                        \
108222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmGetField##_ftype(obj, ifield->byteOffset));                  \
108322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name,                   \
108422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            (u8) GET_REGISTER##_regsize(vdst));                             \
108522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        UPDATE_FIELD_GET(&ifield->field);                                   \
108622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
108722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
108822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
108922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize)             \
109022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
109122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
109222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        Object* obj;                                                        \
109322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_A(inst);                                                \
109422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_B(inst);   /* object ptr */                            \
109522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ref = FETCH(1);         /* field offset */                          \
109622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|iget%s-quick v%d,v%d,field@+%u",                            \
109722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            (_opname), vdst, vsrc1, ref);                                   \
109822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        obj = (Object*) GET_REGISTER(vsrc1);                                \
109922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (!checkForNullExportPC(obj, fp, pc))                             \
110022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();                                         \
110122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref));        \
110222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("+ IGETQ %d=0x%08llx", ref,                                   \
110322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            (u8) GET_REGISTER##_regsize(vdst));                             \
110422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
110522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
110622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
110722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize)                   \
110822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
110922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
111022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        InstField* ifield;                                                  \
111122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        Object* obj;                                                        \
111222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        EXPORT_PC();                                                        \
111322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_A(inst);                                                \
111422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_B(inst);   /* object ptr */                            \
111522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ref = FETCH(1);         /* field ref */                             \
111622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
111722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        obj = (Object*) GET_REGISTER(vsrc1);                                \
111822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (!checkForNull(obj))                                             \
111922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();                                         \
112022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref);  \
112122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (ifield == NULL) {                                               \
112222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ifield = dvmResolveInstField(curMethod->clazz, ref);            \
112322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (ifield == NULL)                                             \
112422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();                                     \
112522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }                                                                   \
112622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmSetField##_ftype(obj, ifield->byteOffset,                        \
112722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GET_REGISTER##_regsize(vdst));                                  \
112822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name,                   \
112922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            (u8) GET_REGISTER##_regsize(vdst));                             \
113022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        UPDATE_FIELD_PUT(&ifield->field);                                   \
113122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
113222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
113322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
113422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize)             \
113522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
113622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
113722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        Object* obj;                                                        \
113822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_A(inst);                                                \
113922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_B(inst);   /* object ptr */                            \
114022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ref = FETCH(1);         /* field offset */                          \
114122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|iput%s-quick v%d,v%d,field@0x%04x",                         \
114222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            (_opname), vdst, vsrc1, ref);                                   \
114322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        obj = (Object*) GET_REGISTER(vsrc1);                                \
114422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (!checkForNullExportPC(obj, fp, pc))                             \
114522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();                                         \
114622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst));        \
114722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("+ IPUTQ %d=0x%08llx", ref,                                   \
114822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            (u8) GET_REGISTER##_regsize(vdst));                             \
114922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
115022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
115122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
115222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize)                   \
115322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/)                              \
115422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
115522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        StaticField* sfield;                                                \
115622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_AA(inst);                                               \
115722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ref = FETCH(1);         /* field ref */                             \
115822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref);           \
115922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
116022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (sfield == NULL) {                                               \
116122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            EXPORT_PC();                                                    \
116222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            sfield = dvmResolveStaticField(curMethod->clazz, ref);          \
116322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (sfield == NULL)                                             \
116422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();                                     \
116522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }                                                                   \
116622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield));    \
116722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("+ SGET '%s'=0x%08llx",                                       \
116822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            sfield->field.name, (u8)GET_REGISTER##_regsize(vdst));          \
116922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        UPDATE_FIELD_GET(&sfield->field);                                   \
117022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
117122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
117222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
117322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize)                   \
117422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/)                              \
117522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {                                                                       \
117622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        StaticField* sfield;                                                \
117722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = INST_AA(inst);                                               \
117822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ref = FETCH(1);         /* field ref */                             \
117922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref);           \
118022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
118122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (sfield == NULL) {                                               \
118222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            EXPORT_PC();                                                    \
118322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            sfield = dvmResolveStaticField(curMethod->clazz, ref);          \
118422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (sfield == NULL)                                             \
118522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();                                     \
118622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }                                                                   \
118722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst));    \
118822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("+ SPUT '%s'=0x%08llx",                                       \
118922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            sfield->field.name, (u8)GET_REGISTER##_regsize(vdst));          \
119022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        UPDATE_FIELD_PUT(&sfield->field);                                   \
119122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }                                                                       \
119222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(2);
119322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
119422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
11954abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden/* File: c/OP_BREAKPOINT.c */
11964abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFaddenHANDLE_OPCODE(OP_BREAKPOINT)
11974abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#if (INTERP_TYPE == INTERP_DBG) && defined(WITH_DEBUGGER)
11984abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden    {
11994abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        /*
12004abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * Restart this instruction with the original opcode.  We do
12014abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * this by simply jumping to the handler.
12024abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         *
12034abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * It's probably not necessary to update "inst", but we do it
12044abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * for the sake of anything that needs to do disambiguation in a
12054abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * common handler with INST_INST.
12064abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         *
12074abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * The breakpoint itself is handled over in updateDebugger(),
12084abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * because we need to detect other events (method entry, single
12094abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * step) and report them in the same event packet, and we're not
12104abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * yet handling those through breakpoint instructions.  By the
12114abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * time we get here, the breakpoint has already been handled and
12124abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * the thread resumed.
12134abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         */
12144abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        u1 originalOpCode = dvmGetOriginalOpCode(pc);
12154abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        LOGV("+++ break 0x%02x (0x%04x -> 0x%04x)\n", originalOpCode, inst,
12164abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            INST_REPLACE_OP(inst, originalOpCode));
12174abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        inst = INST_REPLACE_OP(inst, originalOpCode);
12184abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        FINISH_BKPT(originalOpCode);
12194abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden    }
12204abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#else
12214abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden    LOGE("Breakpoint hit in non-debug interpreter\n");
12224abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden    dvmAbort();
12234abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#endif
12244abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFaddenOP_END
12254abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden
12264abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden/* File: c/OP_EXECUTE_INLINE_RANGE.c */
12274abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFaddenHANDLE_OPCODE(OP_EXECUTE_INLINE_RANGE /*{vCCCC..v(CCCC+AA-1)}, inline@BBBB*/)
12284abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden    {
12294abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        u4 arg0, arg1, arg2, arg3;
12304abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        arg0 = arg1 = arg2 = arg3 = 0;      /* placate gcc */
12314abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden
12324abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        EXPORT_PC();
12334abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden
12344abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        vsrc1 = INST_AA(inst);      /* #of args */
12354abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        ref = FETCH(1);             /* inline call "ref" */
12364abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        vdst = FETCH(2);            /* range base */
12374abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        ILOGV("|execute-inline-range args=%d @%d {regs=v%d-v%d}",
12384abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            vsrc1, ref, vdst, vdst+vsrc1-1);
12394abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden
12404abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        assert((vdst >> 16) == 0);  // 16-bit type -or- high 16 bits clear
12414abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        assert(vsrc1 <= 4);
12424abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden
12434abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        switch (vsrc1) {
12444abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        case 4:
12454abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            arg3 = GET_REGISTER(vdst+3);
12464abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            /* fall through */
12474abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        case 3:
12484abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            arg2 = GET_REGISTER(vdst+2);
12494abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            /* fall through */
12504abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        case 2:
12514abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            arg1 = GET_REGISTER(vdst+1);
12524abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            /* fall through */
12534abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        case 1:
12544abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            arg0 = GET_REGISTER(vdst+0);
12554abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            /* fall through */
12564abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        default:        // case 0
12574abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            ;
12584abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        }
12594abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden
12604abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#if INTERP_TYPE == INTERP_DBG
12614abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        if (!dvmPerformInlineOp4Dbg(arg0, arg1, arg2, arg3, &retval, ref))
12624abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            GOTO_exceptionThrown();
12634abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#else
12644abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        if (!dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref))
12654abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            GOTO_exceptionThrown();
12664abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#endif
12674abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden    }
12684abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden    FINISH(3);
12694abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFaddenOP_END
12704abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden
127122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* File: c/gotoTargets.c */
127222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
127322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * C footer.  This has some common code shared by the various targets.
127422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
127522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
127622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/*
127722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * Everything from here on is a "goto target".  In the basic interpreter
127822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * we jump into these targets and then jump directly to the handler for
127922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch * next instruction.  Here, these are subroutines that return to the caller.
128022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch */
128122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
128222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET(filledNewArray, bool methodCallRange)
128322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {
128422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ClassObject* arrayClass;
128522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ArrayObject* newArray;
128622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u4* contents;
128722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        char typeCh;
128822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        int i;
128922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u4 arg5;
129022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
129122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        EXPORT_PC();
129222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
129322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ref = FETCH(1);             /* class ref */
129422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = FETCH(2);            /* first 4 regs -or- range base */
129522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
129622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (methodCallRange) {
129722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            vsrc1 = INST_AA(inst);  /* #of elements */
129822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            arg5 = -1;              /* silence compiler warning */
129922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|filled-new-array-range args=%d @0x%04x {regs=v%d-v%d}",
130022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vsrc1, ref, vdst, vdst+vsrc1-1);
130122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {
130222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            arg5 = INST_A(inst);
130322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            vsrc1 = INST_B(inst);   /* #of elements */
130422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|filled-new-array args=%d @0x%04x {regs=0x%04x %x}",
130522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vsrc1, ref, vdst, arg5);
130622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
130722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
130822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
130922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Resolve the array class.
131022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
131122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        arrayClass = dvmDexGetResolvedClass(methodClassDex, ref);
131222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (arrayClass == NULL) {
131322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            arrayClass = dvmResolveClass(curMethod->clazz, ref, false);
131422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (arrayClass == NULL)
131522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();
131622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
131722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
131822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (!dvmIsArrayClass(arrayClass)) {
131922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmThrowException("Ljava/lang/RuntimeError;",
132022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                "filled-new-array needs array class");
132122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
132222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
132322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        */
132422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /* verifier guarantees this is an array class */
132522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        assert(dvmIsArrayClass(arrayClass));
132622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        assert(dvmIsClassInitialized(arrayClass));
132722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
132822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
132922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Create an array of the specified type.
133022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
133122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        LOGVV("+++ filled-new-array type is '%s'\n", arrayClass->descriptor);
133222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        typeCh = arrayClass->descriptor[1];
133322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (typeCh == 'D' || typeCh == 'J') {
133422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            /* category 2 primitives not allowed */
133522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmThrowException("Ljava/lang/RuntimeError;",
133622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                "bad filled array req");
133722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
133822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else if (typeCh != 'L' && typeCh != '[' && typeCh != 'I') {
133922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            /* TODO: requires multiple "fill in" loops with different widths */
134022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            LOGE("non-int primitives not implemented\n");
134122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmThrowException("Ljava/lang/InternalError;",
134222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                "filled-new-array not implemented for anything but 'int'");
134322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
134422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
134522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
134622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        newArray = dvmAllocArrayByClass(arrayClass, vsrc1, ALLOC_DONT_TRACK);
134722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (newArray == NULL)
134822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
134922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
135022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
135122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Fill in the elements.  It's legal for vsrc1 to be zero.
135222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
135322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        contents = (u4*) newArray->contents;
135422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (methodCallRange) {
135522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            for (i = 0; i < vsrc1; i++)
135622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                contents[i] = GET_REGISTER(vdst+i);
135722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {
135822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            assert(vsrc1 <= 5);
135922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (vsrc1 == 5) {
136022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                contents[4] = GET_REGISTER(arg5);
136122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vsrc1--;
136222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }
136322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            for (i = 0; i < vsrc1; i++) {
136422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                contents[i] = GET_REGISTER(vdst & 0x0f);
136522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vdst >>= 4;
136622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }
136722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
136822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
136922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        retval.l = newArray;
137022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
137122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    FINISH(3);
137222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_END
137322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
137422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
137522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET(invokeVirtual, bool methodCallRange)
137622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {
137722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        Method* baseMethod;
137822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        Object* thisPtr;
137922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
138022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        EXPORT_PC();
138122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
138222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
138322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ref = FETCH(1);             /* method ref */
138422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = FETCH(2);            /* 4 regs -or- first reg */
138522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
138622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
138722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * The object against which we are executing a method is always
138822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * in the first argument.
138922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
139022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (methodCallRange) {
139122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            assert(vsrc1 > 0);
139222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|invoke-virtual-range args=%d @0x%04x {regs=v%d-v%d}",
139322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vsrc1, ref, vdst, vdst+vsrc1-1);
139422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            thisPtr = (Object*) GET_REGISTER(vdst);
139522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {
139622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            assert((vsrc1>>4) > 0);
139722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|invoke-virtual args=%d @0x%04x {regs=0x%04x %x}",
139822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
139922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
140022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
140122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
140222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (!checkForNull(thisPtr))
140322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
140422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
140522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
140622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Resolve the method.  This is the correct method for the static
140722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * type of the object.  We also verify access permissions here.
140822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
140922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
141022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (baseMethod == NULL) {
141122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
141222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (baseMethod == NULL) {
141322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                ILOGV("+ unknown method or access denied\n");
141422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();
141522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }
141622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
141722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
141822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
141922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Combine the object we found with the vtable offset in the
142022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * method.
142122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
142222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        assert(baseMethod->methodIndex < thisPtr->clazz->vtableCount);
142322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        methodToCall = thisPtr->clazz->vtable[baseMethod->methodIndex];
142422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
142522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if 0
142622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (dvmIsAbstractMethod(methodToCall)) {
142722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            /*
142822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * This can happen if you create two classes, Base and Sub, where
142922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * Sub is a sub-class of Base.  Declare a protected abstract
143022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * method foo() in Base, and invoke foo() from a method in Base.
143122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * Base is an "abstract base class" and is never instantiated
143222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * directly.  Now, Override foo() in Sub, and use Sub.  This
143322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * Works fine unless Sub stops providing an implementation of
143422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * the method.
143522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             */
143622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmThrowException("Ljava/lang/AbstractMethodError;",
143722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                "abstract method not implemented");
143822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
143922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
144022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
144122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        assert(!dvmIsAbstractMethod(methodToCall) ||
144222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            methodToCall->nativeFunc != NULL);
144322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
144422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
144522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        LOGVV("+++ base=%s.%s virtual[%d]=%s.%s\n",
144622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            baseMethod->clazz->descriptor, baseMethod->name,
144722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            (u4) baseMethod->methodIndex,
144822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            methodToCall->clazz->descriptor, methodToCall->name);
144922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        assert(methodToCall != NULL);
145022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
145122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if 0
145222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (vsrc1 != methodToCall->insSize) {
145322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            LOGW("WRONG METHOD: base=%s.%s virtual[%d]=%s.%s\n",
145422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                baseMethod->clazz->descriptor, baseMethod->name,
145522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                (u4) baseMethod->methodIndex,
145622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                methodToCall->clazz->descriptor, methodToCall->name);
145722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            //dvmDumpClass(baseMethod->clazz);
145822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            //dvmDumpClass(methodToCall->clazz);
145922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmDumpAllClasses(0);
146022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
146122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
146222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
146322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
146422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
146522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_END
146622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
146722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET(invokeSuper, bool methodCallRange)
146822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {
146922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        Method* baseMethod;
147022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 thisReg;
147122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
147222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        EXPORT_PC();
147322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
147422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
147522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ref = FETCH(1);             /* method ref */
147622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = FETCH(2);            /* 4 regs -or- first reg */
147722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
147822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (methodCallRange) {
147922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|invoke-super-range args=%d @0x%04x {regs=v%d-v%d}",
148022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vsrc1, ref, vdst, vdst+vsrc1-1);
148122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            thisReg = vdst;
148222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {
148322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|invoke-super args=%d @0x%04x {regs=0x%04x %x}",
148422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
148522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            thisReg = vdst & 0x0f;
148622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
148722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /* impossible in well-formed code, but we must check nevertheless */
148822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (!checkForNull((Object*) GET_REGISTER(thisReg)))
148922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
149022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
149122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
149222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Resolve the method.  This is the correct method for the static
149322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * type of the object.  We also verify access permissions here.
149422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * The first arg to dvmResolveMethod() is just the referring class
149522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * (used for class loaders and such), so we don't want to pass
149622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * the superclass into the resolution call.
149722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
149822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
149922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (baseMethod == NULL) {
150022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
150122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (baseMethod == NULL) {
150222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                ILOGV("+ unknown method or access denied\n");
150322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();
150422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }
150522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
150622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
150722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
150822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Combine the object we found with the vtable offset in the
150922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * method's class.
151022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         *
151122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * We're using the current method's class' superclass, not the
151222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * superclass of "this".  This is because we might be executing
151322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * in a method inherited from a superclass, and we want to run
151422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * in that class' superclass.
151522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
151622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (baseMethod->methodIndex >= curMethod->clazz->super->vtableCount) {
151722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            /*
151822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * Method does not exist in the superclass.  Could happen if
151922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * superclass gets updated.
152022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             */
152122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmThrowException("Ljava/lang/NoSuchMethodError;",
152222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                baseMethod->name);
152322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
152422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
152522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        methodToCall = curMethod->clazz->super->vtable[baseMethod->methodIndex];
152622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if 0
152722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (dvmIsAbstractMethod(methodToCall)) {
152822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmThrowException("Ljava/lang/AbstractMethodError;",
152922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                "abstract method not implemented");
153022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
153122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
153222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
153322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        assert(!dvmIsAbstractMethod(methodToCall) ||
153422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            methodToCall->nativeFunc != NULL);
153522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
153622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        LOGVV("+++ base=%s.%s super-virtual=%s.%s\n",
153722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            baseMethod->clazz->descriptor, baseMethod->name,
153822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            methodToCall->clazz->descriptor, methodToCall->name);
153922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        assert(methodToCall != NULL);
154022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
154122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
154222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
154322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_END
154422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
154522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET(invokeInterface, bool methodCallRange)
154622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {
154722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        Object* thisPtr;
154822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ClassObject* thisClass;
154922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
155022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        EXPORT_PC();
155122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
155222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
155322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ref = FETCH(1);             /* method ref */
155422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = FETCH(2);            /* 4 regs -or- first reg */
155522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
155622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
155722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * The object against which we are executing a method is always
155822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * in the first argument.
155922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
156022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (methodCallRange) {
156122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            assert(vsrc1 > 0);
156222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|invoke-interface-range args=%d @0x%04x {regs=v%d-v%d}",
156322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vsrc1, ref, vdst, vdst+vsrc1-1);
156422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            thisPtr = (Object*) GET_REGISTER(vdst);
156522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {
156622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            assert((vsrc1>>4) > 0);
156722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|invoke-interface args=%d @0x%04x {regs=0x%04x %x}",
156822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
156922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
157022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
157122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (!checkForNull(thisPtr))
157222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
157322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
157422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        thisClass = thisPtr->clazz;
157522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
157622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
157722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Given a class and a method index, find the Method* with the
157822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * actual code we want to execute.
157922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
158022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        methodToCall = dvmFindInterfaceMethodInCache(thisClass, ref, curMethod,
158122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                        methodClassDex);
158222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (methodToCall == NULL) {
158322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            assert(dvmCheckException(self));
158422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
158522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
158622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
158722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
158822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
158922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_END
159022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
159122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET(invokeDirect, bool methodCallRange)
159222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {
159322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 thisReg;
159422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
159522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
159622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ref = FETCH(1);             /* method ref */
159722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = FETCH(2);            /* 4 regs -or- first reg */
159822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
159922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        EXPORT_PC();
160022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
160122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (methodCallRange) {
160222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|invoke-direct-range args=%d @0x%04x {regs=v%d-v%d}",
160322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vsrc1, ref, vdst, vdst+vsrc1-1);
160422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            thisReg = vdst;
160522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {
160622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|invoke-direct args=%d @0x%04x {regs=0x%04x %x}",
160722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
160822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            thisReg = vdst & 0x0f;
160922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
161022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (!checkForNull((Object*) GET_REGISTER(thisReg)))
161122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
161222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
161322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
161422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (methodToCall == NULL) {
161522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            methodToCall = dvmResolveMethod(curMethod->clazz, ref,
161622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                            METHOD_DIRECT);
161722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (methodToCall == NULL) {
161822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                ILOGV("+ unknown direct method\n");     // should be impossible
161922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();
162022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }
162122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
162222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
162322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
162422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_END
162522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
162622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET(invokeStatic, bool methodCallRange)
162722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
162822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    ref = FETCH(1);             /* method ref */
162922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    vdst = FETCH(2);            /* 4 regs -or- first reg */
163022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
163122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    EXPORT_PC();
163222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
163322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    if (methodCallRange)
163422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|invoke-static-range args=%d @0x%04x {regs=v%d-v%d}",
163522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            vsrc1, ref, vdst, vdst+vsrc1-1);
163622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    else
163722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("|invoke-static args=%d @0x%04x {regs=0x%04x %x}",
163822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
163922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
164022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref);
164122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    if (methodToCall == NULL) {
164222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        methodToCall = dvmResolveMethod(curMethod->clazz, ref, METHOD_STATIC);
164322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (methodToCall == NULL) {
164422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("+ unknown method\n");
164522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
164622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
164722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
164822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
164922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_END
165022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
165122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET(invokeVirtualQuick, bool methodCallRange)
165222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {
165322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        Object* thisPtr;
165422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
165522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        EXPORT_PC();
165622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
165722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
165822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ref = FETCH(1);             /* vtable index */
165922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = FETCH(2);            /* 4 regs -or- first reg */
166022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
166122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
166222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * The object against which we are executing a method is always
166322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * in the first argument.
166422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
166522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (methodCallRange) {
166622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            assert(vsrc1 > 0);
166722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|invoke-virtual-quick-range args=%d @0x%04x {regs=v%d-v%d}",
166822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vsrc1, ref, vdst, vdst+vsrc1-1);
166922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            thisPtr = (Object*) GET_REGISTER(vdst);
167022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {
167122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            assert((vsrc1>>4) > 0);
167222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|invoke-virtual-quick args=%d @0x%04x {regs=0x%04x %x}",
167322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
167422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            thisPtr = (Object*) GET_REGISTER(vdst & 0x0f);
167522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
167622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
167722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (!checkForNull(thisPtr))
167822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
167922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
168022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
168122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Combine the object we found with the vtable offset in the
168222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * method.
168322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
168422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        assert(ref < thisPtr->clazz->vtableCount);
168522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        methodToCall = thisPtr->clazz->vtable[ref];
168622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
168722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if 0
168822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (dvmIsAbstractMethod(methodToCall)) {
168922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmThrowException("Ljava/lang/AbstractMethodError;",
169022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                "abstract method not implemented");
169122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
169222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
169322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
169422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        assert(!dvmIsAbstractMethod(methodToCall) ||
169522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            methodToCall->nativeFunc != NULL);
169622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
169722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
169822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        LOGVV("+++ virtual[%d]=%s.%s\n",
169922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ref, methodToCall->clazz->descriptor, methodToCall->name);
170022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        assert(methodToCall != NULL);
170122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
170222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
170322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
170422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_END
170522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
170622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET(invokeSuperQuick, bool methodCallRange)
170722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {
170822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u2 thisReg;
170922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
171022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        EXPORT_PC();
171122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
171222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vsrc1 = INST_AA(inst);      /* AA (count) or BA (count + arg 5) */
171322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ref = FETCH(1);             /* vtable index */
171422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        vdst = FETCH(2);            /* 4 regs -or- first reg */
171522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
171622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (methodCallRange) {
171722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|invoke-super-quick-range args=%d @0x%04x {regs=v%d-v%d}",
171822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vsrc1, ref, vdst, vdst+vsrc1-1);
171922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            thisReg = vdst;
172022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {
172122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGV("|invoke-super-quick args=%d @0x%04x {regs=0x%04x %x}",
172222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
172322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            thisReg = vdst & 0x0f;
172422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
172522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /* impossible in well-formed code, but we must check nevertheless */
172622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (!checkForNull((Object*) GET_REGISTER(thisReg)))
172722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
172822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
172922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if 0   /* impossible in optimized + verified code */
173022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (ref >= curMethod->clazz->super->vtableCount) {
173122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmThrowException("Ljava/lang/NoSuchMethodError;", NULL);
173222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
173322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
173422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
173522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        assert(ref < curMethod->clazz->super->vtableCount);
173622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
173722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
173822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
173922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Combine the object we found with the vtable offset in the
174022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * method's class.
174122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         *
174222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * We're using the current method's class' superclass, not the
174322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * superclass of "this".  This is because we might be executing
174422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * in a method inherited from a superclass, and we want to run
174522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * in the method's class' superclass.
174622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
174722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        methodToCall = curMethod->clazz->super->vtable[ref];
174822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
174922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if 0
175022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (dvmIsAbstractMethod(methodToCall)) {
175122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmThrowException("Ljava/lang/AbstractMethodError;",
175222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                "abstract method not implemented");
175322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_exceptionThrown();
175422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
175522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
175622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        assert(!dvmIsAbstractMethod(methodToCall) ||
175722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            methodToCall->nativeFunc != NULL);
175822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
175922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        LOGVV("+++ super-virtual[%d]=%s.%s\n",
176022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ref, methodToCall->clazz->descriptor, methodToCall->name);
176122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        assert(methodToCall != NULL);
176222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
176322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
176422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
176522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_END
176622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
176722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
176822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
176922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    /*
177022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * General handling for return-void, return, and return-wide.  Put the
177122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * return value in "retval" before jumping here.
177222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     */
177322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET(returnFromMethod)
177422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {
177522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        StackSaveArea* saveArea;
177622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
177722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
177822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * We must do this BEFORE we pop the previous stack frame off, so
177922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * that the GC can see the return value (if any) in the local vars.
178022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         *
178122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Since this is now an interpreter switch point, we must do it before
178222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * we do anything at all.
178322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
178422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        PERIODIC_CHECKS(kInterpEntryReturn, 0);
178522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
178622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("> retval=0x%llx (leaving %s.%s %s)",
178722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            retval.j, curMethod->clazz->descriptor, curMethod->name,
178822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            curMethod->shorty);
178922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        //DUMP_REGS(curMethod, fp);
179022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
179122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        saveArea = SAVEAREA_FROM_FP(fp);
179222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
179322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#ifdef EASY_GDB
179422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        debugSaveArea = saveArea;
179522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
179622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if (INTERP_TYPE == INTERP_DBG) && defined(WITH_PROFILER)
179722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        TRACE_METHOD_EXIT(self, curMethod);
179822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
179922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
180022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /* back up to previous frame and see if we hit a break */
180122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        fp = saveArea->prevFrame;
180222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        assert(fp != NULL);
180322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (dvmIsBreakFrame(fp)) {
180422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            /* bail without popping the method frame from stack */
180522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            LOGVV("+++ returned into break frame\n");
18064abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#if defined(WITH_JIT)
18074abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            /* Let the Jit know the return is terminating normally */
18084abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            CHECK_JIT();
18094abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#endif
181022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_bail();
181122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
181222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
181322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /* update thread FP, and reset local variables */
181422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        self->curFrame = fp;
181522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        curMethod = SAVEAREA_FROM_FP(fp)->method;
181622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        //methodClass = curMethod->clazz;
181722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        methodClassDex = curMethod->clazz->pDvmDex;
181822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        pc = saveArea->savedPc;
181922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor,
182022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            curMethod->name, curMethod->shorty);
182122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
182222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /* use FINISH on the caller's invoke instruction */
182322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        //u2 invokeInstr = INST_INST(FETCH(0));
182422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
182522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            invokeInstr <= OP_INVOKE_INTERFACE*/)
182622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        {
182722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            FINISH(3);
182822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {
182922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            //LOGE("Unknown invoke instr %02x at %d\n",
183022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            //    invokeInstr, (int) (pc - curMethod->insns));
183122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            assert(false);
183222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
183322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
183422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_END
183522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
183622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
183722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    /*
183822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * Jump here when the code throws an exception.
183922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     *
184022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * By the time we get here, the Throwable has been created and the stack
184122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * trace has been saved off.
184222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     */
184322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET(exceptionThrown)
184422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {
184522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        Object* exception;
184622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        int catchRelPc;
184722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
184822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
184922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Since this is now an interpreter switch point, we must do it before
185022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * we do anything at all.
185122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
185222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        PERIODIC_CHECKS(kInterpEntryThrow, 0);
185322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
18544abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#if defined(WITH_JIT)
18554abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        // Something threw during trace selection - abort the current trace
18564abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden        ABORT_JIT_TSELECT();
18574abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#endif
185822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
185922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * We save off the exception and clear the exception status.  While
186022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * processing the exception we might need to load some Throwable
186122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * classes, and we don't want class loader exceptions to get
186222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * confused with this one.
186322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
186422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        assert(dvmCheckException(self));
186522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        exception = dvmGetException(self);
186622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmAddTrackedAlloc(exception, self);
186722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmClearException(self);
186822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
186922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        LOGV("Handling exception %s at %s:%d\n",
187022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            exception->clazz->descriptor, curMethod->name,
187122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmLineNumFromPC(curMethod, pc - curMethod->insns));
187222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
187322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if (INTERP_TYPE == INTERP_DBG) && defined(WITH_DEBUGGER)
187422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
187522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Tell the debugger about it.
187622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         *
187722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * TODO: if the exception was thrown by interpreted code, control
187822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * fell through native, and then back to us, we will report the
187922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * exception at the point of the throw and again here.  We can avoid
188022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * this by not reporting exceptions when we jump here directly from
188122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * the native call code above, but then we won't report exceptions
188222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * that were thrown *from* the JNI code (as opposed to *through* it).
188322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         *
188422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * The correct solution is probably to ignore from-native exceptions
188522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * here, and have the JNI exception code do the reporting to the
188622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * debugger.
188722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
188822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (gDvm.debuggerActive) {
188922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            void* catchFrame;
189022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns,
189122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                        exception, true, &catchFrame);
189222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmDbgPostException(fp, pc - curMethod->insns, catchFrame,
189322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                catchRelPc, exception);
189422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
189522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
189622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
189722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
189822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * We need to unroll to the catch block or the nearest "break"
189922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * frame.
190022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         *
190122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * A break frame could indicate that we have reached an intermediate
190222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * native call, or have gone off the top of the stack and the thread
190322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * needs to exit.  Either way, we return from here, leaving the
190422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * exception raised.
190522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         *
190622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * If we do find a catch block, we want to transfer execution to
190722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * that point.
19084abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         *
19094abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * Note this can cause an exception while resolving classes in
19104abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * the "catch" blocks.
191122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
191222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns,
191322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    exception, false, (void*)&fp);
191422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
191522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
191622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Restore the stack bounds after an overflow.  This isn't going to
191722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * be correct in all circumstances, e.g. if JNI code devours the
191822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * exception this won't happen until some other exception gets
191922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * thrown.  If the code keeps pushing the stack bounds we'll end
192022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * up aborting the VM.
192122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         *
192222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Note we want to do this *after* the call to dvmFindCatchBlock,
192322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * because that may need extra stack space to resolve exception
192422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * classes (e.g. through a class loader).
19254abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         *
19264abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * It's possible for the stack overflow handling to cause an
19274abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * exception (specifically, class resolution in a "catch" block
19284abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * during the call above), so we could see the thread's overflow
19294abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * flag raised but actually be running in a "nested" interpreter
19304abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * frame.  We don't allow doubled-up StackOverflowErrors, so
19314abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * we can check for this by just looking at the exception type
19324abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * in the cleanup function.  Also, we won't unroll past the SOE
19334abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * point because the more-recent exception will hit a break frame
19344abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden         * as it unrolls to here.
193522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
193622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (self->stackOverflowed)
19374abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            dvmCleanupStackOverflow(self, exception);
193822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
193922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (catchRelPc < 0) {
194022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            /* falling through to JNI code or off the bottom of the stack */
194122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if DVM_SHOW_EXCEPTION >= 2
194222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            LOGD("Exception %s from %s:%d not caught locally\n",
194322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod),
194422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                dvmLineNumFromPC(curMethod, pc - curMethod->insns));
194522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
194622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmSetException(self, exception);
194722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmReleaseTrackedAlloc(exception, self);
194822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            GOTO_bail();
194922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
195022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
195122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if DVM_SHOW_EXCEPTION >= 3
195222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        {
195322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            const Method* catchMethod = SAVEAREA_FROM_FP(fp)->method;
195422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            LOGD("Exception %s thrown from %s:%d to %s:%d\n",
195522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod),
195622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                dvmLineNumFromPC(curMethod, pc - curMethod->insns),
195722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                dvmGetMethodSourceFile(catchMethod),
195822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                dvmLineNumFromPC(catchMethod, catchRelPc));
195922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
196022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
196122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
196222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
196322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Adjust local variables to match self->curFrame and the
196422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * updated PC.
196522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
196622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        //fp = (u4*) self->curFrame;
196722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        curMethod = SAVEAREA_FROM_FP(fp)->method;
196822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        //methodClass = curMethod->clazz;
196922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        methodClassDex = curMethod->clazz->pDvmDex;
197022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        pc = curMethod->insns + catchRelPc;
197122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
197222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            curMethod->name, curMethod->shorty);
197322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        DUMP_REGS(curMethod, fp, false);            // show all regs
197422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
197522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
197622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Restore the exception if the handler wants it.
197722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         *
197822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * The Dalvik spec mandates that, if an exception handler wants to
197922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * do something with the exception, the first instruction executed
198022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * must be "move-exception".  We can pass the exception along
198122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * through the thread struct, and let the move-exception instruction
198222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * clear it for us.
198322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         *
198422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * If the handler doesn't call move-exception, we don't want to
198522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * finish here with an exception still pending.
198622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
198722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (INST_INST(FETCH(0)) == OP_MOVE_EXCEPTION)
198822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmSetException(self, exception);
198922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
199022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        dvmReleaseTrackedAlloc(exception, self);
199122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        FINISH(0);
199222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
199322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_END
199422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
199522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
199622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    /*
199722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * General handling for invoke-{virtual,super,direct,static,interface},
199822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * including "quick" variants.
199922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     *
200022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * Set "methodToCall" to the Method we're calling, and "methodCallRange"
200122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * depending on whether this is a "/range" instruction.
200222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     *
200322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * For a range call:
200422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     *  "vsrc1" holds the argument count (8 bits)
200522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     *  "vdst" holds the first argument in the range
200622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * For a non-range call:
200722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     *  "vsrc1" holds the argument count (4 bits) and the 5th argument index
200822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     *  "vdst" holds four 4-bit register indices
200922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     *
201022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * The caller must EXPORT_PC before jumping here, because any method
201122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * call can throw a stack overflow exception.
201222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     */
201322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall,
201422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    u2 count, u2 regs)
201522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {
201622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        STUB_HACK(vsrc1 = count; vdst = regs; methodToCall = _methodToCall;);
201722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
201822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        //printf("range=%d call=%p count=%d regs=0x%04x\n",
201922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        //    methodCallRange, methodToCall, count, regs);
202022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor,
202122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        //    methodToCall->name, methodToCall->shorty);
202222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
202322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u4* outs;
202422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        int i;
202522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
202622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /*
202722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         * Copy args.  This may corrupt vsrc1/vdst.
202822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch         */
202922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (methodCallRange) {
203022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            // could use memcpy or a "Duff's device"; most functions have
203122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            // so few args it won't matter much
203222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            assert(vsrc1 <= curMethod->outsSize);
203322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            assert(vsrc1 == methodToCall->insSize);
203422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            outs = OUTS_FROM_FP(fp, vsrc1);
203522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            for (i = 0; i < vsrc1; i++)
203622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                outs[i] = GET_REGISTER(vdst+i);
203722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {
203822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            u4 count = vsrc1 >> 4;
203922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
204022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            assert(count <= curMethod->outsSize);
204122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            assert(count == methodToCall->insSize);
204222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            assert(count <= 5);
204322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
204422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            outs = OUTS_FROM_FP(fp, count);
204522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if 0
204622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (count == 5) {
204722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                outs[4] = GET_REGISTER(vsrc1 & 0x0f);
204822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                count--;
204922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }
205022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            for (i = 0; i < (int) count; i++) {
205122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                outs[i] = GET_REGISTER(vdst & 0x0f);
205222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                vdst >>= 4;
205322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }
205422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
205522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            // This version executes fewer instructions but is larger
205622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            // overall.  Seems to be a teensy bit faster.
205722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            assert((vdst >> 16) == 0);  // 16 bits -or- high 16 bits clear
205822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            switch (count) {
205922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            case 5:
206022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                outs[4] = GET_REGISTER(vsrc1 & 0x0f);
206122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            case 4:
206222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                outs[3] = GET_REGISTER(vdst >> 12);
206322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            case 3:
206422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                outs[2] = GET_REGISTER((vdst & 0x0f00) >> 8);
206522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            case 2:
206622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                outs[1] = GET_REGISTER((vdst & 0x00f0) >> 4);
206722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            case 1:
206822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                outs[0] = GET_REGISTER(vdst & 0x0f);
206922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            default:
207022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                ;
207122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }
207222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
207322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
207422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
207522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
207622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    /*
207722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * (This was originally a "goto" target; I've kept it separate from the
207822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * stuff above in case we want to refactor things again.)
207922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     *
208022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * At this point, we have the arguments stored in the "outs" area of
208122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * the current method's stack frame, and the method to call in
208222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     * "methodToCall".  Push a new stack frame.
208322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch     */
208422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    {
208522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        StackSaveArea* newSaveArea;
208622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        u4* newFp;
208722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
208822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        ILOGV("> %s%s.%s %s",
208922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "",
209022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            methodToCall->clazz->descriptor, methodToCall->name,
209122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            methodToCall->shorty);
209222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
209322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize;
209422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        newSaveArea = SAVEAREA_FROM_FP(newFp);
209522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
209622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        /* verify that we have enough space */
209722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (true) {
209822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            u1* bottom;
209922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4);
210022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (bottom < self->interpStackEnd) {
210122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                /* stack overflow */
21024abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden                LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')\n",
210322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    self->interpStackStart, self->interpStackEnd, bottom,
21044abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden                    (u1*) fp - bottom, self->interpStackSize,
21054abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden                    methodToCall->name);
21064abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden                dvmHandleStackOverflow(self, methodToCall);
210722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                assert(dvmCheckException(self));
210822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();
210922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }
211022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            //LOGD("+++ fp=%p newFp=%p newSave=%p bottom=%p\n",
211122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            //    fp, newFp, newSaveArea, bottom);
211222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
211322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
211422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#ifdef LOG_INSTR
211522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (methodToCall->registersSize > methodToCall->insSize) {
211622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            /*
211722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * This makes valgrind quiet when we print registers that
211822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * haven't been initialized.  Turn it off when the debug
211922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * messages are disabled -- we want valgrind to report any
212022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * used-before-initialized issues.
212122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             */
212222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            memset(newFp, 0xcc,
212322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                (methodToCall->registersSize - methodToCall->insSize) * 4);
212422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
212522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
212622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
212722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#ifdef EASY_GDB
212822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        newSaveArea->prevSave = SAVEAREA_FROM_FP(fp);
212922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
213022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        newSaveArea->prevFrame = fp;
213122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        newSaveArea->savedPc = pc;
213222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if defined(WITH_JIT)
213322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        newSaveArea->returnAddr = 0;
213422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
213522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        newSaveArea->method = methodToCall;
213622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
213722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        if (!dvmIsNativeMethod(methodToCall)) {
213822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            /*
213922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * "Call" interpreted code.  Reposition the PC, update the
214022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * frame pointer and other local state, and continue.
214122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             */
214222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            curMethod = methodToCall;
214322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            methodClassDex = curMethod->clazz->pDvmDex;
214422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            pc = methodToCall->insns;
214522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            fp = self->curFrame = newFp;
214622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#ifdef EASY_GDB
214722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            debugSaveArea = SAVEAREA_FROM_FP(newFp);
214822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
214922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if INTERP_TYPE == INTERP_DBG
215022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            debugIsMethodEntry = true;              // profiling, debugging
215122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
215222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
215322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                curMethod->name, curMethod->shorty);
215422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            DUMP_REGS(curMethod, fp, true);         // show input args
215522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            FINISH(0);                              // jump to method start
215622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        } else {
215722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            /* set this up for JNI locals, even if not a JNI native */
215822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#ifdef USE_INDIRECT_REF
215922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
216022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#else
216122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.nextEntry;
216222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
216322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
216422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            self->curFrame = newFp;
216522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
216622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            DUMP_REGS(methodToCall, newFp, true);   // show input args
216722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
216822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if (INTERP_TYPE == INTERP_DBG) && defined(WITH_DEBUGGER)
216922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (gDvm.debuggerActive) {
217022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                dvmDbgPostLocationEvent(methodToCall, -1,
217122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    dvmGetThisPtr(curMethod, fp), DBG_METHOD_ENTRY);
217222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }
217322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
217422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if (INTERP_TYPE == INTERP_DBG) && defined(WITH_PROFILER)
217522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            TRACE_METHOD_ENTER(self, methodToCall);
217622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
217722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
217822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
217922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                methodToCall->name, methodToCall->shorty);
218022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
21814abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#if defined(WITH_JIT)
21824abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            /* Allow the Jit to end any pending trace building */
21834abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden            CHECK_JIT();
21844abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden#endif
21854abe4014d3fa6fcdaff6869ca1d60de15a72d124Andy McFadden
218622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            /*
218722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * Jump through native call bridge.  Because we leave no
218822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * space for locals on native calls, "newFp" points directly
218922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * to the method arguments.
219022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             */
219122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            (*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self);
219222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
219322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if (INTERP_TYPE == INTERP_DBG) && defined(WITH_DEBUGGER)
219422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (gDvm.debuggerActive) {
219522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                dvmDbgPostLocationEvent(methodToCall, -1,
219622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                    dvmGetThisPtr(curMethod, fp), DBG_METHOD_EXIT);
219722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }
219822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
219922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#if (INTERP_TYPE == INTERP_DBG) && defined(WITH_PROFILER)
220022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            TRACE_METHOD_EXIT(self, methodToCall);
220122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#endif
220222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
220322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            /* pop frame off */
220422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            dvmPopJniLocals(self, newSaveArea);
220522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            self->curFrame = fp;
220622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
220722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            /*
220822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * If the native code threw an exception, or interpreted code
220922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * invoked by the native call threw one and nobody has cleared
221022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             * it, jump to our local exception handling.
221122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch             */
221222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (dvmCheckException(self)) {
221322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                LOGV("Exception thrown by/below native code\n");
221422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                GOTO_exceptionThrown();
221522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }
221622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
221722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGD("> retval=0x%llx (leaving native)", retval.j);
221822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            ILOGD("> (return from native %s.%s to %s.%s %s)",
221922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                methodToCall->clazz->descriptor, methodToCall->name,
222022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                curMethod->clazz->descriptor, curMethod->name,
222122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                curMethod->shorty);
222222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
222322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            //u2 invokeInstr = INST_INST(FETCH(0));
222422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
222522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                invokeInstr <= OP_INVOKE_INTERFACE*/)
222622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            {
222722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                FINISH(3);
222822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            } else {
222922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                //LOGE("Unknown invoke instr %02x at %d\n",
223022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                //    invokeInstr, (int) (pc - curMethod->insns));
223122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch                assert(false);
223222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch            }
223322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch        }
223422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    }
223522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch    assert(false);      // should not get here
223622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie BirchGOTO_TARGET_END
223722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
223822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* File: cstubs/enddefs.c */
223922d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
224022d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch/* undefine "magic" name remapping */
224122d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#undef retval
224222d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#undef pc
224322d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#undef fp
224422d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#undef curMethod
224522d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#undef methodClassDex
224622d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#undef self
224722d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch#undef debugTrackedRefStart
224822d404a75a00cda0b0ebed1034c2808ba060b05fJohnnie Birch
2249