1a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 2a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * This file was generated automatically by gen-mterp.py for 'mips'. 3a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 4a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * --> DO NOT EDIT <-- 5a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 6a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 7a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* File: c/header.cpp */ 8a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 9a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Copyright (C) 2008 The Android Open Source Project 10a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 11a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Licensed under the Apache License, Version 2.0 (the "License"); 12a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * you may not use this file except in compliance with the License. 13a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * You may obtain a copy of the License at 14a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 15a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * http://www.apache.org/licenses/LICENSE-2.0 16a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 17a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Unless required by applicable law or agreed to in writing, software 18a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * distributed under the License is distributed on an "AS IS" BASIS, 19a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * See the License for the specific language governing permissions and 21a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * limitations under the License. 22a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 23a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 24a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* common includes */ 25a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#include "Dalvik.h" 26a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#include "interp/InterpDefs.h" 27a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#include "mterp/Mterp.h" 28a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#include <math.h> // needed for fmod, fmodf 29a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#include "mterp/common/FindInterface.h" 30a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 31a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 32a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Configuration defines. These affect the C implementations, i.e. the 33a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * portable interpreter(s) and C stubs. 34a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 35a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Some defines are controlled by the Makefile, e.g.: 36a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * WITH_INSTR_CHECKS 37a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * WITH_TRACKREF_CHECKS 38a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * EASY_GDB 39a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * NDEBUG 40a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 41a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 42a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#ifdef WITH_INSTR_CHECKS /* instruction-level paranoia (slow!) */ 43a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define CHECK_BRANCH_OFFSETS 44a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define CHECK_REGISTER_INDICES 45a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 46a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 47a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 48a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Some architectures require 64-bit alignment for access to 64-bit data 49a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * types. We can't just use pointers to copy 64-bit values out of our 50a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * interpreted register set, because gcc may assume the pointer target is 51a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * aligned and generate invalid code. 52a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 53a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * There are two common approaches: 54a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * (1) Use a union that defines a 32-bit pair and a 64-bit value. 55a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * (2) Call memcpy(). 56a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 57a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Depending upon what compiler you're using and what options are specified, 58a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * one may be faster than the other. For example, the compiler might 59a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * convert a memcpy() of 8 bytes into a series of instructions and omit 60a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * the call. The union version could cause some strange side-effects, 61a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * e.g. for a while ARM gcc thought it needed separate storage for each 62a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * inlined instance, and generated instructions to zero out ~700 bytes of 63a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * stack space at the top of the interpreter. 64a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 65a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * The default is to use memcpy(). The current gcc for ARM seems to do 66a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * better with the union. 67a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 68a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if defined(__ARM_EABI__) 69a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define NO_UNALIGN_64__UNION 70a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#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 79a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 80a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 81a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham//#define LOG_INSTR /* verbose debugging */ 82a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */ 83a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 84a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 85a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Export another copy of the PC on every instruction; this is largely 86a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * redundant with EXPORT_PC and the debugger code. This value can be 87a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * compared against what we have stored on the stack with EXPORT_PC to 88a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * help ensure that we aren't missing any export calls. 89a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 90a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if WITH_EXTRA_GC_CHECKS > 1 91a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define EXPORT_EXTRA_PC() (self->currentPc2 = pc) 92a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 93a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define EXPORT_EXTRA_PC() 94a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 95a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 96a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 97a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Adjust the program counter. "_offset" is a signed int, in 16-bit units. 98a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 99a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns". 100a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 101a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * We don't advance the program counter until we finish an instruction or 102a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * branch, because we do want to have to unroll the PC if there's an 103a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * exception. 104a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 105a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#ifdef CHECK_BRANCH_OFFSETS 106a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define ADJUST_PC(_offset) do { \ 107a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham int myoff = _offset; /* deref only once */ \ 108a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (pc + myoff < curMethod->insns || \ 109a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham pc + myoff >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) \ 110a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 111a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham char* desc; \ 112a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham desc = dexProtoCopyMethodDescriptor(&curMethod->prototype); \ 113ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ALOGE("Invalid branch %d at 0x%04x in %s.%s %s", \ 114a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham myoff, (int) (pc - curMethod->insns), \ 115a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham curMethod->clazz->descriptor, curMethod->name, desc); \ 116a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham free(desc); \ 117a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmAbort(); \ 118a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 119a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham pc += myoff; \ 120a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_EXTRA_PC(); \ 121a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } while (false) 122a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 123a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define ADJUST_PC(_offset) do { \ 124a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham pc += _offset; \ 125a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_EXTRA_PC(); \ 126a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } while (false) 127a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 128a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 129a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 130a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * If enabled, log instructions as we execute them. 131a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 132a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#ifdef LOG_INSTR 133a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define ILOGD(...) ILOG(LOG_DEBUG, __VA_ARGS__) 134a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define ILOGV(...) ILOG(LOG_VERBOSE, __VA_ARGS__) 135a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define ILOG(_level, ...) do { \ 136a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham char debugStrBuf[128]; \ 137a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham snprintf(debugStrBuf, sizeof(debugStrBuf), __VA_ARGS__); \ 138a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (curMethod != NULL) \ 139ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ALOG(_level, LOG_TAG"i", "%-2d|%04x%s", \ 140a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->threadId, (int)(pc - curMethod->insns), debugStrBuf); \ 141a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham else \ 142ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ALOG(_level, LOG_TAG"i", "%-2d|####%s", \ 143a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->threadId, debugStrBuf); \ 144a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } while(false) 145a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamvoid dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly); 146a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define DUMP_REGS(_meth, _frame, _inOnly) dvmDumpRegs(_meth, _frame, _inOnly) 147a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamstatic const char kSpacing[] = " "; 148a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 149a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define ILOGD(...) ((void)0) 150a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define ILOGV(...) ((void)0) 151a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define DUMP_REGS(_meth, _frame, _inOnly) ((void)0) 152a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 153a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 154a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* get a long from an array of u4 */ 155a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamstatic inline s8 getLongFromArray(const u4* ptr, int idx) 156a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham{ 157a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if defined(NO_UNALIGN_64__UNION) 158a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham union { s8 ll; u4 parts[2]; } conv; 159a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 160a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ptr += idx; 161a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham conv.parts[0] = ptr[0]; 162a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham conv.parts[1] = ptr[1]; 163a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham return conv.ll; 164a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 165a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham s8 val; 166a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham memcpy(&val, &ptr[idx], 8); 167a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham return val; 168a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 169a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham} 170a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 171a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* store a long into an array of u4 */ 172a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamstatic inline void putLongToArray(u4* ptr, int idx, s8 val) 173a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham{ 174a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if defined(NO_UNALIGN_64__UNION) 175a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham union { s8 ll; u4 parts[2]; } conv; 176a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 177a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ptr += idx; 178a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham conv.ll = val; 179a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ptr[0] = conv.parts[0]; 180a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ptr[1] = conv.parts[1]; 181a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 182a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham memcpy(&ptr[idx], &val, 8); 183a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 184a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham} 185a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 186a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* get a double from an array of u4 */ 187a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamstatic inline double getDoubleFromArray(const u4* ptr, int idx) 188a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham{ 189a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if defined(NO_UNALIGN_64__UNION) 190a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham union { double d; u4 parts[2]; } conv; 191a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 192a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ptr += idx; 193a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham conv.parts[0] = ptr[0]; 194a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham conv.parts[1] = ptr[1]; 195a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham return conv.d; 196a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 197a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham double dval; 198a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham memcpy(&dval, &ptr[idx], 8); 199a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham return dval; 200a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 201a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham} 202a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 203a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* store a double into an array of u4 */ 204a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamstatic inline void putDoubleToArray(u4* ptr, int idx, double dval) 205a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham{ 206a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if defined(NO_UNALIGN_64__UNION) 207a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham union { double d; u4 parts[2]; } conv; 208a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 209a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ptr += idx; 210a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham conv.d = dval; 211a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ptr[0] = conv.parts[0]; 212a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ptr[1] = conv.parts[1]; 213a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 214a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham memcpy(&ptr[idx], &dval, 8); 215a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 216a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham} 217a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 218a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 219a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * If enabled, validate the register number on every access. Otherwise, 220a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * just do an array access. 221a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 222a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Assumes the existence of "u4* fp". 223a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 224a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * "_idx" may be referenced more than once. 225a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 226a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#ifdef CHECK_REGISTER_INDICES 227a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define GET_REGISTER(_idx) \ 228a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ( (_idx) < curMethod->registersSize ? \ 229a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (fp[(_idx)]) : (assert(!"bad reg"),1969) ) 230a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define SET_REGISTER(_idx, _val) \ 231a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ( (_idx) < curMethod->registersSize ? \ 232a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (fp[(_idx)] = (u4)(_val)) : (assert(!"bad reg"),1969) ) 233a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define GET_REGISTER_AS_OBJECT(_idx) ((Object *)GET_REGISTER(_idx)) 234a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define SET_REGISTER_AS_OBJECT(_idx, _val) SET_REGISTER(_idx, (s4)_val) 235a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define GET_REGISTER_INT(_idx) ((s4) GET_REGISTER(_idx)) 236a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val) 237a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define GET_REGISTER_WIDE(_idx) \ 238a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ( (_idx) < curMethod->registersSize-1 ? \ 239a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham getLongFromArray(fp, (_idx)) : (assert(!"bad reg"),1969) ) 240a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define SET_REGISTER_WIDE(_idx, _val) \ 241a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ( (_idx) < curMethod->registersSize-1 ? \ 242a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (void)putLongToArray(fp, (_idx), (_val)) : assert(!"bad reg") ) 243a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define GET_REGISTER_FLOAT(_idx) \ 244a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ( (_idx) < curMethod->registersSize ? \ 245a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (*((float*) &fp[(_idx)])) : (assert(!"bad reg"),1969.0f) ) 246a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define SET_REGISTER_FLOAT(_idx, _val) \ 247a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ( (_idx) < curMethod->registersSize ? \ 248a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (*((float*) &fp[(_idx)]) = (_val)) : (assert(!"bad reg"),1969.0f) ) 249a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define GET_REGISTER_DOUBLE(_idx) \ 250a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ( (_idx) < curMethod->registersSize-1 ? \ 251a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham getDoubleFromArray(fp, (_idx)) : (assert(!"bad reg"),1969.0) ) 252a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define SET_REGISTER_DOUBLE(_idx, _val) \ 253a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ( (_idx) < curMethod->registersSize-1 ? \ 254a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (void)putDoubleToArray(fp, (_idx), (_val)) : assert(!"bad reg") ) 255a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 256a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define GET_REGISTER(_idx) (fp[(_idx)]) 257a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define SET_REGISTER(_idx, _val) (fp[(_idx)] = (_val)) 258a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define GET_REGISTER_AS_OBJECT(_idx) ((Object*) fp[(_idx)]) 259a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define SET_REGISTER_AS_OBJECT(_idx, _val) (fp[(_idx)] = (u4)(_val)) 260a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define GET_REGISTER_INT(_idx) ((s4)GET_REGISTER(_idx)) 261a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val) 262a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define GET_REGISTER_WIDE(_idx) getLongFromArray(fp, (_idx)) 263a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define SET_REGISTER_WIDE(_idx, _val) putLongToArray(fp, (_idx), (_val)) 264a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define GET_REGISTER_FLOAT(_idx) (*((float*) &fp[(_idx)])) 265a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define SET_REGISTER_FLOAT(_idx, _val) (*((float*) &fp[(_idx)]) = (_val)) 266a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define GET_REGISTER_DOUBLE(_idx) getDoubleFromArray(fp, (_idx)) 267a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham# define SET_REGISTER_DOUBLE(_idx, _val) putDoubleToArray(fp, (_idx), (_val)) 268a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 269a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 270a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 271a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Get 16 bits from the specified offset of the program counter. We always 272a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * want to load 16 bits at a time from the instruction stream -- it's more 273a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * efficient than 8 and won't have the alignment problems that 32 might. 274a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 275a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Assumes existence of "const u2* pc". 276a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 277a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define FETCH(_offset) (pc[(_offset)]) 278a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 279a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 280a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Extract instruction byte from 16-bit fetch (_inst is a u2). 281a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 282a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define INST_INST(_inst) ((_inst) & 0xff) 283a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 284a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 285a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Replace the opcode (used when handling breakpoints). _opcode is a u1. 286a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 287a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define INST_REPLACE_OP(_inst, _opcode) (((_inst) & 0xff00) | _opcode) 288a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 289a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 290a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2). 291a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 292a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define INST_A(_inst) (((_inst) >> 8) & 0x0f) 293a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define INST_B(_inst) ((_inst) >> 12) 294a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 295a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 296a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Get the 8-bit "vAA" 8-bit register index from the instruction word. 297a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * (_inst is u2) 298a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 299a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define INST_AA(_inst) ((_inst) >> 8) 300a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 301a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 302a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * The current PC must be available to Throwable constructors, e.g. 303a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * those created by the various exception throw routines, so that the 304a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * exception stack trace can be generated correctly. If we don't do this, 305a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * the offset within the current method won't be shown correctly. See the 306a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * notes in Exception.c. 307a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 308a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * This is also used to determine the address for precise GC. 309a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 310a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Assumes existence of "u4* fp" and "const u2* pc". 311a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 312a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define EXPORT_PC() (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc) 313a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 314a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 315a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Check to see if "obj" is NULL. If so, throw an exception. Assumes the 316a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * pc has already been exported to the stack. 317a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 318a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Perform additional checks on debug builds. 319a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 320a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Use this to check for NULL when the instruction handler calls into 321a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * something that could throw an exception (so we have already called 322a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * EXPORT_PC at the top). 323a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 324a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamstatic inline bool checkForNull(Object* obj) 325a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham{ 326a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (obj == NULL) { 327a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowNullPointerException(NULL); 328a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham return false; 329a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 330a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#ifdef WITH_EXTRA_OBJECT_VALIDATION 331ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes if (!dvmIsHeapAddress(obj)) { 332ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ALOGE("Invalid object %p", obj); 333a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmAbort(); 334a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 335a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 336a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#ifndef NDEBUG 337a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) { 338a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* probable heap corruption */ 339ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ALOGE("Invalid object class %p (in %p)", obj->clazz, obj); 340a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmAbort(); 341a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 342a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 343a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham return true; 344a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham} 345a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 346a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 347a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Check to see if "obj" is NULL. If so, export the PC into the stack 348a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * frame and throw an exception. 349a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 350a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Perform additional checks on debug builds. 351a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 352a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Use this to check for NULL when the instruction handler doesn't do 353a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * anything else that can throw an exception. 354a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 355a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamstatic inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc) 356a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham{ 357a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (obj == NULL) { 358a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); 359a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowNullPointerException(NULL); 360a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham return false; 361a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 362a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#ifdef WITH_EXTRA_OBJECT_VALIDATION 363a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (!dvmIsHeapAddress(obj)) { 364ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ALOGE("Invalid object %p", obj); 365a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmAbort(); 366a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 367a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 368a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#ifndef NDEBUG 369a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) { 370a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* probable heap corruption */ 371ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ALOGE("Invalid object class %p (in %p)", obj->clazz, obj); 372a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmAbort(); 373a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 374a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 375a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham return true; 376a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham} 377a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 378a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* File: cstubs/stubdefs.cpp */ 379a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 380a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * In the C mterp stubs, "goto" is a function call followed immediately 381a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * by a return. 382a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 383a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 384a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define GOTO_TARGET_DECL(_target, ...) \ 385a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham extern "C" void dvmMterp_##_target(Thread* self, ## __VA_ARGS__); 386a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 387a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* (void)xxx to quiet unused variable compiler warnings. */ 388a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define GOTO_TARGET(_target, ...) \ 389a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham void dvmMterp_##_target(Thread* self, ## __VA_ARGS__) { \ 390a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 ref, vsrc1, vsrc2, vdst; \ 391a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 inst = FETCH(0); \ 392a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham const Method* methodToCall; \ 393a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham StackSaveArea* debugSaveArea; \ 394a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst; \ 395a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (void)methodToCall; (void)debugSaveArea; 396a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 397a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define GOTO_TARGET_END } 398a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 399a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 400a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Redefine what used to be local variable accesses into Thread struct 401a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * references. (These are undefined down in "footer.cpp".) 402a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 403a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define retval self->interpSave.retval 404a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define pc self->interpSave.pc 405a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define fp self->interpSave.curFrame 406a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define curMethod self->interpSave.method 407a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define methodClassDex self->interpSave.methodClassDex 408a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define debugTrackedRefStart self->interpSave.debugTrackedRefStart 409a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 410a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* ugh */ 411a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define STUB_HACK(x) x 412a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if defined(WITH_JIT) 413a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define JIT_STUB_HACK(x) x 414a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 415a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define JIT_STUB_HACK(x) 416a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 417a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 418a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 419a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * InterpSave's pc and fp must be valid when breaking out to a 420a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * "Reportxxx" routine. Because the portable interpreter uses local 421a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * variables for these, we must flush prior. Stubs, however, use 422a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * the interpSave vars directly, so this is a nop for stubs. 423a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 424a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define PC_FP_TO_SELF() 425a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define PC_TO_SELF() 426a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 427a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 428a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Opcode handler framing macros. Here, each opcode is a separate function 429a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * that takes a "self" argument and returns void. We can't declare 430a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * these "static" because they may be called from an assembly stub. 431a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * (void)xxx to quiet unused variable compiler warnings. 432a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 433a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OPCODE(_op) \ 434a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham extern "C" void dvmMterp_##_op(Thread* self); \ 435a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham void dvmMterp_##_op(Thread* self) { \ 436a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u4 ref; \ 437a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 vsrc1, vsrc2, vdst; \ 438a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 inst = FETCH(0); \ 439a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (void)ref; (void)vsrc1; (void)vsrc2; (void)vdst; (void)inst; 440a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 441a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define OP_END } 442a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 443a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 444a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Like the "portable" FINISH, but don't reload "inst", and return to caller 445a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * when done. Further, debugger/profiler checks are handled 446a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * before handler execution in mterp, so we don't do them here either. 447a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 448a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if defined(WITH_JIT) 449a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define FINISH(_offset) { \ 450a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ADJUST_PC(_offset); \ 451a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) { \ 452a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmCheckJit(pc, self); \ 453a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 454a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham return; \ 455a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 456a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 457a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define FINISH(_offset) { \ 458a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ADJUST_PC(_offset); \ 459a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham return; \ 460a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 461a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 462a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 463455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham#define FINISH_BKPT(_opcode) /* FIXME? */ 464a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define DISPATCH_EXTENDED(_opcode) /* FIXME? */ 465a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 466a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 467a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * The "goto label" statements turn into function calls followed by 468a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * return statements. Some of the functions take arguments, which in the 469a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * portable interpreter are handled by assigning values to globals. 470a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 471a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 472a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define GOTO_exceptionThrown() \ 473a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham do { \ 474a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmMterp_exceptionThrown(self); \ 475a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham return; \ 476a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } while(false) 477a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 478a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define GOTO_returnFromMethod() \ 479a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham do { \ 480a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmMterp_returnFromMethod(self); \ 481a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham return; \ 482a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } while(false) 483a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 484ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes#define GOTO_invoke(_target, _methodCallRange) \ 485a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham do { \ 486ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes dvmMterp_##_target(self, _methodCallRange); \ 487a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham return; \ 488a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } while(false) 489a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 490a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst) \ 491a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham do { \ 492a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmMterp_invokeMethod(self, _methodCallRange, _methodToCall, \ 493a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham _vsrc1, _vdst); \ 494a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham return; \ 495a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } while(false) 496a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 497a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 498a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * As a special case, "goto bail" turns into a longjmp. 499a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 500a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define GOTO_bail() \ 501455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham dvmMterpStdBail(self) 502a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 503a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 504a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Periodically check for thread suspension. 505a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 506a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * While we're at it, see if a debugger has attached or the profiler has 507a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * started. 508a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 509a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define PERIODIC_CHECKS(_pcadj) { \ 510a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (dvmCheckSuspendQuick(self)) { \ 511a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); /* need for precise GC */ \ 512a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmCheckSuspendPending(self); \ 513a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 514a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 515a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 516a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* File: c/opcommon.cpp */ 517a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* forward declarations of goto targets */ 518ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET_DECL(filledNewArray, bool methodCallRange); 519ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET_DECL(invokeVirtual, bool methodCallRange); 520ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET_DECL(invokeSuper, bool methodCallRange); 521ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET_DECL(invokeInterface, bool methodCallRange); 522ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET_DECL(invokeDirect, bool methodCallRange); 523ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET_DECL(invokeStatic, bool methodCallRange); 524ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET_DECL(invokeVirtualQuick, bool methodCallRange); 525ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET_DECL(invokeSuperQuick, bool methodCallRange); 526a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET_DECL(invokeMethod, bool methodCallRange, const Method* methodToCall, 527a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 count, u2 regs); 528a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET_DECL(returnFromMethod); 529a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET_DECL(exceptionThrown); 530a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 531a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 532a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * =========================================================================== 533a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 534a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * What follows are opcode definitions shared between multiple opcodes with 535a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * minor substitutions handled by the C pre-processor. These should probably 536a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * use the mterp substitution mechanism instead, with the code here moved 537a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * into common fragment files (like the asm "binop.S"), although it's hard 538a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * to give up the C preprocessor in favor of the much simpler text subst. 539a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 540a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * =========================================================================== 541a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 542a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 543a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_NUMCONV(_opcode, _opname, _fromtype, _totype) \ 544a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB*/) \ 545a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_A(inst); \ 546a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_B(inst); \ 547a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \ 548a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER##_totype(vdst, \ 549a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GET_REGISTER##_fromtype(vsrc1)); \ 550a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(1); 551a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 552a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_FLOAT_TO_INT(_opcode, _opname, _fromvtype, _fromrtype, \ 553a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham _tovtype, _tortype) \ 554a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB*/) \ 555a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 556a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* spec defines specific handling for +/- inf and NaN values */ \ 557a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham _fromvtype val; \ 558a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham _tovtype intMin, intMax, result; \ 559a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_A(inst); \ 560a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_B(inst); \ 561a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \ 562a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham val = GET_REGISTER##_fromrtype(vsrc1); \ 563a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham intMin = (_tovtype) 1 << (sizeof(_tovtype) * 8 -1); \ 564a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham intMax = ~intMin; \ 565a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = (_tovtype) val; \ 566a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (val >= intMax) /* +inf */ \ 567a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = intMax; \ 568a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham else if (val <= intMin) /* -inf */ \ 569a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = intMin; \ 570a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham else if (val != val) /* NaN */ \ 571a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = 0; \ 572a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham else \ 573a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = (_tovtype) val; \ 574a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER##_tortype(vdst, result); \ 575a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 576a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(1); 577a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 578a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_INT_TO_SMALL(_opcode, _opname, _type) \ 579a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB*/) \ 580a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_A(inst); \ 581a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_B(inst); \ 582a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|int-to-%s v%d,v%d", (_opname), vdst, vsrc1); \ 583a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER(vdst, (_type) GET_REGISTER(vsrc1)); \ 584a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(1); 585a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 586a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* NOTE: the comparison result is always a signed 4-byte integer */ 587a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_CMPX(_opcode, _opname, _varType, _type, _nanVal) \ 588a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 589a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 590a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham int result; \ 591a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 regs; \ 592a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham _varType val1, val2; \ 593a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_AA(inst); \ 594a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham regs = FETCH(1); \ 595a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = regs & 0xff; \ 596a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc2 = regs >> 8; \ 597a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|cmp%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 598a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham val1 = GET_REGISTER##_type(vsrc1); \ 599a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham val2 = GET_REGISTER##_type(vsrc2); \ 600a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (val1 == val2) \ 601a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = 0; \ 602a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham else if (val1 < val2) \ 603a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = -1; \ 604a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham else if (val1 > val2) \ 605a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = 1; \ 606a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham else \ 607a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = (_nanVal); \ 608a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("+ result=%d", result); \ 609a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER(vdst, result); \ 610a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 611a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 612a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 613a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_IF_XX(_opcode, _opname, _cmp) \ 614a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB, +CCCC*/) \ 615a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_A(inst); \ 616a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc2 = INST_B(inst); \ 617a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if ((s4) GET_REGISTER(vsrc1) _cmp (s4) GET_REGISTER(vsrc2)) { \ 618a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham int branchOffset = (s2)FETCH(1); /* sign-extended */ \ 619a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|if-%s v%d,v%d,+0x%04x", (_opname), vsrc1, vsrc2, \ 620a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham branchOffset); \ 621a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("> branch taken"); \ 622a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (branchOffset < 0) \ 623a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham PERIODIC_CHECKS(branchOffset); \ 624a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(branchOffset); \ 625a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { \ 626a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|if-%s v%d,v%d,-", (_opname), vsrc1, vsrc2); \ 627a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); \ 628a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 629a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 630a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_IF_XXZ(_opcode, _opname, _cmp) \ 631a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vAA, +BBBB*/) \ 632a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_AA(inst); \ 633a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if ((s4) GET_REGISTER(vsrc1) _cmp 0) { \ 634a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham int branchOffset = (s2)FETCH(1); /* sign-extended */ \ 635a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|if-%s v%d,+0x%04x", (_opname), vsrc1, branchOffset); \ 636a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("> branch taken"); \ 637a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (branchOffset < 0) \ 638a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham PERIODIC_CHECKS(branchOffset); \ 639a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(branchOffset); \ 640a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { \ 641a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|if-%s v%d,-", (_opname), vsrc1); \ 642a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); \ 643a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 644a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 645a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_UNOP(_opcode, _opname, _pfx, _sfx, _type) \ 646a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB*/) \ 647a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_A(inst); \ 648a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_B(inst); \ 649a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \ 650a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER##_type(vdst, _pfx GET_REGISTER##_type(vsrc1) _sfx); \ 651a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(1); 652a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 653a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_X_INT(_opcode, _opname, _op, _chkdiv) \ 654a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 655a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 656a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 srcRegs; \ 657a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_AA(inst); \ 658a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham srcRegs = FETCH(1); \ 659a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = srcRegs & 0xff; \ 660a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc2 = srcRegs >> 8; \ 661a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \ 662a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (_chkdiv != 0) { \ 663a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham s4 firstVal, secondVal, result; \ 664a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham firstVal = GET_REGISTER(vsrc1); \ 665a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham secondVal = GET_REGISTER(vsrc2); \ 666a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (secondVal == 0) { \ 667a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); \ 668a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowArithmeticException("divide by zero"); \ 669a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 670a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 671a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if ((u4)firstVal == 0x80000000 && secondVal == -1) { \ 672a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (_chkdiv == 1) \ 673a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = firstVal; /* division */ \ 674a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham else \ 675a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = 0; /* remainder */ \ 676a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { \ 677a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = firstVal _op secondVal; \ 678a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 679a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER(vdst, result); \ 680a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { \ 681a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* non-div/rem case */ \ 682a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER(vdst, \ 683a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2)); \ 684a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 685a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 686a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 687a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 688a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op) \ 689a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 690a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 691a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 srcRegs; \ 692a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_AA(inst); \ 693a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham srcRegs = FETCH(1); \ 694a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = srcRegs & 0xff; \ 695a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc2 = srcRegs >> 8; \ 696a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \ 697a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER(vdst, \ 698a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f)); \ 699a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 700a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 701a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 702a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv) \ 703a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/) \ 704a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_A(inst); \ 705a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_B(inst); \ 706a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc2 = FETCH(1); \ 707a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x", \ 708a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (_opname), vdst, vsrc1, vsrc2); \ 709a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (_chkdiv != 0) { \ 710a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham s4 firstVal, result; \ 711a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham firstVal = GET_REGISTER(vsrc1); \ 712a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if ((s2) vsrc2 == 0) { \ 713a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); \ 714a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowArithmeticException("divide by zero"); \ 715a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 716a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 717a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) { \ 718a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* won't generate /lit16 instr for this; check anyway */ \ 719a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (_chkdiv == 1) \ 720a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = firstVal; /* division */ \ 721a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham else \ 722a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = 0; /* remainder */ \ 723a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { \ 724a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = firstVal _op (s2) vsrc2; \ 725a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 726a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER(vdst, result); \ 727a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { \ 728a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* non-div/rem case */ \ 729a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2); \ 730a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 731a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 732a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 733a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv) \ 734a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \ 735a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 736a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 litInfo; \ 737a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_AA(inst); \ 738a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham litInfo = FETCH(1); \ 739a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = litInfo & 0xff; \ 740a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc2 = litInfo >> 8; /* constant */ \ 741a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \ 742a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (_opname), vdst, vsrc1, vsrc2); \ 743a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (_chkdiv != 0) { \ 744a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham s4 firstVal, result; \ 745a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham firstVal = GET_REGISTER(vsrc1); \ 746a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if ((s1) vsrc2 == 0) { \ 747a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); \ 748a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowArithmeticException("divide by zero"); \ 749a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 750a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 751a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) { \ 752a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (_chkdiv == 1) \ 753a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = firstVal; /* division */ \ 754a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham else \ 755a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = 0; /* remainder */ \ 756a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { \ 757a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = firstVal _op ((s1) vsrc2); \ 758a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 759a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER(vdst, result); \ 760a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { \ 761a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER(vdst, \ 762a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2); \ 763a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 764a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 765a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 766a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 767a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op) \ 768a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \ 769a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 770a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 litInfo; \ 771a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_AA(inst); \ 772a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham litInfo = FETCH(1); \ 773a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = litInfo & 0xff; \ 774a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc2 = litInfo >> 8; /* constant */ \ 775a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \ 776a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (_opname), vdst, vsrc1, vsrc2); \ 777a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER(vdst, \ 778a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f)); \ 779a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 780a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 781a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 782a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv) \ 783a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB*/) \ 784a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_A(inst); \ 785a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_B(inst); \ 786a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 787a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (_chkdiv != 0) { \ 788a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham s4 firstVal, secondVal, result; \ 789a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham firstVal = GET_REGISTER(vdst); \ 790a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham secondVal = GET_REGISTER(vsrc1); \ 791a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (secondVal == 0) { \ 792a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); \ 793a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowArithmeticException("divide by zero"); \ 794a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 795a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 796a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if ((u4)firstVal == 0x80000000 && secondVal == -1) { \ 797a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (_chkdiv == 1) \ 798a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = firstVal; /* division */ \ 799a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham else \ 800a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = 0; /* remainder */ \ 801a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { \ 802a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = firstVal _op secondVal; \ 803a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 804a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER(vdst, result); \ 805a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { \ 806a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER(vdst, \ 807a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1)); \ 808a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 809a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(1); 810a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 811a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op) \ 812a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB*/) \ 813a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_A(inst); \ 814a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_B(inst); \ 815a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 816a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER(vdst, \ 817a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f)); \ 818a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(1); 819a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 820a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv) \ 821a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 822a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 823a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 srcRegs; \ 824a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_AA(inst); \ 825a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham srcRegs = FETCH(1); \ 826a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = srcRegs & 0xff; \ 827a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc2 = srcRegs >> 8; \ 828a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 829a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (_chkdiv != 0) { \ 830a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham s8 firstVal, secondVal, result; \ 831a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham firstVal = GET_REGISTER_WIDE(vsrc1); \ 832a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham secondVal = GET_REGISTER_WIDE(vsrc2); \ 833a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (secondVal == 0LL) { \ 834a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); \ 835a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowArithmeticException("divide by zero"); \ 836a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 837a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 838a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if ((u8)firstVal == 0x8000000000000000ULL && \ 839a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham secondVal == -1LL) \ 840a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 841a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (_chkdiv == 1) \ 842a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = firstVal; /* division */ \ 843a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham else \ 844a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = 0; /* remainder */ \ 845a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { \ 846a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = firstVal _op secondVal; \ 847a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 848a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER_WIDE(vdst, result); \ 849a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { \ 850a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER_WIDE(vdst, \ 851a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \ 852a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 853a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 854a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 855a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 856a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op) \ 857a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 858a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 859a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 srcRegs; \ 860a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_AA(inst); \ 861a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham srcRegs = FETCH(1); \ 862a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = srcRegs & 0xff; \ 863a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc2 = srcRegs >> 8; \ 864a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 865a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER_WIDE(vdst, \ 866a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \ 867a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 868a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 869a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 870a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv) \ 871a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB*/) \ 872a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_A(inst); \ 873a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_B(inst); \ 874a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 875a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (_chkdiv != 0) { \ 876a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham s8 firstVal, secondVal, result; \ 877a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham firstVal = GET_REGISTER_WIDE(vdst); \ 878a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham secondVal = GET_REGISTER_WIDE(vsrc1); \ 879a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (secondVal == 0LL) { \ 880a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); \ 881a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowArithmeticException("divide by zero"); \ 882a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 883a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 884a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if ((u8)firstVal == 0x8000000000000000ULL && \ 885a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham secondVal == -1LL) \ 886a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 887a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (_chkdiv == 1) \ 888a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = firstVal; /* division */ \ 889a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham else \ 890a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = 0; /* remainder */ \ 891a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { \ 892a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham result = firstVal _op secondVal; \ 893a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 894a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER_WIDE(vdst, result); \ 895a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { \ 896a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER_WIDE(vdst, \ 897a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\ 898a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 899a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(1); 900a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 901a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op) \ 902a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB*/) \ 903a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_A(inst); \ 904a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_B(inst); \ 905a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 906a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER_WIDE(vdst, \ 907a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \ 908a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(1); 909a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 910a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_X_FLOAT(_opcode, _opname, _op) \ 911a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 912a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 913a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 srcRegs; \ 914a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_AA(inst); \ 915a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham srcRegs = FETCH(1); \ 916a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = srcRegs & 0xff; \ 917a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc2 = srcRegs >> 8; \ 918a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 919a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER_FLOAT(vdst, \ 920a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2)); \ 921a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 922a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 923a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 924a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op) \ 925a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 926a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 927a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 srcRegs; \ 928a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_AA(inst); \ 929a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham srcRegs = FETCH(1); \ 930a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = srcRegs & 0xff; \ 931a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc2 = srcRegs >> 8; \ 932a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 933a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER_DOUBLE(vdst, \ 934a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2)); \ 935a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 936a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 937a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 938a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op) \ 939a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB*/) \ 940a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_A(inst); \ 941a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_B(inst); \ 942a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 943a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER_FLOAT(vdst, \ 944a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1)); \ 945a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(1); 946a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 947a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op) \ 948a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB*/) \ 949a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_A(inst); \ 950a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_B(inst); \ 951a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 952a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER_DOUBLE(vdst, \ 953a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1)); \ 954a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(1); 955a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 956a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize) \ 957a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 958a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 959a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ArrayObject* arrayObj; \ 960a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 arrayInfo; \ 961a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); \ 962a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_AA(inst); \ 963a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham arrayInfo = FETCH(1); \ 964a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = arrayInfo & 0xff; /* array ptr */ \ 965a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc2 = arrayInfo >> 8; /* index */ \ 966a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 967a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \ 968a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (!checkForNull((Object*) arrayObj)) \ 969a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 970a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (GET_REGISTER(vsrc2) >= arrayObj->length) { \ 971a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowArrayIndexOutOfBoundsException( \ 972a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham arrayObj->length, GET_REGISTER(vsrc2)); \ 973a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 974a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 975a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER##_regsize(vdst, \ 976a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]); \ 977a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("+ AGET[%d]=%#x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \ 978a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 979a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 980a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 981a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize) \ 982a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 983a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 984a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ArrayObject* arrayObj; \ 985a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 arrayInfo; \ 986a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); \ 987a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_AA(inst); /* AA: source value */ \ 988a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham arrayInfo = FETCH(1); \ 989a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = arrayInfo & 0xff; /* BB: array ptr */ \ 990a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc2 = arrayInfo >> 8; /* CC: index */ \ 991a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 992a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \ 993a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (!checkForNull((Object*) arrayObj)) \ 994a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 995a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (GET_REGISTER(vsrc2) >= arrayObj->length) { \ 996a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowArrayIndexOutOfBoundsException( \ 997a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham arrayObj->length, GET_REGISTER(vsrc2)); \ 998a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 999a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 1000a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\ 1001a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] = \ 1002a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GET_REGISTER##_regsize(vdst); \ 1003a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 1004a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 1005a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1006a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 1007a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * It's possible to get a bad value out of a field with sub-32-bit stores 1008a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * because the -quick versions always operate on 32 bits. Consider: 1009a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * short foo = -1 (sets a 32-bit register to 0xffffffff) 1010a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * iput-quick foo (writes all 32 bits to the field) 1011a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * short bar = 1 (sets a 32-bit register to 0x00000001) 1012a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * iput-short (writes the low 16 bits to the field) 1013a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * iget-quick foo (reads all 32 bits from the field, yielding 0xffff0001) 1014a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * This can only happen when optimized and non-optimized code has interleaved 1015a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * access to the same field. This is unlikely but possible. 1016a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1017a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * The easiest way to fix this is to always read/write 32 bits at a time. On 1018a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * a device with a 16-bit data bus this is sub-optimal. (The alternative 1019a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * approach is to have sub-int versions of iget-quick, but now we're wasting 1020a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Dalvik instruction space and making it less likely that handler code will 1021a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * already be in the CPU i-cache.) 1022a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1023a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize) \ 1024a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \ 1025a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 1026a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham InstField* ifield; \ 1027a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham Object* obj; \ 1028a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); \ 1029a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_A(inst); \ 1030a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_B(inst); /* object ptr */ \ 1031a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ref = FETCH(1); /* field ref */ \ 1032a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \ 1033a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham obj = (Object*) GET_REGISTER(vsrc1); \ 1034a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (!checkForNull(obj)) \ 1035a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 1036a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \ 1037a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (ifield == NULL) { \ 1038a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ifield = dvmResolveInstField(curMethod->clazz, ref); \ 1039a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (ifield == NULL) \ 1040a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 1041a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 1042a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER##_regsize(vdst, \ 1043a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmGetField##_ftype(obj, ifield->byteOffset)); \ 1044a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("+ IGET '%s'=0x%08llx", ifield->name, \ 1045a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (u8) GET_REGISTER##_regsize(vdst)); \ 1046a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 1047a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 1048a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1049a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize) \ 1050a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \ 1051a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 1052a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham Object* obj; \ 1053a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_A(inst); \ 1054a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_B(inst); /* object ptr */ \ 1055a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ref = FETCH(1); /* field offset */ \ 1056a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|iget%s-quick v%d,v%d,field@+%u", \ 1057a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (_opname), vdst, vsrc1, ref); \ 1058a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham obj = (Object*) GET_REGISTER(vsrc1); \ 1059a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (!checkForNullExportPC(obj, fp, pc)) \ 1060a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 1061a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref)); \ 1062a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("+ IGETQ %d=0x%08llx", ref, \ 1063a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (u8) GET_REGISTER##_regsize(vdst)); \ 1064a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 1065a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 1066a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1067a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize) \ 1068a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \ 1069a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 1070a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham InstField* ifield; \ 1071a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham Object* obj; \ 1072a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); \ 1073a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_A(inst); \ 1074a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_B(inst); /* object ptr */ \ 1075a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ref = FETCH(1); /* field ref */ \ 1076a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \ 1077a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham obj = (Object*) GET_REGISTER(vsrc1); \ 1078a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (!checkForNull(obj)) \ 1079a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 1080a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \ 1081a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (ifield == NULL) { \ 1082a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ifield = dvmResolveInstField(curMethod->clazz, ref); \ 1083a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (ifield == NULL) \ 1084a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 1085a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 1086a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmSetField##_ftype(obj, ifield->byteOffset, \ 1087a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GET_REGISTER##_regsize(vdst)); \ 1088a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("+ IPUT '%s'=0x%08llx", ifield->name, \ 1089a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (u8) GET_REGISTER##_regsize(vdst)); \ 1090a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 1091a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 1092a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1093a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize) \ 1094a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \ 1095a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 1096a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham Object* obj; \ 1097a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_A(inst); \ 1098a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_B(inst); /* object ptr */ \ 1099a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ref = FETCH(1); /* field offset */ \ 1100a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|iput%s-quick v%d,v%d,field@0x%04x", \ 1101a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (_opname), vdst, vsrc1, ref); \ 1102a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham obj = (Object*) GET_REGISTER(vsrc1); \ 1103a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (!checkForNullExportPC(obj, fp, pc)) \ 1104a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 1105a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst)); \ 1106a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("+ IPUTQ %d=0x%08llx", ref, \ 1107a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (u8) GET_REGISTER##_regsize(vdst)); \ 1108a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 1109a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 1110a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1111a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 1112a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * The JIT needs dvmDexGetResolvedField() to return non-null. 1113a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Because the portable interpreter is not involved with the JIT 1114a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * and trace building, we only need the extra check here when this 1115a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * code is massaged into a stub called from an assembly interpreter. 1116a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * This is controlled by the JIT_STUB_HACK maco. 1117a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1118a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1119a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize) \ 1120a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \ 1121a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 1122a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham StaticField* sfield; \ 1123a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_AA(inst); \ 1124a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ref = FETCH(1); /* field ref */ \ 1125a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref); \ 1126a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \ 1127a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (sfield == NULL) { \ 1128a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); \ 1129a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham sfield = dvmResolveStaticField(curMethod->clazz, ref); \ 1130a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (sfield == NULL) \ 1131a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 1132a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \ 1133a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \ 1134a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 1135a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 1136a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \ 1137a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("+ SGET '%s'=0x%08llx", \ 1138a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham sfield->name, (u8)GET_REGISTER##_regsize(vdst)); \ 1139a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 1140a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 1141a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1142a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize) \ 1143a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \ 1144a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { \ 1145a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham StaticField* sfield; \ 1146a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = INST_AA(inst); \ 1147a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ref = FETCH(1); /* field ref */ \ 1148a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref); \ 1149a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \ 1150a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (sfield == NULL) { \ 1151a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); \ 1152a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham sfield = dvmResolveStaticField(curMethod->clazz, ref); \ 1153a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (sfield == NULL) \ 1154a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); \ 1155a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \ 1156a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \ 1157a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 1158a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 1159a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \ 1160a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("+ SPUT '%s'=0x%08llx", \ 1161a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham sfield->name, (u8)GET_REGISTER##_regsize(vdst)); \ 1162a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } \ 1163a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(2); 1164a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1165a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* File: c/OP_BREAKPOINT.cpp */ 1166a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamHANDLE_OPCODE(OP_BREAKPOINT) 1167a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { 1168a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1169a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Restart this instruction with the original opcode. We do 1170a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * this by simply jumping to the handler. 1171a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1172a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * It's probably not necessary to update "inst", but we do it 1173a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * for the sake of anything that needs to do disambiguation in a 1174a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * common handler with INST_INST. 1175a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1176a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * The breakpoint itself is handled over in updateDebugger(), 1177a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * because we need to detect other events (method entry, single 1178a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * step) and report them in the same event packet, and we're not 1179a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * yet handling those through breakpoint instructions. By the 1180a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * time we get here, the breakpoint has already been handled and 1181a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * the thread resumed. 1182a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1183a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u1 originalOpcode = dvmGetOriginalOpcode(pc); 1184ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ALOGV("+++ break 0x%02x (0x%04x -> 0x%04x)", originalOpcode, inst, 1185a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham INST_REPLACE_OP(inst, originalOpcode)); 1186a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham inst = INST_REPLACE_OP(inst, originalOpcode); 1187a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH_BKPT(originalOpcode); 1188a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1189a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamOP_END 1190a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1191a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* File: c/gotoTargets.cpp */ 1192a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 1193a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * C footer. This has some common code shared by the various targets. 1194a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1195a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1196a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 1197a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Everything from here on is a "goto target". In the basic interpreter 1198a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * we jump into these targets and then jump directly to the handler for 1199a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * next instruction. Here, these are subroutines that return to the caller. 1200a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1201a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1202ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET(filledNewArray, bool methodCallRange, bool) 1203a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { 1204a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ClassObject* arrayClass; 1205a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ArrayObject* newArray; 1206a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u4* contents; 1207a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham char typeCh; 1208a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham int i; 1209a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u4 arg5; 1210a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1211a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); 1212a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1213ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ref = FETCH(1); /* class ref */ 1214ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vdst = FETCH(2); /* first 4 regs -or- range base */ 1215ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes 1216ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes if (methodCallRange) { 1217ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vsrc1 = INST_AA(inst); /* #of elements */ 1218ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes arg5 = -1; /* silence compiler warning */ 1219ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ILOGV("|filled-new-array-range args=%d @0x%04x {regs=v%d-v%d}", 1220a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1, ref, vdst, vdst+vsrc1-1); 1221a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { 1222ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes arg5 = INST_A(inst); 1223ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vsrc1 = INST_B(inst); /* #of elements */ 1224ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ILOGV("|filled-new-array args=%d @0x%04x {regs=0x%04x %x}", 1225ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vsrc1, ref, vdst, arg5); 1226a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1227a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1228a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1229a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Resolve the array class. 1230a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1231a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham arrayClass = dvmDexGetResolvedClass(methodClassDex, ref); 1232a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (arrayClass == NULL) { 1233a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham arrayClass = dvmResolveClass(curMethod->clazz, ref, false); 1234a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (arrayClass == NULL) 1235a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1236a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1237a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1238a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (!dvmIsArrayClass(arrayClass)) { 1239a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowRuntimeException( 1240a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham "filled-new-array needs array class"); 1241a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1242a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1243a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1244a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* verifier guarantees this is an array class */ 1245a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(dvmIsArrayClass(arrayClass)); 1246a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(dvmIsClassInitialized(arrayClass)); 1247a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1248a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1249a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Create an array of the specified type. 1250a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1251a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham LOGVV("+++ filled-new-array type is '%s'", arrayClass->descriptor); 1252a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham typeCh = arrayClass->descriptor[1]; 1253a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (typeCh == 'D' || typeCh == 'J') { 1254a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* category 2 primitives not allowed */ 1255a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowRuntimeException("bad filled array req"); 1256a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1257a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else if (typeCh != 'L' && typeCh != '[' && typeCh != 'I') { 1258a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* TODO: requires multiple "fill in" loops with different widths */ 1259ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ALOGE("non-int primitives not implemented"); 1260a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowInternalError( 1261a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham "filled-new-array not implemented for anything but 'int'"); 1262a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1263a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1264a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1265a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham newArray = dvmAllocArrayByClass(arrayClass, vsrc1, ALLOC_DONT_TRACK); 1266a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (newArray == NULL) 1267a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1268a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1269a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1270a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Fill in the elements. It's legal for vsrc1 to be zero. 1271a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1272a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham contents = (u4*)(void*)newArray->contents; 1273a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (methodCallRange) { 1274a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham for (i = 0; i < vsrc1; i++) 1275a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham contents[i] = GET_REGISTER(vdst+i); 1276a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { 1277a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(vsrc1 <= 5); 1278a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (vsrc1 == 5) { 1279a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham contents[4] = GET_REGISTER(arg5); 1280a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1--; 1281a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1282a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham for (i = 0; i < vsrc1; i++) { 1283a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham contents[i] = GET_REGISTER(vdst & 0x0f); 1284a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst >>= 4; 1285a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1286a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1287a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (typeCh == 'L' || typeCh == '[') { 1288a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmWriteBarrierArray(newArray, 0, newArray->length); 1289a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1290a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1291a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham retval.l = (Object*)newArray; 1292a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1293ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes FINISH(3); 1294a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET_END 1295a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1296a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1297ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET(invokeVirtual, bool methodCallRange, bool) 1298a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { 1299a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham Method* baseMethod; 1300a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham Object* thisPtr; 1301a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1302a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); 1303a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1304ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 1305ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ref = FETCH(1); /* method ref */ 1306ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vdst = FETCH(2); /* 4 regs -or- first reg */ 1307ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes 1308ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes /* 1309ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes * The object against which we are executing a method is always 1310ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes * in the first argument. 1311ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes */ 1312ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes if (methodCallRange) { 1313ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes assert(vsrc1 > 0); 1314ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ILOGV("|invoke-virtual-range args=%d @0x%04x {regs=v%d-v%d}", 1315a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1, ref, vdst, vdst+vsrc1-1); 1316a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham thisPtr = (Object*) GET_REGISTER(vdst); 1317a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { 1318ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes assert((vsrc1>>4) > 0); 1319ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ILOGV("|invoke-virtual args=%d @0x%04x {regs=0x%04x %x}", 1320ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 1321ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes thisPtr = (Object*) GET_REGISTER(vdst & 0x0f); 1322a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1323a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1324a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (!checkForNull(thisPtr)) 1325a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1326a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1327a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1328a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Resolve the method. This is the correct method for the static 1329a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * type of the object. We also verify access permissions here. 1330a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1331a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref); 1332a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (baseMethod == NULL) { 1333a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL); 1334a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (baseMethod == NULL) { 1335a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("+ unknown method or access denied"); 1336a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1337a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1338a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1339a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1340a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1341a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Combine the object we found with the vtable offset in the 1342a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * method. 1343a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1344a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(baseMethod->methodIndex < thisPtr->clazz->vtableCount); 1345a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall = thisPtr->clazz->vtable[baseMethod->methodIndex]; 1346a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1347a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if defined(WITH_JIT) && defined(MTERP_STUB) 1348a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->methodToCall = methodToCall; 1349a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->callsiteClass = thisPtr->clazz; 1350a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 1351a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1352a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if 0 1353a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (dvmIsAbstractMethod(methodToCall)) { 1354a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1355a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * This can happen if you create two classes, Base and Sub, where 1356a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Sub is a sub-class of Base. Declare a protected abstract 1357a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * method foo() in Base, and invoke foo() from a method in Base. 1358a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Base is an "abstract base class" and is never instantiated 1359a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * directly. Now, Override foo() in Sub, and use Sub. This 1360a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Works fine unless Sub stops providing an implementation of 1361a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * the method. 1362a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1363a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowAbstractMethodError("abstract method not implemented"); 1364a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1365a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1366a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 1367a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(!dvmIsAbstractMethod(methodToCall) || 1368a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall->nativeFunc != NULL); 1369a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 1370a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1371a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham LOGVV("+++ base=%s.%s virtual[%d]=%s.%s", 1372a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham baseMethod->clazz->descriptor, baseMethod->name, 1373a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (u4) baseMethod->methodIndex, 1374a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall->clazz->descriptor, methodToCall->name); 1375a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(methodToCall != NULL); 1376a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1377a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if 0 1378a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (vsrc1 != methodToCall->insSize) { 1379ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ALOGW("WRONG METHOD: base=%s.%s virtual[%d]=%s.%s", 1380a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham baseMethod->clazz->descriptor, baseMethod->name, 1381a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (u4) baseMethod->methodIndex, 1382a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall->clazz->descriptor, methodToCall->name); 1383a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //dvmDumpClass(baseMethod->clazz); 1384a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //dvmDumpClass(methodToCall->clazz); 1385a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmDumpAllClasses(0); 1386a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1387a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 1388a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1389a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 1390a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1391a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET_END 1392a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1393ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET(invokeSuper, bool methodCallRange) 1394a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { 1395a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham Method* baseMethod; 1396a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 thisReg; 1397a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1398a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); 1399a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1400ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 1401ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ref = FETCH(1); /* method ref */ 1402ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vdst = FETCH(2); /* 4 regs -or- first reg */ 1403ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes 1404ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes if (methodCallRange) { 1405ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ILOGV("|invoke-super-range args=%d @0x%04x {regs=v%d-v%d}", 1406a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1, ref, vdst, vdst+vsrc1-1); 1407a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham thisReg = vdst; 1408a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { 1409ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ILOGV("|invoke-super args=%d @0x%04x {regs=0x%04x %x}", 1410ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 1411ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes thisReg = vdst & 0x0f; 1412a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1413a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1414a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* impossible in well-formed code, but we must check nevertheless */ 1415a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (!checkForNull((Object*) GET_REGISTER(thisReg))) 1416a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1417a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1418a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1419a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Resolve the method. This is the correct method for the static 1420a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * type of the object. We also verify access permissions here. 1421a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * The first arg to dvmResolveMethod() is just the referring class 1422a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * (used for class loaders and such), so we don't want to pass 1423a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * the superclass into the resolution call. 1424a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1425a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref); 1426a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (baseMethod == NULL) { 1427a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL); 1428a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (baseMethod == NULL) { 1429a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("+ unknown method or access denied"); 1430a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1431a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1432a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1433a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1434a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1435a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Combine the object we found with the vtable offset in the 1436a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * method's class. 1437a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1438a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * We're using the current method's class' superclass, not the 1439a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * superclass of "this". This is because we might be executing 1440a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * in a method inherited from a superclass, and we want to run 1441a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * in that class' superclass. 1442a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1443a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (baseMethod->methodIndex >= curMethod->clazz->super->vtableCount) { 1444a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1445a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Method does not exist in the superclass. Could happen if 1446a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * superclass gets updated. 1447a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1448a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowNoSuchMethodError(baseMethod->name); 1449a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1450a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1451a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall = curMethod->clazz->super->vtable[baseMethod->methodIndex]; 1452a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1453a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if 0 1454a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (dvmIsAbstractMethod(methodToCall)) { 1455a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowAbstractMethodError("abstract method not implemented"); 1456a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1457a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1458a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 1459a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(!dvmIsAbstractMethod(methodToCall) || 1460a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall->nativeFunc != NULL); 1461a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 1462a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham LOGVV("+++ base=%s.%s super-virtual=%s.%s", 1463a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham baseMethod->clazz->descriptor, baseMethod->name, 1464a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall->clazz->descriptor, methodToCall->name); 1465a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(methodToCall != NULL); 1466a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1467a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 1468a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1469a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET_END 1470a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1471ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET(invokeInterface, bool methodCallRange) 1472a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { 1473a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham Object* thisPtr; 1474a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ClassObject* thisClass; 1475a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1476a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); 1477a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1478ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 1479ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ref = FETCH(1); /* method ref */ 1480ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vdst = FETCH(2); /* 4 regs -or- first reg */ 1481ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes 1482ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes /* 1483ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes * The object against which we are executing a method is always 1484ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes * in the first argument. 1485ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes */ 1486ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes if (methodCallRange) { 1487ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes assert(vsrc1 > 0); 1488ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ILOGV("|invoke-interface-range args=%d @0x%04x {regs=v%d-v%d}", 1489a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1, ref, vdst, vdst+vsrc1-1); 1490a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham thisPtr = (Object*) GET_REGISTER(vdst); 1491a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { 1492ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes assert((vsrc1>>4) > 0); 1493ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ILOGV("|invoke-interface args=%d @0x%04x {regs=0x%04x %x}", 1494ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 1495ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes thisPtr = (Object*) GET_REGISTER(vdst & 0x0f); 1496a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1497a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1498a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (!checkForNull(thisPtr)) 1499a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1500a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1501a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham thisClass = thisPtr->clazz; 1502a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1503a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1504a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Given a class and a method index, find the Method* with the 1505a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * actual code we want to execute. 1506a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1507a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall = dvmFindInterfaceMethodInCache(thisClass, ref, curMethod, 1508a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodClassDex); 1509a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if defined(WITH_JIT) && defined(MTERP_STUB) 1510a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->callsiteClass = thisClass; 1511a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->methodToCall = methodToCall; 1512a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 1513a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (methodToCall == NULL) { 1514a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(dvmCheckException(self)); 1515a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1516a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1517a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1518a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 1519a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1520a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET_END 1521a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1522ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET(invokeDirect, bool methodCallRange) 1523a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { 1524a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 thisReg; 1525a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1526a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); 1527a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1528ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 1529ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ref = FETCH(1); /* method ref */ 1530ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vdst = FETCH(2); /* 4 regs -or- first reg */ 1531ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes 1532ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes if (methodCallRange) { 1533ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ILOGV("|invoke-direct-range args=%d @0x%04x {regs=v%d-v%d}", 1534a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1, ref, vdst, vdst+vsrc1-1); 1535a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham thisReg = vdst; 1536a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { 1537ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ILOGV("|invoke-direct args=%d @0x%04x {regs=0x%04x %x}", 1538ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 1539ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes thisReg = vdst & 0x0f; 1540a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1541a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1542a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (!checkForNull((Object*) GET_REGISTER(thisReg))) 1543a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1544a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1545a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref); 1546a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (methodToCall == NULL) { 1547a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall = dvmResolveMethod(curMethod->clazz, ref, 1548a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham METHOD_DIRECT); 1549a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (methodToCall == NULL) { 1550a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("+ unknown direct method"); // should be impossible 1551a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1552a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1553a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1554a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 1555a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1556a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET_END 1557a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1558ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET(invokeStatic, bool methodCallRange) 1559a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); 1560a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1561ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 1562ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ref = FETCH(1); /* method ref */ 1563ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vdst = FETCH(2); /* 4 regs -or- first reg */ 1564a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1565ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes if (methodCallRange) 1566ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ILOGV("|invoke-static-range args=%d @0x%04x {regs=v%d-v%d}", 1567ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vsrc1, ref, vdst, vdst+vsrc1-1); 1568ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes else 1569ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ILOGV("|invoke-static args=%d @0x%04x {regs=0x%04x %x}", 1570ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 1571a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1572a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref); 1573a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (methodToCall == NULL) { 1574a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall = dvmResolveMethod(curMethod->clazz, ref, METHOD_STATIC); 1575a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (methodToCall == NULL) { 1576a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("+ unknown method"); 1577a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1578a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1579a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1580a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if defined(WITH_JIT) && defined(MTERP_STUB) 1581a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1582a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * The JIT needs dvmDexGetResolvedMethod() to return non-null. 1583a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Include the check if this code is being used as a stub 1584a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * called from the assembly interpreter. 1585a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1586a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if ((self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) && 1587a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (dvmDexGetResolvedMethod(methodClassDex, ref) == NULL)) { 1588a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* Class initialization is still ongoing */ 1589a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmJitEndTraceSelect(self,pc); 1590a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1591a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 1592a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1593a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 1594a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET_END 1595a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1596ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET(invokeVirtualQuick, bool methodCallRange) 1597a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { 1598a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham Object* thisPtr; 1599a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1600a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); 1601a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1602a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 1603a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ref = FETCH(1); /* vtable index */ 1604a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = FETCH(2); /* 4 regs -or- first reg */ 1605a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1606a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1607a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * The object against which we are executing a method is always 1608a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * in the first argument. 1609a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1610a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (methodCallRange) { 1611a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(vsrc1 > 0); 1612a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|invoke-virtual-quick-range args=%d @0x%04x {regs=v%d-v%d}", 1613a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1, ref, vdst, vdst+vsrc1-1); 1614a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham thisPtr = (Object*) GET_REGISTER(vdst); 1615a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { 1616a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert((vsrc1>>4) > 0); 1617a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|invoke-virtual-quick args=%d @0x%04x {regs=0x%04x %x}", 1618a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 1619a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham thisPtr = (Object*) GET_REGISTER(vdst & 0x0f); 1620a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1621a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1622a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (!checkForNull(thisPtr)) 1623a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1624a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1625a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1626a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1627a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Combine the object we found with the vtable offset in the 1628a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * method. 1629a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1630a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(ref < (unsigned int) thisPtr->clazz->vtableCount); 1631a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall = thisPtr->clazz->vtable[ref]; 1632a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if defined(WITH_JIT) && defined(MTERP_STUB) 1633a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->callsiteClass = thisPtr->clazz; 1634a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->methodToCall = methodToCall; 1635a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 1636a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1637a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if 0 1638a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (dvmIsAbstractMethod(methodToCall)) { 1639a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowAbstractMethodError("abstract method not implemented"); 1640a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1641a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1642a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 1643a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(!dvmIsAbstractMethod(methodToCall) || 1644a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall->nativeFunc != NULL); 1645a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 1646a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1647a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham LOGVV("+++ virtual[%d]=%s.%s", 1648a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ref, methodToCall->clazz->descriptor, methodToCall->name); 1649a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(methodToCall != NULL); 1650a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1651a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 1652a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1653a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET_END 1654a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1655ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott HughesGOTO_TARGET(invokeSuperQuick, bool methodCallRange) 1656a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { 1657a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 thisReg; 1658a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1659a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham EXPORT_PC(); 1660a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1661a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 1662a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ref = FETCH(1); /* vtable index */ 1663a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst = FETCH(2); /* 4 regs -or- first reg */ 1664a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1665a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (methodCallRange) { 1666a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|invoke-super-quick-range args=%d @0x%04x {regs=v%d-v%d}", 1667a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1, ref, vdst, vdst+vsrc1-1); 1668a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham thisReg = vdst; 1669a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { 1670a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("|invoke-super-quick args=%d @0x%04x {regs=0x%04x %x}", 1671a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 1672a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham thisReg = vdst & 0x0f; 1673a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1674a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* impossible in well-formed code, but we must check nevertheless */ 1675a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (!checkForNull((Object*) GET_REGISTER(thisReg))) 1676a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1677a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1678a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if 0 /* impossible in optimized + verified code */ 1679a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (ref >= curMethod->clazz->super->vtableCount) { 1680a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowNoSuchMethodError(NULL); 1681a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1682a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1683a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 1684a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(ref < (unsigned int) curMethod->clazz->super->vtableCount); 1685a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 1686a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1687a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1688a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Combine the object we found with the vtable offset in the 1689a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * method's class. 1690a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1691a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * We're using the current method's class' superclass, not the 1692a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * superclass of "this". This is because we might be executing 1693a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * in a method inherited from a superclass, and we want to run 1694a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * in the method's class' superclass. 1695a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1696a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall = curMethod->clazz->super->vtable[ref]; 1697a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1698a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if 0 1699a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (dvmIsAbstractMethod(methodToCall)) { 1700a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmThrowAbstractMethodError("abstract method not implemented"); 1701a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 1702a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1703a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 1704a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(!dvmIsAbstractMethod(methodToCall) || 1705a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall->nativeFunc != NULL); 1706a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 1707a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham LOGVV("+++ super-virtual[%d]=%s.%s", 1708a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ref, methodToCall->clazz->descriptor, methodToCall->name); 1709a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(methodToCall != NULL); 1710a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 1711a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1712a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET_END 1713a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1714a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1715a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1716a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * General handling for return-void, return, and return-wide. Put the 1717a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * return value in "retval" before jumping here. 1718a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1719a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET(returnFromMethod) 1720a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { 1721a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham StackSaveArea* saveArea; 1722a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1723a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1724a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * We must do this BEFORE we pop the previous stack frame off, so 1725a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * that the GC can see the return value (if any) in the local vars. 1726a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1727a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Since this is now an interpreter switch point, we must do it before 1728a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * we do anything at all. 1729a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1730a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham PERIODIC_CHECKS(0); 1731a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1732a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("> retval=0x%llx (leaving %s.%s %s)", 1733a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham retval.j, curMethod->clazz->descriptor, curMethod->name, 1734a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham curMethod->shorty); 1735a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //DUMP_REGS(curMethod, fp); 1736a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1737a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham saveArea = SAVEAREA_FROM_FP(fp); 1738a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1739a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#ifdef EASY_GDB 1740a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham debugSaveArea = saveArea; 1741a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 1742a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1743a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* back up to previous frame and see if we hit a break */ 1744a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham fp = (u4*)saveArea->prevFrame; 1745a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(fp != NULL); 1746a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1747a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* Handle any special subMode requirements */ 1748a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (self->interpBreak.ctl.subMode != 0) { 1749a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham PC_FP_TO_SELF(); 1750a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmReportReturn(self); 1751a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1752a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1753a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (dvmIsBreakFrame(fp)) { 1754a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* bail without popping the method frame from stack */ 1755a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham LOGVV("+++ returned into break frame"); 1756a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_bail(); 1757a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1758a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1759a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* update thread FP, and reset local variables */ 1760a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->interpSave.curFrame = fp; 1761a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham curMethod = SAVEAREA_FROM_FP(fp)->method; 1762a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->interpSave.method = curMethod; 1763a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //methodClass = curMethod->clazz; 1764a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodClassDex = curMethod->clazz->pDvmDex; 1765a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham pc = saveArea->savedPc; 1766a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor, 1767a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham curMethod->name, curMethod->shorty); 1768a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1769a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* use FINISH on the caller's invoke instruction */ 1770a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //u2 invokeInstr = INST_INST(FETCH(0)); 1771a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (true /*invokeInstr >= OP_INVOKE_VIRTUAL && 1772a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham invokeInstr <= OP_INVOKE_INTERFACE*/) 1773a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { 1774a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(3); 1775a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { 1776ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes //ALOGE("Unknown invoke instr %02x at %d", 1777a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham // invokeInstr, (int) (pc - curMethod->insns)); 1778a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(false); 1779a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1780a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1781a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET_END 1782a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1783a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1784a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1785a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Jump here when the code throws an exception. 1786a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1787a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * By the time we get here, the Throwable has been created and the stack 1788a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * trace has been saved off. 1789a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1790a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET(exceptionThrown) 1791a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { 1792a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham Object* exception; 1793a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham int catchRelPc; 1794a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1795a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham PERIODIC_CHECKS(0); 1796a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1797a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1798a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * We save off the exception and clear the exception status. While 1799a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * processing the exception we might need to load some Throwable 1800a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * classes, and we don't want class loader exceptions to get 1801a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * confused with this one. 1802a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1803a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(dvmCheckException(self)); 1804a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham exception = dvmGetException(self); 1805a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmAddTrackedAlloc(exception, self); 1806a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmClearException(self); 1807a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1808ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ALOGV("Handling exception %s at %s:%d", 1809a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham exception->clazz->descriptor, curMethod->name, 1810a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmLineNumFromPC(curMethod, pc - curMethod->insns)); 1811a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1812a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1813a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Report the exception throw to any "subMode" watchers. 1814a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1815a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * TODO: if the exception was thrown by interpreted code, control 1816a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * fell through native, and then back to us, we will report the 1817a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * exception at the point of the throw and again here. We can avoid 1818a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * this by not reporting exceptions when we jump here directly from 1819a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * the native call code above, but then we won't report exceptions 1820a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * that were thrown *from* the JNI code (as opposed to *through* it). 1821a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1822a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * The correct solution is probably to ignore from-native exceptions 1823a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * here, and have the JNI exception code do the reporting to the 1824a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * debugger. 1825a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1826a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (self->interpBreak.ctl.subMode != 0) { 1827a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham PC_FP_TO_SELF(); 1828a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmReportExceptionThrow(self, exception); 1829a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1830a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1831a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1832a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * We need to unroll to the catch block or the nearest "break" 1833a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * frame. 1834a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1835a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * A break frame could indicate that we have reached an intermediate 1836a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * native call, or have gone off the top of the stack and the thread 1837a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * needs to exit. Either way, we return from here, leaving the 1838a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * exception raised. 1839a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1840a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * If we do find a catch block, we want to transfer execution to 1841a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * that point. 1842a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1843a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Note this can cause an exception while resolving classes in 1844a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * the "catch" blocks. 1845a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1846a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns, 1847a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham exception, false, (void**)(void*)&fp); 1848a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1849a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1850a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Restore the stack bounds after an overflow. This isn't going to 1851a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * be correct in all circumstances, e.g. if JNI code devours the 1852a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * exception this won't happen until some other exception gets 1853a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * thrown. If the code keeps pushing the stack bounds we'll end 1854a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * up aborting the VM. 1855a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1856a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Note we want to do this *after* the call to dvmFindCatchBlock, 1857a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * because that may need extra stack space to resolve exception 1858a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * classes (e.g. through a class loader). 1859a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1860a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * It's possible for the stack overflow handling to cause an 1861a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * exception (specifically, class resolution in a "catch" block 1862a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * during the call above), so we could see the thread's overflow 1863a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * flag raised but actually be running in a "nested" interpreter 1864a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * frame. We don't allow doubled-up StackOverflowErrors, so 1865a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * we can check for this by just looking at the exception type 1866a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * in the cleanup function. Also, we won't unroll past the SOE 1867a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * point because the more-recent exception will hit a break frame 1868a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * as it unrolls to here. 1869a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1870a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (self->stackOverflowed) 1871a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmCleanupStackOverflow(self, exception); 1872a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1873a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (catchRelPc < 0) { 1874a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* falling through to JNI code or off the bottom of the stack */ 1875a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if DVM_SHOW_EXCEPTION >= 2 1876ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ALOGD("Exception %s from %s:%d not caught locally", 1877a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod), 1878a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmLineNumFromPC(curMethod, pc - curMethod->insns)); 1879a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 1880a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmSetException(self, exception); 1881a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmReleaseTrackedAlloc(exception, self); 1882a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_bail(); 1883a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1884a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1885a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if DVM_SHOW_EXCEPTION >= 3 1886a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { 1887a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham const Method* catchMethod = SAVEAREA_FROM_FP(fp)->method; 1888ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ALOGD("Exception %s thrown from %s:%d to %s:%d", 1889a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod), 1890a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmLineNumFromPC(curMethod, pc - curMethod->insns), 1891a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmGetMethodSourceFile(catchMethod), 1892a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmLineNumFromPC(catchMethod, catchRelPc)); 1893a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1894a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 1895a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1896a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1897a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Adjust local variables to match self->interpSave.curFrame and the 1898a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * updated PC. 1899a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1900a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //fp = (u4*) self->interpSave.curFrame; 1901a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham curMethod = SAVEAREA_FROM_FP(fp)->method; 1902a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->interpSave.method = curMethod; 1903a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //methodClass = curMethod->clazz; 1904a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodClassDex = curMethod->clazz->pDvmDex; 1905a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham pc = curMethod->insns + catchRelPc; 1906a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor, 1907a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham curMethod->name, curMethod->shorty); 1908a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham DUMP_REGS(curMethod, fp, false); // show all regs 1909a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1910a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1911a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Restore the exception if the handler wants it. 1912a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1913a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * The Dalvik spec mandates that, if an exception handler wants to 1914a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * do something with the exception, the first instruction executed 1915a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * must be "move-exception". We can pass the exception along 1916a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * through the thread struct, and let the move-exception instruction 1917a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * clear it for us. 1918a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1919a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * If the handler doesn't call move-exception, we don't want to 1920a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * finish here with an exception still pending. 1921a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1922a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (INST_INST(FETCH(0)) == OP_MOVE_EXCEPTION) 1923a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmSetException(self, exception); 1924a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1925a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmReleaseTrackedAlloc(exception, self); 1926a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(0); 1927a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1928a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET_END 1929a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1930a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1931a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1932a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1933a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * General handling for invoke-{virtual,super,direct,static,interface}, 1934a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * including "quick" variants. 1935a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1936a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Set "methodToCall" to the Method we're calling, and "methodCallRange" 1937a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * depending on whether this is a "/range" instruction. 1938a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1939a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * For a range call: 1940a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * "vsrc1" holds the argument count (8 bits) 1941a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * "vdst" holds the first argument in the range 1942a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * For a non-range call: 1943a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * "vsrc1" holds the argument count (4 bits) and the 5th argument index 1944a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * "vdst" holds four 4-bit register indices 1945a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 1946a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * The caller must EXPORT_PC before jumping here, because any method 1947a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * call can throw a stack overflow exception. 1948a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1949a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall, 1950a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u2 count, u2 regs) 1951a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { 1952a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham STUB_HACK(vsrc1 = count; vdst = regs; methodToCall = _methodToCall;); 1953a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1954a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //printf("range=%d call=%p count=%d regs=0x%04x\n", 1955a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham // methodCallRange, methodToCall, count, regs); 1956a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor, 1957a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham // methodToCall->name, methodToCall->shorty); 1958a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1959a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u4* outs; 1960a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham int i; 1961a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1962a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 1963a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Copy args. This may corrupt vsrc1/vdst. 1964a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 1965a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (methodCallRange) { 1966a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham // could use memcpy or a "Duff's device"; most functions have 1967a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham // so few args it won't matter much 1968a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(vsrc1 <= curMethod->outsSize); 1969a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(vsrc1 == methodToCall->insSize); 1970a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham outs = OUTS_FROM_FP(fp, vsrc1); 1971a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham for (i = 0; i < vsrc1; i++) 1972a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham outs[i] = GET_REGISTER(vdst+i); 1973a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { 1974a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u4 count = vsrc1 >> 4; 1975a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1976a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(count <= curMethod->outsSize); 1977a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(count == methodToCall->insSize); 1978a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(count <= 5); 1979a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 1980a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham outs = OUTS_FROM_FP(fp, count); 1981a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if 0 1982a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (count == 5) { 1983a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham outs[4] = GET_REGISTER(vsrc1 & 0x0f); 1984a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham count--; 1985a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1986a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham for (i = 0; i < (int) count; i++) { 1987a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham outs[i] = GET_REGISTER(vdst & 0x0f); 1988a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham vdst >>= 4; 1989a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 1990a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 1991a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham // This version executes fewer instructions but is larger 1992a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham // overall. Seems to be a teensy bit faster. 1993a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert((vdst >> 16) == 0); // 16 bits -or- high 16 bits clear 1994a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham switch (count) { 1995a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham case 5: 1996a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham outs[4] = GET_REGISTER(vsrc1 & 0x0f); 1997a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham case 4: 1998a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham outs[3] = GET_REGISTER(vdst >> 12); 1999a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham case 3: 2000a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham outs[2] = GET_REGISTER((vdst & 0x0f00) >> 8); 2001a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham case 2: 2002a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham outs[1] = GET_REGISTER((vdst & 0x00f0) >> 4); 2003a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham case 1: 2004a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham outs[0] = GET_REGISTER(vdst & 0x0f); 2005a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham default: 2006a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ; 2007a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 2008a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 2009a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 2010a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 2011a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2012a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 2013a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * (This was originally a "goto" target; I've kept it separate from the 2014a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * stuff above in case we want to refactor things again.) 2015a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 2016a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * At this point, we have the arguments stored in the "outs" area of 2017a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * the current method's stack frame, and the method to call in 2018a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * "methodToCall". Push a new stack frame. 2019a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 2020a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { 2021a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham StackSaveArea* newSaveArea; 2022a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u4* newFp; 2023a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2024a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGV("> %s%s.%s %s", 2025a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "", 2026a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall->clazz->descriptor, methodToCall->name, 2027a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall->shorty); 2028a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2029a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize; 2030a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham newSaveArea = SAVEAREA_FROM_FP(newFp); 2031a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2032a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* verify that we have enough space */ 2033a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (true) { 2034a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham u1* bottom; 2035a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4); 2036a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (bottom < self->interpStackEnd) { 2037a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* stack overflow */ 2038ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ALOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')", 2039a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->interpStackStart, self->interpStackEnd, bottom, 2040a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (u1*) fp - bottom, self->interpStackSize, 2041a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall->name); 2042a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmHandleStackOverflow(self, methodToCall); 2043a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(dvmCheckException(self)); 2044a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 2045a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 2046ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes //ALOGD("+++ fp=%p newFp=%p newSave=%p bottom=%p", 2047a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham // fp, newFp, newSaveArea, bottom); 2048a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 2049a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2050a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#ifdef LOG_INSTR 2051a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (methodToCall->registersSize > methodToCall->insSize) { 2052a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 2053a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * This makes valgrind quiet when we print registers that 2054a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * haven't been initialized. Turn it off when the debug 2055a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * messages are disabled -- we want valgrind to report any 2056a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * used-before-initialized issues. 2057a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 2058a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham memset(newFp, 0xcc, 2059a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (methodToCall->registersSize - methodToCall->insSize) * 4); 2060a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 2061a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 2062a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2063a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#ifdef EASY_GDB 2064a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham newSaveArea->prevSave = SAVEAREA_FROM_FP(fp); 2065a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 2066a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham newSaveArea->prevFrame = fp; 2067a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham newSaveArea->savedPc = pc; 2068a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#if defined(WITH_JIT) && defined(MTERP_STUB) 2069a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham newSaveArea->returnAddr = 0; 2070a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 2071a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham newSaveArea->method = methodToCall; 2072a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2073a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (self->interpBreak.ctl.subMode != 0) { 2074a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 2075a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * We mark ENTER here for both native and non-native 2076a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * calls. For native calls, we'll mark EXIT on return. 2077a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * For non-native calls, EXIT is marked in the RETURN op. 2078a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 2079a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham PC_TO_SELF(); 2080a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmReportInvoke(self, methodToCall); 2081a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 2082a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2083a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (!dvmIsNativeMethod(methodToCall)) { 2084a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 2085a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * "Call" interpreted code. Reposition the PC, update the 2086a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * frame pointer and other local state, and continue. 2087a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 2088a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham curMethod = methodToCall; 2089a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->interpSave.method = curMethod; 2090a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodClassDex = curMethod->clazz->pDvmDex; 2091a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham pc = methodToCall->insns; 2092a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham fp = newFp; 2093ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes self->interpSave.curFrame = fp; 2094a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#ifdef EASY_GDB 2095a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham debugSaveArea = SAVEAREA_FROM_FP(newFp); 2096a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 2097a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->debugIsMethodEntry = true; // profiling, debugging 2098a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor, 2099a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham curMethod->name, curMethod->shorty); 2100a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham DUMP_REGS(curMethod, fp, true); // show input args 2101a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(0); // jump to method start 2102a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { 2103a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* set this up for JNI locals, even if not a JNI native */ 2104a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all; 2105a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2106a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->interpSave.curFrame = newFp; 2107a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2108a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham DUMP_REGS(methodToCall, newFp, true); // show input args 2109a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2110a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (self->interpBreak.ctl.subMode != 0) { 2111a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmReportPreNativeInvoke(methodToCall, self, newSaveArea->prevFrame); 2112a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 2113a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2114a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor, 2115a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall->name, methodToCall->shorty); 2116a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2117a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 2118a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Jump through native call bridge. Because we leave no 2119a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * space for locals on native calls, "newFp" points directly 2120a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * to the method arguments. 2121a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 2122a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self); 2123a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2124a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (self->interpBreak.ctl.subMode != 0) { 2125a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmReportPostNativeInvoke(methodToCall, self, newSaveArea->prevFrame); 2126a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 2127a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2128a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* pop frame off */ 2129a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham dvmPopJniLocals(self, newSaveArea); 2130a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham self->interpSave.curFrame = newSaveArea->prevFrame; 2131a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham fp = newSaveArea->prevFrame; 2132a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2133a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 2134a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * If the native code threw an exception, or interpreted code 2135a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * invoked by the native call threw one and nobody has cleared 2136a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * it, jump to our local exception handling. 2137a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 2138a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (dvmCheckException(self)) { 2139ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes ALOGV("Exception thrown by/below native code"); 2140a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham GOTO_exceptionThrown(); 2141a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 2142a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2143a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGD("> retval=0x%llx (leaving native)", retval.j); 2144a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ILOGD("> (return from native %s.%s to %s.%s %s)", 2145a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham methodToCall->clazz->descriptor, methodToCall->name, 2146a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham curMethod->clazz->descriptor, curMethod->name, 2147a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham curMethod->shorty); 2148a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2149a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //u2 invokeInstr = INST_INST(FETCH(0)); 2150a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham if (true /*invokeInstr >= OP_INVOKE_VIRTUAL && 2151a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham invokeInstr <= OP_INVOKE_INTERFACE*/) 2152a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham { 2153a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham FINISH(3); 2154a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } else { 2155ba1195e1f17456a9a0acab6e122b49f65134fc1fElliott Hughes //ALOGE("Unknown invoke instr %02x at %d", 2156a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham // invokeInstr, (int) (pc - curMethod->insns)); 2157a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(false); 2158a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 2159a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 2160a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham } 2161a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham assert(false); // should not get here 2162a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu GandhamGOTO_TARGET_END 2163a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2164a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* File: cstubs/enddefs.cpp */ 2165a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2166a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* undefine "magic" name remapping */ 2167a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#undef retval 2168a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#undef pc 2169a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#undef fp 2170a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#undef curMethod 2171a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#undef methodClassDex 2172a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#undef self 2173a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#undef debugTrackedRefStart 2174a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2175a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* File: mips/debug.cpp */ 2176455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham/* 2177455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham * Copyright (C) 2008 The Android Open Source Project 2178455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham * 2179455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham * Licensed under the Apache License, Version 2.0 (the "License"); 2180455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham * you may not use this file except in compliance with the License. 2181455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham * You may obtain a copy of the License at 2182455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham * 2183455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham * http://www.apache.org/licenses/LICENSE-2.0 2184455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham * 2185455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham * Unless required by applicable law or agreed to in writing, software 2186455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham * distributed under the License is distributed on an "AS IS" BASIS, 2187455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 2188455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham * See the License for the specific language governing permissions and 2189455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham * limitations under the License. 2190455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham */ 2191455b9bd781f7632c9f10bc088975e2201ad5bfe2Raghu Gandham 2192a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#include <inttypes.h> 2193a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2194a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 2195a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Dump the fixed-purpose MIPS registers, along with some other info. 2196a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * 2197a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 2198a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamvoid dvmMterpDumpMipsRegs(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3) 2199a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham{ 2200a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham register uint32_t rPC asm("s0"); 2201a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham register uint32_t rFP asm("s1"); 2202a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham register uint32_t rSELF asm("s2"); 2203a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham register uint32_t rIBASE asm("s3"); 2204a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham register uint32_t rINST asm("s4"); 2205a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham register uint32_t rOBJ asm("s5"); 2206a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham register uint32_t rBIX asm("s6"); 2207a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham register uint32_t rTEMP asm("s7"); 2208a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2209a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //extern char dvmAsmInstructionStart[]; 2210a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2211a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham printf("REGS: a0=%08x a1=%08x a2=%08x a3=%08x\n", a0, a1, a2, a3); 2212a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham printf(" : rPC=%08x rFP=%08x rSELF=%08x rIBASE=%08x\n", 2213a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham rPC, rFP, rSELF, rIBASE); 2214a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham printf(" : rINST=%08x rOBJ=%08x rBIX=%08x rTEMP=%08x \n", rINST, rOBJ, rBIX, rTEMP); 2215a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2216a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //Thread* self = (Thread*) rSELF; 2217a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //const Method* method = self->method; 2218a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham printf(" + self is %p\n", dvmThreadSelf()); 2219a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //printf(" + currently in %s.%s %s\n", 2220a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham // method->clazz->descriptor, method->name, method->signature); 2221a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //printf(" + dvmAsmInstructionStart = %p\n", dvmAsmInstructionStart); 2222a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham //printf(" + next handler for 0x%02x = %p\n", 2223a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham // rINST & 0xff, dvmAsmInstructionStart + (rINST & 0xff) * 64); 2224a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham} 2225a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2226a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 2227a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Dump the StackSaveArea for the specified frame pointer. 2228a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 2229a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamvoid dvmDumpFp(void* fp, StackSaveArea* otherSaveArea) 2230a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham{ 2231a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp); 2232a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham printf("StackSaveArea for fp %p [%p/%p]:\n", fp, saveArea, otherSaveArea); 2233a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#ifdef EASY_GDB 2234a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham printf(" prevSave=%p, prevFrame=%p savedPc=%p meth=%p curPc=%p\n", 2235a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham saveArea->prevSave, saveArea->prevFrame, saveArea->savedPc, 2236a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham saveArea->method, saveArea->xtra.currentPc); 2237a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#else 2238a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham printf(" prevFrame=%p savedPc=%p meth=%p curPc=%p fp[0]=0x%08x\n", 2239a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham saveArea->prevFrame, saveArea->savedPc, 2240a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham saveArea->method, saveArea->xtra.currentPc, 2241a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham *(u4*)fp); 2242a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham#endif 2243a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham} 2244a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2245a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham/* 2246a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * Does the bulk of the work for common_printMethod(). 2247a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 2248a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandhamvoid dvmMterpPrintMethod(Method* method) 2249a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham{ 2250a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham /* 2251a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * It is a direct (non-virtual) method if it is static, private, 2252a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham * or a constructor. 2253a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham */ 2254a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham bool isDirect = 2255a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham ((method->accessFlags & (ACC_STATIC|ACC_PRIVATE)) != 0) || 2256a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham (method->name[0] == '<'); 2257a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2258a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 2259a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2260a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham printf("<%c:%s.%s %s> ", 2261a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham isDirect ? 'D' : 'V', 2262a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham method->clazz->descriptor, 2263a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham method->name, 2264a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham desc); 2265a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2266a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham free(desc); 2267a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham} 2268a8b91c52fd8a90b784835dfe1f8898035266c4ddRaghu Gandham 2269