blob: c739fdf01173f0facc75c10d58b2e8062af3d042 [file] [log] [blame]
%verify "executed"
%verify "exception handled"
/*
* Execute a "native inline" instruction.
*
* We will be calling through a function table:
*
* (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, pResult)
*
* Ignores argument count - always loads 4.
*
*/
/* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
movl rSELF,%ecx
EXPORT_PC
movzwl 2(rPC),%eax # eax<- BBBB
SPILL(rIBASE) # preserve rIBASE
movl offThread_subMode(%ecx), %edx # edx<- submode flags
andl $$kSubModeDebugProfile, %edx # debug or profile mode active?
jnz .L${opcode}_debugprofile # yes, take slow path
.L${opcode}_resume:
leal offThread_retval(%ecx),%ecx # ecx<- &self->retval
movl %ecx,OUT_ARG4(%esp)
call .L${opcode}_continue # make call; will return after
UNSPILL(rIBASE) # restore rIBASE
testl %eax,%eax # successful?
jz common_exceptionThrown # no, handle exception
FETCH_INST_OPCODE 3 %ecx
ADVANCE_PC 3
GOTO_NEXT_R %ecx
.L${opcode}_continue:
/*
* Extract args, call function.
* ecx = #of args (0-4)
* eax = call index
* @esp = return addr
* esp is -4 from normal
*
* Go ahead and load all 4 args, even if not used.
*/
movzwl 4(rPC),rIBASE
movl $$0xf,%ecx
andl rIBASE,%ecx
GET_VREG_R %ecx %ecx
sarl $$4,rIBASE
movl %ecx,4+OUT_ARG0(%esp)
movl $$0xf,%ecx
andl rIBASE,%ecx
GET_VREG_R %ecx %ecx
sarl $$4,rIBASE
movl %ecx,4+OUT_ARG1(%esp)
movl $$0xf,%ecx
andl rIBASE,%ecx
GET_VREG_R %ecx %ecx
sarl $$4,rIBASE
movl %ecx,4+OUT_ARG2(%esp)
movl $$0xf,%ecx
andl rIBASE,%ecx
GET_VREG_R %ecx %ecx
sarl $$4,rIBASE
movl %ecx,4+OUT_ARG3(%esp)
sall $$4,%eax # index *= sizeof(table entry)
jmp *gDvmInlineOpsTable(%eax)
# will return to caller of .L${opcode}_continue
/*
* We're debugging or profiling.
* eax: opIndex
*/
.L${opcode}_debugprofile:
movl %eax,OUT_ARG0(%esp) # arg0<- BBBB
SPILL_TMP1(%eax) # save opIndex
call dvmResolveInlineNative # dvmResolveInlineNative(opIndex)
movl rSELF,%ecx # restore self
testl %eax,%eax # method resolved?
movl %eax,%edx # save possibly resolved method in edx
UNSPILL_TMP1(%eax) # in case not resolved, restore opIndex
jz .L${opcode}_resume # not resolved, just move on
SPILL_TMP2(%edx) # save method
movl %edx,OUT_ARG0(%esp) # arg0<- method
movl %ecx,OUT_ARG1(%esp) # arg1<- self
call dvmFastMethodTraceEnter # dvmFastMethodTraceEnter(method,self)
movl rSELF,%ecx # restore self
UNSPILL_TMP1(%eax) # restore opIndex
leal offThread_retval(%ecx),%ecx # ecx<- &self->retval
movl %ecx,OUT_ARG4(%esp) # needed for pResult of inline operation handler
call .L${opcode}_continue # make call; will return after
SPILL_TMP1(%eax) # save result of inline
UNSPILL_TMP2(%eax) # restore method
movl rSELF,%ecx # restore self
movl %eax,OUT_ARG0(%esp) # arg0<- method
movl %ecx,OUT_ARG1(%esp) # arg1<- self
call dvmFastNativeMethodTraceExit # dvmFastNativeMethodTraceExit(method,self)
UNSPILL(rIBASE) # restore rIBASE
UNSPILL_TMP1(%eax) # restore result of inline
testl %eax,%eax # successful?
jz common_exceptionThrown # no, handle exception
FETCH_INST_OPCODE 3 %ecx
ADVANCE_PC 3
GOTO_NEXT_R %ecx