1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* common includes */
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "interp/InterpDefs.h"
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "mterp/Mterp.h"
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <math.h>                   // needed for fmod, fmodf
22ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#include "mterp/common/FindInterface.h"
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Configuration defines.  These affect the C implementations, i.e. the
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * portable interpreter(s) and C stubs.
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Some defines are controlled by the Makefile, e.g.:
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   WITH_INSTR_CHECKS
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   WITH_TRACKREF_CHECKS
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   EASY_GDB
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   NDEBUG
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia (slow!) */
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define CHECK_BRANCH_OFFSETS
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define CHECK_REGISTER_INDICES
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
41529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * Some architectures require 64-bit alignment for access to 64-bit data
42529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * types.  We can't just use pointers to copy 64-bit values out of our
43529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * interpreted register set, because gcc may assume the pointer target is
44529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * aligned and generate invalid code.
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
46529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * There are two common approaches:
47529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden *  (1) Use a union that defines a 32-bit pair and a 64-bit value.
48529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden *  (2) Call memcpy().
49529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden *
50529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * Depending upon what compiler you're using and what options are specified,
51529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * one may be faster than the other.  For example, the compiler might
52529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * convert a memcpy() of 8 bytes into a series of instructions and omit
53529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * the call.  The union version could cause some strange side-effects,
54529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * e.g. for a while ARM gcc thought it needed separate storage for each
55529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * inlined instance, and generated instructions to zero out ~700 bytes of
56529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * stack space at the top of the interpreter.
57529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden *
58529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * The default is to use memcpy().  The current gcc for ARM seems to do
59529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden * better with the union.
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if defined(__ARM_EABI__)
62529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden# define NO_UNALIGN_64__UNION
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
65529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project//#define LOG_INSTR                   /* verbose debugging */
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
7099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Export another copy of the PC on every instruction; this is largely
7199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * redundant with EXPORT_PC and the debugger code.  This value can be
7299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * compared against what we have stored on the stack with EXPORT_PC to
7399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * help ensure that we aren't missing any export calls.
7499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project */
7599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project#if WITH_EXTRA_GC_CHECKS > 1
7699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
7799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project#else
7899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project# define EXPORT_EXTRA_PC()
7999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project#endif
8099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
8199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project/*
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Adjust the program counter.  "_offset" is a signed int, in 16-bit units.
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We don't advance the program counter until we finish an instruction or
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * branch, because we do want to have to unroll the PC if there's an
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * exception.
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef CHECK_BRANCH_OFFSETS
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define ADJUST_PC(_offset) do {                                            \
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int myoff = _offset;        /* deref only once */                   \
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pc + myoff < curMethod->insns ||                                \
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            pc + myoff >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) \
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {                                                                   \
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            char* desc;                                                     \
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            desc = dexProtoCopyMethodDescriptor(&curMethod->prototype);     \
98c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Invalid branch %d at 0x%04x in %s.%s %s",                 \
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                myoff, (int) (pc - curMethod->insns),                       \
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                curMethod->clazz->descriptor, curMethod->name, desc);       \
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            free(desc);                                                     \
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dvmAbort();                                                     \
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }                                                                   \
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        pc += myoff;                                                        \
10599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        EXPORT_EXTRA_PC();                                                  \
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } while (false)
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
10899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project# define ADJUST_PC(_offset) do {                                            \
10999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        pc += _offset;                                                      \
11099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        EXPORT_EXTRA_PC();                                                  \
11199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    } while (false)
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If enabled, log instructions as we execute them.
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef LOG_INSTR
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define ILOGD(...) ILOG(LOG_DEBUG, __VA_ARGS__)
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define ILOGV(...) ILOG(LOG_VERBOSE, __VA_ARGS__)
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define ILOG(_level, ...) do {                                             \
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char debugStrBuf[128];                                              \
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        snprintf(debugStrBuf, sizeof(debugStrBuf), __VA_ARGS__);            \
12360fc806b679a3655c228b4093058c59941a49cfeDan Bornstein        if (curMethod != NULL)                                              \
1241663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block            ALOG(_level, LOG_TAG"i", "%-2d|%04x%s",                          \
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                self->threadId, (int)(pc - curMethod->insns), debugStrBuf); \
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else                                                                \
1271663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block            ALOG(_level, LOG_TAG"i", "%-2d|####%s",                          \
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                self->threadId, debugStrBuf);                               \
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } while(false)
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly);
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define DUMP_REGS(_meth, _frame, _inOnly) dvmDumpRegs(_meth, _frame, _inOnly)
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const char kSpacing[] = "            ";
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define ILOGD(...) ((void)0)
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define ILOGV(...) ((void)0)
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define DUMP_REGS(_meth, _frame, _inOnly) ((void)0)
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* get a long from an array of u4 */
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline s8 getLongFromArray(const u4* ptr, int idx)
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if defined(NO_UNALIGN_64__UNION)
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    union { s8 ll; u4 parts[2]; } conv;
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr += idx;
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    conv.parts[0] = ptr[0];
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    conv.parts[1] = ptr[1];
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return conv.ll;
149529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden#else
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    s8 val;
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(&val, &ptr[idx], 8);
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return val;
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* store a long into an array of u4 */
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline void putLongToArray(u4* ptr, int idx, s8 val)
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if defined(NO_UNALIGN_64__UNION)
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    union { s8 ll; u4 parts[2]; } conv;
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr += idx;
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    conv.ll = val;
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr[0] = conv.parts[0];
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr[1] = conv.parts[1];
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
167529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden    memcpy(&ptr[idx], &val, 8);
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* get a double from an array of u4 */
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline double getDoubleFromArray(const u4* ptr, int idx)
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if defined(NO_UNALIGN_64__UNION)
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    union { double d; u4 parts[2]; } conv;
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr += idx;
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    conv.parts[0] = ptr[0];
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    conv.parts[1] = ptr[1];
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return conv.d;
181529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden#else
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    double dval;
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memcpy(&dval, &ptr[idx], 8);
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return dval;
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* store a double into an array of u4 */
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline void putDoubleToArray(u4* ptr, int idx, double dval)
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if defined(NO_UNALIGN_64__UNION)
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    union { double d; u4 parts[2]; } conv;
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr += idx;
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    conv.d = dval;
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr[0] = conv.parts[0];
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ptr[1] = conv.parts[1];
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
199529d6b8112a06daca3bf4a89dec9fbad95efe46bAndy McFadden    memcpy(&ptr[idx], &dval, 8);
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * If enabled, validate the register number on every access.  Otherwise,
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * just do an array access.
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Assumes the existence of "u4* fp".
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "_idx" may be referenced more than once.
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef CHECK_REGISTER_INDICES
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define GET_REGISTER(_idx) \
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ( (_idx) < curMethod->registersSize ? \
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (fp[(_idx)]) : (assert(!"bad reg"),1969) )
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define SET_REGISTER(_idx, _val) \
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ( (_idx) < curMethod->registersSize ? \
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (fp[(_idx)] = (u4)(_val)) : (assert(!"bad reg"),1969) )
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define GET_REGISTER_AS_OBJECT(_idx)       ((Object *)GET_REGISTER(_idx))
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define SET_REGISTER_AS_OBJECT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define GET_REGISTER_INT(_idx) ((s4) GET_REGISTER(_idx))
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define GET_REGISTER_WIDE(_idx) \
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ( (_idx) < curMethod->registersSize-1 ? \
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        getLongFromArray(fp, (_idx)) : (assert(!"bad reg"),1969) )
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define SET_REGISTER_WIDE(_idx, _val) \
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ( (_idx) < curMethod->registersSize-1 ? \
2279c6f0a6a36fcce4a55e3764db45c6c7cced077a5Carl Shapiro        (void)putLongToArray(fp, (_idx), (_val)) : assert(!"bad reg") )
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define GET_REGISTER_FLOAT(_idx) \
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ( (_idx) < curMethod->registersSize ? \
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (*((float*) &fp[(_idx)])) : (assert(!"bad reg"),1969.0f) )
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define SET_REGISTER_FLOAT(_idx, _val) \
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ( (_idx) < curMethod->registersSize ? \
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (*((float*) &fp[(_idx)]) = (_val)) : (assert(!"bad reg"),1969.0f) )
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define GET_REGISTER_DOUBLE(_idx) \
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ( (_idx) < curMethod->registersSize-1 ? \
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        getDoubleFromArray(fp, (_idx)) : (assert(!"bad reg"),1969.0) )
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define SET_REGISTER_DOUBLE(_idx, _val) \
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ( (_idx) < curMethod->registersSize-1 ? \
2399c6f0a6a36fcce4a55e3764db45c6c7cced077a5Carl Shapiro        (void)putDoubleToArray(fp, (_idx), (_val)) : assert(!"bad reg") )
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#else
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define GET_REGISTER(_idx)                 (fp[(_idx)])
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define SET_REGISTER(_idx, _val)           (fp[(_idx)] = (_val))
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define GET_REGISTER_AS_OBJECT(_idx)       ((Object*) fp[(_idx)])
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define SET_REGISTER_AS_OBJECT(_idx, _val) (fp[(_idx)] = (u4)(_val))
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define GET_REGISTER_INT(_idx)             ((s4)GET_REGISTER(_idx))
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define SET_REGISTER_INT(_idx, _val)       SET_REGISTER(_idx, (s4)_val)
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define GET_REGISTER_WIDE(_idx)            getLongFromArray(fp, (_idx))
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define SET_REGISTER_WIDE(_idx, _val)      putLongToArray(fp, (_idx), (_val))
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define GET_REGISTER_FLOAT(_idx)           (*((float*) &fp[(_idx)]))
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define SET_REGISTER_FLOAT(_idx, _val)     (*((float*) &fp[(_idx)]) = (_val))
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define GET_REGISTER_DOUBLE(_idx)          getDoubleFromArray(fp, (_idx))
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project# define SET_REGISTER_DOUBLE(_idx, _val)    putDoubleToArray(fp, (_idx), (_val))
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get 16 bits from the specified offset of the program counter.  We always
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * want to load 16 bits at a time from the instruction stream -- it's more
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * efficient than 8 and won't have the alignment problems that 32 might.
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Assumes existence of "const u2* pc".
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define FETCH(_offset)     (pc[(_offset)])
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Extract instruction byte from 16-bit fetch (_inst is a u2).
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define INST_INST(_inst)    ((_inst) & 0xff)
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
27096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Replace the opcode (used when handling breakpoints).  _opcode is a u1.
27196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
27296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden#define INST_REPLACE_OP(_inst, _opcode) (((_inst) & 0xff00) | _opcode)
27396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
27496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/*
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2).
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define INST_A(_inst)       (((_inst) >> 8) & 0x0f)
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define INST_B(_inst)       ((_inst) >> 12)
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Get the 8-bit "vAA" 8-bit register index from the instruction word.
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (_inst is u2)
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define INST_AA(_inst)      ((_inst) >> 8)
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The current PC must be available to Throwable constructors, e.g.
28898f3eb12bf2a33c49712e093d5cc2aa713a93aa5buzbee * those created by the various exception throw routines, so that the
28998f3eb12bf2a33c49712e093d5cc2aa713a93aa5buzbee * exception stack trace can be generated correctly.  If we don't do this,
29098f3eb12bf2a33c49712e093d5cc2aa713a93aa5buzbee * the offset within the current method won't be shown correctly.  See the
29198f3eb12bf2a33c49712e093d5cc2aa713a93aa5buzbee * notes in Exception.c.
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
29399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * This is also used to determine the address for precise GC.
29499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project *
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Assumes existence of "u4* fp" and "const u2* pc".
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define EXPORT_PC()         (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Check to see if "obj" is NULL.  If so, throw an exception.  Assumes the
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * pc has already been exported to the stack.
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Perform additional checks on debug builds.
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Use this to check for NULL when the instruction handler calls into
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * something that could throw an exception (so we have already called
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * EXPORT_PC at the top).
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline bool checkForNull(Object* obj)
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (obj == NULL) {
312d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowNullPointerException(NULL);
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_EXTRA_OBJECT_VALIDATION
31634987b48d216786454aca59474cb76015af48bd9Jeff Brown    if (!dvmIsHeapAddress(obj)) {
317c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Invalid object %p", obj);
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* probable heap corruption */
324c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Invalid object class %p (in %p)", obj->clazz, obj);
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Check to see if "obj" is NULL.  If so, export the PC into the stack
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * frame and throw an exception.
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Perform additional checks on debug builds.
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Use this to check for NULL when the instruction handler doesn't do
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * anything else that can throw an exception.
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc)
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (obj == NULL) {
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        EXPORT_PC();
344d27f3cf3e7b373487f39e035fc4b55168d55c454Dan Bornstein        dvmThrowNullPointerException(NULL);
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef WITH_EXTRA_OBJECT_VALIDATION
3488bc8bf71a52e17d483021b4c9dc8e735d9bce3edElliott Hughes    if (!dvmIsHeapAddress(obj)) {
349c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Invalid object %p", obj);
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifndef NDEBUG
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* probable heap corruption */
356c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block        ALOGE("Invalid object class %p (in %p)", obj->clazz, obj);
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmAbort();
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
362