InterpC-portable.cpp revision a8b91c52fd8a90b784835dfe1f8898035266c4dd
1/* 2 * This file was generated automatically by gen-mterp.py for 'portable'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: c/header.cpp */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23 24/* common includes */ 25#include "Dalvik.h" 26#include "interp/InterpDefs.h" 27#include "mterp/Mterp.h" 28#include <math.h> // needed for fmod, fmodf 29#include "mterp/common/FindInterface.h" 30 31/* 32 * Configuration defines. These affect the C implementations, i.e. the 33 * portable interpreter(s) and C stubs. 34 * 35 * Some defines are controlled by the Makefile, e.g.: 36 * WITH_INSTR_CHECKS 37 * WITH_TRACKREF_CHECKS 38 * EASY_GDB 39 * NDEBUG 40 */ 41 42#ifdef WITH_INSTR_CHECKS /* instruction-level paranoia (slow!) */ 43# define CHECK_BRANCH_OFFSETS 44# define CHECK_REGISTER_INDICES 45#endif 46 47/* 48 * Some architectures require 64-bit alignment for access to 64-bit data 49 * types. We can't just use pointers to copy 64-bit values out of our 50 * interpreted register set, because gcc may assume the pointer target is 51 * aligned and generate invalid code. 52 * 53 * There are two common approaches: 54 * (1) Use a union that defines a 32-bit pair and a 64-bit value. 55 * (2) Call memcpy(). 56 * 57 * Depending upon what compiler you're using and what options are specified, 58 * one may be faster than the other. For example, the compiler might 59 * convert a memcpy() of 8 bytes into a series of instructions and omit 60 * the call. The union version could cause some strange side-effects, 61 * e.g. for a while ARM gcc thought it needed separate storage for each 62 * inlined instance, and generated instructions to zero out ~700 bytes of 63 * stack space at the top of the interpreter. 64 * 65 * The default is to use memcpy(). The current gcc for ARM seems to do 66 * better with the union. 67 */ 68#if defined(__ARM_EABI__) 69# define NO_UNALIGN_64__UNION 70#endif 71/* 72 * MIPS ABI requires 64-bit alignment for access to 64-bit data types. 73 * 74 * Use memcpy() to do the transfer 75 */ 76#if defined(__mips__) 77/* # define NO_UNALIGN_64__UNION */ 78#endif 79 80 81//#define LOG_INSTR /* verbose debugging */ 82/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */ 83 84/* 85 * Export another copy of the PC on every instruction; this is largely 86 * redundant with EXPORT_PC and the debugger code. This value can be 87 * compared against what we have stored on the stack with EXPORT_PC to 88 * help ensure that we aren't missing any export calls. 89 */ 90#if WITH_EXTRA_GC_CHECKS > 1 91# define EXPORT_EXTRA_PC() (self->currentPc2 = pc) 92#else 93# define EXPORT_EXTRA_PC() 94#endif 95 96/* 97 * Adjust the program counter. "_offset" is a signed int, in 16-bit units. 98 * 99 * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns". 100 * 101 * We don't advance the program counter until we finish an instruction or 102 * branch, because we do want to have to unroll the PC if there's an 103 * exception. 104 */ 105#ifdef CHECK_BRANCH_OFFSETS 106# define ADJUST_PC(_offset) do { \ 107 int myoff = _offset; /* deref only once */ \ 108 if (pc + myoff < curMethod->insns || \ 109 pc + myoff >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) \ 110 { \ 111 char* desc; \ 112 desc = dexProtoCopyMethodDescriptor(&curMethod->prototype); \ 113 LOGE("Invalid branch %d at 0x%04x in %s.%s %s", \ 114 myoff, (int) (pc - curMethod->insns), \ 115 curMethod->clazz->descriptor, curMethod->name, desc); \ 116 free(desc); \ 117 dvmAbort(); \ 118 } \ 119 pc += myoff; \ 120 EXPORT_EXTRA_PC(); \ 121 } while (false) 122#else 123# define ADJUST_PC(_offset) do { \ 124 pc += _offset; \ 125 EXPORT_EXTRA_PC(); \ 126 } while (false) 127#endif 128 129/* 130 * If enabled, log instructions as we execute them. 131 */ 132#ifdef LOG_INSTR 133# define ILOGD(...) ILOG(LOG_DEBUG, __VA_ARGS__) 134# define ILOGV(...) ILOG(LOG_VERBOSE, __VA_ARGS__) 135# define ILOG(_level, ...) do { \ 136 char debugStrBuf[128]; \ 137 snprintf(debugStrBuf, sizeof(debugStrBuf), __VA_ARGS__); \ 138 if (curMethod != NULL) \ 139 LOG(_level, LOG_TAG"i", "%-2d|%04x%s", \ 140 self->threadId, (int)(pc - curMethod->insns), debugStrBuf); \ 141 else \ 142 LOG(_level, LOG_TAG"i", "%-2d|####%s", \ 143 self->threadId, debugStrBuf); \ 144 } while(false) 145void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly); 146# define DUMP_REGS(_meth, _frame, _inOnly) dvmDumpRegs(_meth, _frame, _inOnly) 147static const char kSpacing[] = " "; 148#else 149# define ILOGD(...) ((void)0) 150# define ILOGV(...) ((void)0) 151# define DUMP_REGS(_meth, _frame, _inOnly) ((void)0) 152#endif 153 154/* get a long from an array of u4 */ 155static inline s8 getLongFromArray(const u4* ptr, int idx) 156{ 157#if defined(NO_UNALIGN_64__UNION) 158 union { s8 ll; u4 parts[2]; } conv; 159 160 ptr += idx; 161 conv.parts[0] = ptr[0]; 162 conv.parts[1] = ptr[1]; 163 return conv.ll; 164#else 165 s8 val; 166 memcpy(&val, &ptr[idx], 8); 167 return val; 168#endif 169} 170 171/* store a long into an array of u4 */ 172static inline void putLongToArray(u4* ptr, int idx, s8 val) 173{ 174#if defined(NO_UNALIGN_64__UNION) 175 union { s8 ll; u4 parts[2]; } conv; 176 177 ptr += idx; 178 conv.ll = val; 179 ptr[0] = conv.parts[0]; 180 ptr[1] = conv.parts[1]; 181#else 182 memcpy(&ptr[idx], &val, 8); 183#endif 184} 185 186/* get a double from an array of u4 */ 187static inline double getDoubleFromArray(const u4* ptr, int idx) 188{ 189#if defined(NO_UNALIGN_64__UNION) 190 union { double d; u4 parts[2]; } conv; 191 192 ptr += idx; 193 conv.parts[0] = ptr[0]; 194 conv.parts[1] = ptr[1]; 195 return conv.d; 196#else 197 double dval; 198 memcpy(&dval, &ptr[idx], 8); 199 return dval; 200#endif 201} 202 203/* store a double into an array of u4 */ 204static inline void putDoubleToArray(u4* ptr, int idx, double dval) 205{ 206#if defined(NO_UNALIGN_64__UNION) 207 union { double d; u4 parts[2]; } conv; 208 209 ptr += idx; 210 conv.d = dval; 211 ptr[0] = conv.parts[0]; 212 ptr[1] = conv.parts[1]; 213#else 214 memcpy(&ptr[idx], &dval, 8); 215#endif 216} 217 218/* 219 * If enabled, validate the register number on every access. Otherwise, 220 * just do an array access. 221 * 222 * Assumes the existence of "u4* fp". 223 * 224 * "_idx" may be referenced more than once. 225 */ 226#ifdef CHECK_REGISTER_INDICES 227# define GET_REGISTER(_idx) \ 228 ( (_idx) < curMethod->registersSize ? \ 229 (fp[(_idx)]) : (assert(!"bad reg"),1969) ) 230# define SET_REGISTER(_idx, _val) \ 231 ( (_idx) < curMethod->registersSize ? \ 232 (fp[(_idx)] = (u4)(_val)) : (assert(!"bad reg"),1969) ) 233# define GET_REGISTER_AS_OBJECT(_idx) ((Object *)GET_REGISTER(_idx)) 234# define SET_REGISTER_AS_OBJECT(_idx, _val) SET_REGISTER(_idx, (s4)_val) 235# define GET_REGISTER_INT(_idx) ((s4) GET_REGISTER(_idx)) 236# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val) 237# define GET_REGISTER_WIDE(_idx) \ 238 ( (_idx) < curMethod->registersSize-1 ? \ 239 getLongFromArray(fp, (_idx)) : (assert(!"bad reg"),1969) ) 240# define SET_REGISTER_WIDE(_idx, _val) \ 241 ( (_idx) < curMethod->registersSize-1 ? \ 242 (void)putLongToArray(fp, (_idx), (_val)) : assert(!"bad reg") ) 243# define GET_REGISTER_FLOAT(_idx) \ 244 ( (_idx) < curMethod->registersSize ? \ 245 (*((float*) &fp[(_idx)])) : (assert(!"bad reg"),1969.0f) ) 246# define SET_REGISTER_FLOAT(_idx, _val) \ 247 ( (_idx) < curMethod->registersSize ? \ 248 (*((float*) &fp[(_idx)]) = (_val)) : (assert(!"bad reg"),1969.0f) ) 249# define GET_REGISTER_DOUBLE(_idx) \ 250 ( (_idx) < curMethod->registersSize-1 ? \ 251 getDoubleFromArray(fp, (_idx)) : (assert(!"bad reg"),1969.0) ) 252# define SET_REGISTER_DOUBLE(_idx, _val) \ 253 ( (_idx) < curMethod->registersSize-1 ? \ 254 (void)putDoubleToArray(fp, (_idx), (_val)) : assert(!"bad reg") ) 255#else 256# define GET_REGISTER(_idx) (fp[(_idx)]) 257# define SET_REGISTER(_idx, _val) (fp[(_idx)] = (_val)) 258# define GET_REGISTER_AS_OBJECT(_idx) ((Object*) fp[(_idx)]) 259# define SET_REGISTER_AS_OBJECT(_idx, _val) (fp[(_idx)] = (u4)(_val)) 260# define GET_REGISTER_INT(_idx) ((s4)GET_REGISTER(_idx)) 261# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val) 262# define GET_REGISTER_WIDE(_idx) getLongFromArray(fp, (_idx)) 263# define SET_REGISTER_WIDE(_idx, _val) putLongToArray(fp, (_idx), (_val)) 264# define GET_REGISTER_FLOAT(_idx) (*((float*) &fp[(_idx)])) 265# define SET_REGISTER_FLOAT(_idx, _val) (*((float*) &fp[(_idx)]) = (_val)) 266# define GET_REGISTER_DOUBLE(_idx) getDoubleFromArray(fp, (_idx)) 267# define SET_REGISTER_DOUBLE(_idx, _val) putDoubleToArray(fp, (_idx), (_val)) 268#endif 269 270/* 271 * Get 16 bits from the specified offset of the program counter. We always 272 * want to load 16 bits at a time from the instruction stream -- it's more 273 * efficient than 8 and won't have the alignment problems that 32 might. 274 * 275 * Assumes existence of "const u2* pc". 276 */ 277#define FETCH(_offset) (pc[(_offset)]) 278 279/* 280 * Extract instruction byte from 16-bit fetch (_inst is a u2). 281 */ 282#define INST_INST(_inst) ((_inst) & 0xff) 283 284/* 285 * Replace the opcode (used when handling breakpoints). _opcode is a u1. 286 */ 287#define INST_REPLACE_OP(_inst, _opcode) (((_inst) & 0xff00) | _opcode) 288 289/* 290 * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2). 291 */ 292#define INST_A(_inst) (((_inst) >> 8) & 0x0f) 293#define INST_B(_inst) ((_inst) >> 12) 294 295/* 296 * Get the 8-bit "vAA" 8-bit register index from the instruction word. 297 * (_inst is u2) 298 */ 299#define INST_AA(_inst) ((_inst) >> 8) 300 301/* 302 * The current PC must be available to Throwable constructors, e.g. 303 * those created by the various exception throw routines, so that the 304 * exception stack trace can be generated correctly. If we don't do this, 305 * the offset within the current method won't be shown correctly. See the 306 * notes in Exception.c. 307 * 308 * This is also used to determine the address for precise GC. 309 * 310 * Assumes existence of "u4* fp" and "const u2* pc". 311 */ 312#define EXPORT_PC() (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc) 313 314/* 315 * Check to see if "obj" is NULL. If so, throw an exception. Assumes the 316 * pc has already been exported to the stack. 317 * 318 * Perform additional checks on debug builds. 319 * 320 * Use this to check for NULL when the instruction handler calls into 321 * something that could throw an exception (so we have already called 322 * EXPORT_PC at the top). 323 */ 324static inline bool checkForNull(Object* obj) 325{ 326 if (obj == NULL) { 327 dvmThrowNullPointerException(NULL); 328 return false; 329 } 330#ifdef WITH_EXTRA_OBJECT_VALIDATION 331 if (!dvmIsHeapAddressObject(obj)) { 332 LOGE("Invalid object %p", obj); 333 dvmAbort(); 334 } 335#endif 336#ifndef NDEBUG 337 if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) { 338 /* probable heap corruption */ 339 LOGE("Invalid object class %p (in %p)", obj->clazz, obj); 340 dvmAbort(); 341 } 342#endif 343 return true; 344} 345 346/* 347 * Check to see if "obj" is NULL. If so, export the PC into the stack 348 * frame and throw an exception. 349 * 350 * Perform additional checks on debug builds. 351 * 352 * Use this to check for NULL when the instruction handler doesn't do 353 * anything else that can throw an exception. 354 */ 355static inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc) 356{ 357 if (obj == NULL) { 358 EXPORT_PC(); 359 dvmThrowNullPointerException(NULL); 360 return false; 361 } 362#ifdef WITH_EXTRA_OBJECT_VALIDATION 363 if (!dvmIsHeapAddress(obj)) { 364 LOGE("Invalid object %p", obj); 365 dvmAbort(); 366 } 367#endif 368#ifndef NDEBUG 369 if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) { 370 /* probable heap corruption */ 371 LOGE("Invalid object class %p (in %p)", obj->clazz, obj); 372 dvmAbort(); 373 } 374#endif 375 return true; 376} 377 378/* File: portable/stubdefs.cpp */ 379/* 380 * In the C mterp stubs, "goto" is a function call followed immediately 381 * by a return. 382 */ 383 384#define GOTO_TARGET_DECL(_target, ...) 385 386#define GOTO_TARGET(_target, ...) _target: 387 388#define GOTO_TARGET_END 389 390/* ugh */ 391#define STUB_HACK(x) 392#define JIT_STUB_HACK(x) 393 394/* 395 * InterpSave's pc and fp must be valid when breaking out to a 396 * "Reportxxx" routine. Because the portable interpreter uses local 397 * variables for these, we must flush prior. Stubs, however, use 398 * the interpSave vars directly, so this is a nop for stubs. 399 */ 400#define PC_FP_TO_SELF() \ 401 self->interpSave.pc = pc; \ 402 self->interpSave.curFrame = fp; 403#define PC_TO_SELF() self->interpSave.pc = pc; 404 405/* 406 * Instruction framing. For a switch-oriented implementation this is 407 * case/break, for a threaded implementation it's a goto label and an 408 * instruction fetch/computed goto. 409 * 410 * Assumes the existence of "const u2* pc" and (for threaded operation) 411 * "u2 inst". 412 */ 413# define H(_op) &&op_##_op 414# define HANDLE_OPCODE(_op) op_##_op: 415# define FINISH(_offset) { \ 416 ADJUST_PC(_offset); \ 417 inst = FETCH(0); \ 418 if (self->interpBreak.ctl.subMode) { \ 419 dvmCheckBefore(pc, fp, self); \ 420 } \ 421 goto *handlerTable[INST_INST(inst)]; \ 422 } 423# define FINISH_BKPT(_opcode) { \ 424 goto *handlerTable[_opcode]; \ 425 } 426# define DISPATCH_EXTENDED(_opcode) { \ 427 goto *handlerTable[0x100 + _opcode]; \ 428 } 429 430#define OP_END 431 432/* 433 * The "goto" targets just turn into goto statements. The "arguments" are 434 * passed through local variables. 435 */ 436 437#define GOTO_exceptionThrown() goto exceptionThrown; 438 439#define GOTO_returnFromMethod() goto returnFromMethod; 440 441#define GOTO_invoke(_target, _methodCallRange, _jumboFormat) \ 442 do { \ 443 methodCallRange = _methodCallRange; \ 444 jumboFormat = _jumboFormat; \ 445 goto _target; \ 446 } while(false) 447 448/* for this, the "args" are already in the locals */ 449#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst) goto invokeMethod; 450 451#define GOTO_bail() goto bail; 452 453/* 454 * Periodically check for thread suspension. 455 * 456 * While we're at it, see if a debugger has attached or the profiler has 457 * started. If so, switch to a different "goto" table. 458 */ 459#define PERIODIC_CHECKS(_pcadj) { \ 460 if (dvmCheckSuspendQuick(self)) { \ 461 EXPORT_PC(); /* need for precise GC */ \ 462 dvmCheckSuspendPending(self); \ 463 } \ 464 } 465 466/* File: c/opcommon.cpp */ 467/* forward declarations of goto targets */ 468GOTO_TARGET_DECL(filledNewArray, bool methodCallRange, bool jumboFormat); 469GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange, bool jumboFormat); 470GOTO_TARGET_DECL(invokeSuper, bool methodCallRange, bool jumboFormat); 471GOTO_TARGET_DECL(invokeInterface, bool methodCallRange, bool jumboFormat); 472GOTO_TARGET_DECL(invokeDirect, bool methodCallRange, bool jumboFormat); 473GOTO_TARGET_DECL(invokeStatic, bool methodCallRange, bool jumboFormat); 474GOTO_TARGET_DECL(invokeVirtualQuick, bool methodCallRange, bool jumboFormat); 475GOTO_TARGET_DECL(invokeSuperQuick, bool methodCallRange, bool jumboFormat); 476GOTO_TARGET_DECL(invokeMethod, bool methodCallRange, const Method* methodToCall, 477 u2 count, u2 regs); 478GOTO_TARGET_DECL(returnFromMethod); 479GOTO_TARGET_DECL(exceptionThrown); 480 481/* 482 * =========================================================================== 483 * 484 * What follows are opcode definitions shared between multiple opcodes with 485 * minor substitutions handled by the C pre-processor. These should probably 486 * use the mterp substitution mechanism instead, with the code here moved 487 * into common fragment files (like the asm "binop.S"), although it's hard 488 * to give up the C preprocessor in favor of the much simpler text subst. 489 * 490 * =========================================================================== 491 */ 492 493#define HANDLE_NUMCONV(_opcode, _opname, _fromtype, _totype) \ 494 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 495 vdst = INST_A(inst); \ 496 vsrc1 = INST_B(inst); \ 497 ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \ 498 SET_REGISTER##_totype(vdst, \ 499 GET_REGISTER##_fromtype(vsrc1)); \ 500 FINISH(1); 501 502#define HANDLE_FLOAT_TO_INT(_opcode, _opname, _fromvtype, _fromrtype, \ 503 _tovtype, _tortype) \ 504 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 505 { \ 506 /* spec defines specific handling for +/- inf and NaN values */ \ 507 _fromvtype val; \ 508 _tovtype intMin, intMax, result; \ 509 vdst = INST_A(inst); \ 510 vsrc1 = INST_B(inst); \ 511 ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \ 512 val = GET_REGISTER##_fromrtype(vsrc1); \ 513 intMin = (_tovtype) 1 << (sizeof(_tovtype) * 8 -1); \ 514 intMax = ~intMin; \ 515 result = (_tovtype) val; \ 516 if (val >= intMax) /* +inf */ \ 517 result = intMax; \ 518 else if (val <= intMin) /* -inf */ \ 519 result = intMin; \ 520 else if (val != val) /* NaN */ \ 521 result = 0; \ 522 else \ 523 result = (_tovtype) val; \ 524 SET_REGISTER##_tortype(vdst, result); \ 525 } \ 526 FINISH(1); 527 528#define HANDLE_INT_TO_SMALL(_opcode, _opname, _type) \ 529 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 530 vdst = INST_A(inst); \ 531 vsrc1 = INST_B(inst); \ 532 ILOGV("|int-to-%s v%d,v%d", (_opname), vdst, vsrc1); \ 533 SET_REGISTER(vdst, (_type) GET_REGISTER(vsrc1)); \ 534 FINISH(1); 535 536/* NOTE: the comparison result is always a signed 4-byte integer */ 537#define HANDLE_OP_CMPX(_opcode, _opname, _varType, _type, _nanVal) \ 538 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 539 { \ 540 int result; \ 541 u2 regs; \ 542 _varType val1, val2; \ 543 vdst = INST_AA(inst); \ 544 regs = FETCH(1); \ 545 vsrc1 = regs & 0xff; \ 546 vsrc2 = regs >> 8; \ 547 ILOGV("|cmp%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 548 val1 = GET_REGISTER##_type(vsrc1); \ 549 val2 = GET_REGISTER##_type(vsrc2); \ 550 if (val1 == val2) \ 551 result = 0; \ 552 else if (val1 < val2) \ 553 result = -1; \ 554 else if (val1 > val2) \ 555 result = 1; \ 556 else \ 557 result = (_nanVal); \ 558 ILOGV("+ result=%d", result); \ 559 SET_REGISTER(vdst, result); \ 560 } \ 561 FINISH(2); 562 563#define HANDLE_OP_IF_XX(_opcode, _opname, _cmp) \ 564 HANDLE_OPCODE(_opcode /*vA, vB, +CCCC*/) \ 565 vsrc1 = INST_A(inst); \ 566 vsrc2 = INST_B(inst); \ 567 if ((s4) GET_REGISTER(vsrc1) _cmp (s4) GET_REGISTER(vsrc2)) { \ 568 int branchOffset = (s2)FETCH(1); /* sign-extended */ \ 569 ILOGV("|if-%s v%d,v%d,+0x%04x", (_opname), vsrc1, vsrc2, \ 570 branchOffset); \ 571 ILOGV("> branch taken"); \ 572 if (branchOffset < 0) \ 573 PERIODIC_CHECKS(branchOffset); \ 574 FINISH(branchOffset); \ 575 } else { \ 576 ILOGV("|if-%s v%d,v%d,-", (_opname), vsrc1, vsrc2); \ 577 FINISH(2); \ 578 } 579 580#define HANDLE_OP_IF_XXZ(_opcode, _opname, _cmp) \ 581 HANDLE_OPCODE(_opcode /*vAA, +BBBB*/) \ 582 vsrc1 = INST_AA(inst); \ 583 if ((s4) GET_REGISTER(vsrc1) _cmp 0) { \ 584 int branchOffset = (s2)FETCH(1); /* sign-extended */ \ 585 ILOGV("|if-%s v%d,+0x%04x", (_opname), vsrc1, branchOffset); \ 586 ILOGV("> branch taken"); \ 587 if (branchOffset < 0) \ 588 PERIODIC_CHECKS(branchOffset); \ 589 FINISH(branchOffset); \ 590 } else { \ 591 ILOGV("|if-%s v%d,-", (_opname), vsrc1); \ 592 FINISH(2); \ 593 } 594 595#define HANDLE_UNOP(_opcode, _opname, _pfx, _sfx, _type) \ 596 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 597 vdst = INST_A(inst); \ 598 vsrc1 = INST_B(inst); \ 599 ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1); \ 600 SET_REGISTER##_type(vdst, _pfx GET_REGISTER##_type(vsrc1) _sfx); \ 601 FINISH(1); 602 603#define HANDLE_OP_X_INT(_opcode, _opname, _op, _chkdiv) \ 604 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 605 { \ 606 u2 srcRegs; \ 607 vdst = INST_AA(inst); \ 608 srcRegs = FETCH(1); \ 609 vsrc1 = srcRegs & 0xff; \ 610 vsrc2 = srcRegs >> 8; \ 611 ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \ 612 if (_chkdiv != 0) { \ 613 s4 firstVal, secondVal, result; \ 614 firstVal = GET_REGISTER(vsrc1); \ 615 secondVal = GET_REGISTER(vsrc2); \ 616 if (secondVal == 0) { \ 617 EXPORT_PC(); \ 618 dvmThrowArithmeticException("divide by zero"); \ 619 GOTO_exceptionThrown(); \ 620 } \ 621 if ((u4)firstVal == 0x80000000 && secondVal == -1) { \ 622 if (_chkdiv == 1) \ 623 result = firstVal; /* division */ \ 624 else \ 625 result = 0; /* remainder */ \ 626 } else { \ 627 result = firstVal _op secondVal; \ 628 } \ 629 SET_REGISTER(vdst, result); \ 630 } else { \ 631 /* non-div/rem case */ \ 632 SET_REGISTER(vdst, \ 633 (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2)); \ 634 } \ 635 } \ 636 FINISH(2); 637 638#define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op) \ 639 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 640 { \ 641 u2 srcRegs; \ 642 vdst = INST_AA(inst); \ 643 srcRegs = FETCH(1); \ 644 vsrc1 = srcRegs & 0xff; \ 645 vsrc2 = srcRegs >> 8; \ 646 ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1); \ 647 SET_REGISTER(vdst, \ 648 _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f)); \ 649 } \ 650 FINISH(2); 651 652#define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv) \ 653 HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/) \ 654 vdst = INST_A(inst); \ 655 vsrc1 = INST_B(inst); \ 656 vsrc2 = FETCH(1); \ 657 ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x", \ 658 (_opname), vdst, vsrc1, vsrc2); \ 659 if (_chkdiv != 0) { \ 660 s4 firstVal, result; \ 661 firstVal = GET_REGISTER(vsrc1); \ 662 if ((s2) vsrc2 == 0) { \ 663 EXPORT_PC(); \ 664 dvmThrowArithmeticException("divide by zero"); \ 665 GOTO_exceptionThrown(); \ 666 } \ 667 if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) { \ 668 /* won't generate /lit16 instr for this; check anyway */ \ 669 if (_chkdiv == 1) \ 670 result = firstVal; /* division */ \ 671 else \ 672 result = 0; /* remainder */ \ 673 } else { \ 674 result = firstVal _op (s2) vsrc2; \ 675 } \ 676 SET_REGISTER(vdst, result); \ 677 } else { \ 678 /* non-div/rem case */ \ 679 SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2); \ 680 } \ 681 FINISH(2); 682 683#define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv) \ 684 HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \ 685 { \ 686 u2 litInfo; \ 687 vdst = INST_AA(inst); \ 688 litInfo = FETCH(1); \ 689 vsrc1 = litInfo & 0xff; \ 690 vsrc2 = litInfo >> 8; /* constant */ \ 691 ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \ 692 (_opname), vdst, vsrc1, vsrc2); \ 693 if (_chkdiv != 0) { \ 694 s4 firstVal, result; \ 695 firstVal = GET_REGISTER(vsrc1); \ 696 if ((s1) vsrc2 == 0) { \ 697 EXPORT_PC(); \ 698 dvmThrowArithmeticException("divide by zero"); \ 699 GOTO_exceptionThrown(); \ 700 } \ 701 if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) { \ 702 if (_chkdiv == 1) \ 703 result = firstVal; /* division */ \ 704 else \ 705 result = 0; /* remainder */ \ 706 } else { \ 707 result = firstVal _op ((s1) vsrc2); \ 708 } \ 709 SET_REGISTER(vdst, result); \ 710 } else { \ 711 SET_REGISTER(vdst, \ 712 (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2); \ 713 } \ 714 } \ 715 FINISH(2); 716 717#define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op) \ 718 HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/) \ 719 { \ 720 u2 litInfo; \ 721 vdst = INST_AA(inst); \ 722 litInfo = FETCH(1); \ 723 vsrc1 = litInfo & 0xff; \ 724 vsrc2 = litInfo >> 8; /* constant */ \ 725 ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", \ 726 (_opname), vdst, vsrc1, vsrc2); \ 727 SET_REGISTER(vdst, \ 728 _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f)); \ 729 } \ 730 FINISH(2); 731 732#define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv) \ 733 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 734 vdst = INST_A(inst); \ 735 vsrc1 = INST_B(inst); \ 736 ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 737 if (_chkdiv != 0) { \ 738 s4 firstVal, secondVal, result; \ 739 firstVal = GET_REGISTER(vdst); \ 740 secondVal = GET_REGISTER(vsrc1); \ 741 if (secondVal == 0) { \ 742 EXPORT_PC(); \ 743 dvmThrowArithmeticException("divide by zero"); \ 744 GOTO_exceptionThrown(); \ 745 } \ 746 if ((u4)firstVal == 0x80000000 && secondVal == -1) { \ 747 if (_chkdiv == 1) \ 748 result = firstVal; /* division */ \ 749 else \ 750 result = 0; /* remainder */ \ 751 } else { \ 752 result = firstVal _op secondVal; \ 753 } \ 754 SET_REGISTER(vdst, result); \ 755 } else { \ 756 SET_REGISTER(vdst, \ 757 (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1)); \ 758 } \ 759 FINISH(1); 760 761#define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op) \ 762 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 763 vdst = INST_A(inst); \ 764 vsrc1 = INST_B(inst); \ 765 ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 766 SET_REGISTER(vdst, \ 767 _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f)); \ 768 FINISH(1); 769 770#define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv) \ 771 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 772 { \ 773 u2 srcRegs; \ 774 vdst = INST_AA(inst); \ 775 srcRegs = FETCH(1); \ 776 vsrc1 = srcRegs & 0xff; \ 777 vsrc2 = srcRegs >> 8; \ 778 ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 779 if (_chkdiv != 0) { \ 780 s8 firstVal, secondVal, result; \ 781 firstVal = GET_REGISTER_WIDE(vsrc1); \ 782 secondVal = GET_REGISTER_WIDE(vsrc2); \ 783 if (secondVal == 0LL) { \ 784 EXPORT_PC(); \ 785 dvmThrowArithmeticException("divide by zero"); \ 786 GOTO_exceptionThrown(); \ 787 } \ 788 if ((u8)firstVal == 0x8000000000000000ULL && \ 789 secondVal == -1LL) \ 790 { \ 791 if (_chkdiv == 1) \ 792 result = firstVal; /* division */ \ 793 else \ 794 result = 0; /* remainder */ \ 795 } else { \ 796 result = firstVal _op secondVal; \ 797 } \ 798 SET_REGISTER_WIDE(vdst, result); \ 799 } else { \ 800 SET_REGISTER_WIDE(vdst, \ 801 (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \ 802 } \ 803 } \ 804 FINISH(2); 805 806#define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op) \ 807 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 808 { \ 809 u2 srcRegs; \ 810 vdst = INST_AA(inst); \ 811 srcRegs = FETCH(1); \ 812 vsrc1 = srcRegs & 0xff; \ 813 vsrc2 = srcRegs >> 8; \ 814 ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 815 SET_REGISTER_WIDE(vdst, \ 816 _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \ 817 } \ 818 FINISH(2); 819 820#define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv) \ 821 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 822 vdst = INST_A(inst); \ 823 vsrc1 = INST_B(inst); \ 824 ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 825 if (_chkdiv != 0) { \ 826 s8 firstVal, secondVal, result; \ 827 firstVal = GET_REGISTER_WIDE(vdst); \ 828 secondVal = GET_REGISTER_WIDE(vsrc1); \ 829 if (secondVal == 0LL) { \ 830 EXPORT_PC(); \ 831 dvmThrowArithmeticException("divide by zero"); \ 832 GOTO_exceptionThrown(); \ 833 } \ 834 if ((u8)firstVal == 0x8000000000000000ULL && \ 835 secondVal == -1LL) \ 836 { \ 837 if (_chkdiv == 1) \ 838 result = firstVal; /* division */ \ 839 else \ 840 result = 0; /* remainder */ \ 841 } else { \ 842 result = firstVal _op secondVal; \ 843 } \ 844 SET_REGISTER_WIDE(vdst, result); \ 845 } else { \ 846 SET_REGISTER_WIDE(vdst, \ 847 (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\ 848 } \ 849 FINISH(1); 850 851#define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op) \ 852 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 853 vdst = INST_A(inst); \ 854 vsrc1 = INST_B(inst); \ 855 ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 856 SET_REGISTER_WIDE(vdst, \ 857 _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \ 858 FINISH(1); 859 860#define HANDLE_OP_X_FLOAT(_opcode, _opname, _op) \ 861 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 862 { \ 863 u2 srcRegs; \ 864 vdst = INST_AA(inst); \ 865 srcRegs = FETCH(1); \ 866 vsrc1 = srcRegs & 0xff; \ 867 vsrc2 = srcRegs >> 8; \ 868 ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 869 SET_REGISTER_FLOAT(vdst, \ 870 GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2)); \ 871 } \ 872 FINISH(2); 873 874#define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op) \ 875 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 876 { \ 877 u2 srcRegs; \ 878 vdst = INST_AA(inst); \ 879 srcRegs = FETCH(1); \ 880 vsrc1 = srcRegs & 0xff; \ 881 vsrc2 = srcRegs >> 8; \ 882 ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 883 SET_REGISTER_DOUBLE(vdst, \ 884 GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2)); \ 885 } \ 886 FINISH(2); 887 888#define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op) \ 889 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 890 vdst = INST_A(inst); \ 891 vsrc1 = INST_B(inst); \ 892 ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 893 SET_REGISTER_FLOAT(vdst, \ 894 GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1)); \ 895 FINISH(1); 896 897#define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op) \ 898 HANDLE_OPCODE(_opcode /*vA, vB*/) \ 899 vdst = INST_A(inst); \ 900 vsrc1 = INST_B(inst); \ 901 ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1); \ 902 SET_REGISTER_DOUBLE(vdst, \ 903 GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1)); \ 904 FINISH(1); 905 906#define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize) \ 907 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 908 { \ 909 ArrayObject* arrayObj; \ 910 u2 arrayInfo; \ 911 EXPORT_PC(); \ 912 vdst = INST_AA(inst); \ 913 arrayInfo = FETCH(1); \ 914 vsrc1 = arrayInfo & 0xff; /* array ptr */ \ 915 vsrc2 = arrayInfo >> 8; /* index */ \ 916 ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 917 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \ 918 if (!checkForNull((Object*) arrayObj)) \ 919 GOTO_exceptionThrown(); \ 920 if (GET_REGISTER(vsrc2) >= arrayObj->length) { \ 921 dvmThrowArrayIndexOutOfBoundsException( \ 922 arrayObj->length, GET_REGISTER(vsrc2)); \ 923 GOTO_exceptionThrown(); \ 924 } \ 925 SET_REGISTER##_regsize(vdst, \ 926 ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)]); \ 927 ILOGV("+ AGET[%d]=%#x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); \ 928 } \ 929 FINISH(2); 930 931#define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize) \ 932 HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/) \ 933 { \ 934 ArrayObject* arrayObj; \ 935 u2 arrayInfo; \ 936 EXPORT_PC(); \ 937 vdst = INST_AA(inst); /* AA: source value */ \ 938 arrayInfo = FETCH(1); \ 939 vsrc1 = arrayInfo & 0xff; /* BB: array ptr */ \ 940 vsrc2 = arrayInfo >> 8; /* CC: index */ \ 941 ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2); \ 942 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); \ 943 if (!checkForNull((Object*) arrayObj)) \ 944 GOTO_exceptionThrown(); \ 945 if (GET_REGISTER(vsrc2) >= arrayObj->length) { \ 946 dvmThrowArrayIndexOutOfBoundsException( \ 947 arrayObj->length, GET_REGISTER(vsrc2)); \ 948 GOTO_exceptionThrown(); \ 949 } \ 950 ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\ 951 ((_type*)(void*)arrayObj->contents)[GET_REGISTER(vsrc2)] = \ 952 GET_REGISTER##_regsize(vdst); \ 953 } \ 954 FINISH(2); 955 956/* 957 * It's possible to get a bad value out of a field with sub-32-bit stores 958 * because the -quick versions always operate on 32 bits. Consider: 959 * short foo = -1 (sets a 32-bit register to 0xffffffff) 960 * iput-quick foo (writes all 32 bits to the field) 961 * short bar = 1 (sets a 32-bit register to 0x00000001) 962 * iput-short (writes the low 16 bits to the field) 963 * iget-quick foo (reads all 32 bits from the field, yielding 0xffff0001) 964 * This can only happen when optimized and non-optimized code has interleaved 965 * access to the same field. This is unlikely but possible. 966 * 967 * The easiest way to fix this is to always read/write 32 bits at a time. On 968 * a device with a 16-bit data bus this is sub-optimal. (The alternative 969 * approach is to have sub-int versions of iget-quick, but now we're wasting 970 * Dalvik instruction space and making it less likely that handler code will 971 * already be in the CPU i-cache.) 972 */ 973#define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize) \ 974 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \ 975 { \ 976 InstField* ifield; \ 977 Object* obj; \ 978 EXPORT_PC(); \ 979 vdst = INST_A(inst); \ 980 vsrc1 = INST_B(inst); /* object ptr */ \ 981 ref = FETCH(1); /* field ref */ \ 982 ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \ 983 obj = (Object*) GET_REGISTER(vsrc1); \ 984 if (!checkForNull(obj)) \ 985 GOTO_exceptionThrown(); \ 986 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \ 987 if (ifield == NULL) { \ 988 ifield = dvmResolveInstField(curMethod->clazz, ref); \ 989 if (ifield == NULL) \ 990 GOTO_exceptionThrown(); \ 991 } \ 992 SET_REGISTER##_regsize(vdst, \ 993 dvmGetField##_ftype(obj, ifield->byteOffset)); \ 994 ILOGV("+ IGET '%s'=0x%08llx", ifield->name, \ 995 (u8) GET_REGISTER##_regsize(vdst)); \ 996 } \ 997 FINISH(2); 998 999#define HANDLE_IGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \ 1000 HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \ 1001 { \ 1002 InstField* ifield; \ 1003 Object* obj; \ 1004 EXPORT_PC(); \ 1005 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \ 1006 vdst = FETCH(3); \ 1007 vsrc1 = FETCH(4); /* object ptr */ \ 1008 ILOGV("|iget%s/jumbo v%d,v%d,field@0x%08x", \ 1009 (_opname), vdst, vsrc1, ref); \ 1010 obj = (Object*) GET_REGISTER(vsrc1); \ 1011 if (!checkForNull(obj)) \ 1012 GOTO_exceptionThrown(); \ 1013 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \ 1014 if (ifield == NULL) { \ 1015 ifield = dvmResolveInstField(curMethod->clazz, ref); \ 1016 if (ifield == NULL) \ 1017 GOTO_exceptionThrown(); \ 1018 } \ 1019 SET_REGISTER##_regsize(vdst, \ 1020 dvmGetField##_ftype(obj, ifield->byteOffset)); \ 1021 ILOGV("+ IGET '%s'=0x%08llx", ifield->name, \ 1022 (u8) GET_REGISTER##_regsize(vdst)); \ 1023 } \ 1024 FINISH(5); 1025 1026#define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize) \ 1027 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \ 1028 { \ 1029 Object* obj; \ 1030 vdst = INST_A(inst); \ 1031 vsrc1 = INST_B(inst); /* object ptr */ \ 1032 ref = FETCH(1); /* field offset */ \ 1033 ILOGV("|iget%s-quick v%d,v%d,field@+%u", \ 1034 (_opname), vdst, vsrc1, ref); \ 1035 obj = (Object*) GET_REGISTER(vsrc1); \ 1036 if (!checkForNullExportPC(obj, fp, pc)) \ 1037 GOTO_exceptionThrown(); \ 1038 SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref)); \ 1039 ILOGV("+ IGETQ %d=0x%08llx", ref, \ 1040 (u8) GET_REGISTER##_regsize(vdst)); \ 1041 } \ 1042 FINISH(2); 1043 1044#define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize) \ 1045 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \ 1046 { \ 1047 InstField* ifield; \ 1048 Object* obj; \ 1049 EXPORT_PC(); \ 1050 vdst = INST_A(inst); \ 1051 vsrc1 = INST_B(inst); /* object ptr */ \ 1052 ref = FETCH(1); /* field ref */ \ 1053 ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \ 1054 obj = (Object*) GET_REGISTER(vsrc1); \ 1055 if (!checkForNull(obj)) \ 1056 GOTO_exceptionThrown(); \ 1057 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \ 1058 if (ifield == NULL) { \ 1059 ifield = dvmResolveInstField(curMethod->clazz, ref); \ 1060 if (ifield == NULL) \ 1061 GOTO_exceptionThrown(); \ 1062 } \ 1063 dvmSetField##_ftype(obj, ifield->byteOffset, \ 1064 GET_REGISTER##_regsize(vdst)); \ 1065 ILOGV("+ IPUT '%s'=0x%08llx", ifield->name, \ 1066 (u8) GET_REGISTER##_regsize(vdst)); \ 1067 } \ 1068 FINISH(2); 1069 1070#define HANDLE_IPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \ 1071 HANDLE_OPCODE(_opcode /*vBBBB, vCCCC, class@AAAAAAAA*/) \ 1072 { \ 1073 InstField* ifield; \ 1074 Object* obj; \ 1075 EXPORT_PC(); \ 1076 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \ 1077 vdst = FETCH(3); \ 1078 vsrc1 = FETCH(4); /* object ptr */ \ 1079 ILOGV("|iput%s/jumbo v%d,v%d,field@0x%08x", \ 1080 (_opname), vdst, vsrc1, ref); \ 1081 obj = (Object*) GET_REGISTER(vsrc1); \ 1082 if (!checkForNull(obj)) \ 1083 GOTO_exceptionThrown(); \ 1084 ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref); \ 1085 if (ifield == NULL) { \ 1086 ifield = dvmResolveInstField(curMethod->clazz, ref); \ 1087 if (ifield == NULL) \ 1088 GOTO_exceptionThrown(); \ 1089 } \ 1090 dvmSetField##_ftype(obj, ifield->byteOffset, \ 1091 GET_REGISTER##_regsize(vdst)); \ 1092 ILOGV("+ IPUT '%s'=0x%08llx", ifield->name, \ 1093 (u8) GET_REGISTER##_regsize(vdst)); \ 1094 } \ 1095 FINISH(5); 1096 1097#define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize) \ 1098 HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/) \ 1099 { \ 1100 Object* obj; \ 1101 vdst = INST_A(inst); \ 1102 vsrc1 = INST_B(inst); /* object ptr */ \ 1103 ref = FETCH(1); /* field offset */ \ 1104 ILOGV("|iput%s-quick v%d,v%d,field@0x%04x", \ 1105 (_opname), vdst, vsrc1, ref); \ 1106 obj = (Object*) GET_REGISTER(vsrc1); \ 1107 if (!checkForNullExportPC(obj, fp, pc)) \ 1108 GOTO_exceptionThrown(); \ 1109 dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst)); \ 1110 ILOGV("+ IPUTQ %d=0x%08llx", ref, \ 1111 (u8) GET_REGISTER##_regsize(vdst)); \ 1112 } \ 1113 FINISH(2); 1114 1115/* 1116 * The JIT needs dvmDexGetResolvedField() to return non-null. 1117 * Because the portable interpreter is not involved with the JIT 1118 * and trace building, we only need the extra check here when this 1119 * code is massaged into a stub called from an assembly interpreter. 1120 * This is controlled by the JIT_STUB_HACK maco. 1121 */ 1122 1123#define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize) \ 1124 HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \ 1125 { \ 1126 StaticField* sfield; \ 1127 vdst = INST_AA(inst); \ 1128 ref = FETCH(1); /* field ref */ \ 1129 ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref); \ 1130 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \ 1131 if (sfield == NULL) { \ 1132 EXPORT_PC(); \ 1133 sfield = dvmResolveStaticField(curMethod->clazz, ref); \ 1134 if (sfield == NULL) \ 1135 GOTO_exceptionThrown(); \ 1136 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \ 1137 JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \ 1138 } \ 1139 } \ 1140 SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \ 1141 ILOGV("+ SGET '%s'=0x%08llx", \ 1142 sfield->name, (u8)GET_REGISTER##_regsize(vdst)); \ 1143 } \ 1144 FINISH(2); 1145 1146#define HANDLE_SGET_X_JUMBO(_opcode, _opname, _ftype, _regsize) \ 1147 HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \ 1148 { \ 1149 StaticField* sfield; \ 1150 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \ 1151 vdst = FETCH(3); \ 1152 ILOGV("|sget%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \ 1153 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \ 1154 if (sfield == NULL) { \ 1155 EXPORT_PC(); \ 1156 sfield = dvmResolveStaticField(curMethod->clazz, ref); \ 1157 if (sfield == NULL) \ 1158 GOTO_exceptionThrown(); \ 1159 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \ 1160 JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \ 1161 } \ 1162 } \ 1163 SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield)); \ 1164 ILOGV("+ SGET '%s'=0x%08llx", \ 1165 sfield->name, (u8)GET_REGISTER##_regsize(vdst)); \ 1166 } \ 1167 FINISH(4); 1168 1169#define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize) \ 1170 HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/) \ 1171 { \ 1172 StaticField* sfield; \ 1173 vdst = INST_AA(inst); \ 1174 ref = FETCH(1); /* field ref */ \ 1175 ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref); \ 1176 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \ 1177 if (sfield == NULL) { \ 1178 EXPORT_PC(); \ 1179 sfield = dvmResolveStaticField(curMethod->clazz, ref); \ 1180 if (sfield == NULL) \ 1181 GOTO_exceptionThrown(); \ 1182 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \ 1183 JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \ 1184 } \ 1185 } \ 1186 dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \ 1187 ILOGV("+ SPUT '%s'=0x%08llx", \ 1188 sfield->name, (u8)GET_REGISTER##_regsize(vdst)); \ 1189 } \ 1190 FINISH(2); 1191 1192#define HANDLE_SPUT_X_JUMBO(_opcode, _opname, _ftype, _regsize) \ 1193 HANDLE_OPCODE(_opcode /*vBBBB, class@AAAAAAAA*/) \ 1194 { \ 1195 StaticField* sfield; \ 1196 ref = FETCH(1) | (u4)FETCH(2) << 16; /* field ref */ \ 1197 vdst = FETCH(3); \ 1198 ILOGV("|sput%s/jumbo v%d,sfield@0x%08x", (_opname), vdst, ref); \ 1199 sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \ 1200 if (sfield == NULL) { \ 1201 EXPORT_PC(); \ 1202 sfield = dvmResolveStaticField(curMethod->clazz, ref); \ 1203 if (sfield == NULL) \ 1204 GOTO_exceptionThrown(); \ 1205 if (dvmDexGetResolvedField(methodClassDex, ref) == NULL) { \ 1206 JIT_STUB_HACK(dvmJitEndTraceSelect(self,pc)); \ 1207 } \ 1208 } \ 1209 dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst)); \ 1210 ILOGV("+ SPUT '%s'=0x%08llx", \ 1211 sfield->name, (u8)GET_REGISTER##_regsize(vdst)); \ 1212 } \ 1213 FINISH(4); 1214 1215/* File: portable/entry.cpp */ 1216/* 1217 * Main interpreter loop. 1218 * 1219 * This was written with an ARM implementation in mind. 1220 */ 1221void dvmInterpretPortable(Thread* self) 1222{ 1223#if defined(EASY_GDB) 1224 StackSaveArea* debugSaveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame); 1225#endif 1226 DvmDex* methodClassDex; // curMethod->clazz->pDvmDex 1227 JValue retval; 1228 1229 /* core state */ 1230 const Method* curMethod; // method we're interpreting 1231 const u2* pc; // program counter 1232 u4* fp; // frame pointer 1233 u2 inst; // current instruction 1234 /* instruction decoding */ 1235 u4 ref; // 16 or 32-bit quantity fetched directly 1236 u2 vsrc1, vsrc2, vdst; // usually used for register indexes 1237 /* method call setup */ 1238 const Method* methodToCall; 1239 bool methodCallRange; 1240 bool jumboFormat; 1241 1242 1243 /* static computed goto table */ 1244 DEFINE_GOTO_TABLE(handlerTable); 1245 1246 /* copy state in */ 1247 curMethod = self->interpSave.method; 1248 pc = self->interpSave.pc; 1249 fp = self->interpSave.curFrame; 1250 retval = self->interpSave.retval; /* only need for kInterpEntryReturn? */ 1251 1252 methodClassDex = curMethod->clazz->pDvmDex; 1253 1254 LOGVV("threadid=%d: %s.%s pc=%#x fp=%p", 1255 self->threadId, curMethod->clazz->descriptor, curMethod->name, 1256 pc - curMethod->insns, fp); 1257 1258 /* 1259 * Handle any ongoing profiling and prep for debugging. 1260 */ 1261 if (self->interpBreak.ctl.subMode != 0) { 1262 TRACE_METHOD_ENTER(self, curMethod); 1263 self->debugIsMethodEntry = true; // Always true on startup 1264 } 1265 /* 1266 * DEBUG: scramble this to ensure we're not relying on it. 1267 */ 1268 methodToCall = (const Method*) -1; 1269 1270#if 0 1271 if (self->debugIsMethodEntry) { 1272 ILOGD("|-- Now interpreting %s.%s", curMethod->clazz->descriptor, 1273 curMethod->name); 1274 DUMP_REGS(curMethod, self->interpSave.curFrame, false); 1275 } 1276#endif 1277 1278 FINISH(0); /* fetch and execute first instruction */ 1279 1280/*--- start of opcodes ---*/ 1281 1282/* File: c/OP_NOP.cpp */ 1283HANDLE_OPCODE(OP_NOP) 1284 FINISH(1); 1285OP_END 1286 1287/* File: c/OP_MOVE.cpp */ 1288HANDLE_OPCODE(OP_MOVE /*vA, vB*/) 1289 vdst = INST_A(inst); 1290 vsrc1 = INST_B(inst); 1291 ILOGV("|move%s v%d,v%d %s(v%d=0x%08x)", 1292 (INST_INST(inst) == OP_MOVE) ? "" : "-object", vdst, vsrc1, 1293 kSpacing, vdst, GET_REGISTER(vsrc1)); 1294 SET_REGISTER(vdst, GET_REGISTER(vsrc1)); 1295 FINISH(1); 1296OP_END 1297 1298/* File: c/OP_MOVE_FROM16.cpp */ 1299HANDLE_OPCODE(OP_MOVE_FROM16 /*vAA, vBBBB*/) 1300 vdst = INST_AA(inst); 1301 vsrc1 = FETCH(1); 1302 ILOGV("|move%s/from16 v%d,v%d %s(v%d=0x%08x)", 1303 (INST_INST(inst) == OP_MOVE_FROM16) ? "" : "-object", vdst, vsrc1, 1304 kSpacing, vdst, GET_REGISTER(vsrc1)); 1305 SET_REGISTER(vdst, GET_REGISTER(vsrc1)); 1306 FINISH(2); 1307OP_END 1308 1309/* File: c/OP_MOVE_16.cpp */ 1310HANDLE_OPCODE(OP_MOVE_16 /*vAAAA, vBBBB*/) 1311 vdst = FETCH(1); 1312 vsrc1 = FETCH(2); 1313 ILOGV("|move%s/16 v%d,v%d %s(v%d=0x%08x)", 1314 (INST_INST(inst) == OP_MOVE_16) ? "" : "-object", vdst, vsrc1, 1315 kSpacing, vdst, GET_REGISTER(vsrc1)); 1316 SET_REGISTER(vdst, GET_REGISTER(vsrc1)); 1317 FINISH(3); 1318OP_END 1319 1320/* File: c/OP_MOVE_WIDE.cpp */ 1321HANDLE_OPCODE(OP_MOVE_WIDE /*vA, vB*/) 1322 /* IMPORTANT: must correctly handle overlapping registers, e.g. both 1323 * "move-wide v6, v7" and "move-wide v7, v6" */ 1324 vdst = INST_A(inst); 1325 vsrc1 = INST_B(inst); 1326 ILOGV("|move-wide v%d,v%d %s(v%d=0x%08llx)", vdst, vsrc1, 1327 kSpacing+5, vdst, GET_REGISTER_WIDE(vsrc1)); 1328 SET_REGISTER_WIDE(vdst, GET_REGISTER_WIDE(vsrc1)); 1329 FINISH(1); 1330OP_END 1331 1332/* File: c/OP_MOVE_WIDE_FROM16.cpp */ 1333HANDLE_OPCODE(OP_MOVE_WIDE_FROM16 /*vAA, vBBBB*/) 1334 vdst = INST_AA(inst); 1335 vsrc1 = FETCH(1); 1336 ILOGV("|move-wide/from16 v%d,v%d (v%d=0x%08llx)", vdst, vsrc1, 1337 vdst, GET_REGISTER_WIDE(vsrc1)); 1338 SET_REGISTER_WIDE(vdst, GET_REGISTER_WIDE(vsrc1)); 1339 FINISH(2); 1340OP_END 1341 1342/* File: c/OP_MOVE_WIDE_16.cpp */ 1343HANDLE_OPCODE(OP_MOVE_WIDE_16 /*vAAAA, vBBBB*/) 1344 vdst = FETCH(1); 1345 vsrc1 = FETCH(2); 1346 ILOGV("|move-wide/16 v%d,v%d %s(v%d=0x%08llx)", vdst, vsrc1, 1347 kSpacing+8, vdst, GET_REGISTER_WIDE(vsrc1)); 1348 SET_REGISTER_WIDE(vdst, GET_REGISTER_WIDE(vsrc1)); 1349 FINISH(3); 1350OP_END 1351 1352/* File: c/OP_MOVE_OBJECT.cpp */ 1353/* File: c/OP_MOVE.cpp */ 1354HANDLE_OPCODE(OP_MOVE_OBJECT /*vA, vB*/) 1355 vdst = INST_A(inst); 1356 vsrc1 = INST_B(inst); 1357 ILOGV("|move%s v%d,v%d %s(v%d=0x%08x)", 1358 (INST_INST(inst) == OP_MOVE) ? "" : "-object", vdst, vsrc1, 1359 kSpacing, vdst, GET_REGISTER(vsrc1)); 1360 SET_REGISTER(vdst, GET_REGISTER(vsrc1)); 1361 FINISH(1); 1362OP_END 1363 1364 1365/* File: c/OP_MOVE_OBJECT_FROM16.cpp */ 1366/* File: c/OP_MOVE_FROM16.cpp */ 1367HANDLE_OPCODE(OP_MOVE_OBJECT_FROM16 /*vAA, vBBBB*/) 1368 vdst = INST_AA(inst); 1369 vsrc1 = FETCH(1); 1370 ILOGV("|move%s/from16 v%d,v%d %s(v%d=0x%08x)", 1371 (INST_INST(inst) == OP_MOVE_FROM16) ? "" : "-object", vdst, vsrc1, 1372 kSpacing, vdst, GET_REGISTER(vsrc1)); 1373 SET_REGISTER(vdst, GET_REGISTER(vsrc1)); 1374 FINISH(2); 1375OP_END 1376 1377 1378/* File: c/OP_MOVE_OBJECT_16.cpp */ 1379/* File: c/OP_MOVE_16.cpp */ 1380HANDLE_OPCODE(OP_MOVE_OBJECT_16 /*vAAAA, vBBBB*/) 1381 vdst = FETCH(1); 1382 vsrc1 = FETCH(2); 1383 ILOGV("|move%s/16 v%d,v%d %s(v%d=0x%08x)", 1384 (INST_INST(inst) == OP_MOVE_16) ? "" : "-object", vdst, vsrc1, 1385 kSpacing, vdst, GET_REGISTER(vsrc1)); 1386 SET_REGISTER(vdst, GET_REGISTER(vsrc1)); 1387 FINISH(3); 1388OP_END 1389 1390 1391/* File: c/OP_MOVE_RESULT.cpp */ 1392HANDLE_OPCODE(OP_MOVE_RESULT /*vAA*/) 1393 vdst = INST_AA(inst); 1394 ILOGV("|move-result%s v%d %s(v%d=0x%08x)", 1395 (INST_INST(inst) == OP_MOVE_RESULT) ? "" : "-object", 1396 vdst, kSpacing+4, vdst,retval.i); 1397 SET_REGISTER(vdst, retval.i); 1398 FINISH(1); 1399OP_END 1400 1401/* File: c/OP_MOVE_RESULT_WIDE.cpp */ 1402HANDLE_OPCODE(OP_MOVE_RESULT_WIDE /*vAA*/) 1403 vdst = INST_AA(inst); 1404 ILOGV("|move-result-wide v%d %s(0x%08llx)", vdst, kSpacing, retval.j); 1405 SET_REGISTER_WIDE(vdst, retval.j); 1406 FINISH(1); 1407OP_END 1408 1409/* File: c/OP_MOVE_RESULT_OBJECT.cpp */ 1410/* File: c/OP_MOVE_RESULT.cpp */ 1411HANDLE_OPCODE(OP_MOVE_RESULT_OBJECT /*vAA*/) 1412 vdst = INST_AA(inst); 1413 ILOGV("|move-result%s v%d %s(v%d=0x%08x)", 1414 (INST_INST(inst) == OP_MOVE_RESULT) ? "" : "-object", 1415 vdst, kSpacing+4, vdst,retval.i); 1416 SET_REGISTER(vdst, retval.i); 1417 FINISH(1); 1418OP_END 1419 1420 1421/* File: c/OP_MOVE_EXCEPTION.cpp */ 1422HANDLE_OPCODE(OP_MOVE_EXCEPTION /*vAA*/) 1423 vdst = INST_AA(inst); 1424 ILOGV("|move-exception v%d", vdst); 1425 assert(self->exception != NULL); 1426 SET_REGISTER(vdst, (u4)self->exception); 1427 dvmClearException(self); 1428 FINISH(1); 1429OP_END 1430 1431/* File: c/OP_RETURN_VOID.cpp */ 1432HANDLE_OPCODE(OP_RETURN_VOID /**/) 1433 ILOGV("|return-void"); 1434#ifndef NDEBUG 1435 retval.j = 0xababababULL; // placate valgrind 1436#endif 1437 GOTO_returnFromMethod(); 1438OP_END 1439 1440/* File: c/OP_RETURN.cpp */ 1441HANDLE_OPCODE(OP_RETURN /*vAA*/) 1442 vsrc1 = INST_AA(inst); 1443 ILOGV("|return%s v%d", 1444 (INST_INST(inst) == OP_RETURN) ? "" : "-object", vsrc1); 1445 retval.i = GET_REGISTER(vsrc1); 1446 GOTO_returnFromMethod(); 1447OP_END 1448 1449/* File: c/OP_RETURN_WIDE.cpp */ 1450HANDLE_OPCODE(OP_RETURN_WIDE /*vAA*/) 1451 vsrc1 = INST_AA(inst); 1452 ILOGV("|return-wide v%d", vsrc1); 1453 retval.j = GET_REGISTER_WIDE(vsrc1); 1454 GOTO_returnFromMethod(); 1455OP_END 1456 1457/* File: c/OP_RETURN_OBJECT.cpp */ 1458/* File: c/OP_RETURN.cpp */ 1459HANDLE_OPCODE(OP_RETURN_OBJECT /*vAA*/) 1460 vsrc1 = INST_AA(inst); 1461 ILOGV("|return%s v%d", 1462 (INST_INST(inst) == OP_RETURN) ? "" : "-object", vsrc1); 1463 retval.i = GET_REGISTER(vsrc1); 1464 GOTO_returnFromMethod(); 1465OP_END 1466 1467 1468/* File: c/OP_CONST_4.cpp */ 1469HANDLE_OPCODE(OP_CONST_4 /*vA, #+B*/) 1470 { 1471 s4 tmp; 1472 1473 vdst = INST_A(inst); 1474 tmp = (s4) (INST_B(inst) << 28) >> 28; // sign extend 4-bit value 1475 ILOGV("|const/4 v%d,#0x%02x", vdst, (s4)tmp); 1476 SET_REGISTER(vdst, tmp); 1477 } 1478 FINISH(1); 1479OP_END 1480 1481/* File: c/OP_CONST_16.cpp */ 1482HANDLE_OPCODE(OP_CONST_16 /*vAA, #+BBBB*/) 1483 vdst = INST_AA(inst); 1484 vsrc1 = FETCH(1); 1485 ILOGV("|const/16 v%d,#0x%04x", vdst, (s2)vsrc1); 1486 SET_REGISTER(vdst, (s2) vsrc1); 1487 FINISH(2); 1488OP_END 1489 1490/* File: c/OP_CONST.cpp */ 1491HANDLE_OPCODE(OP_CONST /*vAA, #+BBBBBBBB*/) 1492 { 1493 u4 tmp; 1494 1495 vdst = INST_AA(inst); 1496 tmp = FETCH(1); 1497 tmp |= (u4)FETCH(2) << 16; 1498 ILOGV("|const v%d,#0x%08x", vdst, tmp); 1499 SET_REGISTER(vdst, tmp); 1500 } 1501 FINISH(3); 1502OP_END 1503 1504/* File: c/OP_CONST_HIGH16.cpp */ 1505HANDLE_OPCODE(OP_CONST_HIGH16 /*vAA, #+BBBB0000*/) 1506 vdst = INST_AA(inst); 1507 vsrc1 = FETCH(1); 1508 ILOGV("|const/high16 v%d,#0x%04x0000", vdst, vsrc1); 1509 SET_REGISTER(vdst, vsrc1 << 16); 1510 FINISH(2); 1511OP_END 1512 1513/* File: c/OP_CONST_WIDE_16.cpp */ 1514HANDLE_OPCODE(OP_CONST_WIDE_16 /*vAA, #+BBBB*/) 1515 vdst = INST_AA(inst); 1516 vsrc1 = FETCH(1); 1517 ILOGV("|const-wide/16 v%d,#0x%04x", vdst, (s2)vsrc1); 1518 SET_REGISTER_WIDE(vdst, (s2)vsrc1); 1519 FINISH(2); 1520OP_END 1521 1522/* File: c/OP_CONST_WIDE_32.cpp */ 1523HANDLE_OPCODE(OP_CONST_WIDE_32 /*vAA, #+BBBBBBBB*/) 1524 { 1525 u4 tmp; 1526 1527 vdst = INST_AA(inst); 1528 tmp = FETCH(1); 1529 tmp |= (u4)FETCH(2) << 16; 1530 ILOGV("|const-wide/32 v%d,#0x%08x", vdst, tmp); 1531 SET_REGISTER_WIDE(vdst, (s4) tmp); 1532 } 1533 FINISH(3); 1534OP_END 1535 1536/* File: c/OP_CONST_WIDE.cpp */ 1537HANDLE_OPCODE(OP_CONST_WIDE /*vAA, #+BBBBBBBBBBBBBBBB*/) 1538 { 1539 u8 tmp; 1540 1541 vdst = INST_AA(inst); 1542 tmp = FETCH(1); 1543 tmp |= (u8)FETCH(2) << 16; 1544 tmp |= (u8)FETCH(3) << 32; 1545 tmp |= (u8)FETCH(4) << 48; 1546 ILOGV("|const-wide v%d,#0x%08llx", vdst, tmp); 1547 SET_REGISTER_WIDE(vdst, tmp); 1548 } 1549 FINISH(5); 1550OP_END 1551 1552/* File: c/OP_CONST_WIDE_HIGH16.cpp */ 1553HANDLE_OPCODE(OP_CONST_WIDE_HIGH16 /*vAA, #+BBBB000000000000*/) 1554 vdst = INST_AA(inst); 1555 vsrc1 = FETCH(1); 1556 ILOGV("|const-wide/high16 v%d,#0x%04x000000000000", vdst, vsrc1); 1557 SET_REGISTER_WIDE(vdst, ((u8) vsrc1) << 48); 1558 FINISH(2); 1559OP_END 1560 1561/* File: c/OP_CONST_STRING.cpp */ 1562HANDLE_OPCODE(OP_CONST_STRING /*vAA, string@BBBB*/) 1563 { 1564 StringObject* strObj; 1565 1566 vdst = INST_AA(inst); 1567 ref = FETCH(1); 1568 ILOGV("|const-string v%d string@0x%04x", vdst, ref); 1569 strObj = dvmDexGetResolvedString(methodClassDex, ref); 1570 if (strObj == NULL) { 1571 EXPORT_PC(); 1572 strObj = dvmResolveString(curMethod->clazz, ref); 1573 if (strObj == NULL) 1574 GOTO_exceptionThrown(); 1575 } 1576 SET_REGISTER(vdst, (u4) strObj); 1577 } 1578 FINISH(2); 1579OP_END 1580 1581/* File: c/OP_CONST_STRING_JUMBO.cpp */ 1582HANDLE_OPCODE(OP_CONST_STRING_JUMBO /*vAA, string@BBBBBBBB*/) 1583 { 1584 StringObject* strObj; 1585 u4 tmp; 1586 1587 vdst = INST_AA(inst); 1588 tmp = FETCH(1); 1589 tmp |= (u4)FETCH(2) << 16; 1590 ILOGV("|const-string/jumbo v%d string@0x%08x", vdst, tmp); 1591 strObj = dvmDexGetResolvedString(methodClassDex, tmp); 1592 if (strObj == NULL) { 1593 EXPORT_PC(); 1594 strObj = dvmResolveString(curMethod->clazz, tmp); 1595 if (strObj == NULL) 1596 GOTO_exceptionThrown(); 1597 } 1598 SET_REGISTER(vdst, (u4) strObj); 1599 } 1600 FINISH(3); 1601OP_END 1602 1603/* File: c/OP_CONST_CLASS.cpp */ 1604HANDLE_OPCODE(OP_CONST_CLASS /*vAA, class@BBBB*/) 1605 { 1606 ClassObject* clazz; 1607 1608 vdst = INST_AA(inst); 1609 ref = FETCH(1); 1610 ILOGV("|const-class v%d class@0x%04x", vdst, ref); 1611 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 1612 if (clazz == NULL) { 1613 EXPORT_PC(); 1614 clazz = dvmResolveClass(curMethod->clazz, ref, true); 1615 if (clazz == NULL) 1616 GOTO_exceptionThrown(); 1617 } 1618 SET_REGISTER(vdst, (u4) clazz); 1619 } 1620 FINISH(2); 1621OP_END 1622 1623/* File: c/OP_MONITOR_ENTER.cpp */ 1624HANDLE_OPCODE(OP_MONITOR_ENTER /*vAA*/) 1625 { 1626 Object* obj; 1627 1628 vsrc1 = INST_AA(inst); 1629 ILOGV("|monitor-enter v%d %s(0x%08x)", 1630 vsrc1, kSpacing+6, GET_REGISTER(vsrc1)); 1631 obj = (Object*)GET_REGISTER(vsrc1); 1632 if (!checkForNullExportPC(obj, fp, pc)) 1633 GOTO_exceptionThrown(); 1634 ILOGV("+ locking %p %s", obj, obj->clazz->descriptor); 1635 EXPORT_PC(); /* need for precise GC */ 1636 dvmLockObject(self, obj); 1637 } 1638 FINISH(1); 1639OP_END 1640 1641/* File: c/OP_MONITOR_EXIT.cpp */ 1642HANDLE_OPCODE(OP_MONITOR_EXIT /*vAA*/) 1643 { 1644 Object* obj; 1645 1646 EXPORT_PC(); 1647 1648 vsrc1 = INST_AA(inst); 1649 ILOGV("|monitor-exit v%d %s(0x%08x)", 1650 vsrc1, kSpacing+5, GET_REGISTER(vsrc1)); 1651 obj = (Object*)GET_REGISTER(vsrc1); 1652 if (!checkForNull(obj)) { 1653 /* 1654 * The exception needs to be processed at the *following* 1655 * instruction, not the current instruction (see the Dalvik 1656 * spec). Because we're jumping to an exception handler, 1657 * we're not actually at risk of skipping an instruction 1658 * by doing so. 1659 */ 1660 ADJUST_PC(1); /* monitor-exit width is 1 */ 1661 GOTO_exceptionThrown(); 1662 } 1663 ILOGV("+ unlocking %p %s", obj, obj->clazz->descriptor); 1664 if (!dvmUnlockObject(self, obj)) { 1665 assert(dvmCheckException(self)); 1666 ADJUST_PC(1); 1667 GOTO_exceptionThrown(); 1668 } 1669 } 1670 FINISH(1); 1671OP_END 1672 1673/* File: c/OP_CHECK_CAST.cpp */ 1674HANDLE_OPCODE(OP_CHECK_CAST /*vAA, class@BBBB*/) 1675 { 1676 ClassObject* clazz; 1677 Object* obj; 1678 1679 EXPORT_PC(); 1680 1681 vsrc1 = INST_AA(inst); 1682 ref = FETCH(1); /* class to check against */ 1683 ILOGV("|check-cast v%d,class@0x%04x", vsrc1, ref); 1684 1685 obj = (Object*)GET_REGISTER(vsrc1); 1686 if (obj != NULL) { 1687#if defined(WITH_EXTRA_OBJECT_VALIDATION) 1688 if (!checkForNull(obj)) 1689 GOTO_exceptionThrown(); 1690#endif 1691 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 1692 if (clazz == NULL) { 1693 clazz = dvmResolveClass(curMethod->clazz, ref, false); 1694 if (clazz == NULL) 1695 GOTO_exceptionThrown(); 1696 } 1697 if (!dvmInstanceof(obj->clazz, clazz)) { 1698 dvmThrowClassCastException(obj->clazz, clazz); 1699 GOTO_exceptionThrown(); 1700 } 1701 } 1702 } 1703 FINISH(2); 1704OP_END 1705 1706/* File: c/OP_INSTANCE_OF.cpp */ 1707HANDLE_OPCODE(OP_INSTANCE_OF /*vA, vB, class@CCCC*/) 1708 { 1709 ClassObject* clazz; 1710 Object* obj; 1711 1712 vdst = INST_A(inst); 1713 vsrc1 = INST_B(inst); /* object to check */ 1714 ref = FETCH(1); /* class to check against */ 1715 ILOGV("|instance-of v%d,v%d,class@0x%04x", vdst, vsrc1, ref); 1716 1717 obj = (Object*)GET_REGISTER(vsrc1); 1718 if (obj == NULL) { 1719 SET_REGISTER(vdst, 0); 1720 } else { 1721#if defined(WITH_EXTRA_OBJECT_VALIDATION) 1722 if (!checkForNullExportPC(obj, fp, pc)) 1723 GOTO_exceptionThrown(); 1724#endif 1725 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 1726 if (clazz == NULL) { 1727 EXPORT_PC(); 1728 clazz = dvmResolveClass(curMethod->clazz, ref, true); 1729 if (clazz == NULL) 1730 GOTO_exceptionThrown(); 1731 } 1732 SET_REGISTER(vdst, dvmInstanceof(obj->clazz, clazz)); 1733 } 1734 } 1735 FINISH(2); 1736OP_END 1737 1738/* File: c/OP_ARRAY_LENGTH.cpp */ 1739HANDLE_OPCODE(OP_ARRAY_LENGTH /*vA, vB*/) 1740 { 1741 ArrayObject* arrayObj; 1742 1743 vdst = INST_A(inst); 1744 vsrc1 = INST_B(inst); 1745 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); 1746 ILOGV("|array-length v%d,v%d (%p)", vdst, vsrc1, arrayObj); 1747 if (!checkForNullExportPC((Object*) arrayObj, fp, pc)) 1748 GOTO_exceptionThrown(); 1749 /* verifier guarantees this is an array reference */ 1750 SET_REGISTER(vdst, arrayObj->length); 1751 } 1752 FINISH(1); 1753OP_END 1754 1755/* File: c/OP_NEW_INSTANCE.cpp */ 1756HANDLE_OPCODE(OP_NEW_INSTANCE /*vAA, class@BBBB*/) 1757 { 1758 ClassObject* clazz; 1759 Object* newObj; 1760 1761 EXPORT_PC(); 1762 1763 vdst = INST_AA(inst); 1764 ref = FETCH(1); 1765 ILOGV("|new-instance v%d,class@0x%04x", vdst, ref); 1766 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 1767 if (clazz == NULL) { 1768 clazz = dvmResolveClass(curMethod->clazz, ref, false); 1769 if (clazz == NULL) 1770 GOTO_exceptionThrown(); 1771 } 1772 1773 if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) 1774 GOTO_exceptionThrown(); 1775 1776#if defined(WITH_JIT) 1777 /* 1778 * The JIT needs dvmDexGetResolvedClass() to return non-null. 1779 * Since we use the portable interpreter to build the trace, this extra 1780 * check is not needed for mterp. 1781 */ 1782 if ((self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) && 1783 (!dvmDexGetResolvedClass(methodClassDex, ref))) { 1784 /* Class initialization is still ongoing - end the trace */ 1785 dvmJitEndTraceSelect(self,pc); 1786 } 1787#endif 1788 1789 /* 1790 * Verifier now tests for interface/abstract class. 1791 */ 1792 //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) { 1793 // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError, 1794 // clazz->descriptor); 1795 // GOTO_exceptionThrown(); 1796 //} 1797 newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK); 1798 if (newObj == NULL) 1799 GOTO_exceptionThrown(); 1800 SET_REGISTER(vdst, (u4) newObj); 1801 } 1802 FINISH(2); 1803OP_END 1804 1805/* File: c/OP_NEW_ARRAY.cpp */ 1806HANDLE_OPCODE(OP_NEW_ARRAY /*vA, vB, class@CCCC*/) 1807 { 1808 ClassObject* arrayClass; 1809 ArrayObject* newArray; 1810 s4 length; 1811 1812 EXPORT_PC(); 1813 1814 vdst = INST_A(inst); 1815 vsrc1 = INST_B(inst); /* length reg */ 1816 ref = FETCH(1); 1817 ILOGV("|new-array v%d,v%d,class@0x%04x (%d elements)", 1818 vdst, vsrc1, ref, (s4) GET_REGISTER(vsrc1)); 1819 length = (s4) GET_REGISTER(vsrc1); 1820 if (length < 0) { 1821 dvmThrowNegativeArraySizeException(length); 1822 GOTO_exceptionThrown(); 1823 } 1824 arrayClass = dvmDexGetResolvedClass(methodClassDex, ref); 1825 if (arrayClass == NULL) { 1826 arrayClass = dvmResolveClass(curMethod->clazz, ref, false); 1827 if (arrayClass == NULL) 1828 GOTO_exceptionThrown(); 1829 } 1830 /* verifier guarantees this is an array class */ 1831 assert(dvmIsArrayClass(arrayClass)); 1832 assert(dvmIsClassInitialized(arrayClass)); 1833 1834 newArray = dvmAllocArrayByClass(arrayClass, length, ALLOC_DONT_TRACK); 1835 if (newArray == NULL) 1836 GOTO_exceptionThrown(); 1837 SET_REGISTER(vdst, (u4) newArray); 1838 } 1839 FINISH(2); 1840OP_END 1841 1842/* File: c/OP_FILLED_NEW_ARRAY.cpp */ 1843HANDLE_OPCODE(OP_FILLED_NEW_ARRAY /*vB, {vD, vE, vF, vG, vA}, class@CCCC*/) 1844 GOTO_invoke(filledNewArray, false, false); 1845OP_END 1846 1847/* File: c/OP_FILLED_NEW_ARRAY_RANGE.cpp */ 1848HANDLE_OPCODE(OP_FILLED_NEW_ARRAY_RANGE /*{vCCCC..v(CCCC+AA-1)}, class@BBBB*/) 1849 GOTO_invoke(filledNewArray, true, false); 1850OP_END 1851 1852/* File: c/OP_FILL_ARRAY_DATA.cpp */ 1853HANDLE_OPCODE(OP_FILL_ARRAY_DATA) /*vAA, +BBBBBBBB*/ 1854 { 1855 const u2* arrayData; 1856 s4 offset; 1857 ArrayObject* arrayObj; 1858 1859 EXPORT_PC(); 1860 vsrc1 = INST_AA(inst); 1861 offset = FETCH(1) | (((s4) FETCH(2)) << 16); 1862 ILOGV("|fill-array-data v%d +0x%04x", vsrc1, offset); 1863 arrayData = pc + offset; // offset in 16-bit units 1864#ifndef NDEBUG 1865 if (arrayData < curMethod->insns || 1866 arrayData >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) 1867 { 1868 /* should have been caught in verifier */ 1869 dvmThrowInternalError("bad fill array data"); 1870 GOTO_exceptionThrown(); 1871 } 1872#endif 1873 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); 1874 if (!dvmInterpHandleFillArrayData(arrayObj, arrayData)) { 1875 GOTO_exceptionThrown(); 1876 } 1877 FINISH(3); 1878 } 1879OP_END 1880 1881/* File: c/OP_THROW.cpp */ 1882HANDLE_OPCODE(OP_THROW /*vAA*/) 1883 { 1884 Object* obj; 1885 1886 /* 1887 * We don't create an exception here, but the process of searching 1888 * for a catch block can do class lookups and throw exceptions. 1889 * We need to update the saved PC. 1890 */ 1891 EXPORT_PC(); 1892 1893 vsrc1 = INST_AA(inst); 1894 ILOGV("|throw v%d (%p)", vsrc1, (void*)GET_REGISTER(vsrc1)); 1895 obj = (Object*) GET_REGISTER(vsrc1); 1896 if (!checkForNull(obj)) { 1897 /* will throw a null pointer exception */ 1898 LOGVV("Bad exception"); 1899 } else { 1900 /* use the requested exception */ 1901 dvmSetException(self, obj); 1902 } 1903 GOTO_exceptionThrown(); 1904 } 1905OP_END 1906 1907/* File: c/OP_GOTO.cpp */ 1908HANDLE_OPCODE(OP_GOTO /*+AA*/) 1909 vdst = INST_AA(inst); 1910 if ((s1)vdst < 0) 1911 ILOGV("|goto -0x%02x", -((s1)vdst)); 1912 else 1913 ILOGV("|goto +0x%02x", ((s1)vdst)); 1914 ILOGV("> branch taken"); 1915 if ((s1)vdst < 0) 1916 PERIODIC_CHECKS((s1)vdst); 1917 FINISH((s1)vdst); 1918OP_END 1919 1920/* File: c/OP_GOTO_16.cpp */ 1921HANDLE_OPCODE(OP_GOTO_16 /*+AAAA*/) 1922 { 1923 s4 offset = (s2) FETCH(1); /* sign-extend next code unit */ 1924 1925 if (offset < 0) 1926 ILOGV("|goto/16 -0x%04x", -offset); 1927 else 1928 ILOGV("|goto/16 +0x%04x", offset); 1929 ILOGV("> branch taken"); 1930 if (offset < 0) 1931 PERIODIC_CHECKS(offset); 1932 FINISH(offset); 1933 } 1934OP_END 1935 1936/* File: c/OP_GOTO_32.cpp */ 1937HANDLE_OPCODE(OP_GOTO_32 /*+AAAAAAAA*/) 1938 { 1939 s4 offset = FETCH(1); /* low-order 16 bits */ 1940 offset |= ((s4) FETCH(2)) << 16; /* high-order 16 bits */ 1941 1942 if (offset < 0) 1943 ILOGV("|goto/32 -0x%08x", -offset); 1944 else 1945 ILOGV("|goto/32 +0x%08x", offset); 1946 ILOGV("> branch taken"); 1947 if (offset <= 0) /* allowed to branch to self */ 1948 PERIODIC_CHECKS(offset); 1949 FINISH(offset); 1950 } 1951OP_END 1952 1953/* File: c/OP_PACKED_SWITCH.cpp */ 1954HANDLE_OPCODE(OP_PACKED_SWITCH /*vAA, +BBBB*/) 1955 { 1956 const u2* switchData; 1957 u4 testVal; 1958 s4 offset; 1959 1960 vsrc1 = INST_AA(inst); 1961 offset = FETCH(1) | (((s4) FETCH(2)) << 16); 1962 ILOGV("|packed-switch v%d +0x%04x", vsrc1, offset); 1963 switchData = pc + offset; // offset in 16-bit units 1964#ifndef NDEBUG 1965 if (switchData < curMethod->insns || 1966 switchData >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) 1967 { 1968 /* should have been caught in verifier */ 1969 EXPORT_PC(); 1970 dvmThrowInternalError("bad packed switch"); 1971 GOTO_exceptionThrown(); 1972 } 1973#endif 1974 testVal = GET_REGISTER(vsrc1); 1975 1976 offset = dvmInterpHandlePackedSwitch(switchData, testVal); 1977 ILOGV("> branch taken (0x%04x)", offset); 1978 if (offset <= 0) /* uncommon */ 1979 PERIODIC_CHECKS(offset); 1980 FINISH(offset); 1981 } 1982OP_END 1983 1984/* File: c/OP_SPARSE_SWITCH.cpp */ 1985HANDLE_OPCODE(OP_SPARSE_SWITCH /*vAA, +BBBB*/) 1986 { 1987 const u2* switchData; 1988 u4 testVal; 1989 s4 offset; 1990 1991 vsrc1 = INST_AA(inst); 1992 offset = FETCH(1) | (((s4) FETCH(2)) << 16); 1993 ILOGV("|sparse-switch v%d +0x%04x", vsrc1, offset); 1994 switchData = pc + offset; // offset in 16-bit units 1995#ifndef NDEBUG 1996 if (switchData < curMethod->insns || 1997 switchData >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) 1998 { 1999 /* should have been caught in verifier */ 2000 EXPORT_PC(); 2001 dvmThrowInternalError("bad sparse switch"); 2002 GOTO_exceptionThrown(); 2003 } 2004#endif 2005 testVal = GET_REGISTER(vsrc1); 2006 2007 offset = dvmInterpHandleSparseSwitch(switchData, testVal); 2008 ILOGV("> branch taken (0x%04x)", offset); 2009 if (offset <= 0) /* uncommon */ 2010 PERIODIC_CHECKS(offset); 2011 FINISH(offset); 2012 } 2013OP_END 2014 2015/* File: c/OP_CMPL_FLOAT.cpp */ 2016HANDLE_OP_CMPX(OP_CMPL_FLOAT, "l-float", float, _FLOAT, -1) 2017OP_END 2018 2019/* File: c/OP_CMPG_FLOAT.cpp */ 2020HANDLE_OP_CMPX(OP_CMPG_FLOAT, "g-float", float, _FLOAT, 1) 2021OP_END 2022 2023/* File: c/OP_CMPL_DOUBLE.cpp */ 2024HANDLE_OP_CMPX(OP_CMPL_DOUBLE, "l-double", double, _DOUBLE, -1) 2025OP_END 2026 2027/* File: c/OP_CMPG_DOUBLE.cpp */ 2028HANDLE_OP_CMPX(OP_CMPG_DOUBLE, "g-double", double, _DOUBLE, 1) 2029OP_END 2030 2031/* File: c/OP_CMP_LONG.cpp */ 2032HANDLE_OP_CMPX(OP_CMP_LONG, "-long", s8, _WIDE, 0) 2033OP_END 2034 2035/* File: c/OP_IF_EQ.cpp */ 2036HANDLE_OP_IF_XX(OP_IF_EQ, "eq", ==) 2037OP_END 2038 2039/* File: c/OP_IF_NE.cpp */ 2040HANDLE_OP_IF_XX(OP_IF_NE, "ne", !=) 2041OP_END 2042 2043/* File: c/OP_IF_LT.cpp */ 2044HANDLE_OP_IF_XX(OP_IF_LT, "lt", <) 2045OP_END 2046 2047/* File: c/OP_IF_GE.cpp */ 2048HANDLE_OP_IF_XX(OP_IF_GE, "ge", >=) 2049OP_END 2050 2051/* File: c/OP_IF_GT.cpp */ 2052HANDLE_OP_IF_XX(OP_IF_GT, "gt", >) 2053OP_END 2054 2055/* File: c/OP_IF_LE.cpp */ 2056HANDLE_OP_IF_XX(OP_IF_LE, "le", <=) 2057OP_END 2058 2059/* File: c/OP_IF_EQZ.cpp */ 2060HANDLE_OP_IF_XXZ(OP_IF_EQZ, "eqz", ==) 2061OP_END 2062 2063/* File: c/OP_IF_NEZ.cpp */ 2064HANDLE_OP_IF_XXZ(OP_IF_NEZ, "nez", !=) 2065OP_END 2066 2067/* File: c/OP_IF_LTZ.cpp */ 2068HANDLE_OP_IF_XXZ(OP_IF_LTZ, "ltz", <) 2069OP_END 2070 2071/* File: c/OP_IF_GEZ.cpp */ 2072HANDLE_OP_IF_XXZ(OP_IF_GEZ, "gez", >=) 2073OP_END 2074 2075/* File: c/OP_IF_GTZ.cpp */ 2076HANDLE_OP_IF_XXZ(OP_IF_GTZ, "gtz", >) 2077OP_END 2078 2079/* File: c/OP_IF_LEZ.cpp */ 2080HANDLE_OP_IF_XXZ(OP_IF_LEZ, "lez", <=) 2081OP_END 2082 2083/* File: c/OP_UNUSED_3E.cpp */ 2084HANDLE_OPCODE(OP_UNUSED_3E) 2085OP_END 2086 2087/* File: c/OP_UNUSED_3F.cpp */ 2088HANDLE_OPCODE(OP_UNUSED_3F) 2089OP_END 2090 2091/* File: c/OP_UNUSED_40.cpp */ 2092HANDLE_OPCODE(OP_UNUSED_40) 2093OP_END 2094 2095/* File: c/OP_UNUSED_41.cpp */ 2096HANDLE_OPCODE(OP_UNUSED_41) 2097OP_END 2098 2099/* File: c/OP_UNUSED_42.cpp */ 2100HANDLE_OPCODE(OP_UNUSED_42) 2101OP_END 2102 2103/* File: c/OP_UNUSED_43.cpp */ 2104HANDLE_OPCODE(OP_UNUSED_43) 2105OP_END 2106 2107/* File: c/OP_AGET.cpp */ 2108HANDLE_OP_AGET(OP_AGET, "", u4, ) 2109OP_END 2110 2111/* File: c/OP_AGET_WIDE.cpp */ 2112HANDLE_OP_AGET(OP_AGET_WIDE, "-wide", s8, _WIDE) 2113OP_END 2114 2115/* File: c/OP_AGET_OBJECT.cpp */ 2116HANDLE_OP_AGET(OP_AGET_OBJECT, "-object", u4, ) 2117OP_END 2118 2119/* File: c/OP_AGET_BOOLEAN.cpp */ 2120HANDLE_OP_AGET(OP_AGET_BOOLEAN, "-boolean", u1, ) 2121OP_END 2122 2123/* File: c/OP_AGET_BYTE.cpp */ 2124HANDLE_OP_AGET(OP_AGET_BYTE, "-byte", s1, ) 2125OP_END 2126 2127/* File: c/OP_AGET_CHAR.cpp */ 2128HANDLE_OP_AGET(OP_AGET_CHAR, "-char", u2, ) 2129OP_END 2130 2131/* File: c/OP_AGET_SHORT.cpp */ 2132HANDLE_OP_AGET(OP_AGET_SHORT, "-short", s2, ) 2133OP_END 2134 2135/* File: c/OP_APUT.cpp */ 2136HANDLE_OP_APUT(OP_APUT, "", u4, ) 2137OP_END 2138 2139/* File: c/OP_APUT_WIDE.cpp */ 2140HANDLE_OP_APUT(OP_APUT_WIDE, "-wide", s8, _WIDE) 2141OP_END 2142 2143/* File: c/OP_APUT_OBJECT.cpp */ 2144HANDLE_OPCODE(OP_APUT_OBJECT /*vAA, vBB, vCC*/) 2145 { 2146 ArrayObject* arrayObj; 2147 Object* obj; 2148 u2 arrayInfo; 2149 EXPORT_PC(); 2150 vdst = INST_AA(inst); /* AA: source value */ 2151 arrayInfo = FETCH(1); 2152 vsrc1 = arrayInfo & 0xff; /* BB: array ptr */ 2153 vsrc2 = arrayInfo >> 8; /* CC: index */ 2154 ILOGV("|aput%s v%d,v%d,v%d", "-object", vdst, vsrc1, vsrc2); 2155 arrayObj = (ArrayObject*) GET_REGISTER(vsrc1); 2156 if (!checkForNull((Object*) arrayObj)) 2157 GOTO_exceptionThrown(); 2158 if (GET_REGISTER(vsrc2) >= arrayObj->length) { 2159 dvmThrowArrayIndexOutOfBoundsException( 2160 arrayObj->length, GET_REGISTER(vsrc2)); 2161 GOTO_exceptionThrown(); 2162 } 2163 obj = (Object*) GET_REGISTER(vdst); 2164 if (obj != NULL) { 2165 if (!checkForNull(obj)) 2166 GOTO_exceptionThrown(); 2167 if (!dvmCanPutArrayElement(obj->clazz, arrayObj->clazz)) { 2168 LOGV("Can't put a '%s'(%p) into array type='%s'(%p)", 2169 obj->clazz->descriptor, obj, 2170 arrayObj->obj.clazz->descriptor, arrayObj); 2171 dvmThrowArrayStoreExceptionIncompatibleElement(obj->clazz, arrayObj->clazz); 2172 GOTO_exceptionThrown(); 2173 } 2174 } 2175 ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst)); 2176 dvmSetObjectArrayElement(arrayObj, 2177 GET_REGISTER(vsrc2), 2178 (Object *)GET_REGISTER(vdst)); 2179 } 2180 FINISH(2); 2181OP_END 2182 2183/* File: c/OP_APUT_BOOLEAN.cpp */ 2184HANDLE_OP_APUT(OP_APUT_BOOLEAN, "-boolean", u1, ) 2185OP_END 2186 2187/* File: c/OP_APUT_BYTE.cpp */ 2188HANDLE_OP_APUT(OP_APUT_BYTE, "-byte", s1, ) 2189OP_END 2190 2191/* File: c/OP_APUT_CHAR.cpp */ 2192HANDLE_OP_APUT(OP_APUT_CHAR, "-char", u2, ) 2193OP_END 2194 2195/* File: c/OP_APUT_SHORT.cpp */ 2196HANDLE_OP_APUT(OP_APUT_SHORT, "-short", s2, ) 2197OP_END 2198 2199/* File: c/OP_IGET.cpp */ 2200HANDLE_IGET_X(OP_IGET, "", Int, ) 2201OP_END 2202 2203/* File: c/OP_IGET_WIDE.cpp */ 2204HANDLE_IGET_X(OP_IGET_WIDE, "-wide", Long, _WIDE) 2205OP_END 2206 2207/* File: c/OP_IGET_OBJECT.cpp */ 2208HANDLE_IGET_X(OP_IGET_OBJECT, "-object", Object, _AS_OBJECT) 2209OP_END 2210 2211/* File: c/OP_IGET_BOOLEAN.cpp */ 2212HANDLE_IGET_X(OP_IGET_BOOLEAN, "", Int, ) 2213OP_END 2214 2215/* File: c/OP_IGET_BYTE.cpp */ 2216HANDLE_IGET_X(OP_IGET_BYTE, "", Int, ) 2217OP_END 2218 2219/* File: c/OP_IGET_CHAR.cpp */ 2220HANDLE_IGET_X(OP_IGET_CHAR, "", Int, ) 2221OP_END 2222 2223/* File: c/OP_IGET_SHORT.cpp */ 2224HANDLE_IGET_X(OP_IGET_SHORT, "", Int, ) 2225OP_END 2226 2227/* File: c/OP_IPUT.cpp */ 2228HANDLE_IPUT_X(OP_IPUT, "", Int, ) 2229OP_END 2230 2231/* File: c/OP_IPUT_WIDE.cpp */ 2232HANDLE_IPUT_X(OP_IPUT_WIDE, "-wide", Long, _WIDE) 2233OP_END 2234 2235/* File: c/OP_IPUT_OBJECT.cpp */ 2236/* 2237 * The VM spec says we should verify that the reference being stored into 2238 * the field is assignment compatible. In practice, many popular VMs don't 2239 * do this because it slows down a very common operation. It's not so bad 2240 * for us, since "dexopt" quickens it whenever possible, but it's still an 2241 * issue. 2242 * 2243 * To make this spec-complaint, we'd need to add a ClassObject pointer to 2244 * the Field struct, resolve the field's type descriptor at link or class 2245 * init time, and then verify the type here. 2246 */ 2247HANDLE_IPUT_X(OP_IPUT_OBJECT, "-object", Object, _AS_OBJECT) 2248OP_END 2249 2250/* File: c/OP_IPUT_BOOLEAN.cpp */ 2251HANDLE_IPUT_X(OP_IPUT_BOOLEAN, "", Int, ) 2252OP_END 2253 2254/* File: c/OP_IPUT_BYTE.cpp */ 2255HANDLE_IPUT_X(OP_IPUT_BYTE, "", Int, ) 2256OP_END 2257 2258/* File: c/OP_IPUT_CHAR.cpp */ 2259HANDLE_IPUT_X(OP_IPUT_CHAR, "", Int, ) 2260OP_END 2261 2262/* File: c/OP_IPUT_SHORT.cpp */ 2263HANDLE_IPUT_X(OP_IPUT_SHORT, "", Int, ) 2264OP_END 2265 2266/* File: c/OP_SGET.cpp */ 2267HANDLE_SGET_X(OP_SGET, "", Int, ) 2268OP_END 2269 2270/* File: c/OP_SGET_WIDE.cpp */ 2271HANDLE_SGET_X(OP_SGET_WIDE, "-wide", Long, _WIDE) 2272OP_END 2273 2274/* File: c/OP_SGET_OBJECT.cpp */ 2275HANDLE_SGET_X(OP_SGET_OBJECT, "-object", Object, _AS_OBJECT) 2276OP_END 2277 2278/* File: c/OP_SGET_BOOLEAN.cpp */ 2279HANDLE_SGET_X(OP_SGET_BOOLEAN, "", Int, ) 2280OP_END 2281 2282/* File: c/OP_SGET_BYTE.cpp */ 2283HANDLE_SGET_X(OP_SGET_BYTE, "", Int, ) 2284OP_END 2285 2286/* File: c/OP_SGET_CHAR.cpp */ 2287HANDLE_SGET_X(OP_SGET_CHAR, "", Int, ) 2288OP_END 2289 2290/* File: c/OP_SGET_SHORT.cpp */ 2291HANDLE_SGET_X(OP_SGET_SHORT, "", Int, ) 2292OP_END 2293 2294/* File: c/OP_SPUT.cpp */ 2295HANDLE_SPUT_X(OP_SPUT, "", Int, ) 2296OP_END 2297 2298/* File: c/OP_SPUT_WIDE.cpp */ 2299HANDLE_SPUT_X(OP_SPUT_WIDE, "-wide", Long, _WIDE) 2300OP_END 2301 2302/* File: c/OP_SPUT_OBJECT.cpp */ 2303HANDLE_SPUT_X(OP_SPUT_OBJECT, "-object", Object, _AS_OBJECT) 2304OP_END 2305 2306/* File: c/OP_SPUT_BOOLEAN.cpp */ 2307HANDLE_SPUT_X(OP_SPUT_BOOLEAN, "", Int, ) 2308OP_END 2309 2310/* File: c/OP_SPUT_BYTE.cpp */ 2311HANDLE_SPUT_X(OP_SPUT_BYTE, "", Int, ) 2312OP_END 2313 2314/* File: c/OP_SPUT_CHAR.cpp */ 2315HANDLE_SPUT_X(OP_SPUT_CHAR, "", Int, ) 2316OP_END 2317 2318/* File: c/OP_SPUT_SHORT.cpp */ 2319HANDLE_SPUT_X(OP_SPUT_SHORT, "", Int, ) 2320OP_END 2321 2322/* File: c/OP_INVOKE_VIRTUAL.cpp */ 2323HANDLE_OPCODE(OP_INVOKE_VIRTUAL /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/) 2324 GOTO_invoke(invokeVirtual, false, false); 2325OP_END 2326 2327/* File: c/OP_INVOKE_SUPER.cpp */ 2328HANDLE_OPCODE(OP_INVOKE_SUPER /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/) 2329 GOTO_invoke(invokeSuper, false, false); 2330OP_END 2331 2332/* File: c/OP_INVOKE_DIRECT.cpp */ 2333HANDLE_OPCODE(OP_INVOKE_DIRECT /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/) 2334 GOTO_invoke(invokeDirect, false, false); 2335OP_END 2336 2337/* File: c/OP_INVOKE_STATIC.cpp */ 2338HANDLE_OPCODE(OP_INVOKE_STATIC /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/) 2339 GOTO_invoke(invokeStatic, false, false); 2340OP_END 2341 2342/* File: c/OP_INVOKE_INTERFACE.cpp */ 2343HANDLE_OPCODE(OP_INVOKE_INTERFACE /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/) 2344 GOTO_invoke(invokeInterface, false, false); 2345OP_END 2346 2347/* File: c/OP_UNUSED_73.cpp */ 2348HANDLE_OPCODE(OP_UNUSED_73) 2349OP_END 2350 2351/* File: c/OP_INVOKE_VIRTUAL_RANGE.cpp */ 2352HANDLE_OPCODE(OP_INVOKE_VIRTUAL_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 2353 GOTO_invoke(invokeVirtual, true, false); 2354OP_END 2355 2356/* File: c/OP_INVOKE_SUPER_RANGE.cpp */ 2357HANDLE_OPCODE(OP_INVOKE_SUPER_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 2358 GOTO_invoke(invokeSuper, true, false); 2359OP_END 2360 2361/* File: c/OP_INVOKE_DIRECT_RANGE.cpp */ 2362HANDLE_OPCODE(OP_INVOKE_DIRECT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 2363 GOTO_invoke(invokeDirect, true, false); 2364OP_END 2365 2366/* File: c/OP_INVOKE_STATIC_RANGE.cpp */ 2367HANDLE_OPCODE(OP_INVOKE_STATIC_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 2368 GOTO_invoke(invokeStatic, true, false); 2369OP_END 2370 2371/* File: c/OP_INVOKE_INTERFACE_RANGE.cpp */ 2372HANDLE_OPCODE(OP_INVOKE_INTERFACE_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 2373 GOTO_invoke(invokeInterface, true, false); 2374OP_END 2375 2376/* File: c/OP_UNUSED_79.cpp */ 2377HANDLE_OPCODE(OP_UNUSED_79) 2378OP_END 2379 2380/* File: c/OP_UNUSED_7A.cpp */ 2381HANDLE_OPCODE(OP_UNUSED_7A) 2382OP_END 2383 2384/* File: c/OP_NEG_INT.cpp */ 2385HANDLE_UNOP(OP_NEG_INT, "neg-int", -, , ) 2386OP_END 2387 2388/* File: c/OP_NOT_INT.cpp */ 2389HANDLE_UNOP(OP_NOT_INT, "not-int", , ^ 0xffffffff, ) 2390OP_END 2391 2392/* File: c/OP_NEG_LONG.cpp */ 2393HANDLE_UNOP(OP_NEG_LONG, "neg-long", -, , _WIDE) 2394OP_END 2395 2396/* File: c/OP_NOT_LONG.cpp */ 2397HANDLE_UNOP(OP_NOT_LONG, "not-long", , ^ 0xffffffffffffffffULL, _WIDE) 2398OP_END 2399 2400/* File: c/OP_NEG_FLOAT.cpp */ 2401HANDLE_UNOP(OP_NEG_FLOAT, "neg-float", -, , _FLOAT) 2402OP_END 2403 2404/* File: c/OP_NEG_DOUBLE.cpp */ 2405HANDLE_UNOP(OP_NEG_DOUBLE, "neg-double", -, , _DOUBLE) 2406OP_END 2407 2408/* File: c/OP_INT_TO_LONG.cpp */ 2409HANDLE_NUMCONV(OP_INT_TO_LONG, "int-to-long", _INT, _WIDE) 2410OP_END 2411 2412/* File: c/OP_INT_TO_FLOAT.cpp */ 2413HANDLE_NUMCONV(OP_INT_TO_FLOAT, "int-to-float", _INT, _FLOAT) 2414OP_END 2415 2416/* File: c/OP_INT_TO_DOUBLE.cpp */ 2417HANDLE_NUMCONV(OP_INT_TO_DOUBLE, "int-to-double", _INT, _DOUBLE) 2418OP_END 2419 2420/* File: c/OP_LONG_TO_INT.cpp */ 2421HANDLE_NUMCONV(OP_LONG_TO_INT, "long-to-int", _WIDE, _INT) 2422OP_END 2423 2424/* File: c/OP_LONG_TO_FLOAT.cpp */ 2425HANDLE_NUMCONV(OP_LONG_TO_FLOAT, "long-to-float", _WIDE, _FLOAT) 2426OP_END 2427 2428/* File: c/OP_LONG_TO_DOUBLE.cpp */ 2429HANDLE_NUMCONV(OP_LONG_TO_DOUBLE, "long-to-double", _WIDE, _DOUBLE) 2430OP_END 2431 2432/* File: c/OP_FLOAT_TO_INT.cpp */ 2433HANDLE_FLOAT_TO_INT(OP_FLOAT_TO_INT, "float-to-int", 2434 float, _FLOAT, s4, _INT) 2435OP_END 2436 2437/* File: c/OP_FLOAT_TO_LONG.cpp */ 2438HANDLE_FLOAT_TO_INT(OP_FLOAT_TO_LONG, "float-to-long", 2439 float, _FLOAT, s8, _WIDE) 2440OP_END 2441 2442/* File: c/OP_FLOAT_TO_DOUBLE.cpp */ 2443HANDLE_NUMCONV(OP_FLOAT_TO_DOUBLE, "float-to-double", _FLOAT, _DOUBLE) 2444OP_END 2445 2446/* File: c/OP_DOUBLE_TO_INT.cpp */ 2447HANDLE_FLOAT_TO_INT(OP_DOUBLE_TO_INT, "double-to-int", 2448 double, _DOUBLE, s4, _INT) 2449OP_END 2450 2451/* File: c/OP_DOUBLE_TO_LONG.cpp */ 2452HANDLE_FLOAT_TO_INT(OP_DOUBLE_TO_LONG, "double-to-long", 2453 double, _DOUBLE, s8, _WIDE) 2454OP_END 2455 2456/* File: c/OP_DOUBLE_TO_FLOAT.cpp */ 2457HANDLE_NUMCONV(OP_DOUBLE_TO_FLOAT, "double-to-float", _DOUBLE, _FLOAT) 2458OP_END 2459 2460/* File: c/OP_INT_TO_BYTE.cpp */ 2461HANDLE_INT_TO_SMALL(OP_INT_TO_BYTE, "byte", s1) 2462OP_END 2463 2464/* File: c/OP_INT_TO_CHAR.cpp */ 2465HANDLE_INT_TO_SMALL(OP_INT_TO_CHAR, "char", u2) 2466OP_END 2467 2468/* File: c/OP_INT_TO_SHORT.cpp */ 2469HANDLE_INT_TO_SMALL(OP_INT_TO_SHORT, "short", s2) /* want sign bit */ 2470OP_END 2471 2472/* File: c/OP_ADD_INT.cpp */ 2473HANDLE_OP_X_INT(OP_ADD_INT, "add", +, 0) 2474OP_END 2475 2476/* File: c/OP_SUB_INT.cpp */ 2477HANDLE_OP_X_INT(OP_SUB_INT, "sub", -, 0) 2478OP_END 2479 2480/* File: c/OP_MUL_INT.cpp */ 2481HANDLE_OP_X_INT(OP_MUL_INT, "mul", *, 0) 2482OP_END 2483 2484/* File: c/OP_DIV_INT.cpp */ 2485HANDLE_OP_X_INT(OP_DIV_INT, "div", /, 1) 2486OP_END 2487 2488/* File: c/OP_REM_INT.cpp */ 2489HANDLE_OP_X_INT(OP_REM_INT, "rem", %, 2) 2490OP_END 2491 2492/* File: c/OP_AND_INT.cpp */ 2493HANDLE_OP_X_INT(OP_AND_INT, "and", &, 0) 2494OP_END 2495 2496/* File: c/OP_OR_INT.cpp */ 2497HANDLE_OP_X_INT(OP_OR_INT, "or", |, 0) 2498OP_END 2499 2500/* File: c/OP_XOR_INT.cpp */ 2501HANDLE_OP_X_INT(OP_XOR_INT, "xor", ^, 0) 2502OP_END 2503 2504/* File: c/OP_SHL_INT.cpp */ 2505HANDLE_OP_SHX_INT(OP_SHL_INT, "shl", (s4), <<) 2506OP_END 2507 2508/* File: c/OP_SHR_INT.cpp */ 2509HANDLE_OP_SHX_INT(OP_SHR_INT, "shr", (s4), >>) 2510OP_END 2511 2512/* File: c/OP_USHR_INT.cpp */ 2513HANDLE_OP_SHX_INT(OP_USHR_INT, "ushr", (u4), >>) 2514OP_END 2515 2516/* File: c/OP_ADD_LONG.cpp */ 2517HANDLE_OP_X_LONG(OP_ADD_LONG, "add", +, 0) 2518OP_END 2519 2520/* File: c/OP_SUB_LONG.cpp */ 2521HANDLE_OP_X_LONG(OP_SUB_LONG, "sub", -, 0) 2522OP_END 2523 2524/* File: c/OP_MUL_LONG.cpp */ 2525HANDLE_OP_X_LONG(OP_MUL_LONG, "mul", *, 0) 2526OP_END 2527 2528/* File: c/OP_DIV_LONG.cpp */ 2529HANDLE_OP_X_LONG(OP_DIV_LONG, "div", /, 1) 2530OP_END 2531 2532/* File: c/OP_REM_LONG.cpp */ 2533HANDLE_OP_X_LONG(OP_REM_LONG, "rem", %, 2) 2534OP_END 2535 2536/* File: c/OP_AND_LONG.cpp */ 2537HANDLE_OP_X_LONG(OP_AND_LONG, "and", &, 0) 2538OP_END 2539 2540/* File: c/OP_OR_LONG.cpp */ 2541HANDLE_OP_X_LONG(OP_OR_LONG, "or", |, 0) 2542OP_END 2543 2544/* File: c/OP_XOR_LONG.cpp */ 2545HANDLE_OP_X_LONG(OP_XOR_LONG, "xor", ^, 0) 2546OP_END 2547 2548/* File: c/OP_SHL_LONG.cpp */ 2549HANDLE_OP_SHX_LONG(OP_SHL_LONG, "shl", (s8), <<) 2550OP_END 2551 2552/* File: c/OP_SHR_LONG.cpp */ 2553HANDLE_OP_SHX_LONG(OP_SHR_LONG, "shr", (s8), >>) 2554OP_END 2555 2556/* File: c/OP_USHR_LONG.cpp */ 2557HANDLE_OP_SHX_LONG(OP_USHR_LONG, "ushr", (u8), >>) 2558OP_END 2559 2560/* File: c/OP_ADD_FLOAT.cpp */ 2561HANDLE_OP_X_FLOAT(OP_ADD_FLOAT, "add", +) 2562OP_END 2563 2564/* File: c/OP_SUB_FLOAT.cpp */ 2565HANDLE_OP_X_FLOAT(OP_SUB_FLOAT, "sub", -) 2566OP_END 2567 2568/* File: c/OP_MUL_FLOAT.cpp */ 2569HANDLE_OP_X_FLOAT(OP_MUL_FLOAT, "mul", *) 2570OP_END 2571 2572/* File: c/OP_DIV_FLOAT.cpp */ 2573HANDLE_OP_X_FLOAT(OP_DIV_FLOAT, "div", /) 2574OP_END 2575 2576/* File: c/OP_REM_FLOAT.cpp */ 2577HANDLE_OPCODE(OP_REM_FLOAT /*vAA, vBB, vCC*/) 2578 { 2579 u2 srcRegs; 2580 vdst = INST_AA(inst); 2581 srcRegs = FETCH(1); 2582 vsrc1 = srcRegs & 0xff; 2583 vsrc2 = srcRegs >> 8; 2584 ILOGV("|%s-float v%d,v%d,v%d", "mod", vdst, vsrc1, vsrc2); 2585 SET_REGISTER_FLOAT(vdst, 2586 fmodf(GET_REGISTER_FLOAT(vsrc1), GET_REGISTER_FLOAT(vsrc2))); 2587 } 2588 FINISH(2); 2589OP_END 2590 2591/* File: c/OP_ADD_DOUBLE.cpp */ 2592HANDLE_OP_X_DOUBLE(OP_ADD_DOUBLE, "add", +) 2593OP_END 2594 2595/* File: c/OP_SUB_DOUBLE.cpp */ 2596HANDLE_OP_X_DOUBLE(OP_SUB_DOUBLE, "sub", -) 2597OP_END 2598 2599/* File: c/OP_MUL_DOUBLE.cpp */ 2600HANDLE_OP_X_DOUBLE(OP_MUL_DOUBLE, "mul", *) 2601OP_END 2602 2603/* File: c/OP_DIV_DOUBLE.cpp */ 2604HANDLE_OP_X_DOUBLE(OP_DIV_DOUBLE, "div", /) 2605OP_END 2606 2607/* File: c/OP_REM_DOUBLE.cpp */ 2608HANDLE_OPCODE(OP_REM_DOUBLE /*vAA, vBB, vCC*/) 2609 { 2610 u2 srcRegs; 2611 vdst = INST_AA(inst); 2612 srcRegs = FETCH(1); 2613 vsrc1 = srcRegs & 0xff; 2614 vsrc2 = srcRegs >> 8; 2615 ILOGV("|%s-double v%d,v%d,v%d", "mod", vdst, vsrc1, vsrc2); 2616 SET_REGISTER_DOUBLE(vdst, 2617 fmod(GET_REGISTER_DOUBLE(vsrc1), GET_REGISTER_DOUBLE(vsrc2))); 2618 } 2619 FINISH(2); 2620OP_END 2621 2622/* File: c/OP_ADD_INT_2ADDR.cpp */ 2623HANDLE_OP_X_INT_2ADDR(OP_ADD_INT_2ADDR, "add", +, 0) 2624OP_END 2625 2626/* File: c/OP_SUB_INT_2ADDR.cpp */ 2627HANDLE_OP_X_INT_2ADDR(OP_SUB_INT_2ADDR, "sub", -, 0) 2628OP_END 2629 2630/* File: c/OP_MUL_INT_2ADDR.cpp */ 2631HANDLE_OP_X_INT_2ADDR(OP_MUL_INT_2ADDR, "mul", *, 0) 2632OP_END 2633 2634/* File: c/OP_DIV_INT_2ADDR.cpp */ 2635HANDLE_OP_X_INT_2ADDR(OP_DIV_INT_2ADDR, "div", /, 1) 2636OP_END 2637 2638/* File: c/OP_REM_INT_2ADDR.cpp */ 2639HANDLE_OP_X_INT_2ADDR(OP_REM_INT_2ADDR, "rem", %, 2) 2640OP_END 2641 2642/* File: c/OP_AND_INT_2ADDR.cpp */ 2643HANDLE_OP_X_INT_2ADDR(OP_AND_INT_2ADDR, "and", &, 0) 2644OP_END 2645 2646/* File: c/OP_OR_INT_2ADDR.cpp */ 2647HANDLE_OP_X_INT_2ADDR(OP_OR_INT_2ADDR, "or", |, 0) 2648OP_END 2649 2650/* File: c/OP_XOR_INT_2ADDR.cpp */ 2651HANDLE_OP_X_INT_2ADDR(OP_XOR_INT_2ADDR, "xor", ^, 0) 2652OP_END 2653 2654/* File: c/OP_SHL_INT_2ADDR.cpp */ 2655HANDLE_OP_SHX_INT_2ADDR(OP_SHL_INT_2ADDR, "shl", (s4), <<) 2656OP_END 2657 2658/* File: c/OP_SHR_INT_2ADDR.cpp */ 2659HANDLE_OP_SHX_INT_2ADDR(OP_SHR_INT_2ADDR, "shr", (s4), >>) 2660OP_END 2661 2662/* File: c/OP_USHR_INT_2ADDR.cpp */ 2663HANDLE_OP_SHX_INT_2ADDR(OP_USHR_INT_2ADDR, "ushr", (u4), >>) 2664OP_END 2665 2666/* File: c/OP_ADD_LONG_2ADDR.cpp */ 2667HANDLE_OP_X_LONG_2ADDR(OP_ADD_LONG_2ADDR, "add", +, 0) 2668OP_END 2669 2670/* File: c/OP_SUB_LONG_2ADDR.cpp */ 2671HANDLE_OP_X_LONG_2ADDR(OP_SUB_LONG_2ADDR, "sub", -, 0) 2672OP_END 2673 2674/* File: c/OP_MUL_LONG_2ADDR.cpp */ 2675HANDLE_OP_X_LONG_2ADDR(OP_MUL_LONG_2ADDR, "mul", *, 0) 2676OP_END 2677 2678/* File: c/OP_DIV_LONG_2ADDR.cpp */ 2679HANDLE_OP_X_LONG_2ADDR(OP_DIV_LONG_2ADDR, "div", /, 1) 2680OP_END 2681 2682/* File: c/OP_REM_LONG_2ADDR.cpp */ 2683HANDLE_OP_X_LONG_2ADDR(OP_REM_LONG_2ADDR, "rem", %, 2) 2684OP_END 2685 2686/* File: c/OP_AND_LONG_2ADDR.cpp */ 2687HANDLE_OP_X_LONG_2ADDR(OP_AND_LONG_2ADDR, "and", &, 0) 2688OP_END 2689 2690/* File: c/OP_OR_LONG_2ADDR.cpp */ 2691HANDLE_OP_X_LONG_2ADDR(OP_OR_LONG_2ADDR, "or", |, 0) 2692OP_END 2693 2694/* File: c/OP_XOR_LONG_2ADDR.cpp */ 2695HANDLE_OP_X_LONG_2ADDR(OP_XOR_LONG_2ADDR, "xor", ^, 0) 2696OP_END 2697 2698/* File: c/OP_SHL_LONG_2ADDR.cpp */ 2699HANDLE_OP_SHX_LONG_2ADDR(OP_SHL_LONG_2ADDR, "shl", (s8), <<) 2700OP_END 2701 2702/* File: c/OP_SHR_LONG_2ADDR.cpp */ 2703HANDLE_OP_SHX_LONG_2ADDR(OP_SHR_LONG_2ADDR, "shr", (s8), >>) 2704OP_END 2705 2706/* File: c/OP_USHR_LONG_2ADDR.cpp */ 2707HANDLE_OP_SHX_LONG_2ADDR(OP_USHR_LONG_2ADDR, "ushr", (u8), >>) 2708OP_END 2709 2710/* File: c/OP_ADD_FLOAT_2ADDR.cpp */ 2711HANDLE_OP_X_FLOAT_2ADDR(OP_ADD_FLOAT_2ADDR, "add", +) 2712OP_END 2713 2714/* File: c/OP_SUB_FLOAT_2ADDR.cpp */ 2715HANDLE_OP_X_FLOAT_2ADDR(OP_SUB_FLOAT_2ADDR, "sub", -) 2716OP_END 2717 2718/* File: c/OP_MUL_FLOAT_2ADDR.cpp */ 2719HANDLE_OP_X_FLOAT_2ADDR(OP_MUL_FLOAT_2ADDR, "mul", *) 2720OP_END 2721 2722/* File: c/OP_DIV_FLOAT_2ADDR.cpp */ 2723HANDLE_OP_X_FLOAT_2ADDR(OP_DIV_FLOAT_2ADDR, "div", /) 2724OP_END 2725 2726/* File: c/OP_REM_FLOAT_2ADDR.cpp */ 2727HANDLE_OPCODE(OP_REM_FLOAT_2ADDR /*vA, vB*/) 2728 vdst = INST_A(inst); 2729 vsrc1 = INST_B(inst); 2730 ILOGV("|%s-float-2addr v%d,v%d", "mod", vdst, vsrc1); 2731 SET_REGISTER_FLOAT(vdst, 2732 fmodf(GET_REGISTER_FLOAT(vdst), GET_REGISTER_FLOAT(vsrc1))); 2733 FINISH(1); 2734OP_END 2735 2736/* File: c/OP_ADD_DOUBLE_2ADDR.cpp */ 2737HANDLE_OP_X_DOUBLE_2ADDR(OP_ADD_DOUBLE_2ADDR, "add", +) 2738OP_END 2739 2740/* File: c/OP_SUB_DOUBLE_2ADDR.cpp */ 2741HANDLE_OP_X_DOUBLE_2ADDR(OP_SUB_DOUBLE_2ADDR, "sub", -) 2742OP_END 2743 2744/* File: c/OP_MUL_DOUBLE_2ADDR.cpp */ 2745HANDLE_OP_X_DOUBLE_2ADDR(OP_MUL_DOUBLE_2ADDR, "mul", *) 2746OP_END 2747 2748/* File: c/OP_DIV_DOUBLE_2ADDR.cpp */ 2749HANDLE_OP_X_DOUBLE_2ADDR(OP_DIV_DOUBLE_2ADDR, "div", /) 2750OP_END 2751 2752/* File: c/OP_REM_DOUBLE_2ADDR.cpp */ 2753HANDLE_OPCODE(OP_REM_DOUBLE_2ADDR /*vA, vB*/) 2754 vdst = INST_A(inst); 2755 vsrc1 = INST_B(inst); 2756 ILOGV("|%s-double-2addr v%d,v%d", "mod", vdst, vsrc1); 2757 SET_REGISTER_DOUBLE(vdst, 2758 fmod(GET_REGISTER_DOUBLE(vdst), GET_REGISTER_DOUBLE(vsrc1))); 2759 FINISH(1); 2760OP_END 2761 2762/* File: c/OP_ADD_INT_LIT16.cpp */ 2763HANDLE_OP_X_INT_LIT16(OP_ADD_INT_LIT16, "add", +, 0) 2764OP_END 2765 2766/* File: c/OP_RSUB_INT.cpp */ 2767HANDLE_OPCODE(OP_RSUB_INT /*vA, vB, #+CCCC*/) 2768 { 2769 vdst = INST_A(inst); 2770 vsrc1 = INST_B(inst); 2771 vsrc2 = FETCH(1); 2772 ILOGV("|rsub-int v%d,v%d,#+0x%04x", vdst, vsrc1, vsrc2); 2773 SET_REGISTER(vdst, (s2) vsrc2 - (s4) GET_REGISTER(vsrc1)); 2774 } 2775 FINISH(2); 2776OP_END 2777 2778/* File: c/OP_MUL_INT_LIT16.cpp */ 2779HANDLE_OP_X_INT_LIT16(OP_MUL_INT_LIT16, "mul", *, 0) 2780OP_END 2781 2782/* File: c/OP_DIV_INT_LIT16.cpp */ 2783HANDLE_OP_X_INT_LIT16(OP_DIV_INT_LIT16, "div", /, 1) 2784OP_END 2785 2786/* File: c/OP_REM_INT_LIT16.cpp */ 2787HANDLE_OP_X_INT_LIT16(OP_REM_INT_LIT16, "rem", %, 2) 2788OP_END 2789 2790/* File: c/OP_AND_INT_LIT16.cpp */ 2791HANDLE_OP_X_INT_LIT16(OP_AND_INT_LIT16, "and", &, 0) 2792OP_END 2793 2794/* File: c/OP_OR_INT_LIT16.cpp */ 2795HANDLE_OP_X_INT_LIT16(OP_OR_INT_LIT16, "or", |, 0) 2796OP_END 2797 2798/* File: c/OP_XOR_INT_LIT16.cpp */ 2799HANDLE_OP_X_INT_LIT16(OP_XOR_INT_LIT16, "xor", ^, 0) 2800OP_END 2801 2802/* File: c/OP_ADD_INT_LIT8.cpp */ 2803HANDLE_OP_X_INT_LIT8(OP_ADD_INT_LIT8, "add", +, 0) 2804OP_END 2805 2806/* File: c/OP_RSUB_INT_LIT8.cpp */ 2807HANDLE_OPCODE(OP_RSUB_INT_LIT8 /*vAA, vBB, #+CC*/) 2808 { 2809 u2 litInfo; 2810 vdst = INST_AA(inst); 2811 litInfo = FETCH(1); 2812 vsrc1 = litInfo & 0xff; 2813 vsrc2 = litInfo >> 8; 2814 ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x", "rsub", vdst, vsrc1, vsrc2); 2815 SET_REGISTER(vdst, (s1) vsrc2 - (s4) GET_REGISTER(vsrc1)); 2816 } 2817 FINISH(2); 2818OP_END 2819 2820/* File: c/OP_MUL_INT_LIT8.cpp */ 2821HANDLE_OP_X_INT_LIT8(OP_MUL_INT_LIT8, "mul", *, 0) 2822OP_END 2823 2824/* File: c/OP_DIV_INT_LIT8.cpp */ 2825HANDLE_OP_X_INT_LIT8(OP_DIV_INT_LIT8, "div", /, 1) 2826OP_END 2827 2828/* File: c/OP_REM_INT_LIT8.cpp */ 2829HANDLE_OP_X_INT_LIT8(OP_REM_INT_LIT8, "rem", %, 2) 2830OP_END 2831 2832/* File: c/OP_AND_INT_LIT8.cpp */ 2833HANDLE_OP_X_INT_LIT8(OP_AND_INT_LIT8, "and", &, 0) 2834OP_END 2835 2836/* File: c/OP_OR_INT_LIT8.cpp */ 2837HANDLE_OP_X_INT_LIT8(OP_OR_INT_LIT8, "or", |, 0) 2838OP_END 2839 2840/* File: c/OP_XOR_INT_LIT8.cpp */ 2841HANDLE_OP_X_INT_LIT8(OP_XOR_INT_LIT8, "xor", ^, 0) 2842OP_END 2843 2844/* File: c/OP_SHL_INT_LIT8.cpp */ 2845HANDLE_OP_SHX_INT_LIT8(OP_SHL_INT_LIT8, "shl", (s4), <<) 2846OP_END 2847 2848/* File: c/OP_SHR_INT_LIT8.cpp */ 2849HANDLE_OP_SHX_INT_LIT8(OP_SHR_INT_LIT8, "shr", (s4), >>) 2850OP_END 2851 2852/* File: c/OP_USHR_INT_LIT8.cpp */ 2853HANDLE_OP_SHX_INT_LIT8(OP_USHR_INT_LIT8, "ushr", (u4), >>) 2854OP_END 2855 2856/* File: c/OP_IGET_VOLATILE.cpp */ 2857HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, ) 2858OP_END 2859 2860/* File: c/OP_IPUT_VOLATILE.cpp */ 2861HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, ) 2862OP_END 2863 2864/* File: c/OP_SGET_VOLATILE.cpp */ 2865HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, ) 2866OP_END 2867 2868/* File: c/OP_SPUT_VOLATILE.cpp */ 2869HANDLE_SPUT_X(OP_SPUT_VOLATILE, "-volatile", IntVolatile, ) 2870OP_END 2871 2872/* File: c/OP_IGET_OBJECT_VOLATILE.cpp */ 2873HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) 2874OP_END 2875 2876/* File: c/OP_IGET_WIDE_VOLATILE.cpp */ 2877HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE) 2878OP_END 2879 2880/* File: c/OP_IPUT_WIDE_VOLATILE.cpp */ 2881HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE) 2882OP_END 2883 2884/* File: c/OP_SGET_WIDE_VOLATILE.cpp */ 2885HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE) 2886OP_END 2887 2888/* File: c/OP_SPUT_WIDE_VOLATILE.cpp */ 2889HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE) 2890OP_END 2891 2892/* File: c/OP_BREAKPOINT.cpp */ 2893HANDLE_OPCODE(OP_BREAKPOINT) 2894 { 2895 /* 2896 * Restart this instruction with the original opcode. We do 2897 * this by simply jumping to the handler. 2898 * 2899 * It's probably not necessary to update "inst", but we do it 2900 * for the sake of anything that needs to do disambiguation in a 2901 * common handler with INST_INST. 2902 * 2903 * The breakpoint itself is handled over in updateDebugger(), 2904 * because we need to detect other events (method entry, single 2905 * step) and report them in the same event packet, and we're not 2906 * yet handling those through breakpoint instructions. By the 2907 * time we get here, the breakpoint has already been handled and 2908 * the thread resumed. 2909 */ 2910 u1 originalOpcode = dvmGetOriginalOpcode(pc); 2911 LOGV("+++ break 0x%02x (0x%04x -> 0x%04x)", originalOpcode, inst, 2912 INST_REPLACE_OP(inst, originalOpcode)); 2913 inst = INST_REPLACE_OP(inst, originalOpcode); 2914 FINISH_BKPT(originalOpcode); 2915 } 2916OP_END 2917 2918/* File: c/OP_THROW_VERIFICATION_ERROR.cpp */ 2919HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR) 2920 EXPORT_PC(); 2921 vsrc1 = INST_AA(inst); 2922 ref = FETCH(1); /* class/field/method ref */ 2923 dvmThrowVerificationError(curMethod, vsrc1, ref); 2924 GOTO_exceptionThrown(); 2925OP_END 2926 2927/* File: c/OP_EXECUTE_INLINE.cpp */ 2928HANDLE_OPCODE(OP_EXECUTE_INLINE /*vB, {vD, vE, vF, vG}, inline@CCCC*/) 2929 { 2930 /* 2931 * This has the same form as other method calls, but we ignore 2932 * the 5th argument (vA). This is chiefly because the first four 2933 * arguments to a function on ARM are in registers. 2934 * 2935 * We only set the arguments that are actually used, leaving 2936 * the rest uninitialized. We're assuming that, if the method 2937 * needs them, they'll be specified in the call. 2938 * 2939 * However, this annoys gcc when optimizations are enabled, 2940 * causing a "may be used uninitialized" warning. Quieting 2941 * the warnings incurs a slight penalty (5%: 373ns vs. 393ns 2942 * on empty method). Note that valgrind is perfectly happy 2943 * either way as the uninitialiezd values are never actually 2944 * used. 2945 */ 2946 u4 arg0, arg1, arg2, arg3; 2947 arg0 = arg1 = arg2 = arg3 = 0; 2948 2949 EXPORT_PC(); 2950 2951 vsrc1 = INST_B(inst); /* #of args */ 2952 ref = FETCH(1); /* inline call "ref" */ 2953 vdst = FETCH(2); /* 0-4 register indices */ 2954 ILOGV("|execute-inline args=%d @%d {regs=0x%04x}", 2955 vsrc1, ref, vdst); 2956 2957 assert((vdst >> 16) == 0); // 16-bit type -or- high 16 bits clear 2958 assert(vsrc1 <= 4); 2959 2960 switch (vsrc1) { 2961 case 4: 2962 arg3 = GET_REGISTER(vdst >> 12); 2963 /* fall through */ 2964 case 3: 2965 arg2 = GET_REGISTER((vdst & 0x0f00) >> 8); 2966 /* fall through */ 2967 case 2: 2968 arg1 = GET_REGISTER((vdst & 0x00f0) >> 4); 2969 /* fall through */ 2970 case 1: 2971 arg0 = GET_REGISTER(vdst & 0x0f); 2972 /* fall through */ 2973 default: // case 0 2974 ; 2975 } 2976 2977 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 2978 if (!dvmPerformInlineOp4Dbg(arg0, arg1, arg2, arg3, &retval, ref)) 2979 GOTO_exceptionThrown(); 2980 } else { 2981 if (!dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)) 2982 GOTO_exceptionThrown(); 2983 } 2984 } 2985 FINISH(3); 2986OP_END 2987 2988/* File: c/OP_EXECUTE_INLINE_RANGE.cpp */ 2989HANDLE_OPCODE(OP_EXECUTE_INLINE_RANGE /*{vCCCC..v(CCCC+AA-1)}, inline@BBBB*/) 2990 { 2991 u4 arg0, arg1, arg2, arg3; 2992 arg0 = arg1 = arg2 = arg3 = 0; /* placate gcc */ 2993 2994 EXPORT_PC(); 2995 2996 vsrc1 = INST_AA(inst); /* #of args */ 2997 ref = FETCH(1); /* inline call "ref" */ 2998 vdst = FETCH(2); /* range base */ 2999 ILOGV("|execute-inline-range args=%d @%d {regs=v%d-v%d}", 3000 vsrc1, ref, vdst, vdst+vsrc1-1); 3001 3002 assert((vdst >> 16) == 0); // 16-bit type -or- high 16 bits clear 3003 assert(vsrc1 <= 4); 3004 3005 switch (vsrc1) { 3006 case 4: 3007 arg3 = GET_REGISTER(vdst+3); 3008 /* fall through */ 3009 case 3: 3010 arg2 = GET_REGISTER(vdst+2); 3011 /* fall through */ 3012 case 2: 3013 arg1 = GET_REGISTER(vdst+1); 3014 /* fall through */ 3015 case 1: 3016 arg0 = GET_REGISTER(vdst+0); 3017 /* fall through */ 3018 default: // case 0 3019 ; 3020 } 3021 3022 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 3023 if (!dvmPerformInlineOp4Dbg(arg0, arg1, arg2, arg3, &retval, ref)) 3024 GOTO_exceptionThrown(); 3025 } else { 3026 if (!dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)) 3027 GOTO_exceptionThrown(); 3028 } 3029 } 3030 FINISH(3); 3031OP_END 3032 3033/* File: c/OP_INVOKE_OBJECT_INIT_RANGE.cpp */ 3034HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 3035 { 3036 Object* obj; 3037 3038 vsrc1 = FETCH(2); /* reg number of "this" pointer */ 3039 obj = GET_REGISTER_AS_OBJECT(vsrc1); 3040 3041 if (!checkForNullExportPC(obj, fp, pc)) 3042 GOTO_exceptionThrown(); 3043 3044 /* 3045 * The object should be marked "finalizable" when Object.<init> 3046 * completes normally. We're going to assume it does complete 3047 * (by virtue of being nothing but a return-void) and set it now. 3048 */ 3049 if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISFINALIZABLE)) { 3050 EXPORT_PC(); 3051 dvmSetFinalizable(obj); 3052 if (dvmGetException(self)) 3053 GOTO_exceptionThrown(); 3054 } 3055 3056 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 3057 /* behave like OP_INVOKE_DIRECT_RANGE */ 3058 GOTO_invoke(invokeDirect, true, false); 3059 } 3060 FINISH(3); 3061 } 3062OP_END 3063 3064/* File: c/OP_RETURN_VOID_BARRIER.cpp */ 3065HANDLE_OPCODE(OP_RETURN_VOID_BARRIER /**/) 3066 ILOGV("|return-void"); 3067#ifndef NDEBUG 3068 retval.j = 0xababababULL; /* placate valgrind */ 3069#endif 3070 ANDROID_MEMBAR_STORE(); 3071 GOTO_returnFromMethod(); 3072OP_END 3073 3074/* File: c/OP_IGET_QUICK.cpp */ 3075HANDLE_IGET_X_QUICK(OP_IGET_QUICK, "", Int, ) 3076OP_END 3077 3078/* File: c/OP_IGET_WIDE_QUICK.cpp */ 3079HANDLE_IGET_X_QUICK(OP_IGET_WIDE_QUICK, "-wide", Long, _WIDE) 3080OP_END 3081 3082/* File: c/OP_IGET_OBJECT_QUICK.cpp */ 3083HANDLE_IGET_X_QUICK(OP_IGET_OBJECT_QUICK, "-object", Object, _AS_OBJECT) 3084OP_END 3085 3086/* File: c/OP_IPUT_QUICK.cpp */ 3087HANDLE_IPUT_X_QUICK(OP_IPUT_QUICK, "", Int, ) 3088OP_END 3089 3090/* File: c/OP_IPUT_WIDE_QUICK.cpp */ 3091HANDLE_IPUT_X_QUICK(OP_IPUT_WIDE_QUICK, "-wide", Long, _WIDE) 3092OP_END 3093 3094/* File: c/OP_IPUT_OBJECT_QUICK.cpp */ 3095HANDLE_IPUT_X_QUICK(OP_IPUT_OBJECT_QUICK, "-object", Object, _AS_OBJECT) 3096OP_END 3097 3098/* File: c/OP_INVOKE_VIRTUAL_QUICK.cpp */ 3099HANDLE_OPCODE(OP_INVOKE_VIRTUAL_QUICK /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/) 3100 GOTO_invoke(invokeVirtualQuick, false, false); 3101OP_END 3102 3103/* File: c/OP_INVOKE_VIRTUAL_QUICK_RANGE.cpp */ 3104HANDLE_OPCODE(OP_INVOKE_VIRTUAL_QUICK_RANGE/*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 3105 GOTO_invoke(invokeVirtualQuick, true, false); 3106OP_END 3107 3108/* File: c/OP_INVOKE_SUPER_QUICK.cpp */ 3109HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK /*vB, {vD, vE, vF, vG, vA}, meth@CCCC*/) 3110 GOTO_invoke(invokeSuperQuick, false, false); 3111OP_END 3112 3113/* File: c/OP_INVOKE_SUPER_QUICK_RANGE.cpp */ 3114HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) 3115 GOTO_invoke(invokeSuperQuick, true, false); 3116OP_END 3117 3118/* File: c/OP_IPUT_OBJECT_VOLATILE.cpp */ 3119HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) 3120OP_END 3121 3122/* File: c/OP_SGET_OBJECT_VOLATILE.cpp */ 3123HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) 3124OP_END 3125 3126/* File: c/OP_SPUT_OBJECT_VOLATILE.cpp */ 3127HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) 3128OP_END 3129 3130/* File: c/OP_DISPATCH_FF.cpp */ 3131HANDLE_OPCODE(OP_DISPATCH_FF) 3132 /* 3133 * Indicates extended opcode. Use next 8 bits to choose where to branch. 3134 */ 3135 DISPATCH_EXTENDED(INST_AA(inst)); 3136OP_END 3137 3138/* File: c/OP_CONST_CLASS_JUMBO.cpp */ 3139HANDLE_OPCODE(OP_CONST_CLASS_JUMBO /*vBBBB, class@AAAAAAAA*/) 3140 { 3141 ClassObject* clazz; 3142 3143 ref = FETCH(1) | (u4)FETCH(2) << 16; 3144 vdst = FETCH(3); 3145 ILOGV("|const-class/jumbo v%d class@0x%08x", vdst, ref); 3146 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 3147 if (clazz == NULL) { 3148 EXPORT_PC(); 3149 clazz = dvmResolveClass(curMethod->clazz, ref, true); 3150 if (clazz == NULL) 3151 GOTO_exceptionThrown(); 3152 } 3153 SET_REGISTER(vdst, (u4) clazz); 3154 } 3155 FINISH(4); 3156OP_END 3157 3158/* File: c/OP_CHECK_CAST_JUMBO.cpp */ 3159HANDLE_OPCODE(OP_CHECK_CAST_JUMBO /*vBBBB, class@AAAAAAAA*/) 3160 { 3161 ClassObject* clazz; 3162 Object* obj; 3163 3164 EXPORT_PC(); 3165 3166 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class to check against */ 3167 vsrc1 = FETCH(3); 3168 ILOGV("|check-cast/jumbo v%d,class@0x%08x", vsrc1, ref); 3169 3170 obj = (Object*)GET_REGISTER(vsrc1); 3171 if (obj != NULL) { 3172#if defined(WITH_EXTRA_OBJECT_VALIDATION) 3173 if (!checkForNull(obj)) 3174 GOTO_exceptionThrown(); 3175#endif 3176 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 3177 if (clazz == NULL) { 3178 clazz = dvmResolveClass(curMethod->clazz, ref, false); 3179 if (clazz == NULL) 3180 GOTO_exceptionThrown(); 3181 } 3182 if (!dvmInstanceof(obj->clazz, clazz)) { 3183 dvmThrowClassCastException(obj->clazz, clazz); 3184 GOTO_exceptionThrown(); 3185 } 3186 } 3187 } 3188 FINISH(4); 3189OP_END 3190 3191/* File: c/OP_INSTANCE_OF_JUMBO.cpp */ 3192HANDLE_OPCODE(OP_INSTANCE_OF_JUMBO /*vBBBB, vCCCC, class@AAAAAAAA*/) 3193 { 3194 ClassObject* clazz; 3195 Object* obj; 3196 3197 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class to check against */ 3198 vdst = FETCH(3); 3199 vsrc1 = FETCH(4); /* object to check */ 3200 ILOGV("|instance-of/jumbo v%d,v%d,class@0x%08x", vdst, vsrc1, ref); 3201 3202 obj = (Object*)GET_REGISTER(vsrc1); 3203 if (obj == NULL) { 3204 SET_REGISTER(vdst, 0); 3205 } else { 3206#if defined(WITH_EXTRA_OBJECT_VALIDATION) 3207 if (!checkForNullExportPC(obj, fp, pc)) 3208 GOTO_exceptionThrown(); 3209#endif 3210 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 3211 if (clazz == NULL) { 3212 EXPORT_PC(); 3213 clazz = dvmResolveClass(curMethod->clazz, ref, true); 3214 if (clazz == NULL) 3215 GOTO_exceptionThrown(); 3216 } 3217 SET_REGISTER(vdst, dvmInstanceof(obj->clazz, clazz)); 3218 } 3219 } 3220 FINISH(5); 3221OP_END 3222 3223/* File: c/OP_NEW_INSTANCE_JUMBO.cpp */ 3224HANDLE_OPCODE(OP_NEW_INSTANCE_JUMBO /*vBBBB, class@AAAAAAAA*/) 3225 { 3226 ClassObject* clazz; 3227 Object* newObj; 3228 3229 EXPORT_PC(); 3230 3231 ref = FETCH(1) | (u4)FETCH(2) << 16; 3232 vdst = FETCH(3); 3233 ILOGV("|new-instance/jumbo v%d,class@0x%08x", vdst, ref); 3234 clazz = dvmDexGetResolvedClass(methodClassDex, ref); 3235 if (clazz == NULL) { 3236 clazz = dvmResolveClass(curMethod->clazz, ref, false); 3237 if (clazz == NULL) 3238 GOTO_exceptionThrown(); 3239 } 3240 3241 if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) 3242 GOTO_exceptionThrown(); 3243 3244#if defined(WITH_JIT) 3245 /* 3246 * The JIT needs dvmDexGetResolvedClass() to return non-null. 3247 * Since we use the portable interpreter to build the trace, this extra 3248 * check is not needed for mterp. 3249 */ 3250 if ((self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) && 3251 (!dvmDexGetResolvedClass(methodClassDex, ref))) { 3252 /* Class initialization is still ongoing - end the trace */ 3253 dvmJitEndTraceSelect(self,pc); 3254 } 3255#endif 3256 3257 /* 3258 * Verifier now tests for interface/abstract class. 3259 */ 3260 //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) { 3261 // dvmThrowExceptionWithClassMessage(gDvm.exInstantiationError, 3262 // clazz->descriptor); 3263 // GOTO_exceptionThrown(); 3264 //} 3265 newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK); 3266 if (newObj == NULL) 3267 GOTO_exceptionThrown(); 3268 SET_REGISTER(vdst, (u4) newObj); 3269 } 3270 FINISH(4); 3271OP_END 3272 3273/* File: c/OP_NEW_ARRAY_JUMBO.cpp */ 3274HANDLE_OPCODE(OP_NEW_ARRAY_JUMBO /*vBBBB, vCCCC, class@AAAAAAAA*/) 3275 { 3276 ClassObject* arrayClass; 3277 ArrayObject* newArray; 3278 s4 length; 3279 3280 EXPORT_PC(); 3281 3282 ref = FETCH(1) | (u4)FETCH(2) << 16; 3283 vdst = FETCH(3); 3284 vsrc1 = FETCH(4); /* length reg */ 3285 ILOGV("|new-array/jumbo v%d,v%d,class@0x%08x (%d elements)", 3286 vdst, vsrc1, ref, (s4) GET_REGISTER(vsrc1)); 3287 length = (s4) GET_REGISTER(vsrc1); 3288 if (length < 0) { 3289 dvmThrowNegativeArraySizeException(length); 3290 GOTO_exceptionThrown(); 3291 } 3292 arrayClass = dvmDexGetResolvedClass(methodClassDex, ref); 3293 if (arrayClass == NULL) { 3294 arrayClass = dvmResolveClass(curMethod->clazz, ref, false); 3295 if (arrayClass == NULL) 3296 GOTO_exceptionThrown(); 3297 } 3298 /* verifier guarantees this is an array class */ 3299 assert(dvmIsArrayClass(arrayClass)); 3300 assert(dvmIsClassInitialized(arrayClass)); 3301 3302 newArray = dvmAllocArrayByClass(arrayClass, length, ALLOC_DONT_TRACK); 3303 if (newArray == NULL) 3304 GOTO_exceptionThrown(); 3305 SET_REGISTER(vdst, (u4) newArray); 3306 } 3307 FINISH(5); 3308OP_END 3309 3310/* File: c/OP_FILLED_NEW_ARRAY_JUMBO.cpp */ 3311HANDLE_OPCODE(OP_FILLED_NEW_ARRAY_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, class@AAAAAAAA*/) 3312 GOTO_invoke(filledNewArray, true, true); 3313OP_END 3314 3315/* File: c/OP_IGET_JUMBO.cpp */ 3316HANDLE_IGET_X_JUMBO(OP_IGET_JUMBO, "", Int, ) 3317OP_END 3318 3319/* File: c/OP_IGET_WIDE_JUMBO.cpp */ 3320HANDLE_IGET_X_JUMBO(OP_IGET_WIDE_JUMBO, "-wide", Long, _WIDE) 3321OP_END 3322 3323/* File: c/OP_IGET_OBJECT_JUMBO.cpp */ 3324HANDLE_IGET_X_JUMBO(OP_IGET_OBJECT_JUMBO, "-object", Object, _AS_OBJECT) 3325OP_END 3326 3327/* File: c/OP_IGET_BOOLEAN_JUMBO.cpp */ 3328HANDLE_IGET_X_JUMBO(OP_IGET_BOOLEAN_JUMBO, "", Int, ) 3329OP_END 3330 3331/* File: c/OP_IGET_BYTE_JUMBO.cpp */ 3332HANDLE_IGET_X_JUMBO(OP_IGET_BYTE_JUMBO, "", Int, ) 3333OP_END 3334 3335/* File: c/OP_IGET_CHAR_JUMBO.cpp */ 3336HANDLE_IGET_X_JUMBO(OP_IGET_CHAR_JUMBO, "", Int, ) 3337OP_END 3338 3339/* File: c/OP_IGET_SHORT_JUMBO.cpp */ 3340HANDLE_IGET_X_JUMBO(OP_IGET_SHORT_JUMBO, "", Int, ) 3341OP_END 3342 3343/* File: c/OP_IPUT_JUMBO.cpp */ 3344HANDLE_IPUT_X_JUMBO(OP_IPUT_JUMBO, "", Int, ) 3345OP_END 3346 3347/* File: c/OP_IPUT_WIDE_JUMBO.cpp */ 3348HANDLE_IPUT_X_JUMBO(OP_IPUT_WIDE_JUMBO, "-wide", Long, _WIDE) 3349OP_END 3350 3351/* File: c/OP_IPUT_OBJECT_JUMBO.cpp */ 3352/* 3353 * The VM spec says we should verify that the reference being stored into 3354 * the field is assignment compatible. In practice, many popular VMs don't 3355 * do this because it slows down a very common operation. It's not so bad 3356 * for us, since "dexopt" quickens it whenever possible, but it's still an 3357 * issue. 3358 * 3359 * To make this spec-complaint, we'd need to add a ClassObject pointer to 3360 * the Field struct, resolve the field's type descriptor at link or class 3361 * init time, and then verify the type here. 3362 */ 3363HANDLE_IPUT_X_JUMBO(OP_IPUT_OBJECT_JUMBO, "-object", Object, _AS_OBJECT) 3364OP_END 3365 3366/* File: c/OP_IPUT_BOOLEAN_JUMBO.cpp */ 3367HANDLE_IPUT_X_JUMBO(OP_IPUT_BOOLEAN_JUMBO, "", Int, ) 3368OP_END 3369 3370/* File: c/OP_IPUT_BYTE_JUMBO.cpp */ 3371HANDLE_IPUT_X_JUMBO(OP_IPUT_BYTE_JUMBO, "", Int, ) 3372OP_END 3373 3374/* File: c/OP_IPUT_CHAR_JUMBO.cpp */ 3375HANDLE_IPUT_X_JUMBO(OP_IPUT_CHAR_JUMBO, "", Int, ) 3376OP_END 3377 3378/* File: c/OP_IPUT_SHORT_JUMBO.cpp */ 3379HANDLE_IPUT_X_JUMBO(OP_IPUT_SHORT_JUMBO, "", Int, ) 3380OP_END 3381 3382/* File: c/OP_SGET_JUMBO.cpp */ 3383HANDLE_SGET_X_JUMBO(OP_SGET_JUMBO, "", Int, ) 3384OP_END 3385 3386/* File: c/OP_SGET_WIDE_JUMBO.cpp */ 3387HANDLE_SGET_X_JUMBO(OP_SGET_WIDE_JUMBO, "-wide", Long, _WIDE) 3388OP_END 3389 3390/* File: c/OP_SGET_OBJECT_JUMBO.cpp */ 3391HANDLE_SGET_X_JUMBO(OP_SGET_OBJECT_JUMBO, "-object", Object, _AS_OBJECT) 3392OP_END 3393 3394/* File: c/OP_SGET_BOOLEAN_JUMBO.cpp */ 3395HANDLE_SGET_X_JUMBO(OP_SGET_BOOLEAN_JUMBO, "", Int, ) 3396OP_END 3397 3398/* File: c/OP_SGET_BYTE_JUMBO.cpp */ 3399HANDLE_SGET_X_JUMBO(OP_SGET_BYTE_JUMBO, "", Int, ) 3400OP_END 3401 3402/* File: c/OP_SGET_CHAR_JUMBO.cpp */ 3403HANDLE_SGET_X_JUMBO(OP_SGET_CHAR_JUMBO, "", Int, ) 3404OP_END 3405 3406/* File: c/OP_SGET_SHORT_JUMBO.cpp */ 3407HANDLE_SGET_X_JUMBO(OP_SGET_SHORT_JUMBO, "", Int, ) 3408OP_END 3409 3410/* File: c/OP_SPUT_JUMBO.cpp */ 3411HANDLE_SPUT_X_JUMBO(OP_SPUT_JUMBO, "", Int, ) 3412OP_END 3413 3414/* File: c/OP_SPUT_WIDE_JUMBO.cpp */ 3415HANDLE_SPUT_X_JUMBO(OP_SPUT_WIDE_JUMBO, "-wide", Long, _WIDE) 3416OP_END 3417 3418/* File: c/OP_SPUT_OBJECT_JUMBO.cpp */ 3419HANDLE_SPUT_X_JUMBO(OP_SPUT_OBJECT_JUMBO, "-object", Object, _AS_OBJECT) 3420OP_END 3421 3422/* File: c/OP_SPUT_BOOLEAN_JUMBO.cpp */ 3423HANDLE_SPUT_X_JUMBO(OP_SPUT_BOOLEAN_JUMBO, "", Int, ) 3424OP_END 3425 3426/* File: c/OP_SPUT_BYTE_JUMBO.cpp */ 3427HANDLE_SPUT_X_JUMBO(OP_SPUT_BYTE_JUMBO, "", Int, ) 3428OP_END 3429 3430/* File: c/OP_SPUT_CHAR_JUMBO.cpp */ 3431HANDLE_SPUT_X_JUMBO(OP_SPUT_CHAR_JUMBO, "", Int, ) 3432OP_END 3433 3434/* File: c/OP_SPUT_SHORT_JUMBO.cpp */ 3435HANDLE_SPUT_X_JUMBO(OP_SPUT_SHORT_JUMBO, "", Int, ) 3436OP_END 3437 3438/* File: c/OP_INVOKE_VIRTUAL_JUMBO.cpp */ 3439HANDLE_OPCODE(OP_INVOKE_VIRTUAL_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/) 3440 GOTO_invoke(invokeVirtual, true, true); 3441OP_END 3442 3443/* File: c/OP_INVOKE_SUPER_JUMBO.cpp */ 3444HANDLE_OPCODE(OP_INVOKE_SUPER_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/) 3445 GOTO_invoke(invokeSuper, true, true); 3446OP_END 3447 3448/* File: c/OP_INVOKE_DIRECT_JUMBO.cpp */ 3449HANDLE_OPCODE(OP_INVOKE_DIRECT_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/) 3450 GOTO_invoke(invokeDirect, true, true); 3451OP_END 3452 3453/* File: c/OP_INVOKE_STATIC_JUMBO.cpp */ 3454HANDLE_OPCODE(OP_INVOKE_STATIC_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/) 3455 GOTO_invoke(invokeStatic, true, true); 3456OP_END 3457 3458/* File: c/OP_INVOKE_INTERFACE_JUMBO.cpp */ 3459HANDLE_OPCODE(OP_INVOKE_INTERFACE_JUMBO /*{vCCCC..v(CCCC+BBBB-1)}, meth@AAAAAAAA*/) 3460 GOTO_invoke(invokeInterface, true, true); 3461OP_END 3462 3463/* File: c/OP_UNUSED_27FF.cpp */ 3464HANDLE_OPCODE(OP_UNUSED_27FF) 3465OP_END 3466 3467/* File: c/OP_UNUSED_28FF.cpp */ 3468HANDLE_OPCODE(OP_UNUSED_28FF) 3469OP_END 3470 3471/* File: c/OP_UNUSED_29FF.cpp */ 3472HANDLE_OPCODE(OP_UNUSED_29FF) 3473OP_END 3474 3475/* File: c/OP_UNUSED_2AFF.cpp */ 3476HANDLE_OPCODE(OP_UNUSED_2AFF) 3477OP_END 3478 3479/* File: c/OP_UNUSED_2BFF.cpp */ 3480HANDLE_OPCODE(OP_UNUSED_2BFF) 3481OP_END 3482 3483/* File: c/OP_UNUSED_2CFF.cpp */ 3484HANDLE_OPCODE(OP_UNUSED_2CFF) 3485OP_END 3486 3487/* File: c/OP_UNUSED_2DFF.cpp */ 3488HANDLE_OPCODE(OP_UNUSED_2DFF) 3489OP_END 3490 3491/* File: c/OP_UNUSED_2EFF.cpp */ 3492HANDLE_OPCODE(OP_UNUSED_2EFF) 3493OP_END 3494 3495/* File: c/OP_UNUSED_2FFF.cpp */ 3496HANDLE_OPCODE(OP_UNUSED_2FFF) 3497OP_END 3498 3499/* File: c/OP_UNUSED_30FF.cpp */ 3500HANDLE_OPCODE(OP_UNUSED_30FF) 3501OP_END 3502 3503/* File: c/OP_UNUSED_31FF.cpp */ 3504HANDLE_OPCODE(OP_UNUSED_31FF) 3505OP_END 3506 3507/* File: c/OP_UNUSED_32FF.cpp */ 3508HANDLE_OPCODE(OP_UNUSED_32FF) 3509OP_END 3510 3511/* File: c/OP_UNUSED_33FF.cpp */ 3512HANDLE_OPCODE(OP_UNUSED_33FF) 3513OP_END 3514 3515/* File: c/OP_UNUSED_34FF.cpp */ 3516HANDLE_OPCODE(OP_UNUSED_34FF) 3517OP_END 3518 3519/* File: c/OP_UNUSED_35FF.cpp */ 3520HANDLE_OPCODE(OP_UNUSED_35FF) 3521OP_END 3522 3523/* File: c/OP_UNUSED_36FF.cpp */ 3524HANDLE_OPCODE(OP_UNUSED_36FF) 3525OP_END 3526 3527/* File: c/OP_UNUSED_37FF.cpp */ 3528HANDLE_OPCODE(OP_UNUSED_37FF) 3529OP_END 3530 3531/* File: c/OP_UNUSED_38FF.cpp */ 3532HANDLE_OPCODE(OP_UNUSED_38FF) 3533OP_END 3534 3535/* File: c/OP_UNUSED_39FF.cpp */ 3536HANDLE_OPCODE(OP_UNUSED_39FF) 3537OP_END 3538 3539/* File: c/OP_UNUSED_3AFF.cpp */ 3540HANDLE_OPCODE(OP_UNUSED_3AFF) 3541OP_END 3542 3543/* File: c/OP_UNUSED_3BFF.cpp */ 3544HANDLE_OPCODE(OP_UNUSED_3BFF) 3545OP_END 3546 3547/* File: c/OP_UNUSED_3CFF.cpp */ 3548HANDLE_OPCODE(OP_UNUSED_3CFF) 3549OP_END 3550 3551/* File: c/OP_UNUSED_3DFF.cpp */ 3552HANDLE_OPCODE(OP_UNUSED_3DFF) 3553OP_END 3554 3555/* File: c/OP_UNUSED_3EFF.cpp */ 3556HANDLE_OPCODE(OP_UNUSED_3EFF) 3557OP_END 3558 3559/* File: c/OP_UNUSED_3FFF.cpp */ 3560HANDLE_OPCODE(OP_UNUSED_3FFF) 3561OP_END 3562 3563/* File: c/OP_UNUSED_40FF.cpp */ 3564HANDLE_OPCODE(OP_UNUSED_40FF) 3565OP_END 3566 3567/* File: c/OP_UNUSED_41FF.cpp */ 3568HANDLE_OPCODE(OP_UNUSED_41FF) 3569OP_END 3570 3571/* File: c/OP_UNUSED_42FF.cpp */ 3572HANDLE_OPCODE(OP_UNUSED_42FF) 3573OP_END 3574 3575/* File: c/OP_UNUSED_43FF.cpp */ 3576HANDLE_OPCODE(OP_UNUSED_43FF) 3577OP_END 3578 3579/* File: c/OP_UNUSED_44FF.cpp */ 3580HANDLE_OPCODE(OP_UNUSED_44FF) 3581OP_END 3582 3583/* File: c/OP_UNUSED_45FF.cpp */ 3584HANDLE_OPCODE(OP_UNUSED_45FF) 3585OP_END 3586 3587/* File: c/OP_UNUSED_46FF.cpp */ 3588HANDLE_OPCODE(OP_UNUSED_46FF) 3589OP_END 3590 3591/* File: c/OP_UNUSED_47FF.cpp */ 3592HANDLE_OPCODE(OP_UNUSED_47FF) 3593OP_END 3594 3595/* File: c/OP_UNUSED_48FF.cpp */ 3596HANDLE_OPCODE(OP_UNUSED_48FF) 3597OP_END 3598 3599/* File: c/OP_UNUSED_49FF.cpp */ 3600HANDLE_OPCODE(OP_UNUSED_49FF) 3601OP_END 3602 3603/* File: c/OP_UNUSED_4AFF.cpp */ 3604HANDLE_OPCODE(OP_UNUSED_4AFF) 3605OP_END 3606 3607/* File: c/OP_UNUSED_4BFF.cpp */ 3608HANDLE_OPCODE(OP_UNUSED_4BFF) 3609OP_END 3610 3611/* File: c/OP_UNUSED_4CFF.cpp */ 3612HANDLE_OPCODE(OP_UNUSED_4CFF) 3613OP_END 3614 3615/* File: c/OP_UNUSED_4DFF.cpp */ 3616HANDLE_OPCODE(OP_UNUSED_4DFF) 3617OP_END 3618 3619/* File: c/OP_UNUSED_4EFF.cpp */ 3620HANDLE_OPCODE(OP_UNUSED_4EFF) 3621OP_END 3622 3623/* File: c/OP_UNUSED_4FFF.cpp */ 3624HANDLE_OPCODE(OP_UNUSED_4FFF) 3625OP_END 3626 3627/* File: c/OP_UNUSED_50FF.cpp */ 3628HANDLE_OPCODE(OP_UNUSED_50FF) 3629OP_END 3630 3631/* File: c/OP_UNUSED_51FF.cpp */ 3632HANDLE_OPCODE(OP_UNUSED_51FF) 3633OP_END 3634 3635/* File: c/OP_UNUSED_52FF.cpp */ 3636HANDLE_OPCODE(OP_UNUSED_52FF) 3637OP_END 3638 3639/* File: c/OP_UNUSED_53FF.cpp */ 3640HANDLE_OPCODE(OP_UNUSED_53FF) 3641OP_END 3642 3643/* File: c/OP_UNUSED_54FF.cpp */ 3644HANDLE_OPCODE(OP_UNUSED_54FF) 3645OP_END 3646 3647/* File: c/OP_UNUSED_55FF.cpp */ 3648HANDLE_OPCODE(OP_UNUSED_55FF) 3649OP_END 3650 3651/* File: c/OP_UNUSED_56FF.cpp */ 3652HANDLE_OPCODE(OP_UNUSED_56FF) 3653OP_END 3654 3655/* File: c/OP_UNUSED_57FF.cpp */ 3656HANDLE_OPCODE(OP_UNUSED_57FF) 3657OP_END 3658 3659/* File: c/OP_UNUSED_58FF.cpp */ 3660HANDLE_OPCODE(OP_UNUSED_58FF) 3661OP_END 3662 3663/* File: c/OP_UNUSED_59FF.cpp */ 3664HANDLE_OPCODE(OP_UNUSED_59FF) 3665OP_END 3666 3667/* File: c/OP_UNUSED_5AFF.cpp */ 3668HANDLE_OPCODE(OP_UNUSED_5AFF) 3669OP_END 3670 3671/* File: c/OP_UNUSED_5BFF.cpp */ 3672HANDLE_OPCODE(OP_UNUSED_5BFF) 3673OP_END 3674 3675/* File: c/OP_UNUSED_5CFF.cpp */ 3676HANDLE_OPCODE(OP_UNUSED_5CFF) 3677OP_END 3678 3679/* File: c/OP_UNUSED_5DFF.cpp */ 3680HANDLE_OPCODE(OP_UNUSED_5DFF) 3681OP_END 3682 3683/* File: c/OP_UNUSED_5EFF.cpp */ 3684HANDLE_OPCODE(OP_UNUSED_5EFF) 3685OP_END 3686 3687/* File: c/OP_UNUSED_5FFF.cpp */ 3688HANDLE_OPCODE(OP_UNUSED_5FFF) 3689OP_END 3690 3691/* File: c/OP_UNUSED_60FF.cpp */ 3692HANDLE_OPCODE(OP_UNUSED_60FF) 3693OP_END 3694 3695/* File: c/OP_UNUSED_61FF.cpp */ 3696HANDLE_OPCODE(OP_UNUSED_61FF) 3697OP_END 3698 3699/* File: c/OP_UNUSED_62FF.cpp */ 3700HANDLE_OPCODE(OP_UNUSED_62FF) 3701OP_END 3702 3703/* File: c/OP_UNUSED_63FF.cpp */ 3704HANDLE_OPCODE(OP_UNUSED_63FF) 3705OP_END 3706 3707/* File: c/OP_UNUSED_64FF.cpp */ 3708HANDLE_OPCODE(OP_UNUSED_64FF) 3709OP_END 3710 3711/* File: c/OP_UNUSED_65FF.cpp */ 3712HANDLE_OPCODE(OP_UNUSED_65FF) 3713OP_END 3714 3715/* File: c/OP_UNUSED_66FF.cpp */ 3716HANDLE_OPCODE(OP_UNUSED_66FF) 3717OP_END 3718 3719/* File: c/OP_UNUSED_67FF.cpp */ 3720HANDLE_OPCODE(OP_UNUSED_67FF) 3721OP_END 3722 3723/* File: c/OP_UNUSED_68FF.cpp */ 3724HANDLE_OPCODE(OP_UNUSED_68FF) 3725OP_END 3726 3727/* File: c/OP_UNUSED_69FF.cpp */ 3728HANDLE_OPCODE(OP_UNUSED_69FF) 3729OP_END 3730 3731/* File: c/OP_UNUSED_6AFF.cpp */ 3732HANDLE_OPCODE(OP_UNUSED_6AFF) 3733OP_END 3734 3735/* File: c/OP_UNUSED_6BFF.cpp */ 3736HANDLE_OPCODE(OP_UNUSED_6BFF) 3737OP_END 3738 3739/* File: c/OP_UNUSED_6CFF.cpp */ 3740HANDLE_OPCODE(OP_UNUSED_6CFF) 3741OP_END 3742 3743/* File: c/OP_UNUSED_6DFF.cpp */ 3744HANDLE_OPCODE(OP_UNUSED_6DFF) 3745OP_END 3746 3747/* File: c/OP_UNUSED_6EFF.cpp */ 3748HANDLE_OPCODE(OP_UNUSED_6EFF) 3749OP_END 3750 3751/* File: c/OP_UNUSED_6FFF.cpp */ 3752HANDLE_OPCODE(OP_UNUSED_6FFF) 3753OP_END 3754 3755/* File: c/OP_UNUSED_70FF.cpp */ 3756HANDLE_OPCODE(OP_UNUSED_70FF) 3757OP_END 3758 3759/* File: c/OP_UNUSED_71FF.cpp */ 3760HANDLE_OPCODE(OP_UNUSED_71FF) 3761OP_END 3762 3763/* File: c/OP_UNUSED_72FF.cpp */ 3764HANDLE_OPCODE(OP_UNUSED_72FF) 3765OP_END 3766 3767/* File: c/OP_UNUSED_73FF.cpp */ 3768HANDLE_OPCODE(OP_UNUSED_73FF) 3769OP_END 3770 3771/* File: c/OP_UNUSED_74FF.cpp */ 3772HANDLE_OPCODE(OP_UNUSED_74FF) 3773OP_END 3774 3775/* File: c/OP_UNUSED_75FF.cpp */ 3776HANDLE_OPCODE(OP_UNUSED_75FF) 3777OP_END 3778 3779/* File: c/OP_UNUSED_76FF.cpp */ 3780HANDLE_OPCODE(OP_UNUSED_76FF) 3781OP_END 3782 3783/* File: c/OP_UNUSED_77FF.cpp */ 3784HANDLE_OPCODE(OP_UNUSED_77FF) 3785OP_END 3786 3787/* File: c/OP_UNUSED_78FF.cpp */ 3788HANDLE_OPCODE(OP_UNUSED_78FF) 3789OP_END 3790 3791/* File: c/OP_UNUSED_79FF.cpp */ 3792HANDLE_OPCODE(OP_UNUSED_79FF) 3793OP_END 3794 3795/* File: c/OP_UNUSED_7AFF.cpp */ 3796HANDLE_OPCODE(OP_UNUSED_7AFF) 3797OP_END 3798 3799/* File: c/OP_UNUSED_7BFF.cpp */ 3800HANDLE_OPCODE(OP_UNUSED_7BFF) 3801OP_END 3802 3803/* File: c/OP_UNUSED_7CFF.cpp */ 3804HANDLE_OPCODE(OP_UNUSED_7CFF) 3805OP_END 3806 3807/* File: c/OP_UNUSED_7DFF.cpp */ 3808HANDLE_OPCODE(OP_UNUSED_7DFF) 3809OP_END 3810 3811/* File: c/OP_UNUSED_7EFF.cpp */ 3812HANDLE_OPCODE(OP_UNUSED_7EFF) 3813OP_END 3814 3815/* File: c/OP_UNUSED_7FFF.cpp */ 3816HANDLE_OPCODE(OP_UNUSED_7FFF) 3817OP_END 3818 3819/* File: c/OP_UNUSED_80FF.cpp */ 3820HANDLE_OPCODE(OP_UNUSED_80FF) 3821OP_END 3822 3823/* File: c/OP_UNUSED_81FF.cpp */ 3824HANDLE_OPCODE(OP_UNUSED_81FF) 3825OP_END 3826 3827/* File: c/OP_UNUSED_82FF.cpp */ 3828HANDLE_OPCODE(OP_UNUSED_82FF) 3829OP_END 3830 3831/* File: c/OP_UNUSED_83FF.cpp */ 3832HANDLE_OPCODE(OP_UNUSED_83FF) 3833OP_END 3834 3835/* File: c/OP_UNUSED_84FF.cpp */ 3836HANDLE_OPCODE(OP_UNUSED_84FF) 3837OP_END 3838 3839/* File: c/OP_UNUSED_85FF.cpp */ 3840HANDLE_OPCODE(OP_UNUSED_85FF) 3841OP_END 3842 3843/* File: c/OP_UNUSED_86FF.cpp */ 3844HANDLE_OPCODE(OP_UNUSED_86FF) 3845OP_END 3846 3847/* File: c/OP_UNUSED_87FF.cpp */ 3848HANDLE_OPCODE(OP_UNUSED_87FF) 3849OP_END 3850 3851/* File: c/OP_UNUSED_88FF.cpp */ 3852HANDLE_OPCODE(OP_UNUSED_88FF) 3853OP_END 3854 3855/* File: c/OP_UNUSED_89FF.cpp */ 3856HANDLE_OPCODE(OP_UNUSED_89FF) 3857OP_END 3858 3859/* File: c/OP_UNUSED_8AFF.cpp */ 3860HANDLE_OPCODE(OP_UNUSED_8AFF) 3861OP_END 3862 3863/* File: c/OP_UNUSED_8BFF.cpp */ 3864HANDLE_OPCODE(OP_UNUSED_8BFF) 3865OP_END 3866 3867/* File: c/OP_UNUSED_8CFF.cpp */ 3868HANDLE_OPCODE(OP_UNUSED_8CFF) 3869OP_END 3870 3871/* File: c/OP_UNUSED_8DFF.cpp */ 3872HANDLE_OPCODE(OP_UNUSED_8DFF) 3873OP_END 3874 3875/* File: c/OP_UNUSED_8EFF.cpp */ 3876HANDLE_OPCODE(OP_UNUSED_8EFF) 3877OP_END 3878 3879/* File: c/OP_UNUSED_8FFF.cpp */ 3880HANDLE_OPCODE(OP_UNUSED_8FFF) 3881OP_END 3882 3883/* File: c/OP_UNUSED_90FF.cpp */ 3884HANDLE_OPCODE(OP_UNUSED_90FF) 3885OP_END 3886 3887/* File: c/OP_UNUSED_91FF.cpp */ 3888HANDLE_OPCODE(OP_UNUSED_91FF) 3889OP_END 3890 3891/* File: c/OP_UNUSED_92FF.cpp */ 3892HANDLE_OPCODE(OP_UNUSED_92FF) 3893OP_END 3894 3895/* File: c/OP_UNUSED_93FF.cpp */ 3896HANDLE_OPCODE(OP_UNUSED_93FF) 3897OP_END 3898 3899/* File: c/OP_UNUSED_94FF.cpp */ 3900HANDLE_OPCODE(OP_UNUSED_94FF) 3901OP_END 3902 3903/* File: c/OP_UNUSED_95FF.cpp */ 3904HANDLE_OPCODE(OP_UNUSED_95FF) 3905OP_END 3906 3907/* File: c/OP_UNUSED_96FF.cpp */ 3908HANDLE_OPCODE(OP_UNUSED_96FF) 3909OP_END 3910 3911/* File: c/OP_UNUSED_97FF.cpp */ 3912HANDLE_OPCODE(OP_UNUSED_97FF) 3913OP_END 3914 3915/* File: c/OP_UNUSED_98FF.cpp */ 3916HANDLE_OPCODE(OP_UNUSED_98FF) 3917OP_END 3918 3919/* File: c/OP_UNUSED_99FF.cpp */ 3920HANDLE_OPCODE(OP_UNUSED_99FF) 3921OP_END 3922 3923/* File: c/OP_UNUSED_9AFF.cpp */ 3924HANDLE_OPCODE(OP_UNUSED_9AFF) 3925OP_END 3926 3927/* File: c/OP_UNUSED_9BFF.cpp */ 3928HANDLE_OPCODE(OP_UNUSED_9BFF) 3929OP_END 3930 3931/* File: c/OP_UNUSED_9CFF.cpp */ 3932HANDLE_OPCODE(OP_UNUSED_9CFF) 3933OP_END 3934 3935/* File: c/OP_UNUSED_9DFF.cpp */ 3936HANDLE_OPCODE(OP_UNUSED_9DFF) 3937OP_END 3938 3939/* File: c/OP_UNUSED_9EFF.cpp */ 3940HANDLE_OPCODE(OP_UNUSED_9EFF) 3941OP_END 3942 3943/* File: c/OP_UNUSED_9FFF.cpp */ 3944HANDLE_OPCODE(OP_UNUSED_9FFF) 3945OP_END 3946 3947/* File: c/OP_UNUSED_A0FF.cpp */ 3948HANDLE_OPCODE(OP_UNUSED_A0FF) 3949OP_END 3950 3951/* File: c/OP_UNUSED_A1FF.cpp */ 3952HANDLE_OPCODE(OP_UNUSED_A1FF) 3953OP_END 3954 3955/* File: c/OP_UNUSED_A2FF.cpp */ 3956HANDLE_OPCODE(OP_UNUSED_A2FF) 3957OP_END 3958 3959/* File: c/OP_UNUSED_A3FF.cpp */ 3960HANDLE_OPCODE(OP_UNUSED_A3FF) 3961OP_END 3962 3963/* File: c/OP_UNUSED_A4FF.cpp */ 3964HANDLE_OPCODE(OP_UNUSED_A4FF) 3965OP_END 3966 3967/* File: c/OP_UNUSED_A5FF.cpp */ 3968HANDLE_OPCODE(OP_UNUSED_A5FF) 3969OP_END 3970 3971/* File: c/OP_UNUSED_A6FF.cpp */ 3972HANDLE_OPCODE(OP_UNUSED_A6FF) 3973OP_END 3974 3975/* File: c/OP_UNUSED_A7FF.cpp */ 3976HANDLE_OPCODE(OP_UNUSED_A7FF) 3977OP_END 3978 3979/* File: c/OP_UNUSED_A8FF.cpp */ 3980HANDLE_OPCODE(OP_UNUSED_A8FF) 3981OP_END 3982 3983/* File: c/OP_UNUSED_A9FF.cpp */ 3984HANDLE_OPCODE(OP_UNUSED_A9FF) 3985OP_END 3986 3987/* File: c/OP_UNUSED_AAFF.cpp */ 3988HANDLE_OPCODE(OP_UNUSED_AAFF) 3989OP_END 3990 3991/* File: c/OP_UNUSED_ABFF.cpp */ 3992HANDLE_OPCODE(OP_UNUSED_ABFF) 3993OP_END 3994 3995/* File: c/OP_UNUSED_ACFF.cpp */ 3996HANDLE_OPCODE(OP_UNUSED_ACFF) 3997OP_END 3998 3999/* File: c/OP_UNUSED_ADFF.cpp */ 4000HANDLE_OPCODE(OP_UNUSED_ADFF) 4001OP_END 4002 4003/* File: c/OP_UNUSED_AEFF.cpp */ 4004HANDLE_OPCODE(OP_UNUSED_AEFF) 4005OP_END 4006 4007/* File: c/OP_UNUSED_AFFF.cpp */ 4008HANDLE_OPCODE(OP_UNUSED_AFFF) 4009OP_END 4010 4011/* File: c/OP_UNUSED_B0FF.cpp */ 4012HANDLE_OPCODE(OP_UNUSED_B0FF) 4013OP_END 4014 4015/* File: c/OP_UNUSED_B1FF.cpp */ 4016HANDLE_OPCODE(OP_UNUSED_B1FF) 4017OP_END 4018 4019/* File: c/OP_UNUSED_B2FF.cpp */ 4020HANDLE_OPCODE(OP_UNUSED_B2FF) 4021OP_END 4022 4023/* File: c/OP_UNUSED_B3FF.cpp */ 4024HANDLE_OPCODE(OP_UNUSED_B3FF) 4025OP_END 4026 4027/* File: c/OP_UNUSED_B4FF.cpp */ 4028HANDLE_OPCODE(OP_UNUSED_B4FF) 4029OP_END 4030 4031/* File: c/OP_UNUSED_B5FF.cpp */ 4032HANDLE_OPCODE(OP_UNUSED_B5FF) 4033OP_END 4034 4035/* File: c/OP_UNUSED_B6FF.cpp */ 4036HANDLE_OPCODE(OP_UNUSED_B6FF) 4037OP_END 4038 4039/* File: c/OP_UNUSED_B7FF.cpp */ 4040HANDLE_OPCODE(OP_UNUSED_B7FF) 4041OP_END 4042 4043/* File: c/OP_UNUSED_B8FF.cpp */ 4044HANDLE_OPCODE(OP_UNUSED_B8FF) 4045OP_END 4046 4047/* File: c/OP_UNUSED_B9FF.cpp */ 4048HANDLE_OPCODE(OP_UNUSED_B9FF) 4049OP_END 4050 4051/* File: c/OP_UNUSED_BAFF.cpp */ 4052HANDLE_OPCODE(OP_UNUSED_BAFF) 4053OP_END 4054 4055/* File: c/OP_UNUSED_BBFF.cpp */ 4056HANDLE_OPCODE(OP_UNUSED_BBFF) 4057OP_END 4058 4059/* File: c/OP_UNUSED_BCFF.cpp */ 4060HANDLE_OPCODE(OP_UNUSED_BCFF) 4061OP_END 4062 4063/* File: c/OP_UNUSED_BDFF.cpp */ 4064HANDLE_OPCODE(OP_UNUSED_BDFF) 4065OP_END 4066 4067/* File: c/OP_UNUSED_BEFF.cpp */ 4068HANDLE_OPCODE(OP_UNUSED_BEFF) 4069OP_END 4070 4071/* File: c/OP_UNUSED_BFFF.cpp */ 4072HANDLE_OPCODE(OP_UNUSED_BFFF) 4073OP_END 4074 4075/* File: c/OP_UNUSED_C0FF.cpp */ 4076HANDLE_OPCODE(OP_UNUSED_C0FF) 4077OP_END 4078 4079/* File: c/OP_UNUSED_C1FF.cpp */ 4080HANDLE_OPCODE(OP_UNUSED_C1FF) 4081OP_END 4082 4083/* File: c/OP_UNUSED_C2FF.cpp */ 4084HANDLE_OPCODE(OP_UNUSED_C2FF) 4085OP_END 4086 4087/* File: c/OP_UNUSED_C3FF.cpp */ 4088HANDLE_OPCODE(OP_UNUSED_C3FF) 4089OP_END 4090 4091/* File: c/OP_UNUSED_C4FF.cpp */ 4092HANDLE_OPCODE(OP_UNUSED_C4FF) 4093OP_END 4094 4095/* File: c/OP_UNUSED_C5FF.cpp */ 4096HANDLE_OPCODE(OP_UNUSED_C5FF) 4097OP_END 4098 4099/* File: c/OP_UNUSED_C6FF.cpp */ 4100HANDLE_OPCODE(OP_UNUSED_C6FF) 4101OP_END 4102 4103/* File: c/OP_UNUSED_C7FF.cpp */ 4104HANDLE_OPCODE(OP_UNUSED_C7FF) 4105OP_END 4106 4107/* File: c/OP_UNUSED_C8FF.cpp */ 4108HANDLE_OPCODE(OP_UNUSED_C8FF) 4109OP_END 4110 4111/* File: c/OP_UNUSED_C9FF.cpp */ 4112HANDLE_OPCODE(OP_UNUSED_C9FF) 4113OP_END 4114 4115/* File: c/OP_UNUSED_CAFF.cpp */ 4116HANDLE_OPCODE(OP_UNUSED_CAFF) 4117OP_END 4118 4119/* File: c/OP_UNUSED_CBFF.cpp */ 4120HANDLE_OPCODE(OP_UNUSED_CBFF) 4121OP_END 4122 4123/* File: c/OP_UNUSED_CCFF.cpp */ 4124HANDLE_OPCODE(OP_UNUSED_CCFF) 4125OP_END 4126 4127/* File: c/OP_UNUSED_CDFF.cpp */ 4128HANDLE_OPCODE(OP_UNUSED_CDFF) 4129OP_END 4130 4131/* File: c/OP_UNUSED_CEFF.cpp */ 4132HANDLE_OPCODE(OP_UNUSED_CEFF) 4133OP_END 4134 4135/* File: c/OP_UNUSED_CFFF.cpp */ 4136HANDLE_OPCODE(OP_UNUSED_CFFF) 4137OP_END 4138 4139/* File: c/OP_UNUSED_D0FF.cpp */ 4140HANDLE_OPCODE(OP_UNUSED_D0FF) 4141OP_END 4142 4143/* File: c/OP_UNUSED_D1FF.cpp */ 4144HANDLE_OPCODE(OP_UNUSED_D1FF) 4145OP_END 4146 4147/* File: c/OP_UNUSED_D2FF.cpp */ 4148HANDLE_OPCODE(OP_UNUSED_D2FF) 4149OP_END 4150 4151/* File: c/OP_UNUSED_D3FF.cpp */ 4152HANDLE_OPCODE(OP_UNUSED_D3FF) 4153OP_END 4154 4155/* File: c/OP_UNUSED_D4FF.cpp */ 4156HANDLE_OPCODE(OP_UNUSED_D4FF) 4157OP_END 4158 4159/* File: c/OP_UNUSED_D5FF.cpp */ 4160HANDLE_OPCODE(OP_UNUSED_D5FF) 4161OP_END 4162 4163/* File: c/OP_UNUSED_D6FF.cpp */ 4164HANDLE_OPCODE(OP_UNUSED_D6FF) 4165OP_END 4166 4167/* File: c/OP_UNUSED_D7FF.cpp */ 4168HANDLE_OPCODE(OP_UNUSED_D7FF) 4169OP_END 4170 4171/* File: c/OP_UNUSED_D8FF.cpp */ 4172HANDLE_OPCODE(OP_UNUSED_D8FF) 4173OP_END 4174 4175/* File: c/OP_UNUSED_D9FF.cpp */ 4176HANDLE_OPCODE(OP_UNUSED_D9FF) 4177OP_END 4178 4179/* File: c/OP_UNUSED_DAFF.cpp */ 4180HANDLE_OPCODE(OP_UNUSED_DAFF) 4181OP_END 4182 4183/* File: c/OP_UNUSED_DBFF.cpp */ 4184HANDLE_OPCODE(OP_UNUSED_DBFF) 4185OP_END 4186 4187/* File: c/OP_UNUSED_DCFF.cpp */ 4188HANDLE_OPCODE(OP_UNUSED_DCFF) 4189OP_END 4190 4191/* File: c/OP_UNUSED_DDFF.cpp */ 4192HANDLE_OPCODE(OP_UNUSED_DDFF) 4193OP_END 4194 4195/* File: c/OP_UNUSED_DEFF.cpp */ 4196HANDLE_OPCODE(OP_UNUSED_DEFF) 4197OP_END 4198 4199/* File: c/OP_UNUSED_DFFF.cpp */ 4200HANDLE_OPCODE(OP_UNUSED_DFFF) 4201OP_END 4202 4203/* File: c/OP_UNUSED_E0FF.cpp */ 4204HANDLE_OPCODE(OP_UNUSED_E0FF) 4205OP_END 4206 4207/* File: c/OP_UNUSED_E1FF.cpp */ 4208HANDLE_OPCODE(OP_UNUSED_E1FF) 4209OP_END 4210 4211/* File: c/OP_UNUSED_E2FF.cpp */ 4212HANDLE_OPCODE(OP_UNUSED_E2FF) 4213OP_END 4214 4215/* File: c/OP_UNUSED_E3FF.cpp */ 4216HANDLE_OPCODE(OP_UNUSED_E3FF) 4217OP_END 4218 4219/* File: c/OP_UNUSED_E4FF.cpp */ 4220HANDLE_OPCODE(OP_UNUSED_E4FF) 4221OP_END 4222 4223/* File: c/OP_UNUSED_E5FF.cpp */ 4224HANDLE_OPCODE(OP_UNUSED_E5FF) 4225OP_END 4226 4227/* File: c/OP_UNUSED_E6FF.cpp */ 4228HANDLE_OPCODE(OP_UNUSED_E6FF) 4229OP_END 4230 4231/* File: c/OP_UNUSED_E7FF.cpp */ 4232HANDLE_OPCODE(OP_UNUSED_E7FF) 4233OP_END 4234 4235/* File: c/OP_UNUSED_E8FF.cpp */ 4236HANDLE_OPCODE(OP_UNUSED_E8FF) 4237OP_END 4238 4239/* File: c/OP_UNUSED_E9FF.cpp */ 4240HANDLE_OPCODE(OP_UNUSED_E9FF) 4241OP_END 4242 4243/* File: c/OP_UNUSED_EAFF.cpp */ 4244HANDLE_OPCODE(OP_UNUSED_EAFF) 4245OP_END 4246 4247/* File: c/OP_UNUSED_EBFF.cpp */ 4248HANDLE_OPCODE(OP_UNUSED_EBFF) 4249OP_END 4250 4251/* File: c/OP_UNUSED_ECFF.cpp */ 4252HANDLE_OPCODE(OP_UNUSED_ECFF) 4253OP_END 4254 4255/* File: c/OP_UNUSED_EDFF.cpp */ 4256HANDLE_OPCODE(OP_UNUSED_EDFF) 4257OP_END 4258 4259/* File: c/OP_UNUSED_EEFF.cpp */ 4260HANDLE_OPCODE(OP_UNUSED_EEFF) 4261OP_END 4262 4263/* File: c/OP_UNUSED_EFFF.cpp */ 4264HANDLE_OPCODE(OP_UNUSED_EFFF) 4265OP_END 4266 4267/* File: c/OP_UNUSED_F0FF.cpp */ 4268HANDLE_OPCODE(OP_UNUSED_F0FF) 4269OP_END 4270 4271/* File: c/OP_UNUSED_F1FF.cpp */ 4272HANDLE_OPCODE(OP_UNUSED_F1FF) 4273 /* 4274 * In portable interp, most unused opcodes will fall through to here. 4275 */ 4276 LOGE("unknown opcode 0x%04x", inst); 4277 dvmAbort(); 4278 FINISH(1); 4279OP_END 4280 4281/* File: c/OP_INVOKE_OBJECT_INIT_JUMBO.cpp */ 4282HANDLE_OPCODE(OP_INVOKE_OBJECT_INIT_JUMBO /*{vCCCC..vNNNN}, meth@AAAAAAAA*/) 4283 { 4284 Object* obj; 4285 4286 vsrc1 = FETCH(4); /* reg number of "this" pointer */ 4287 obj = GET_REGISTER_AS_OBJECT(vsrc1); 4288 4289 if (!checkForNullExportPC(obj, fp, pc)) 4290 GOTO_exceptionThrown(); 4291 4292 /* 4293 * The object should be marked "finalizable" when Object.<init> 4294 * completes normally. We're going to assume it does complete 4295 * (by virtue of being nothing but a return-void) and set it now. 4296 */ 4297 if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISFINALIZABLE)) { 4298 EXPORT_PC(); 4299 dvmSetFinalizable(obj); 4300 if (dvmGetException(self)) 4301 GOTO_exceptionThrown(); 4302 } 4303 4304 if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) { 4305 /* behave like OP_INVOKE_DIRECT_RANGE */ 4306 GOTO_invoke(invokeDirect, true, true); 4307 } 4308 FINISH(5); 4309 } 4310OP_END 4311 4312/* File: c/OP_IGET_VOLATILE_JUMBO.cpp */ 4313HANDLE_IGET_X_JUMBO(OP_IGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, ) 4314OP_END 4315 4316/* File: c/OP_IGET_WIDE_VOLATILE_JUMBO.cpp */ 4317HANDLE_IGET_X_JUMBO(OP_IGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE) 4318OP_END 4319 4320/* File: c/OP_IGET_OBJECT_VOLATILE_JUMBO.cpp */ 4321HANDLE_IGET_X_JUMBO(OP_IGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT) 4322OP_END 4323 4324/* File: c/OP_IPUT_VOLATILE_JUMBO.cpp */ 4325HANDLE_IPUT_X_JUMBO(OP_IPUT_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, ) 4326OP_END 4327 4328/* File: c/OP_IPUT_WIDE_VOLATILE_JUMBO.cpp */ 4329HANDLE_IPUT_X_JUMBO(OP_IPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE) 4330OP_END 4331 4332/* File: c/OP_IPUT_OBJECT_VOLATILE_JUMBO.cpp */ 4333HANDLE_IPUT_X_JUMBO(OP_IPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT) 4334OP_END 4335 4336/* File: c/OP_SGET_VOLATILE_JUMBO.cpp */ 4337HANDLE_SGET_X_JUMBO(OP_SGET_VOLATILE_JUMBO, "-volatile/jumbo", IntVolatile, ) 4338OP_END 4339 4340/* File: c/OP_SGET_WIDE_VOLATILE_JUMBO.cpp */ 4341HANDLE_SGET_X_JUMBO(OP_SGET_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE) 4342OP_END 4343 4344/* File: c/OP_SGET_OBJECT_VOLATILE_JUMBO.cpp */ 4345HANDLE_SGET_X_JUMBO(OP_SGET_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT) 4346OP_END 4347 4348/* File: c/OP_SPUT_VOLATILE_JUMBO.cpp */ 4349HANDLE_SPUT_X_JUMBO(OP_SPUT_VOLATILE_JUMBO, "-volatile", IntVolatile, ) 4350OP_END 4351 4352/* File: c/OP_SPUT_WIDE_VOLATILE_JUMBO.cpp */ 4353HANDLE_SPUT_X_JUMBO(OP_SPUT_WIDE_VOLATILE_JUMBO, "-wide-volatile/jumbo", LongVolatile, _WIDE) 4354OP_END 4355 4356/* File: c/OP_SPUT_OBJECT_VOLATILE_JUMBO.cpp */ 4357HANDLE_SPUT_X_JUMBO(OP_SPUT_OBJECT_VOLATILE_JUMBO, "-object-volatile/jumbo", ObjectVolatile, _AS_OBJECT) 4358OP_END 4359 4360/* File: c/OP_THROW_VERIFICATION_ERROR_JUMBO.cpp */ 4361HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR_JUMBO) 4362 EXPORT_PC(); 4363 vsrc1 = FETCH(3); 4364 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class/field/method ref */ 4365 dvmThrowVerificationError(curMethod, vsrc1, ref); 4366 GOTO_exceptionThrown(); 4367OP_END 4368 4369/* File: c/gotoTargets.cpp */ 4370/* 4371 * C footer. This has some common code shared by the various targets. 4372 */ 4373 4374/* 4375 * Everything from here on is a "goto target". In the basic interpreter 4376 * we jump into these targets and then jump directly to the handler for 4377 * next instruction. Here, these are subroutines that return to the caller. 4378 */ 4379 4380GOTO_TARGET(filledNewArray, bool methodCallRange, bool jumboFormat) 4381 { 4382 ClassObject* arrayClass; 4383 ArrayObject* newArray; 4384 u4* contents; 4385 char typeCh; 4386 int i; 4387 u4 arg5; 4388 4389 EXPORT_PC(); 4390 4391 if (jumboFormat) { 4392 ref = FETCH(1) | (u4)FETCH(2) << 16; /* class ref */ 4393 vsrc1 = FETCH(3); /* #of elements */ 4394 vdst = FETCH(4); /* range base */ 4395 arg5 = -1; /* silence compiler warning */ 4396 ILOGV("|filled-new-array/jumbo args=%d @0x%08x {regs=v%d-v%d}", 4397 vsrc1, ref, vdst, vdst+vsrc1-1); 4398 } else { 4399 ref = FETCH(1); /* class ref */ 4400 vdst = FETCH(2); /* first 4 regs -or- range base */ 4401 4402 if (methodCallRange) { 4403 vsrc1 = INST_AA(inst); /* #of elements */ 4404 arg5 = -1; /* silence compiler warning */ 4405 ILOGV("|filled-new-array-range args=%d @0x%04x {regs=v%d-v%d}", 4406 vsrc1, ref, vdst, vdst+vsrc1-1); 4407 } else { 4408 arg5 = INST_A(inst); 4409 vsrc1 = INST_B(inst); /* #of elements */ 4410 ILOGV("|filled-new-array args=%d @0x%04x {regs=0x%04x %x}", 4411 vsrc1, ref, vdst, arg5); 4412 } 4413 } 4414 4415 /* 4416 * Resolve the array class. 4417 */ 4418 arrayClass = dvmDexGetResolvedClass(methodClassDex, ref); 4419 if (arrayClass == NULL) { 4420 arrayClass = dvmResolveClass(curMethod->clazz, ref, false); 4421 if (arrayClass == NULL) 4422 GOTO_exceptionThrown(); 4423 } 4424 /* 4425 if (!dvmIsArrayClass(arrayClass)) { 4426 dvmThrowRuntimeException( 4427 "filled-new-array needs array class"); 4428 GOTO_exceptionThrown(); 4429 } 4430 */ 4431 /* verifier guarantees this is an array class */ 4432 assert(dvmIsArrayClass(arrayClass)); 4433 assert(dvmIsClassInitialized(arrayClass)); 4434 4435 /* 4436 * Create an array of the specified type. 4437 */ 4438 LOGVV("+++ filled-new-array type is '%s'", arrayClass->descriptor); 4439 typeCh = arrayClass->descriptor[1]; 4440 if (typeCh == 'D' || typeCh == 'J') { 4441 /* category 2 primitives not allowed */ 4442 dvmThrowRuntimeException("bad filled array req"); 4443 GOTO_exceptionThrown(); 4444 } else if (typeCh != 'L' && typeCh != '[' && typeCh != 'I') { 4445 /* TODO: requires multiple "fill in" loops with different widths */ 4446 LOGE("non-int primitives not implemented"); 4447 dvmThrowInternalError( 4448 "filled-new-array not implemented for anything but 'int'"); 4449 GOTO_exceptionThrown(); 4450 } 4451 4452 newArray = dvmAllocArrayByClass(arrayClass, vsrc1, ALLOC_DONT_TRACK); 4453 if (newArray == NULL) 4454 GOTO_exceptionThrown(); 4455 4456 /* 4457 * Fill in the elements. It's legal for vsrc1 to be zero. 4458 */ 4459 contents = (u4*)(void*)newArray->contents; 4460 if (methodCallRange) { 4461 for (i = 0; i < vsrc1; i++) 4462 contents[i] = GET_REGISTER(vdst+i); 4463 } else { 4464 assert(vsrc1 <= 5); 4465 if (vsrc1 == 5) { 4466 contents[4] = GET_REGISTER(arg5); 4467 vsrc1--; 4468 } 4469 for (i = 0; i < vsrc1; i++) { 4470 contents[i] = GET_REGISTER(vdst & 0x0f); 4471 vdst >>= 4; 4472 } 4473 } 4474 if (typeCh == 'L' || typeCh == '[') { 4475 dvmWriteBarrierArray(newArray, 0, newArray->length); 4476 } 4477 4478 retval.l = (Object*)newArray; 4479 } 4480 if (jumboFormat) { 4481 FINISH(5); 4482 } else { 4483 FINISH(3); 4484 } 4485GOTO_TARGET_END 4486 4487 4488GOTO_TARGET(invokeVirtual, bool methodCallRange, bool jumboFormat) 4489 { 4490 Method* baseMethod; 4491 Object* thisPtr; 4492 4493 EXPORT_PC(); 4494 4495 if (jumboFormat) { 4496 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */ 4497 vsrc1 = FETCH(3); /* count */ 4498 vdst = FETCH(4); /* first reg */ 4499 ADJUST_PC(2); /* advance pc partially to make returns easier */ 4500 ILOGV("|invoke-virtual/jumbo args=%d @0x%08x {regs=v%d-v%d}", 4501 vsrc1, ref, vdst, vdst+vsrc1-1); 4502 thisPtr = (Object*) GET_REGISTER(vdst); 4503 } else { 4504 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 4505 ref = FETCH(1); /* method ref */ 4506 vdst = FETCH(2); /* 4 regs -or- first reg */ 4507 4508 /* 4509 * The object against which we are executing a method is always 4510 * in the first argument. 4511 */ 4512 if (methodCallRange) { 4513 assert(vsrc1 > 0); 4514 ILOGV("|invoke-virtual-range args=%d @0x%04x {regs=v%d-v%d}", 4515 vsrc1, ref, vdst, vdst+vsrc1-1); 4516 thisPtr = (Object*) GET_REGISTER(vdst); 4517 } else { 4518 assert((vsrc1>>4) > 0); 4519 ILOGV("|invoke-virtual args=%d @0x%04x {regs=0x%04x %x}", 4520 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 4521 thisPtr = (Object*) GET_REGISTER(vdst & 0x0f); 4522 } 4523 } 4524 4525 if (!checkForNull(thisPtr)) 4526 GOTO_exceptionThrown(); 4527 4528 /* 4529 * Resolve the method. This is the correct method for the static 4530 * type of the object. We also verify access permissions here. 4531 */ 4532 baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref); 4533 if (baseMethod == NULL) { 4534 baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL); 4535 if (baseMethod == NULL) { 4536 ILOGV("+ unknown method or access denied"); 4537 GOTO_exceptionThrown(); 4538 } 4539 } 4540 4541 /* 4542 * Combine the object we found with the vtable offset in the 4543 * method. 4544 */ 4545 assert(baseMethod->methodIndex < thisPtr->clazz->vtableCount); 4546 methodToCall = thisPtr->clazz->vtable[baseMethod->methodIndex]; 4547 4548#if defined(WITH_JIT) && defined(MTERP_STUB) 4549 self->methodToCall = methodToCall; 4550 self->callsiteClass = thisPtr->clazz; 4551#endif 4552 4553#if 0 4554 if (dvmIsAbstractMethod(methodToCall)) { 4555 /* 4556 * This can happen if you create two classes, Base and Sub, where 4557 * Sub is a sub-class of Base. Declare a protected abstract 4558 * method foo() in Base, and invoke foo() from a method in Base. 4559 * Base is an "abstract base class" and is never instantiated 4560 * directly. Now, Override foo() in Sub, and use Sub. This 4561 * Works fine unless Sub stops providing an implementation of 4562 * the method. 4563 */ 4564 dvmThrowAbstractMethodError("abstract method not implemented"); 4565 GOTO_exceptionThrown(); 4566 } 4567#else 4568 assert(!dvmIsAbstractMethod(methodToCall) || 4569 methodToCall->nativeFunc != NULL); 4570#endif 4571 4572 LOGVV("+++ base=%s.%s virtual[%d]=%s.%s", 4573 baseMethod->clazz->descriptor, baseMethod->name, 4574 (u4) baseMethod->methodIndex, 4575 methodToCall->clazz->descriptor, methodToCall->name); 4576 assert(methodToCall != NULL); 4577 4578#if 0 4579 if (vsrc1 != methodToCall->insSize) { 4580 LOGW("WRONG METHOD: base=%s.%s virtual[%d]=%s.%s", 4581 baseMethod->clazz->descriptor, baseMethod->name, 4582 (u4) baseMethod->methodIndex, 4583 methodToCall->clazz->descriptor, methodToCall->name); 4584 //dvmDumpClass(baseMethod->clazz); 4585 //dvmDumpClass(methodToCall->clazz); 4586 dvmDumpAllClasses(0); 4587 } 4588#endif 4589 4590 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 4591 } 4592GOTO_TARGET_END 4593 4594GOTO_TARGET(invokeSuper, bool methodCallRange, bool jumboFormat) 4595 { 4596 Method* baseMethod; 4597 u2 thisReg; 4598 4599 EXPORT_PC(); 4600 4601 if (jumboFormat) { 4602 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */ 4603 vsrc1 = FETCH(3); /* count */ 4604 vdst = FETCH(4); /* first reg */ 4605 ADJUST_PC(2); /* advance pc partially to make returns easier */ 4606 ILOGV("|invoke-super/jumbo args=%d @0x%08x {regs=v%d-v%d}", 4607 vsrc1, ref, vdst, vdst+vsrc1-1); 4608 thisReg = vdst; 4609 } else { 4610 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 4611 ref = FETCH(1); /* method ref */ 4612 vdst = FETCH(2); /* 4 regs -or- first reg */ 4613 4614 if (methodCallRange) { 4615 ILOGV("|invoke-super-range args=%d @0x%04x {regs=v%d-v%d}", 4616 vsrc1, ref, vdst, vdst+vsrc1-1); 4617 thisReg = vdst; 4618 } else { 4619 ILOGV("|invoke-super args=%d @0x%04x {regs=0x%04x %x}", 4620 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 4621 thisReg = vdst & 0x0f; 4622 } 4623 } 4624 4625 /* impossible in well-formed code, but we must check nevertheless */ 4626 if (!checkForNull((Object*) GET_REGISTER(thisReg))) 4627 GOTO_exceptionThrown(); 4628 4629 /* 4630 * Resolve the method. This is the correct method for the static 4631 * type of the object. We also verify access permissions here. 4632 * The first arg to dvmResolveMethod() is just the referring class 4633 * (used for class loaders and such), so we don't want to pass 4634 * the superclass into the resolution call. 4635 */ 4636 baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref); 4637 if (baseMethod == NULL) { 4638 baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL); 4639 if (baseMethod == NULL) { 4640 ILOGV("+ unknown method or access denied"); 4641 GOTO_exceptionThrown(); 4642 } 4643 } 4644 4645 /* 4646 * Combine the object we found with the vtable offset in the 4647 * method's class. 4648 * 4649 * We're using the current method's class' superclass, not the 4650 * superclass of "this". This is because we might be executing 4651 * in a method inherited from a superclass, and we want to run 4652 * in that class' superclass. 4653 */ 4654 if (baseMethod->methodIndex >= curMethod->clazz->super->vtableCount) { 4655 /* 4656 * Method does not exist in the superclass. Could happen if 4657 * superclass gets updated. 4658 */ 4659 dvmThrowNoSuchMethodError(baseMethod->name); 4660 GOTO_exceptionThrown(); 4661 } 4662 methodToCall = curMethod->clazz->super->vtable[baseMethod->methodIndex]; 4663 4664#if 0 4665 if (dvmIsAbstractMethod(methodToCall)) { 4666 dvmThrowAbstractMethodError("abstract method not implemented"); 4667 GOTO_exceptionThrown(); 4668 } 4669#else 4670 assert(!dvmIsAbstractMethod(methodToCall) || 4671 methodToCall->nativeFunc != NULL); 4672#endif 4673 LOGVV("+++ base=%s.%s super-virtual=%s.%s", 4674 baseMethod->clazz->descriptor, baseMethod->name, 4675 methodToCall->clazz->descriptor, methodToCall->name); 4676 assert(methodToCall != NULL); 4677 4678 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 4679 } 4680GOTO_TARGET_END 4681 4682GOTO_TARGET(invokeInterface, bool methodCallRange, bool jumboFormat) 4683 { 4684 Object* thisPtr; 4685 ClassObject* thisClass; 4686 4687 EXPORT_PC(); 4688 4689 if (jumboFormat) { 4690 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */ 4691 vsrc1 = FETCH(3); /* count */ 4692 vdst = FETCH(4); /* first reg */ 4693 ADJUST_PC(2); /* advance pc partially to make returns easier */ 4694 ILOGV("|invoke-interface/jumbo args=%d @0x%08x {regs=v%d-v%d}", 4695 vsrc1, ref, vdst, vdst+vsrc1-1); 4696 thisPtr = (Object*) GET_REGISTER(vdst); 4697 } else { 4698 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 4699 ref = FETCH(1); /* method ref */ 4700 vdst = FETCH(2); /* 4 regs -or- first reg */ 4701 4702 /* 4703 * The object against which we are executing a method is always 4704 * in the first argument. 4705 */ 4706 if (methodCallRange) { 4707 assert(vsrc1 > 0); 4708 ILOGV("|invoke-interface-range args=%d @0x%04x {regs=v%d-v%d}", 4709 vsrc1, ref, vdst, vdst+vsrc1-1); 4710 thisPtr = (Object*) GET_REGISTER(vdst); 4711 } else { 4712 assert((vsrc1>>4) > 0); 4713 ILOGV("|invoke-interface args=%d @0x%04x {regs=0x%04x %x}", 4714 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 4715 thisPtr = (Object*) GET_REGISTER(vdst & 0x0f); 4716 } 4717 } 4718 4719 if (!checkForNull(thisPtr)) 4720 GOTO_exceptionThrown(); 4721 4722 thisClass = thisPtr->clazz; 4723 4724 4725 /* 4726 * Given a class and a method index, find the Method* with the 4727 * actual code we want to execute. 4728 */ 4729 methodToCall = dvmFindInterfaceMethodInCache(thisClass, ref, curMethod, 4730 methodClassDex); 4731#if defined(WITH_JIT) && defined(MTERP_STUB) 4732 self->callsiteClass = thisClass; 4733 self->methodToCall = methodToCall; 4734#endif 4735 if (methodToCall == NULL) { 4736 assert(dvmCheckException(self)); 4737 GOTO_exceptionThrown(); 4738 } 4739 4740 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 4741 } 4742GOTO_TARGET_END 4743 4744GOTO_TARGET(invokeDirect, bool methodCallRange, bool jumboFormat) 4745 { 4746 u2 thisReg; 4747 4748 EXPORT_PC(); 4749 4750 if (jumboFormat) { 4751 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */ 4752 vsrc1 = FETCH(3); /* count */ 4753 vdst = FETCH(4); /* first reg */ 4754 ADJUST_PC(2); /* advance pc partially to make returns easier */ 4755 ILOGV("|invoke-direct/jumbo args=%d @0x%08x {regs=v%d-v%d}", 4756 vsrc1, ref, vdst, vdst+vsrc1-1); 4757 thisReg = vdst; 4758 } else { 4759 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 4760 ref = FETCH(1); /* method ref */ 4761 vdst = FETCH(2); /* 4 regs -or- first reg */ 4762 4763 if (methodCallRange) { 4764 ILOGV("|invoke-direct-range args=%d @0x%04x {regs=v%d-v%d}", 4765 vsrc1, ref, vdst, vdst+vsrc1-1); 4766 thisReg = vdst; 4767 } else { 4768 ILOGV("|invoke-direct args=%d @0x%04x {regs=0x%04x %x}", 4769 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 4770 thisReg = vdst & 0x0f; 4771 } 4772 } 4773 4774 if (!checkForNull((Object*) GET_REGISTER(thisReg))) 4775 GOTO_exceptionThrown(); 4776 4777 methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref); 4778 if (methodToCall == NULL) { 4779 methodToCall = dvmResolveMethod(curMethod->clazz, ref, 4780 METHOD_DIRECT); 4781 if (methodToCall == NULL) { 4782 ILOGV("+ unknown direct method"); // should be impossible 4783 GOTO_exceptionThrown(); 4784 } 4785 } 4786 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 4787 } 4788GOTO_TARGET_END 4789 4790GOTO_TARGET(invokeStatic, bool methodCallRange, bool jumboFormat) 4791 EXPORT_PC(); 4792 4793 if (jumboFormat) { 4794 ref = FETCH(1) | (u4)FETCH(2) << 16; /* method ref */ 4795 vsrc1 = FETCH(3); /* count */ 4796 vdst = FETCH(4); /* first reg */ 4797 ADJUST_PC(2); /* advance pc partially to make returns easier */ 4798 ILOGV("|invoke-static/jumbo args=%d @0x%08x {regs=v%d-v%d}", 4799 vsrc1, ref, vdst, vdst+vsrc1-1); 4800 } else { 4801 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 4802 ref = FETCH(1); /* method ref */ 4803 vdst = FETCH(2); /* 4 regs -or- first reg */ 4804 4805 if (methodCallRange) 4806 ILOGV("|invoke-static-range args=%d @0x%04x {regs=v%d-v%d}", 4807 vsrc1, ref, vdst, vdst+vsrc1-1); 4808 else 4809 ILOGV("|invoke-static args=%d @0x%04x {regs=0x%04x %x}", 4810 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 4811 } 4812 4813 methodToCall = dvmDexGetResolvedMethod(methodClassDex, ref); 4814 if (methodToCall == NULL) { 4815 methodToCall = dvmResolveMethod(curMethod->clazz, ref, METHOD_STATIC); 4816 if (methodToCall == NULL) { 4817 ILOGV("+ unknown method"); 4818 GOTO_exceptionThrown(); 4819 } 4820 4821#if defined(WITH_JIT) && defined(MTERP_STUB) 4822 /* 4823 * The JIT needs dvmDexGetResolvedMethod() to return non-null. 4824 * Include the check if this code is being used as a stub 4825 * called from the assembly interpreter. 4826 */ 4827 if ((self->interpBreak.ctl.subMode & kSubModeJitTraceBuild) && 4828 (dvmDexGetResolvedMethod(methodClassDex, ref) == NULL)) { 4829 /* Class initialization is still ongoing */ 4830 dvmJitEndTraceSelect(self,pc); 4831 } 4832#endif 4833 } 4834 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 4835GOTO_TARGET_END 4836 4837GOTO_TARGET(invokeVirtualQuick, bool methodCallRange, bool jumboFormat) 4838 { 4839 Object* thisPtr; 4840 4841 EXPORT_PC(); 4842 4843 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 4844 ref = FETCH(1); /* vtable index */ 4845 vdst = FETCH(2); /* 4 regs -or- first reg */ 4846 4847 /* 4848 * The object against which we are executing a method is always 4849 * in the first argument. 4850 */ 4851 if (methodCallRange) { 4852 assert(vsrc1 > 0); 4853 ILOGV("|invoke-virtual-quick-range args=%d @0x%04x {regs=v%d-v%d}", 4854 vsrc1, ref, vdst, vdst+vsrc1-1); 4855 thisPtr = (Object*) GET_REGISTER(vdst); 4856 } else { 4857 assert((vsrc1>>4) > 0); 4858 ILOGV("|invoke-virtual-quick args=%d @0x%04x {regs=0x%04x %x}", 4859 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 4860 thisPtr = (Object*) GET_REGISTER(vdst & 0x0f); 4861 } 4862 4863 if (!checkForNull(thisPtr)) 4864 GOTO_exceptionThrown(); 4865 4866 4867 /* 4868 * Combine the object we found with the vtable offset in the 4869 * method. 4870 */ 4871 assert(ref < (unsigned int) thisPtr->clazz->vtableCount); 4872 methodToCall = thisPtr->clazz->vtable[ref]; 4873#if defined(WITH_JIT) && defined(MTERP_STUB) 4874 self->callsiteClass = thisPtr->clazz; 4875 self->methodToCall = methodToCall; 4876#endif 4877 4878#if 0 4879 if (dvmIsAbstractMethod(methodToCall)) { 4880 dvmThrowAbstractMethodError("abstract method not implemented"); 4881 GOTO_exceptionThrown(); 4882 } 4883#else 4884 assert(!dvmIsAbstractMethod(methodToCall) || 4885 methodToCall->nativeFunc != NULL); 4886#endif 4887 4888 LOGVV("+++ virtual[%d]=%s.%s", 4889 ref, methodToCall->clazz->descriptor, methodToCall->name); 4890 assert(methodToCall != NULL); 4891 4892 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 4893 } 4894GOTO_TARGET_END 4895 4896GOTO_TARGET(invokeSuperQuick, bool methodCallRange, bool jumboFormat) 4897 { 4898 u2 thisReg; 4899 4900 EXPORT_PC(); 4901 4902 vsrc1 = INST_AA(inst); /* AA (count) or BA (count + arg 5) */ 4903 ref = FETCH(1); /* vtable index */ 4904 vdst = FETCH(2); /* 4 regs -or- first reg */ 4905 4906 if (methodCallRange) { 4907 ILOGV("|invoke-super-quick-range args=%d @0x%04x {regs=v%d-v%d}", 4908 vsrc1, ref, vdst, vdst+vsrc1-1); 4909 thisReg = vdst; 4910 } else { 4911 ILOGV("|invoke-super-quick args=%d @0x%04x {regs=0x%04x %x}", 4912 vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f); 4913 thisReg = vdst & 0x0f; 4914 } 4915 /* impossible in well-formed code, but we must check nevertheless */ 4916 if (!checkForNull((Object*) GET_REGISTER(thisReg))) 4917 GOTO_exceptionThrown(); 4918 4919#if 0 /* impossible in optimized + verified code */ 4920 if (ref >= curMethod->clazz->super->vtableCount) { 4921 dvmThrowNoSuchMethodError(NULL); 4922 GOTO_exceptionThrown(); 4923 } 4924#else 4925 assert(ref < (unsigned int) curMethod->clazz->super->vtableCount); 4926#endif 4927 4928 /* 4929 * Combine the object we found with the vtable offset in the 4930 * method's class. 4931 * 4932 * We're using the current method's class' superclass, not the 4933 * superclass of "this". This is because we might be executing 4934 * in a method inherited from a superclass, and we want to run 4935 * in the method's class' superclass. 4936 */ 4937 methodToCall = curMethod->clazz->super->vtable[ref]; 4938 4939#if 0 4940 if (dvmIsAbstractMethod(methodToCall)) { 4941 dvmThrowAbstractMethodError("abstract method not implemented"); 4942 GOTO_exceptionThrown(); 4943 } 4944#else 4945 assert(!dvmIsAbstractMethod(methodToCall) || 4946 methodToCall->nativeFunc != NULL); 4947#endif 4948 LOGVV("+++ super-virtual[%d]=%s.%s", 4949 ref, methodToCall->clazz->descriptor, methodToCall->name); 4950 assert(methodToCall != NULL); 4951 GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst); 4952 } 4953GOTO_TARGET_END 4954 4955 4956 /* 4957 * General handling for return-void, return, and return-wide. Put the 4958 * return value in "retval" before jumping here. 4959 */ 4960GOTO_TARGET(returnFromMethod) 4961 { 4962 StackSaveArea* saveArea; 4963 4964 /* 4965 * We must do this BEFORE we pop the previous stack frame off, so 4966 * that the GC can see the return value (if any) in the local vars. 4967 * 4968 * Since this is now an interpreter switch point, we must do it before 4969 * we do anything at all. 4970 */ 4971 PERIODIC_CHECKS(0); 4972 4973 ILOGV("> retval=0x%llx (leaving %s.%s %s)", 4974 retval.j, curMethod->clazz->descriptor, curMethod->name, 4975 curMethod->shorty); 4976 //DUMP_REGS(curMethod, fp); 4977 4978 saveArea = SAVEAREA_FROM_FP(fp); 4979 4980#ifdef EASY_GDB 4981 debugSaveArea = saveArea; 4982#endif 4983 4984 /* back up to previous frame and see if we hit a break */ 4985 fp = (u4*)saveArea->prevFrame; 4986 assert(fp != NULL); 4987 4988 /* Handle any special subMode requirements */ 4989 if (self->interpBreak.ctl.subMode != 0) { 4990 PC_FP_TO_SELF(); 4991 dvmReportReturn(self); 4992 } 4993 4994 if (dvmIsBreakFrame(fp)) { 4995 /* bail without popping the method frame from stack */ 4996 LOGVV("+++ returned into break frame"); 4997 GOTO_bail(); 4998 } 4999 5000 /* update thread FP, and reset local variables */ 5001 self->interpSave.curFrame = fp; 5002 curMethod = SAVEAREA_FROM_FP(fp)->method; 5003 self->interpSave.method = curMethod; 5004 //methodClass = curMethod->clazz; 5005 methodClassDex = curMethod->clazz->pDvmDex; 5006 pc = saveArea->savedPc; 5007 ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor, 5008 curMethod->name, curMethod->shorty); 5009 5010 /* use FINISH on the caller's invoke instruction */ 5011 //u2 invokeInstr = INST_INST(FETCH(0)); 5012 if (true /*invokeInstr >= OP_INVOKE_VIRTUAL && 5013 invokeInstr <= OP_INVOKE_INTERFACE*/) 5014 { 5015 FINISH(3); 5016 } else { 5017 //LOGE("Unknown invoke instr %02x at %d", 5018 // invokeInstr, (int) (pc - curMethod->insns)); 5019 assert(false); 5020 } 5021 } 5022GOTO_TARGET_END 5023 5024 5025 /* 5026 * Jump here when the code throws an exception. 5027 * 5028 * By the time we get here, the Throwable has been created and the stack 5029 * trace has been saved off. 5030 */ 5031GOTO_TARGET(exceptionThrown) 5032 { 5033 Object* exception; 5034 int catchRelPc; 5035 5036 PERIODIC_CHECKS(0); 5037 5038 /* 5039 * We save off the exception and clear the exception status. While 5040 * processing the exception we might need to load some Throwable 5041 * classes, and we don't want class loader exceptions to get 5042 * confused with this one. 5043 */ 5044 assert(dvmCheckException(self)); 5045 exception = dvmGetException(self); 5046 dvmAddTrackedAlloc(exception, self); 5047 dvmClearException(self); 5048 5049 LOGV("Handling exception %s at %s:%d", 5050 exception->clazz->descriptor, curMethod->name, 5051 dvmLineNumFromPC(curMethod, pc - curMethod->insns)); 5052 5053 /* 5054 * Report the exception throw to any "subMode" watchers. 5055 * 5056 * TODO: if the exception was thrown by interpreted code, control 5057 * fell through native, and then back to us, we will report the 5058 * exception at the point of the throw and again here. We can avoid 5059 * this by not reporting exceptions when we jump here directly from 5060 * the native call code above, but then we won't report exceptions 5061 * that were thrown *from* the JNI code (as opposed to *through* it). 5062 * 5063 * The correct solution is probably to ignore from-native exceptions 5064 * here, and have the JNI exception code do the reporting to the 5065 * debugger. 5066 */ 5067 if (self->interpBreak.ctl.subMode != 0) { 5068 PC_FP_TO_SELF(); 5069 dvmReportExceptionThrow(self, exception); 5070 } 5071 5072 /* 5073 * We need to unroll to the catch block or the nearest "break" 5074 * frame. 5075 * 5076 * A break frame could indicate that we have reached an intermediate 5077 * native call, or have gone off the top of the stack and the thread 5078 * needs to exit. Either way, we return from here, leaving the 5079 * exception raised. 5080 * 5081 * If we do find a catch block, we want to transfer execution to 5082 * that point. 5083 * 5084 * Note this can cause an exception while resolving classes in 5085 * the "catch" blocks. 5086 */ 5087 catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns, 5088 exception, false, (void**)(void*)&fp); 5089 5090 /* 5091 * Restore the stack bounds after an overflow. This isn't going to 5092 * be correct in all circumstances, e.g. if JNI code devours the 5093 * exception this won't happen until some other exception gets 5094 * thrown. If the code keeps pushing the stack bounds we'll end 5095 * up aborting the VM. 5096 * 5097 * Note we want to do this *after* the call to dvmFindCatchBlock, 5098 * because that may need extra stack space to resolve exception 5099 * classes (e.g. through a class loader). 5100 * 5101 * It's possible for the stack overflow handling to cause an 5102 * exception (specifically, class resolution in a "catch" block 5103 * during the call above), so we could see the thread's overflow 5104 * flag raised but actually be running in a "nested" interpreter 5105 * frame. We don't allow doubled-up StackOverflowErrors, so 5106 * we can check for this by just looking at the exception type 5107 * in the cleanup function. Also, we won't unroll past the SOE 5108 * point because the more-recent exception will hit a break frame 5109 * as it unrolls to here. 5110 */ 5111 if (self->stackOverflowed) 5112 dvmCleanupStackOverflow(self, exception); 5113 5114 if (catchRelPc < 0) { 5115 /* falling through to JNI code or off the bottom of the stack */ 5116#if DVM_SHOW_EXCEPTION >= 2 5117 LOGD("Exception %s from %s:%d not caught locally", 5118 exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod), 5119 dvmLineNumFromPC(curMethod, pc - curMethod->insns)); 5120#endif 5121 dvmSetException(self, exception); 5122 dvmReleaseTrackedAlloc(exception, self); 5123 GOTO_bail(); 5124 } 5125 5126#if DVM_SHOW_EXCEPTION >= 3 5127 { 5128 const Method* catchMethod = SAVEAREA_FROM_FP(fp)->method; 5129 LOGD("Exception %s thrown from %s:%d to %s:%d", 5130 exception->clazz->descriptor, dvmGetMethodSourceFile(curMethod), 5131 dvmLineNumFromPC(curMethod, pc - curMethod->insns), 5132 dvmGetMethodSourceFile(catchMethod), 5133 dvmLineNumFromPC(catchMethod, catchRelPc)); 5134 } 5135#endif 5136 5137 /* 5138 * Adjust local variables to match self->interpSave.curFrame and the 5139 * updated PC. 5140 */ 5141 //fp = (u4*) self->interpSave.curFrame; 5142 curMethod = SAVEAREA_FROM_FP(fp)->method; 5143 self->interpSave.method = curMethod; 5144 //methodClass = curMethod->clazz; 5145 methodClassDex = curMethod->clazz->pDvmDex; 5146 pc = curMethod->insns + catchRelPc; 5147 ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor, 5148 curMethod->name, curMethod->shorty); 5149 DUMP_REGS(curMethod, fp, false); // show all regs 5150 5151 /* 5152 * Restore the exception if the handler wants it. 5153 * 5154 * The Dalvik spec mandates that, if an exception handler wants to 5155 * do something with the exception, the first instruction executed 5156 * must be "move-exception". We can pass the exception along 5157 * through the thread struct, and let the move-exception instruction 5158 * clear it for us. 5159 * 5160 * If the handler doesn't call move-exception, we don't want to 5161 * finish here with an exception still pending. 5162 */ 5163 if (INST_INST(FETCH(0)) == OP_MOVE_EXCEPTION) 5164 dvmSetException(self, exception); 5165 5166 dvmReleaseTrackedAlloc(exception, self); 5167 FINISH(0); 5168 } 5169GOTO_TARGET_END 5170 5171 5172 5173 /* 5174 * General handling for invoke-{virtual,super,direct,static,interface}, 5175 * including "quick" variants. 5176 * 5177 * Set "methodToCall" to the Method we're calling, and "methodCallRange" 5178 * depending on whether this is a "/range" instruction. 5179 * 5180 * For a range call: 5181 * "vsrc1" holds the argument count (8 bits) 5182 * "vdst" holds the first argument in the range 5183 * For a non-range call: 5184 * "vsrc1" holds the argument count (4 bits) and the 5th argument index 5185 * "vdst" holds four 4-bit register indices 5186 * 5187 * The caller must EXPORT_PC before jumping here, because any method 5188 * call can throw a stack overflow exception. 5189 */ 5190GOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall, 5191 u2 count, u2 regs) 5192 { 5193 STUB_HACK(vsrc1 = count; vdst = regs; methodToCall = _methodToCall;); 5194 5195 //printf("range=%d call=%p count=%d regs=0x%04x\n", 5196 // methodCallRange, methodToCall, count, regs); 5197 //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor, 5198 // methodToCall->name, methodToCall->shorty); 5199 5200 u4* outs; 5201 int i; 5202 5203 /* 5204 * Copy args. This may corrupt vsrc1/vdst. 5205 */ 5206 if (methodCallRange) { 5207 // could use memcpy or a "Duff's device"; most functions have 5208 // so few args it won't matter much 5209 assert(vsrc1 <= curMethod->outsSize); 5210 assert(vsrc1 == methodToCall->insSize); 5211 outs = OUTS_FROM_FP(fp, vsrc1); 5212 for (i = 0; i < vsrc1; i++) 5213 outs[i] = GET_REGISTER(vdst+i); 5214 } else { 5215 u4 count = vsrc1 >> 4; 5216 5217 assert(count <= curMethod->outsSize); 5218 assert(count == methodToCall->insSize); 5219 assert(count <= 5); 5220 5221 outs = OUTS_FROM_FP(fp, count); 5222#if 0 5223 if (count == 5) { 5224 outs[4] = GET_REGISTER(vsrc1 & 0x0f); 5225 count--; 5226 } 5227 for (i = 0; i < (int) count; i++) { 5228 outs[i] = GET_REGISTER(vdst & 0x0f); 5229 vdst >>= 4; 5230 } 5231#else 5232 // This version executes fewer instructions but is larger 5233 // overall. Seems to be a teensy bit faster. 5234 assert((vdst >> 16) == 0); // 16 bits -or- high 16 bits clear 5235 switch (count) { 5236 case 5: 5237 outs[4] = GET_REGISTER(vsrc1 & 0x0f); 5238 case 4: 5239 outs[3] = GET_REGISTER(vdst >> 12); 5240 case 3: 5241 outs[2] = GET_REGISTER((vdst & 0x0f00) >> 8); 5242 case 2: 5243 outs[1] = GET_REGISTER((vdst & 0x00f0) >> 4); 5244 case 1: 5245 outs[0] = GET_REGISTER(vdst & 0x0f); 5246 default: 5247 ; 5248 } 5249#endif 5250 } 5251 } 5252 5253 /* 5254 * (This was originally a "goto" target; I've kept it separate from the 5255 * stuff above in case we want to refactor things again.) 5256 * 5257 * At this point, we have the arguments stored in the "outs" area of 5258 * the current method's stack frame, and the method to call in 5259 * "methodToCall". Push a new stack frame. 5260 */ 5261 { 5262 StackSaveArea* newSaveArea; 5263 u4* newFp; 5264 5265 ILOGV("> %s%s.%s %s", 5266 dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "", 5267 methodToCall->clazz->descriptor, methodToCall->name, 5268 methodToCall->shorty); 5269 5270 newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize; 5271 newSaveArea = SAVEAREA_FROM_FP(newFp); 5272 5273 /* verify that we have enough space */ 5274 if (true) { 5275 u1* bottom; 5276 bottom = (u1*) newSaveArea - methodToCall->outsSize * sizeof(u4); 5277 if (bottom < self->interpStackEnd) { 5278 /* stack overflow */ 5279 LOGV("Stack overflow on method call (start=%p end=%p newBot=%p(%d) size=%d '%s')", 5280 self->interpStackStart, self->interpStackEnd, bottom, 5281 (u1*) fp - bottom, self->interpStackSize, 5282 methodToCall->name); 5283 dvmHandleStackOverflow(self, methodToCall); 5284 assert(dvmCheckException(self)); 5285 GOTO_exceptionThrown(); 5286 } 5287 //LOGD("+++ fp=%p newFp=%p newSave=%p bottom=%p", 5288 // fp, newFp, newSaveArea, bottom); 5289 } 5290 5291#ifdef LOG_INSTR 5292 if (methodToCall->registersSize > methodToCall->insSize) { 5293 /* 5294 * This makes valgrind quiet when we print registers that 5295 * haven't been initialized. Turn it off when the debug 5296 * messages are disabled -- we want valgrind to report any 5297 * used-before-initialized issues. 5298 */ 5299 memset(newFp, 0xcc, 5300 (methodToCall->registersSize - methodToCall->insSize) * 4); 5301 } 5302#endif 5303 5304#ifdef EASY_GDB 5305 newSaveArea->prevSave = SAVEAREA_FROM_FP(fp); 5306#endif 5307 newSaveArea->prevFrame = fp; 5308 newSaveArea->savedPc = pc; 5309#if defined(WITH_JIT) && defined(MTERP_STUB) 5310 newSaveArea->returnAddr = 0; 5311#endif 5312 newSaveArea->method = methodToCall; 5313 5314 if (self->interpBreak.ctl.subMode != 0) { 5315 /* 5316 * We mark ENTER here for both native and non-native 5317 * calls. For native calls, we'll mark EXIT on return. 5318 * For non-native calls, EXIT is marked in the RETURN op. 5319 */ 5320 PC_TO_SELF(); 5321 dvmReportInvoke(self, methodToCall); 5322 } 5323 5324 if (!dvmIsNativeMethod(methodToCall)) { 5325 /* 5326 * "Call" interpreted code. Reposition the PC, update the 5327 * frame pointer and other local state, and continue. 5328 */ 5329 curMethod = methodToCall; 5330 self->interpSave.method = curMethod; 5331 methodClassDex = curMethod->clazz->pDvmDex; 5332 pc = methodToCall->insns; 5333 self->interpSave.curFrame = newFp; 5334 fp = newFp; 5335#ifdef EASY_GDB 5336 debugSaveArea = SAVEAREA_FROM_FP(newFp); 5337#endif 5338 self->debugIsMethodEntry = true; // profiling, debugging 5339 ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor, 5340 curMethod->name, curMethod->shorty); 5341 DUMP_REGS(curMethod, fp, true); // show input args 5342 FINISH(0); // jump to method start 5343 } else { 5344 /* set this up for JNI locals, even if not a JNI native */ 5345 newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all; 5346 5347 self->interpSave.curFrame = newFp; 5348 5349 DUMP_REGS(methodToCall, newFp, true); // show input args 5350 5351 if (self->interpBreak.ctl.subMode != 0) { 5352 dvmReportPreNativeInvoke(methodToCall, self, newSaveArea->prevFrame); 5353 } 5354 5355 ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor, 5356 methodToCall->name, methodToCall->shorty); 5357 5358 /* 5359 * Jump through native call bridge. Because we leave no 5360 * space for locals on native calls, "newFp" points directly 5361 * to the method arguments. 5362 */ 5363 (*methodToCall->nativeFunc)(newFp, &retval, methodToCall, self); 5364 5365 if (self->interpBreak.ctl.subMode != 0) { 5366 dvmReportPostNativeInvoke(methodToCall, self, newSaveArea->prevFrame); 5367 } 5368 5369 /* pop frame off */ 5370 dvmPopJniLocals(self, newSaveArea); 5371 self->interpSave.curFrame = newSaveArea->prevFrame; 5372 fp = newSaveArea->prevFrame; 5373 5374 /* 5375 * If the native code threw an exception, or interpreted code 5376 * invoked by the native call threw one and nobody has cleared 5377 * it, jump to our local exception handling. 5378 */ 5379 if (dvmCheckException(self)) { 5380 LOGV("Exception thrown by/below native code"); 5381 GOTO_exceptionThrown(); 5382 } 5383 5384 ILOGD("> retval=0x%llx (leaving native)", retval.j); 5385 ILOGD("> (return from native %s.%s to %s.%s %s)", 5386 methodToCall->clazz->descriptor, methodToCall->name, 5387 curMethod->clazz->descriptor, curMethod->name, 5388 curMethod->shorty); 5389 5390 //u2 invokeInstr = INST_INST(FETCH(0)); 5391 if (true /*invokeInstr >= OP_INVOKE_VIRTUAL && 5392 invokeInstr <= OP_INVOKE_INTERFACE*/) 5393 { 5394 FINISH(3); 5395 } else { 5396 //LOGE("Unknown invoke instr %02x at %d", 5397 // invokeInstr, (int) (pc - curMethod->insns)); 5398 assert(false); 5399 } 5400 } 5401 } 5402 assert(false); // should not get here 5403GOTO_TARGET_END 5404 5405/* File: portable/enddefs.cpp */ 5406/*--- end of opcodes ---*/ 5407 5408bail: 5409 ILOGD("|-- Leaving interpreter loop"); // note "curMethod" may be NULL 5410 5411 self->interpSave.retval = retval; 5412} 5413 5414