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