1a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
2a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
3a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
4a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * --> DO NOT EDIT <--
5a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
6a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
7cd8f5e701547739f241594b43e9470c92d98e9cfCarl Shapiro/* File: c/header.cpp */
8a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
9a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Copyright (C) 2008 The Android Open Source Project
10a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
11a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Licensed under the Apache License, Version 2.0 (the "License");
12a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * you may not use this file except in compliance with the License.
13a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * You may obtain a copy of the License at
14a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
15a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *      http://www.apache.org/licenses/LICENSE-2.0
16a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
17a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Unless required by applicable law or agreed to in writing, software
18a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * distributed under the License is distributed on an "AS IS" BASIS,
19a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * See the License for the specific language governing permissions and
21a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * limitations under the License.
22a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
23a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
24a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/* common includes */
25a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#include "Dalvik.h"
26a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#include "interp/InterpDefs.h"
27a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#include "mterp/Mterp.h"
28a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#include <math.h>                   // needed for fmod, fmodf
29ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include "mterp/common/FindInterface.h"
30a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
31a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
32a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Configuration defines.  These affect the C implementations, i.e. the
33a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * portable interpreter(s) and C stubs.
34a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
35a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Some defines are controlled by the Makefile, e.g.:
36a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *   WITH_INSTR_CHECKS
37a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *   WITH_TRACKREF_CHECKS
38a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *   EASY_GDB
39a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *   NDEBUG
40a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
41a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
42a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia (slow!) */
43a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define CHECK_BRANCH_OFFSETS
44a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define CHECK_REGISTER_INDICES
45a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#endif
46a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
47a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
48529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * Some architectures require 64-bit alignment for access to 64-bit data
49529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * types.  We can't just use pointers to copy 64-bit values out of our
50529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * interpreted register set, because gcc may assume the pointer target is
51529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * aligned and generate invalid code.
52a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
53529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * There are two common approaches:
54529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden *  (1) Use a union that defines a 32-bit pair and a 64-bit value.
55529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden *  (2) Call memcpy().
56529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden *
57529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * Depending upon what compiler you're using and what options are specified,
58529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * one may be faster than the other.  For example, the compiler might
59529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * convert a memcpy() of 8 bytes into a series of instructions and omit
60529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * the call.  The union version could cause some strange side-effects,
61529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * e.g. for a while ARM gcc thought it needed separate storage for each
62529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * inlined instance, and generated instructions to zero out ~700 bytes of
63529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * stack space at the top of the interpreter.
64529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden *
65529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * The default is to use memcpy().  The current gcc for ARM seems to do
66529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * better with the union.
67a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
68a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#if defined(__ARM_EABI__)
69529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden# define NO_UNALIGN_64__UNION
70a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#endif
71a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/*
72a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * MIPS ABI requires 64-bit alignment for access to 64-bit data types.
73a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *
74a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Use memcpy() to do the transfer
75a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */
76a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if defined(__mips__)
77a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* # define NO_UNALIGN_64__UNION */
78a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif
79a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
80529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden
81a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden//#define LOG_INSTR                   /* verbose debugging */
82a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
83a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
84a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
85a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Export another copy of the PC on every instruction; this is largely
86a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * redundant with EXPORT_PC and the debugger code.  This value can be
87a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * compared against what we have stored on the stack with EXPORT_PC to
88a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * help ensure that we aren't missing any export calls.
89a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
90a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#if WITH_EXTRA_GC_CHECKS > 1
91a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
92a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#else
93a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define EXPORT_EXTRA_PC()
94a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#endif
95a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
96a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
97a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Adjust the program counter.  "_offset" is a signed int, in 16-bit units.
98a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
99a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
100a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
101a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * We don't advance the program counter until we finish an instruction or
102a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * branch, because we do want to have to unroll the PC if there's an
103a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * exception.
104a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
105a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#ifdef CHECK_BRANCH_OFFSETS
106a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define ADJUST_PC(_offset) do {                                            \
107a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        int myoff = _offset;        /* deref only once */                   \
108a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (pc + myoff < curMethod->insns ||                                \
109a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            pc + myoff >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) \
110a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        {                                                                   \
111a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            char* desc;                                                     \
112a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            desc = dexProtoCopyMethodDescriptor(&curMethod->prototype);     \
113c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Invalid branch %d at 0x%04x in %s.%s %s",                 \
114a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                myoff, (int) (pc - curMethod->insns),                       \
115a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                curMethod->clazz->descriptor, curMethod->name, desc);       \
116a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            free(desc);                                                     \
117a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            dvmAbort();                                                     \
118a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }                                                                   \
119a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        pc += myoff;                                                        \
120a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        EXPORT_EXTRA_PC();                                                  \
121a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    } while (false)
122a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#else
123a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define ADJUST_PC(_offset) do {                                            \
124a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        pc += _offset;                                                      \
125a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        EXPORT_EXTRA_PC();                                                  \
126a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    } while (false)
127a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#endif
128a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
129a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
130a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * If enabled, log instructions as we execute them.
131a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
132a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#ifdef LOG_INSTR
133a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define ILOGD(...) ILOG(LOG_DEBUG, __VA_ARGS__)
134a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define ILOGV(...) ILOG(LOG_VERBOSE, __VA_ARGS__)
135a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define ILOG(_level, ...) do {                                             \
136a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        char debugStrBuf[128];                                              \
137a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        snprintf(debugStrBuf, sizeof(debugStrBuf), __VA_ARGS__);            \
13860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        if (curMethod != NULL)                                              \
1391663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block            ALOG(_level, LOG_TAG"i", "%-2d|%04x%s",                          \
140a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                self->threadId, (int)(pc - curMethod->insns), debugStrBuf); \
141a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        else                                                                \
1421663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block            ALOG(_level, LOG_TAG"i", "%-2d|####%s",                          \
143a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                self->threadId, debugStrBuf);                               \
144a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    } while(false)
145a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFaddenvoid dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly);
146a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define DUMP_REGS(_meth, _frame, _inOnly) dvmDumpRegs(_meth, _frame, _inOnly)
147a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFaddenstatic const char kSpacing[] = "            ";
148a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#else
149a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define ILOGD(...) ((void)0)
150a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define ILOGV(...) ((void)0)
151a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define DUMP_REGS(_meth, _frame, _inOnly) ((void)0)
152a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#endif
153a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
154a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/* get a long from an array of u4 */
155a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFaddenstatic inline s8 getLongFromArray(const u4* ptr, int idx)
156a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden{
157a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#if defined(NO_UNALIGN_64__UNION)
158a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    union { s8 ll; u4 parts[2]; } conv;
159a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
160a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ptr += idx;
161a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    conv.parts[0] = ptr[0];
162a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    conv.parts[1] = ptr[1];
163a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    return conv.ll;
164529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden#else
165a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    s8 val;
166a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    memcpy(&val, &ptr[idx], 8);
167a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    return val;
168a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#endif
169a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden}
170a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
171a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/* store a long into an array of u4 */
172a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFaddenstatic inline void putLongToArray(u4* ptr, int idx, s8 val)
173a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden{
174a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#if defined(NO_UNALIGN_64__UNION)
175a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    union { s8 ll; u4 parts[2]; } conv;
176a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
177a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ptr += idx;
178a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    conv.ll = val;
179a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ptr[0] = conv.parts[0];
180a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ptr[1] = conv.parts[1];
181a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#else
182529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden    memcpy(&ptr[idx], &val, 8);
183a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#endif
184a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden}
185a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
186a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/* get a double from an array of u4 */
187a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFaddenstatic inline double getDoubleFromArray(const u4* ptr, int idx)
188a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden{
189a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#if defined(NO_UNALIGN_64__UNION)
190a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    union { double d; u4 parts[2]; } conv;
191a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
192a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ptr += idx;
193a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    conv.parts[0] = ptr[0];
194a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    conv.parts[1] = ptr[1];
195a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    return conv.d;
196529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden#else
197a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    double dval;
198a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    memcpy(&dval, &ptr[idx], 8);
199a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    return dval;
200a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#endif
201a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden}
202a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
203a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/* store a double into an array of u4 */
204a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFaddenstatic inline void putDoubleToArray(u4* ptr, int idx, double dval)
205a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden{
206a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#if defined(NO_UNALIGN_64__UNION)
207a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    union { double d; u4 parts[2]; } conv;
208a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
209a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ptr += idx;
210a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    conv.d = dval;
211a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ptr[0] = conv.parts[0];
212a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ptr[1] = conv.parts[1];
213a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#else
214529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden    memcpy(&ptr[idx], &dval, 8);
215a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#endif
216a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden}
217a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
218a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
219a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * If enabled, validate the register number on every access.  Otherwise,
220a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * just do an array access.
221a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
222a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Assumes the existence of "u4* fp".
223a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
224a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * "_idx" may be referenced more than once.
225a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
226a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#ifdef CHECK_REGISTER_INDICES
227a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define GET_REGISTER(_idx) \
228a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ( (_idx) < curMethod->registersSize ? \
229a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        (fp[(_idx)]) : (assert(!"bad reg"),1969) )
230a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define SET_REGISTER(_idx, _val) \
231a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ( (_idx) < curMethod->registersSize ? \
232a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        (fp[(_idx)] = (u4)(_val)) : (assert(!"bad reg"),1969) )
233a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define GET_REGISTER_AS_OBJECT(_idx)       ((Object *)GET_REGISTER(_idx))
234a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define SET_REGISTER_AS_OBJECT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
235a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define GET_REGISTER_INT(_idx) ((s4) GET_REGISTER(_idx))
236a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
237a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define GET_REGISTER_WIDE(_idx) \
238a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ( (_idx) < curMethod->registersSize-1 ? \
239a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        getLongFromArray(fp, (_idx)) : (assert(!"bad reg"),1969) )
240a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define SET_REGISTER_WIDE(_idx, _val) \
241a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ( (_idx) < curMethod->registersSize-1 ? \
2429c6f0a6a36fcce4a55e3764db45c6c7cced077a5Carl Shapiro        (void)putLongToArray(fp, (_idx), (_val)) : assert(!"bad reg") )
243a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define GET_REGISTER_FLOAT(_idx) \
244a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ( (_idx) < curMethod->registersSize ? \
245a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        (*((float*) &fp[(_idx)])) : (assert(!"bad reg"),1969.0f) )
246a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define SET_REGISTER_FLOAT(_idx, _val) \
247a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ( (_idx) < curMethod->registersSize ? \
248a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        (*((float*) &fp[(_idx)]) = (_val)) : (assert(!"bad reg"),1969.0f) )
249a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define GET_REGISTER_DOUBLE(_idx) \
250a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ( (_idx) < curMethod->registersSize-1 ? \
251a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        getDoubleFromArray(fp, (_idx)) : (assert(!"bad reg"),1969.0) )
252a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define SET_REGISTER_DOUBLE(_idx, _val) \
253a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    ( (_idx) < curMethod->registersSize-1 ? \
2549c6f0a6a36fcce4a55e3764db45c6c7cced077a5Carl Shapiro        (void)putDoubleToArray(fp, (_idx), (_val)) : assert(!"bad reg") )
255a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#else
256a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define GET_REGISTER(_idx)                 (fp[(_idx)])
257a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define SET_REGISTER(_idx, _val)           (fp[(_idx)] = (_val))
258a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define GET_REGISTER_AS_OBJECT(_idx)       ((Object*) fp[(_idx)])
259a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define SET_REGISTER_AS_OBJECT(_idx, _val) (fp[(_idx)] = (u4)(_val))
260a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define GET_REGISTER_INT(_idx)             ((s4)GET_REGISTER(_idx))
261a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define SET_REGISTER_INT(_idx, _val)       SET_REGISTER(_idx, (s4)_val)
262a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define GET_REGISTER_WIDE(_idx)            getLongFromArray(fp, (_idx))
263a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define SET_REGISTER_WIDE(_idx, _val)      putLongToArray(fp, (_idx), (_val))
264a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define GET_REGISTER_FLOAT(_idx)           (*((float*) &fp[(_idx)]))
265a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define SET_REGISTER_FLOAT(_idx, _val)     (*((float*) &fp[(_idx)]) = (_val))
266a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define GET_REGISTER_DOUBLE(_idx)          getDoubleFromArray(fp, (_idx))
267a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden# define SET_REGISTER_DOUBLE(_idx, _val)    putDoubleToArray(fp, (_idx), (_val))
268a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#endif
269a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
270a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
271a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Get 16 bits from the specified offset of the program counter.  We always
272a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * want to load 16 bits at a time from the instruction stream -- it's more
273a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * efficient than 8 and won't have the alignment problems that 32 might.
274a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
275a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Assumes existence of "const u2* pc".
276a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
277a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define FETCH(_offset)     (pc[(_offset)])
278a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
279a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
280a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Extract instruction byte from 16-bit fetch (_inst is a u2).
281a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
282a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define INST_INST(_inst)    ((_inst) & 0xff)
283a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
284a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
28596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Replace the opcode (used when handling breakpoints).  _opcode is a u1.
28696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
28796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden#define INST_REPLACE_OP(_inst, _opcode) (((_inst) & 0xff00) | _opcode)
28896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
28996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
290a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2).
291a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
292a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define INST_A(_inst)       (((_inst) >> 8) & 0x0f)
293a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define INST_B(_inst)       ((_inst) >> 12)
294a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
295a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
296a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Get the 8-bit "vAA" 8-bit register index from the instruction word.
297a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * (_inst is u2)
298a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
299a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define INST_AA(_inst)      ((_inst) >> 8)
300a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
301a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
302a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * The current PC must be available to Throwable constructors, e.g.
30398f3eb12bf2a33c49712e093d5cc2aa713a93aa5buzbee * those created by the various exception throw routines, so that the
30498f3eb12bf2a33c49712e093d5cc2aa713a93aa5buzbee * exception stack trace can be generated correctly.  If we don't do this,
30598f3eb12bf2a33c49712e093d5cc2aa713a93aa5buzbee * the offset within the current method won't be shown correctly.  See the
30698f3eb12bf2a33c49712e093d5cc2aa713a93aa5buzbee * notes in Exception.c.
307a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
308a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * This is also used to determine the address for precise GC.
309a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
310a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Assumes existence of "u4* fp" and "const u2* pc".
311a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
312a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define EXPORT_PC()         (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
313a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
314a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
315a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Check to see if "obj" is NULL.  If so, throw an exception.  Assumes the
316a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * pc has already been exported to the stack.
317a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
318a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Perform additional checks on debug builds.
319a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
320a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Use this to check for NULL when the instruction handler calls into
321a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * something that could throw an exception (so we have already called
322a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * EXPORT_PC at the top).
323a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
324a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFaddenstatic inline bool checkForNull(Object* obj)
325a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden{
326a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    if (obj == NULL) {
327d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowNullPointerException(NULL);
328a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        return false;
329a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }
330a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#ifdef WITH_EXTRA_OBJECT_VALIDATION
33134987b48d216786454aca59474cb76015af48bd9Jeff Brown    if (!dvmIsHeapAddress(obj)) {
332c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Invalid object %p", obj);
333a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        dvmAbort();
334a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }
335a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#endif
336a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#ifndef NDEBUG
337a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
338a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        /* probable heap corruption */
339c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Invalid object class %p (in %p)", obj->clazz, obj);
340a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        dvmAbort();
341a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }
342a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#endif
343a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    return true;
344a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden}
345a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
346a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
347a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Check to see if "obj" is NULL.  If so, export the PC into the stack
348a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * frame and throw an exception.
349a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
350a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Perform additional checks on debug builds.
351a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
352a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Use this to check for NULL when the instruction handler doesn't do
353a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * anything else that can throw an exception.
354a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
355a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFaddenstatic inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc)
356a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden{
357a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    if (obj == NULL) {
358a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        EXPORT_PC();
359d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowNullPointerException(NULL);
360a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        return false;
361a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }
362a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#ifdef WITH_EXTRA_OBJECT_VALIDATION
3638bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes    if (!dvmIsHeapAddress(obj)) {
364c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Invalid object %p", obj);
365a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        dvmAbort();
366a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }
367a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#endif
368a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#ifndef NDEBUG
369a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
370a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        /* probable heap corruption */
371c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Invalid object class %p (in %p)", obj->clazz, obj);
372a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        dvmAbort();
373a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }
374a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#endif
375a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    return true;
376a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden}
377a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
378cd8f5e701547739f241594b43e9470c92d98e9cfCarl Shapiro/* File: cstubs/stubdefs.cpp */
379a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
380a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * In the C mterp stubs, "goto" is a function call followed immediately
381a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * by a return.
382a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
383a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
384a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define GOTO_TARGET_DECL(_target, ...)                                      \
385cd8f5e701547739f241594b43e9470c92d98e9cfCarl Shapiro    extern "C" void dvmMterp_##_target(Thread* self, ## __VA_ARGS__);
386a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
3877520ee7ff226e12e06818561b15741d2575072e3buzbee/* (void)xxx to quiet unused variable compiler warnings. */
388a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define GOTO_TARGET(_target, ...)                                           \
3899f601a917c8878204482c37aec7005054b6776fabuzbee    void dvmMterp_##_target(Thread* self, ## __VA_ARGS__) {                 \
390a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        u2 ref, vsrc1, vsrc2, vdst;                                         \
391a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        u2 inst = FETCH(0);                                                 \
392a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        const Method* methodToCall;                                         \
3937520ee7ff226e12e06818561b15741d2575072e3buzbee        StackSaveArea* debugSaveArea;                                       \
3947520ee7ff226e12e06818561b15741d2575072e3buzbee        (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst;        \
3957520ee7ff226e12e06818561b15741d2575072e3buzbee        (void)methodToCall; (void)debugSaveArea;
396a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
397a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define GOTO_TARGET_END }
398a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
399a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
4009f601a917c8878204482c37aec7005054b6776fabuzbee * Redefine what used to be local variable accesses into Thread struct
401bbf31b58c50fb892423b7fef0d8c1093bd0c1a6cBrian Carlstrom * references.  (These are undefined down in "footer.cpp".)
402a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
403cf4a20cf0cbc53f03a5b16c7152bbb29907f7108buzbee#define retval                  self->interpSave.retval
4049f601a917c8878204482c37aec7005054b6776fabuzbee#define pc                      self->interpSave.pc
40530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee#define fp                      self->interpSave.curFrame
4069f601a917c8878204482c37aec7005054b6776fabuzbee#define curMethod               self->interpSave.method
4079f601a917c8878204482c37aec7005054b6776fabuzbee#define methodClassDex          self->interpSave.methodClassDex
4089f601a917c8878204482c37aec7005054b6776fabuzbee#define debugTrackedRefStart    self->interpSave.debugTrackedRefStart
409a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
410a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/* ugh */
411a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define STUB_HACK(x) x
4129a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT)
4139a3147c7412f4794434b4c2604aa2ba784867774buzbee#define JIT_STUB_HACK(x) x
4149a3147c7412f4794434b4c2604aa2ba784867774buzbee#else
4159a3147c7412f4794434b4c2604aa2ba784867774buzbee#define JIT_STUB_HACK(x)
4169a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
417a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
41899e3e6e72e3471eb85fc2e405866392b01c080febuzbee/*
41999e3e6e72e3471eb85fc2e405866392b01c080febuzbee * InterpSave's pc and fp must be valid when breaking out to a
42099e3e6e72e3471eb85fc2e405866392b01c080febuzbee * "Reportxxx" routine.  Because the portable interpreter uses local
42199e3e6e72e3471eb85fc2e405866392b01c080febuzbee * variables for these, we must flush prior.  Stubs, however, use
42299e3e6e72e3471eb85fc2e405866392b01c080febuzbee * the interpSave vars directly, so this is a nop for stubs.
42399e3e6e72e3471eb85fc2e405866392b01c080febuzbee */
42499e3e6e72e3471eb85fc2e405866392b01c080febuzbee#define PC_FP_TO_SELF()
42530bc0d46ae730d78c42c39cfa56a59ba3025380bbuzbee#define PC_TO_SELF()
426a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
427a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
428a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Opcode handler framing macros.  Here, each opcode is a separate function
4299f601a917c8878204482c37aec7005054b6776fabuzbee * that takes a "self" argument and returns void.  We can't declare
430a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * these "static" because they may be called from an assembly stub.
4317520ee7ff226e12e06818561b15741d2575072e3buzbee * (void)xxx to quiet unused variable compiler warnings.
432a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
433a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OPCODE(_op)                                                  \
434cd8f5e701547739f241594b43e9470c92d98e9cfCarl Shapiro    extern "C" void dvmMterp_##_op(Thread* self);                           \
4359f601a917c8878204482c37aec7005054b6776fabuzbee    void dvmMterp_##_op(Thread* self) {                                     \
4366aed656b06aa274948bf5c5f8f65873814554c13Andy McFadden        u4 ref;                                                             \
4376aed656b06aa274948bf5c5f8f65873814554c13Andy McFadden        u2 vsrc1, vsrc2, vdst;                                              \
4387520ee7ff226e12e06818561b15741d2575072e3buzbee        u2 inst = FETCH(0);                                                 \
4397520ee7ff226e12e06818561b15741d2575072e3buzbee        (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst;
440a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
441a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define OP_END }
442a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
443a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
444a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Like the "portable" FINISH, but don't reload "inst", and return to caller
4459a3147c7412f4794434b4c2604aa2ba784867774buzbee * when done.  Further, debugger/profiler checks are handled
4469a3147c7412f4794434b4c2604aa2ba784867774buzbee * before handler execution in mterp, so we don't do them here either.
447a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
4489a3147c7412f4794434b4c2604aa2ba784867774buzbee#if defined(WITH_JIT)
449a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define FINISH(_offset) {                                                   \
450a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ADJUST_PC(_offset);                                                 \
4519a3147c7412f4794434b4c2604aa2ba784867774buzbee        if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) {        \
4529a3147c7412f4794434b4c2604aa2ba784867774buzbee            dvmCheckJit(pc, self);                                          \
4539a3147c7412f4794434b4c2604aa2ba784867774buzbee        }                                                                   \
454a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        return;                                                             \
455a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }
4569a3147c7412f4794434b4c2604aa2ba784867774buzbee#else
4579a3147c7412f4794434b4c2604aa2ba784867774buzbee#define FINISH(_offset) {                                                   \
4589a3147c7412f4794434b4c2604aa2ba784867774buzbee        ADJUST_PC(_offset);                                                 \
4599a3147c7412f4794434b4c2604aa2ba784867774buzbee        return;                                                             \
4609a3147c7412f4794434b4c2604aa2ba784867774buzbee    }
4619a3147c7412f4794434b4c2604aa2ba784867774buzbee#endif
462a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
46375425b731c514bf90c985275d80aa7886727d83fChris Dearman#define FINISH_BKPT(_opcode)       /* FIXME? */
46475425b731c514bf90c985275d80aa7886727d83fChris Dearman#define DISPATCH_EXTENDED(_opcode) /* FIXME? */
465a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
466a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
467a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * The "goto label" statements turn into function calls followed by
468a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * return statements.  Some of the functions take arguments, which in the
469a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * portable interpreter are handled by assigning values to globals.
470a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
471a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
472a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define GOTO_exceptionThrown()                                              \
473a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    do {                                                                    \
4749f601a917c8878204482c37aec7005054b6776fabuzbee        dvmMterp_exceptionThrown(self);                                     \
475a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        return;                                                             \
476a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    } while(false)
477a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
478a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define GOTO_returnFromMethod()                                             \
479a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    do {                                                                    \
4809f601a917c8878204482c37aec7005054b6776fabuzbee        dvmMterp_returnFromMethod(self);                                    \
481a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        return;                                                             \
482a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    } while(false)
483a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
484ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes#define GOTO_invoke(_target, _methodCallRange)                              \
485a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    do {                                                                    \
486ab35b50311951feea3782151dd5422ee944685c2Elliott Hughes        dvmMterp_##_target(self, _methodCallRange);                         \
487a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        return;                                                             \
488a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    } while(false)
489a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
490a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst)   \
491a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    do {                                                                    \
4929f601a917c8878204482c37aec7005054b6776fabuzbee        dvmMterp_invokeMethod(self, _methodCallRange, _methodToCall,        \
493a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            _vsrc1, _vdst);                                                 \
494a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        return;                                                             \
495a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    } while(false)
496a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
497a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
4989a3147c7412f4794434b4c2604aa2ba784867774buzbee * As a special case, "goto bail" turns into a longjmp.
499a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
500a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define GOTO_bail()                                                         \
50175425b731c514bf90c985275d80aa7886727d83fChris Dearman    dvmMterpStdBail(self)
502a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
503a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
504a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Periodically check for thread suspension.
505a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
506a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * While we're at it, see if a debugger has attached or the profiler has
5079a3147c7412f4794434b4c2604aa2ba784867774buzbee * started.
508a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
5099a3147c7412f4794434b4c2604aa2ba784867774buzbee#define PERIODIC_CHECKS(_pcadj) {                              \
510a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (dvmCheckSuspendQuick(self)) {                                   \
511a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            EXPORT_PC();  /* need for precise GC */                         \
512a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            dvmCheckSuspendPending(self);                                   \
513a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }                                                                   \
514a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }
515a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
516cd8f5e701547739f241594b43e9470c92d98e9cfCarl Shapiro/* File: c/opcommon.cpp */
517a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/* forward declarations of goto targets */
518ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET_DECL(filledNewArray, bool methodCallRange);
519ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET_DECL(invokeVirtual, bool methodCallRange);
520ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET_DECL(invokeSuper, bool methodCallRange);
521ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET_DECL(invokeInterface, bool methodCallRange);
522ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET_DECL(invokeDirect, bool methodCallRange);
523ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET_DECL(invokeStatic, bool methodCallRange);
524ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET_DECL(invokeVirtualQuick, bool methodCallRange);
525ab35b50311951feea3782151dd5422ee944685c2Elliott HughesGOTO_TARGET_DECL(invokeSuperQuick, bool methodCallRange);
526a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFaddenGOTO_TARGET_DECL(invokeMethod, bool methodCallRange, const Method* methodToCall,
527a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    u2 count, u2 regs);
528a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFaddenGOTO_TARGET_DECL(returnFromMethod);
529a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFaddenGOTO_TARGET_DECL(exceptionThrown);
530a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
531a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
532a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * ===========================================================================
533a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
534a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * What follows are opcode definitions shared between multiple opcodes with
535a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * minor substitutions handled by the C pre-processor.  These should probably
536a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * use the mterp substitution mechanism instead, with the code here moved
537a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * into common fragment files (like the asm "binop.S"), although it's hard
538a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * to give up the C preprocessor in favor of the much simpler text subst.
539a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
540a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * ===========================================================================
541a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
542a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
543a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_NUMCONV(_opcode, _opname, _fromtype, _totype)                \
544a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
545a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_A(inst);                                                \
546a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_B(inst);                                               \
547a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \
548a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER##_totype(vdst,                                         \
549a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            GET_REGISTER##_fromtype(vsrc1));                                \
550a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        FINISH(1);
551a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
552a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_FLOAT_TO_INT(_opcode, _opname, _fromvtype, _fromrtype,       \
553a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        _tovtype, _tortype)                                                 \
554a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
555a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
556a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        /* spec defines specific handling for +/- inf and NaN values */     \
557a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        _fromvtype val;                                                     \
558a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        _tovtype intMin, intMax, result;                                    \
559a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_A(inst);                                                \
560a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_B(inst);                                               \
561a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \
562a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        val = GET_REGISTER##_fromrtype(vsrc1);                              \
563a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        intMin = (_tovtype) 1 << (sizeof(_tovtype) * 8 -1);                 \
564a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        intMax = ~intMin;                                                   \
565a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        result = (_tovtype) val;                                            \
566a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (val >= intMax)          /* +inf */                              \
567a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            result = intMax;                                                \
568a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        else if (val <= intMin)     /* -inf */                              \
569a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            result = intMin;                                                \
570a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        else if (val != val)        /* NaN */                               \
571a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            result = 0;                                                     \
572a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        else                                                                \
573a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            result = (_tovtype) val;                                        \
574a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER##_tortype(vdst, result);                               \
575a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
576a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(1);
577a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
578a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_INT_TO_SMALL(_opcode, _opname, _type)                        \
579a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
580a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_A(inst);                                                \
581a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_B(inst);                                               \
582a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|int-to-%s v%d,v%d", (_opname), vdst, vsrc1);                \
583a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER(vdst, (_type) GET_REGISTER(vsrc1));                    \
584a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        FINISH(1);
585a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
586a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/* NOTE: the comparison result is always a signed 4-byte integer */
587a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_CMPX(_opcode, _opname, _varType, _type, _nanVal)          \
588a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
589a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
590a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        int result;                                                         \
591a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        u2 regs;                                                            \
592a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        _varType val1, val2;                                                \
593a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_AA(inst);                                               \
594a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        regs = FETCH(1);                                                    \
595a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = regs & 0xff;                                                \
596a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc2 = regs >> 8;                                                  \
597a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|cmp%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);         \
598a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        val1 = GET_REGISTER##_type(vsrc1);                                  \
599a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        val2 = GET_REGISTER##_type(vsrc2);                                  \
600a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (val1 == val2)                                                   \
601a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            result = 0;                                                     \
602a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        else if (val1 < val2)                                               \
603a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            result = -1;                                                    \
604a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        else if (val1 > val2)                                               \
605a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            result = 1;                                                     \
606a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        else                                                                \
607a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            result = (_nanVal);                                             \
60860fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        ILOGV("+ result=%d", result);                                       \
609a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER(vdst, result);                                         \
610a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
611a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
612a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
613a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_IF_XX(_opcode, _opname, _cmp)                             \
614a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB, +CCCC*/)                                \
615a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_A(inst);                                               \
616a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc2 = INST_B(inst);                                               \
617a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if ((s4) GET_REGISTER(vsrc1) _cmp (s4) GET_REGISTER(vsrc2)) {       \
618a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            int branchOffset = (s2)FETCH(1);    /* sign-extended */         \
619a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            ILOGV("|if-%s v%d,v%d,+0x%04x", (_opname), vsrc1, vsrc2,        \
620a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                branchOffset);                                              \
621a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            ILOGV("> branch taken");                                        \
622a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if (branchOffset < 0)                                           \
6239a3147c7412f4794434b4c2604aa2ba784867774buzbee                PERIODIC_CHECKS(branchOffset);                              \
624a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            FINISH(branchOffset);                                           \
625a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        } else {                                                            \
626a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            ILOGV("|if-%s v%d,v%d,-", (_opname), vsrc1, vsrc2);             \
627a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            FINISH(2);                                                      \
628a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }
629a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
630a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_IF_XXZ(_opcode, _opname, _cmp)                            \
631a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vAA, +BBBB*/)                                   \
632a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_AA(inst);                                              \
633a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if ((s4) GET_REGISTER(vsrc1) _cmp 0) {                              \
634a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            int branchOffset = (s2)FETCH(1);    /* sign-extended */         \
635a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            ILOGV("|if-%s v%d,+0x%04x", (_opname), vsrc1, branchOffset);    \
636a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            ILOGV("> branch taken");                                        \
637a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if (branchOffset < 0)                                           \
6389a3147c7412f4794434b4c2604aa2ba784867774buzbee                PERIODIC_CHECKS(branchOffset);                              \
639a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            FINISH(branchOffset);                                           \
640a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        } else {                                                            \
641a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            ILOGV("|if-%s v%d,-", (_opname), vsrc1);                        \
642a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            FINISH(2);                                                      \
643a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }
644a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
645a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_UNOP(_opcode, _opname, _pfx, _sfx, _type)                    \
646a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
647a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_A(inst);                                                \
648a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_B(inst);                                               \
649a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \
650a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER##_type(vdst, _pfx GET_REGISTER##_type(vsrc1) _sfx);    \
651a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        FINISH(1);
652a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
653a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_X_INT(_opcode, _opname, _op, _chkdiv)                     \
654a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
655a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
656a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        u2 srcRegs;                                                         \
657a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_AA(inst);                                               \
658a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        srcRegs = FETCH(1);                                                 \
659a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = srcRegs & 0xff;                                             \
660a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc2 = srcRegs >> 8;                                               \
661a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1);                   \
662a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (_chkdiv != 0) {                                                 \
663a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            s4 firstVal, secondVal, result;                                 \
664a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            firstVal = GET_REGISTER(vsrc1);                                 \
665a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            secondVal = GET_REGISTER(vsrc2);                                \
666a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if (secondVal == 0) {                                           \
667a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                EXPORT_PC();                                                \
668d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein                dvmThrowArithmeticException("divide by zero");              \
669a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                GOTO_exceptionThrown();                                     \
670a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            }                                                               \
671a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if ((u4)firstVal == 0x80000000 && secondVal == -1) {            \
672a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                if (_chkdiv == 1)                                           \
673a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                    result = firstVal;  /* division */                      \
674a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                else                                                        \
675a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                    result = 0;         /* remainder */                     \
676a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            } else {                                                        \
677a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                result = firstVal _op secondVal;                            \
678a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            }                                                               \
679a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            SET_REGISTER(vdst, result);                                     \
680a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        } else {                                                            \
681a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            /* non-div/rem case */                                          \
682a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            SET_REGISTER(vdst,                                              \
683a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2));     \
684a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }                                                                   \
685a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
686a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
687a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
688a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op)                     \
689a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
690a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
691a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        u2 srcRegs;                                                         \
692a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_AA(inst);                                               \
693a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        srcRegs = FETCH(1);                                                 \
694a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = srcRegs & 0xff;                                             \
695a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc2 = srcRegs >> 8;                                               \
696a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1);                   \
697a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER(vdst,                                                  \
698a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f));    \
699a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
700a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
701a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
702a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv)               \
703a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/)                               \
704a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_A(inst);                                                \
705a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_B(inst);                                               \
706a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc2 = FETCH(1);                                                   \
707a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x",                             \
708a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            (_opname), vdst, vsrc1, vsrc2);                                 \
709a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (_chkdiv != 0) {                                                 \
710a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            s4 firstVal, result;                                            \
711a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            firstVal = GET_REGISTER(vsrc1);                                 \
712a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if ((s2) vsrc2 == 0) {                                          \
713a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                EXPORT_PC();                                                \
714d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein                dvmThrowArithmeticException("divide by zero");              \
715d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein                GOTO_exceptionThrown();                                     \
716a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            }                                                               \
717a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) {         \
718a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                /* won't generate /lit16 instr for this; check anyway */    \
719a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                if (_chkdiv == 1)                                           \
720a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                    result = firstVal;  /* division */                      \
721a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                else                                                        \
722a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                    result = 0;         /* remainder */                     \
723a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            } else {                                                        \
724a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                result = firstVal _op (s2) vsrc2;                           \
725a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            }                                                               \
726a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            SET_REGISTER(vdst, result);                                     \
727a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        } else {                                                            \
728a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            /* non-div/rem case */                                          \
729a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2);         \
730a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }                                                                   \
731a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        FINISH(2);
732a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
733a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv)                \
734a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/)                               \
735a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
736a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        u2 litInfo;                                                         \
737a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_AA(inst);                                               \
738a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        litInfo = FETCH(1);                                                 \
739a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = litInfo & 0xff;                                             \
740a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc2 = litInfo >> 8;       /* constant */                          \
741a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x",                              \
742a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            (_opname), vdst, vsrc1, vsrc2);                                 \
743a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (_chkdiv != 0) {                                                 \
744a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            s4 firstVal, result;                                            \
745a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            firstVal = GET_REGISTER(vsrc1);                                 \
746a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if ((s1) vsrc2 == 0) {                                          \
747a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                EXPORT_PC();                                                \
748d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein                dvmThrowArithmeticException("divide by zero");              \
749a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                GOTO_exceptionThrown();                                     \
750a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            }                                                               \
751a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) {         \
752a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                if (_chkdiv == 1)                                           \
753a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                    result = firstVal;  /* division */                      \
754a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                else                                                        \
755a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                    result = 0;         /* remainder */                     \
756a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            } else {                                                        \
757a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                result = firstVal _op ((s1) vsrc2);                         \
758a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            }                                                               \
759a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            SET_REGISTER(vdst, result);                                     \
760a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        } else {                                                            \
761a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            SET_REGISTER(vdst,                                              \
762a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2);                   \
763a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }                                                                   \
764a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
765a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
766a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
767a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op)                \
768a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/)                               \
769a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
770a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        u2 litInfo;                                                         \
771a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_AA(inst);                                               \
772a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        litInfo = FETCH(1);                                                 \
773a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = litInfo & 0xff;                                             \
774a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc2 = litInfo >> 8;       /* constant */                          \
775a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x",                              \
776a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            (_opname), vdst, vsrc1, vsrc2);                                 \
777a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER(vdst,                                                  \
778a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f));                  \
779a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
780a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
781a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
782a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv)               \
783a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
784a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_A(inst);                                                \
785a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_B(inst);                                               \
786a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1);             \
787a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (_chkdiv != 0) {                                                 \
788a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            s4 firstVal, secondVal, result;                                 \
789a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            firstVal = GET_REGISTER(vdst);                                  \
790a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            secondVal = GET_REGISTER(vsrc1);                                \
791a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if (secondVal == 0) {                                           \
792a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                EXPORT_PC();                                                \
793d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein                dvmThrowArithmeticException("divide by zero");              \
794a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                GOTO_exceptionThrown();                                     \
795a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            }                                                               \
796a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if ((u4)firstVal == 0x80000000 && secondVal == -1) {            \
797a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                if (_chkdiv == 1)                                           \
798a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                    result = firstVal;  /* division */                      \
799a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                else                                                        \
800a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                    result = 0;         /* remainder */                     \
801a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            } else {                                                        \
802a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                result = firstVal _op secondVal;                            \
803a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            }                                                               \
804a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            SET_REGISTER(vdst, result);                                     \
805a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        } else {                                                            \
806a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            SET_REGISTER(vdst,                                              \
807a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1));      \
808a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }                                                                   \
809a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        FINISH(1);
810a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
811a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op)               \
812a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
813a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_A(inst);                                                \
814a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_B(inst);                                               \
815a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1);             \
816a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER(vdst,                                                  \
817a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f));     \
818a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        FINISH(1);
819a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
820a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv)                    \
821a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
822a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
823a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        u2 srcRegs;                                                         \
824a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_AA(inst);                                               \
825a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        srcRegs = FETCH(1);                                                 \
826a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = srcRegs & 0xff;                                             \
827a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc2 = srcRegs >> 8;                                               \
828a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);       \
829a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (_chkdiv != 0) {                                                 \
830a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            s8 firstVal, secondVal, result;                                 \
831a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            firstVal = GET_REGISTER_WIDE(vsrc1);                            \
832a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            secondVal = GET_REGISTER_WIDE(vsrc2);                           \
833a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if (secondVal == 0LL) {                                         \
834a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                EXPORT_PC();                                                \
835d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein                dvmThrowArithmeticException("divide by zero");              \
836a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                GOTO_exceptionThrown();                                     \
837a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            }                                                               \
838a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if ((u8)firstVal == 0x8000000000000000ULL &&                    \
839a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                secondVal == -1LL)                                          \
840a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            {                                                               \
841a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                if (_chkdiv == 1)                                           \
842a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                    result = firstVal;  /* division */                      \
843a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                else                                                        \
844a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                    result = 0;         /* remainder */                     \
845a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            } else {                                                        \
846a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                result = firstVal _op secondVal;                            \
847a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            }                                                               \
848a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            SET_REGISTER_WIDE(vdst, result);                                \
849a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        } else {                                                            \
850a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            SET_REGISTER_WIDE(vdst,                                         \
851a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \
852a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }                                                                   \
853a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
854a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
855a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
856a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op)                    \
857a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
858a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
859a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        u2 srcRegs;                                                         \
860a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_AA(inst);                                               \
861a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        srcRegs = FETCH(1);                                                 \
862a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = srcRegs & 0xff;                                             \
863a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc2 = srcRegs >> 8;                                               \
864a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);       \
865a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER_WIDE(vdst,                                             \
866a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \
867a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
868a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
869a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
870a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv)              \
871a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
872a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_A(inst);                                                \
873a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_B(inst);                                               \
874a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1);            \
875a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (_chkdiv != 0) {                                                 \
876a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            s8 firstVal, secondVal, result;                                 \
877a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            firstVal = GET_REGISTER_WIDE(vdst);                             \
878a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            secondVal = GET_REGISTER_WIDE(vsrc1);                           \
879a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if (secondVal == 0LL) {                                         \
880a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                EXPORT_PC();                                                \
881d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein                dvmThrowArithmeticException("divide by zero");              \
882a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                GOTO_exceptionThrown();                                     \
883a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            }                                                               \
884a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if ((u8)firstVal == 0x8000000000000000ULL &&                    \
885a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                secondVal == -1LL)                                          \
886a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            {                                                               \
887a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                if (_chkdiv == 1)                                           \
888a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                    result = firstVal;  /* division */                      \
889a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                else                                                        \
890a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                    result = 0;         /* remainder */                     \
891a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            } else {                                                        \
892a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                result = firstVal _op secondVal;                            \
893a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            }                                                               \
894a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            SET_REGISTER_WIDE(vdst, result);                                \
895a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        } else {                                                            \
896a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            SET_REGISTER_WIDE(vdst,                                         \
897a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\
898a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }                                                                   \
899a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        FINISH(1);
900a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
901a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op)              \
902a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
903a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_A(inst);                                                \
904a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_B(inst);                                               \
905a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1);            \
906a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER_WIDE(vdst,                                             \
907a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \
908a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        FINISH(1);
909a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
910a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_X_FLOAT(_opcode, _opname, _op)                            \
911a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
912a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
913a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        u2 srcRegs;                                                         \
914a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_AA(inst);                                               \
915a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        srcRegs = FETCH(1);                                                 \
916a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = srcRegs & 0xff;                                             \
917a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc2 = srcRegs >> 8;                                               \
918a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);      \
919a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER_FLOAT(vdst,                                            \
920a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2));       \
921a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
922a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
923a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
924a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op)                           \
925a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
926a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
927a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        u2 srcRegs;                                                         \
928a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_AA(inst);                                               \
929a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        srcRegs = FETCH(1);                                                 \
930a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = srcRegs & 0xff;                                             \
931a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc2 = srcRegs >> 8;                                               \
932a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);     \
933a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER_DOUBLE(vdst,                                           \
934a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2));     \
935a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
936a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
937a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
938a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op)                      \
939a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
940a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_A(inst);                                                \
941a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_B(inst);                                               \
942a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1);           \
943a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER_FLOAT(vdst,                                            \
944a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1));        \
945a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        FINISH(1);
946a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
947a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op)                     \
948a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
949a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_A(inst);                                                \
950a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_B(inst);                                               \
951a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1);          \
952a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER_DOUBLE(vdst,                                           \
953a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1));      \
954a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        FINISH(1);
955a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
956a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize)                   \
957a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
958a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
959a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ArrayObject* arrayObj;                                              \
960a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        u2 arrayInfo;                                                       \
961a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        EXPORT_PC();                                                        \
962a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_AA(inst);                                               \
963a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        arrayInfo = FETCH(1);                                               \
964a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = arrayInfo & 0xff;    /* array ptr */                        \
965a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc2 = arrayInfo >> 8;      /* index */                            \
966a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);        \
967a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);                      \
968a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (!checkForNull((Object*) arrayObj))                              \
969a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            GOTO_exceptionThrown();                                         \
970a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (GET_REGISTER(vsrc2) >= arrayObj->length) {                      \
97174501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein            dvmThrowArrayIndexOutOfBoundsException(                         \
97247f58250c5177adba475b0b11a36151ac0ce9ab9Dan Bornstein                arrayObj->length, GET_REGISTER(vsrc2));                     \
973a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            GOTO_exceptionThrown();                                         \
974a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }                                                                   \
975a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER##_regsize(vdst,                                        \
976cd8f5e701547739f241594b43e9470c92d98e9cfCarl Shapiro            ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]);      \
977291c84f60853d30e1c0d79dd08c5e5164f588e26Dan Bornstein        ILOGV("+ AGET[%d]=%#x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));   \
978a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
979a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
980a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
981a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize)                   \
982a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
983a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
984a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ArrayObject* arrayObj;                                              \
985a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        u2 arrayInfo;                                                       \
986a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        EXPORT_PC();                                                        \
987a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_AA(inst);       /* AA: source value */                  \
988a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        arrayInfo = FETCH(1);                                               \
989a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = arrayInfo & 0xff;   /* BB: array ptr */                     \
990a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc2 = arrayInfo >> 8;     /* CC: index */                         \
991a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);        \
992a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);                      \
993a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (!checkForNull((Object*) arrayObj))                              \
994a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            GOTO_exceptionThrown();                                         \
995a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (GET_REGISTER(vsrc2) >= arrayObj->length) {                      \
99674501e600dcb5634aa26aee0a3f57f2b45b213f2Dan Bornstein            dvmThrowArrayIndexOutOfBoundsException(                         \
99747f58250c5177adba475b0b11a36151ac0ce9ab9Dan Bornstein                arrayObj->length, GET_REGISTER(vsrc2));                     \
998a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            GOTO_exceptionThrown();                                         \
999a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }                                                                   \
1000a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
1001cd8f5e701547739f241594b43e9470c92d98e9cfCarl Shapiro        ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] =          \
1002a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            GET_REGISTER##_regsize(vdst);                                   \
1003a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
1004a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
1005a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1006a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
1007a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * It's possible to get a bad value out of a field with sub-32-bit stores
1008a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * because the -quick versions always operate on 32 bits.  Consider:
1009a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *   short foo = -1  (sets a 32-bit register to 0xffffffff)
1010a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *   iput-quick foo  (writes all 32 bits to the field)
1011a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *   short bar = 1   (sets a 32-bit register to 0x00000001)
1012a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *   iput-short      (writes the low 16 bits to the field)
1013a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *   iget-quick foo  (reads all 32 bits from the field, yielding 0xffff0001)
1014a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * This can only happen when optimized and non-optimized code has interleaved
1015a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * access to the same field.  This is unlikely but possible.
1016a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
1017a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * The easiest way to fix this is to always read/write 32 bits at a time.  On
1018a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * a device with a 16-bit data bus this is sub-optimal.  (The alternative
1019a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * approach is to have sub-int versions of iget-quick, but now we're wasting
1020a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Dalvik instruction space and making it less likely that handler code will
1021a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * already be in the CPU i-cache.)
1022a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
1023a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize)                   \
1024a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
1025a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
1026a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        InstField* ifield;                                                  \
1027a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        Object* obj;                                                        \
1028a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        EXPORT_PC();                                                        \
1029a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_A(inst);                                                \
1030a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_B(inst);   /* object ptr */                            \
1031a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ref = FETCH(1);         /* field ref */                             \
1032a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
1033a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        obj = (Object*) GET_REGISTER(vsrc1);                                \
1034a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (!checkForNull(obj))                                             \
1035a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            GOTO_exceptionThrown();                                         \
1036a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref);  \
1037a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (ifield == NULL) {                                               \
1038a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            ifield = dvmResolveInstField(curMethod->clazz, ref);            \
1039a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if (ifield == NULL)                                             \
1040a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                GOTO_exceptionThrown();                                     \
1041a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }                                                                   \
1042a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER##_regsize(vdst,                                        \
1043a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            dvmGetField##_ftype(obj, ifield->byteOffset));                  \
104446f3fd49ebda372887192fa32b16040ed6710f58Chris Dearman        ILOGV("+ IGET '%s'=0x%08llx", ifield->name,                         \
1045a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            (u8) GET_REGISTER##_regsize(vdst));                             \
1046a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
1047a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
1048a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1049a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize)             \
1050a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
1051a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
1052a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        Object* obj;                                                        \
1053a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_A(inst);                                                \
1054a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_B(inst);   /* object ptr */                            \
1055a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ref = FETCH(1);         /* field offset */                          \
1056a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|iget%s-quick v%d,v%d,field@+%u",                            \
1057a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            (_opname), vdst, vsrc1, ref);                                   \
1058a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        obj = (Object*) GET_REGISTER(vsrc1);                                \
1059a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (!checkForNullExportPC(obj, fp, pc))                             \
1060a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            GOTO_exceptionThrown();                                         \
1061a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref));        \
1062a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("+ IGETQ %d=0x%08llx", ref,                                   \
1063a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            (u8) GET_REGISTER##_regsize(vdst));                             \
1064a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
1065a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
1066a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1067a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize)                   \
1068a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
1069a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
1070a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        InstField* ifield;                                                  \
1071a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        Object* obj;                                                        \
1072a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        EXPORT_PC();                                                        \
1073a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_A(inst);                                                \
1074a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_B(inst);   /* object ptr */                            \
1075a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ref = FETCH(1);         /* field ref */                             \
1076a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
1077a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        obj = (Object*) GET_REGISTER(vsrc1);                                \
1078a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (!checkForNull(obj))                                             \
1079a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            GOTO_exceptionThrown();                                         \
1080a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref);  \
1081a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (ifield == NULL) {                                               \
1082a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            ifield = dvmResolveInstField(curMethod->clazz, ref);            \
1083a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if (ifield == NULL)                                             \
1084a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                GOTO_exceptionThrown();                                     \
1085a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }                                                                   \
1086a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        dvmSetField##_ftype(obj, ifield->byteOffset,                        \
1087a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            GET_REGISTER##_regsize(vdst));                                  \
108846f3fd49ebda372887192fa32b16040ed6710f58Chris Dearman        ILOGV("+ IPUT '%s'=0x%08llx", ifield->name,                         \
1089a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            (u8) GET_REGISTER##_regsize(vdst));                             \
1090a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
1091a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
1092a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1093a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize)             \
1094a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
1095a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
1096a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        Object* obj;                                                        \
1097a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_A(inst);                                                \
1098a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vsrc1 = INST_B(inst);   /* object ptr */                            \
1099a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ref = FETCH(1);         /* field offset */                          \
1100a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|iput%s-quick v%d,v%d,field@0x%04x",                         \
1101a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            (_opname), vdst, vsrc1, ref);                                   \
1102a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        obj = (Object*) GET_REGISTER(vsrc1);                                \
1103a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (!checkForNullExportPC(obj, fp, pc))                             \
1104a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            GOTO_exceptionThrown();                                         \
1105a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst));        \
1106a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("+ IPUTQ %d=0x%08llx", ref,                                   \
1107a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            (u8) GET_REGISTER##_regsize(vdst));                             \
1108a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
1109a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
1110a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1111dd6e87095071e4e987910732062545f7303023e5Ben Cheng/*
1112dd6e87095071e4e987910732062545f7303023e5Ben Cheng * The JIT needs dvmDexGetResolvedField() to return non-null.
11139a3147c7412f4794434b4c2604aa2ba784867774buzbee * Because the portable interpreter is not involved with the JIT
11149a3147c7412f4794434b4c2604aa2ba784867774buzbee * and trace building, we only need the extra check here when this
11159a3147c7412f4794434b4c2604aa2ba784867774buzbee * code is massaged into a stub called from an assembly interpreter.
11169a3147c7412f4794434b4c2604aa2ba784867774buzbee * This is controlled by the JIT_STUB_HACK maco.
1117dd6e87095071e4e987910732062545f7303023e5Ben Cheng */
11189a3147c7412f4794434b4c2604aa2ba784867774buzbee
1119a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize)                   \
1120a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/)                              \
1121a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
1122a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        StaticField* sfield;                                                \
1123a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_AA(inst);                                               \
1124a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ref = FETCH(1);         /* field ref */                             \
1125a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref);           \
1126a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
1127a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (sfield == NULL) {                                               \
1128a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            EXPORT_PC();                                                    \
1129a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            sfield = dvmResolveStaticField(curMethod->clazz, ref);          \
1130a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if (sfield == NULL)                                             \
1131a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                GOTO_exceptionThrown();                                     \
1132dd6e87095071e4e987910732062545f7303023e5Ben Cheng            if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) {      \
113360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein                JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc));               \
1134dd6e87095071e4e987910732062545f7303023e5Ben Cheng            }                                                               \
1135a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }                                                                   \
1136a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield));    \
1137a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("+ SGET '%s'=0x%08llx",                                       \
113846f3fd49ebda372887192fa32b16040ed6710f58Chris Dearman            sfield->name, (u8)GET_REGISTER##_regsize(vdst));                \
1139a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
1140a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
1141a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1142a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize)                   \
1143a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/)                              \
1144a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    {                                                                       \
1145a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        StaticField* sfield;                                                \
1146a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        vdst = INST_AA(inst);                                               \
1147a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ref = FETCH(1);         /* field ref */                             \
1148a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref);           \
1149a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
1150a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        if (sfield == NULL) {                                               \
1151a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            EXPORT_PC();                                                    \
1152a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            sfield = dvmResolveStaticField(curMethod->clazz, ref);          \
1153a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            if (sfield == NULL)                                             \
1154a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden                GOTO_exceptionThrown();                                     \
1155dd6e87095071e4e987910732062545f7303023e5Ben Cheng            if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) {      \
115660fc806b679a3655c228b4093058c59941a49cfeDan Bornstein                JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc));               \
1157dd6e87095071e4e987910732062545f7303023e5Ben Cheng            }                                                               \
1158a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        }                                                                   \
1159a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst));    \
1160a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ILOGV("+ SPUT '%s'=0x%08llx",                                       \
116146f3fd49ebda372887192fa32b16040ed6710f58Chris Dearman            sfield->name, (u8)GET_REGISTER##_regsize(vdst));                \
1162a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    }                                                                       \
1163a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    FINISH(2);
1164a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1165cd8f5e701547739f241594b43e9470c92d98e9cfCarl Shapiro/* File: cstubs/enddefs.cpp */
1166a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1167a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/* undefine "magic" name remapping */
1168a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#undef retval
1169a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#undef pc
1170a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#undef fp
1171a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#undef curMethod
1172a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#undef methodClassDex
1173a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#undef self
1174a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#undef debugTrackedRefStart
1175a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1176cd8f5e701547739f241594b43e9470c92d98e9cfCarl Shapiro/* File: armv5te/debug.cpp */
1177a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#include <inttypes.h>
1178a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1179a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
1180a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Dump the fixed-purpose ARM registers, along with some other info.
1181a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
1182a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * This function MUST be compiled in ARM mode -- THUMB will yield bogus
1183a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * results.
1184a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden *
1185a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * This will NOT preserve r0-r3/ip.
1186a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
1187a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFaddenvoid dvmMterpDumpArmRegs(uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3)
1188a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden{
118995b0899ad3412596baa600b22ea2ecd7dd1acc43Evgeniy Stepanov  // TODO: Clang does not support asm declaration syntax.
119095b0899ad3412596baa600b22ea2ecd7dd1acc43Evgeniy Stepanov#ifndef __clang__
1191a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    register uint32_t rPC       asm("r4");
1192a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    register uint32_t rFP       asm("r5");
11939f601a917c8878204482c37aec7005054b6776fabuzbee    register uint32_t rSELF     asm("r6");
11941da12167d913efde56ec3b40491524b051679f2cAndy McFadden    register uint32_t rINST     asm("r7");
11951da12167d913efde56ec3b40491524b051679f2cAndy McFadden    register uint32_t rIBASE    asm("r8");
1196a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    register uint32_t r9        asm("r9");
1197a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    register uint32_t r10       asm("r10");
1198a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1199b31b30131bbf58280a515c40027aa958b81b5cd6Carl Shapiro    //extern char dvmAsmInstructionStart[];
1200a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1201a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    printf("REGS: r0=%08x r1=%08x r2=%08x r3=%08x\n", r0, r1, r2, r3);
12029f601a917c8878204482c37aec7005054b6776fabuzbee    printf("    : rPC=%08x rFP=%08x rSELF=%08x rINST=%08x\n",
12039f601a917c8878204482c37aec7005054b6776fabuzbee        rPC, rFP, rSELF, rINST);
12041da12167d913efde56ec3b40491524b051679f2cAndy McFadden    printf("    : rIBASE=%08x r9=%08x r10=%08x\n", rIBASE, r9, r10);
120595b0899ad3412596baa600b22ea2ecd7dd1acc43Evgeniy Stepanov#endif
1206a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
12079f601a917c8878204482c37aec7005054b6776fabuzbee    //Thread* self = (Thread*) rSELF;
12089f601a917c8878204482c37aec7005054b6776fabuzbee    //const Method* method = self->method;
1209a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    printf("    + self is %p\n", dvmThreadSelf());
1210a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    //printf("    + currently in %s.%s %s\n",
1211be323ec573918ef1674e4883c8766ddc4ee2a10cJean-Baptiste Queru    //    method->clazz->descriptor, method->name, method->shorty);
1212a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    //printf("    + dvmAsmInstructionStart = %p\n", dvmAsmInstructionStart);
1213a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    //printf("    + next handler for 0x%02x = %p\n",
1214a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    //    rINST & 0xff, dvmAsmInstructionStart + (rINST & 0xff) * 64);
1215a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden}
1216a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1217a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
1218a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Dump the StackSaveArea for the specified frame pointer.
1219a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
1220a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFaddenvoid dvmDumpFp(void* fp, StackSaveArea* otherSaveArea)
1221a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden{
1222a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
1223a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    printf("StackSaveArea for fp %p [%p/%p]:\n", fp, saveArea, otherSaveArea);
1224a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#ifdef EASY_GDB
1225a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    printf("  prevSave=%p, prevFrame=%p savedPc=%p meth=%p curPc=%p\n",
1226a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        saveArea->prevSave, saveArea->prevFrame, saveArea->savedPc,
1227a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        saveArea->method, saveArea->xtra.currentPc);
1228a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#else
1229a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    printf("  prevFrame=%p savedPc=%p meth=%p curPc=%p fp[0]=0x%08x\n",
1230a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        saveArea->prevFrame, saveArea->savedPc,
1231a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        saveArea->method, saveArea->xtra.currentPc,
1232a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        *(u4*)fp);
1233a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden#endif
1234a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden}
1235a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1236a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden/*
1237a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden * Does the bulk of the work for common_printMethod().
1238a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden */
1239a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFaddenvoid dvmMterpPrintMethod(Method* method)
1240a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden{
1241a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    /*
1242a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden     * It is a direct (non-virtual) method if it is static, private,
1243a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden     * or a constructor.
1244a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden     */
1245a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    bool isDirect =
1246a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        ((method->accessFlags & (ACC_STATIC|ACC_PRIVATE)) != 0) ||
1247a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden        (method->name[0] == '<');
1248a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1249a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
1250a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1251a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    printf("<%c:%s.%s %s> ",
1252a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            isDirect ? 'D' : 'V',
1253a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            method->clazz->descriptor,
1254a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            method->name,
1255a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden            desc);
1256a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1257a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden    free(desc);
1258a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden}
1259a80b76553c2b9f33c4063ae8c69c5362d961de81Andy McFadden
1260