HANDLE_OPCODE(OP_EXECUTE_INLINE /*vB, {vD, vE, vF, vG}, inline@CCCC*/)
{
/*
* This has the same form as other method calls, but we ignore
* the 5th argument (vA). This is chiefly because the first four
* arguments to a function on ARM are in registers.
*
* We only set the arguments that are actually used, leaving
* the rest uninitialized. We're assuming that, if the method
* needs them, they'll be specified in the call.
*
* However, this annoys gcc when optimizations are enabled,
* causing a "may be used uninitialized" warning. Quieting
* the warnings incurs a slight penalty (5%: 373ns vs. 393ns
* on empty method). Note that valgrind is perfectly happy
* either way as the uninitialiezd values are never actually
* used.
*/
u4 arg0, arg1, arg2, arg3;
arg0 = arg1 = arg2 = arg3 = 0;
EXPORT_PC();
vsrc1 = INST_B(inst); /* #of args */
ref = FETCH(1); /* inline call "ref" */
vdst = FETCH(2); /* 0-4 register indices */
ILOGV("|execute-inline args=%d @%d {regs=0x%04x}",
vsrc1, ref, vdst);
assert((vdst >> 16) == 0); // 16-bit type -or- high 16 bits clear
assert(vsrc1 <= 4);
switch (vsrc1) {
case 4:
arg3 = GET_REGISTER(vdst >> 12);
/* fall through */
case 3:
arg2 = GET_REGISTER((vdst & 0x0f00) >> 8);
/* fall through */
case 2:
arg1 = GET_REGISTER((vdst & 0x00f0) >> 4);
/* fall through */
case 1:
arg0 = GET_REGISTER(vdst & 0x0f);
/* fall through */
default: // case 0
;
}
if (self->interpBreak.ctl.subMode & kSubModeDebuggerActive) {
if (!dvmPerformInlineOp4Dbg(arg0, arg1, arg2, arg3, &retval, ref))
GOTO_exceptionThrown();
} else {
if (!dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref))
GOTO_exceptionThrown();
}
}
FINISH(3);
OP_END