blob: 083dc152059163aa0f17d96d31d31d304ea11b7f [file] [log] [blame]
/*
* ===========================================================================
* Common subroutines and data
* ===========================================================================
*/
.text
.align 2
/*
* We've detected a condition that will result in an exception, but the exception
* has not yet been thrown. Just bail out to the reference interpreter to deal with it.
* TUNING: for consistency, we may want to just go ahead and handle these here.
*/
common_errDivideByZero:
EXPORT_PC()
#if MTERP_LOGGING
move a0, rSELF
addu a1, rFP, OFF_FP_SHADOWFRAME
JAL(MterpLogDivideByZeroException)
#endif
b MterpCommonFallback
common_errArrayIndex:
EXPORT_PC()
#if MTERP_LOGGING
move a0, rSELF
addu a1, rFP, OFF_FP_SHADOWFRAME
JAL(MterpLogArrayIndexException)
#endif
b MterpCommonFallback
common_errNegativeArraySize:
EXPORT_PC()
#if MTERP_LOGGING
move a0, rSELF
addu a1, rFP, OFF_FP_SHADOWFRAME
JAL(MterpLogNegativeArraySizeException)
#endif
b MterpCommonFallback
common_errNoSuchMethod:
EXPORT_PC()
#if MTERP_LOGGING
move a0, rSELF
addu a1, rFP, OFF_FP_SHADOWFRAME
JAL(MterpLogNoSuchMethodException)
#endif
b MterpCommonFallback
common_errNullObject:
EXPORT_PC()
#if MTERP_LOGGING
move a0, rSELF
addu a1, rFP, OFF_FP_SHADOWFRAME
JAL(MterpLogNullObjectException)
#endif
b MterpCommonFallback
common_exceptionThrown:
EXPORT_PC()
#if MTERP_LOGGING
move a0, rSELF
addu a1, rFP, OFF_FP_SHADOWFRAME
JAL(MterpLogExceptionThrownException)
#endif
b MterpCommonFallback
MterpSuspendFallback:
EXPORT_PC()
#if MTERP_LOGGING
move a0, rSELF
addu a1, rFP, OFF_FP_SHADOWFRAME
lw a2, THREAD_FLAGS_OFFSET(rSELF)
JAL(MterpLogSuspendFallback)
#endif
b MterpCommonFallback
/*
* If we're here, something is out of the ordinary. If there is a pending
* exception, handle it. Otherwise, roll back and retry with the reference
* interpreter.
*/
MterpPossibleException:
lw a0, THREAD_EXCEPTION_OFFSET(rSELF)
beqz a0, MterpFallback # If exception, fall back to reference interpreter.
/* intentional fallthrough - handle pending exception. */
/*
* On return from a runtime helper routine, we've found a pending exception.
* Can we handle it here - or need to bail out to caller?
*
*/
MterpException:
move a0, rSELF
addu a1, rFP, OFF_FP_SHADOWFRAME
JAL(MterpHandleException) # (self, shadow_frame)
beqz v0, MterpExceptionReturn # no local catch, back to caller.
lw a0, OFF_FP_CODE_ITEM(rFP)
lw a1, OFF_FP_DEX_PC(rFP)
lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF)
addu rPC, a0, CODEITEM_INSNS_OFFSET
sll a1, a1, 1
addu rPC, rPC, a1 # generate new dex_pc_ptr
/* Do we need to switch interpreters? */
JAL(MterpShouldSwitchInterpreters)
bnez v0, MterpFallback
/* resume execution at catch block */
EXPORT_PC()
FETCH_INST()
GET_INST_OPCODE(t0)
GOTO_OPCODE(t0)
/* NOTE: no fallthrough */
/*
* Check for suspend check request. Assumes rINST already loaded, rPC advanced and
* still needs to get the opcode and branch to it, and flags are in lr.
*/
MterpCheckSuspendAndContinue:
lw rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF) # refresh rIBASE
and ra, (THREAD_SUSPEND_REQUEST | THREAD_CHECKPOINT_REQUEST)
bnez ra, 1f
GET_INST_OPCODE(t0) # extract opcode from rINST
GOTO_OPCODE(t0) # jump to next instruction
1:
EXPORT_PC()
move a0, rSELF
JAL(MterpSuspendCheck) # (self)
bnez v0, MterpFallback
GET_INST_OPCODE(t0) # extract opcode from rINST
GOTO_OPCODE(t0) # jump to next instruction
/*
* On-stack replacement has happened, and now we've returned from the compiled method.
*/
MterpOnStackReplacement:
#if MTERP_LOGGING
move a0, rSELF
addu a1, rFP, OFF_FP_SHADOWFRAME
move a2, rINST
JAL(MterpLogOSR)
#endif
li v0, 1 # Signal normal return
b MterpDone
/*
* Bail out to reference interpreter.
*/
MterpFallback:
EXPORT_PC()
#if MTERP_LOGGING
move a0, rSELF
addu a1, rFP, OFF_FP_SHADOWFRAME
JAL(MterpLogFallback)
#endif
MterpCommonFallback:
move v0, zero # signal retry with reference interpreter.
b MterpDone
/*
* We pushed some registers on the stack in ExecuteMterpImpl, then saved
* SP and LR. Here we restore SP, restore the registers, and then restore
* LR to PC.
*
* On entry:
* uint32_t* rFP (should still be live, pointer to base of vregs)
*/
MterpExceptionReturn:
li v0, 1 # signal return to caller.
b MterpDone
MterpReturn:
lw a2, OFF_FP_RESULT_REGISTER(rFP)
sw v0, 0(a2)
sw v1, 4(a2)
li v0, 1 # signal return to caller.
MterpDone:
/* Restore from the stack and return. Frame size = STACK_SIZE */
STACK_LOAD_FULL()
jalr zero, ra
.end ExecuteMterpImpl