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