diff options
Diffstat (limited to 'vm/mterp/x86-atom/footer.S')
-rw-r--r-- | vm/mterp/x86-atom/footer.S | 662 |
1 files changed, 662 insertions, 0 deletions
diff --git a/vm/mterp/x86-atom/footer.S b/vm/mterp/x86-atom/footer.S new file mode 100644 index 0000000..cb9970d --- /dev/null +++ b/vm/mterp/x86-atom/footer.S @@ -0,0 +1,662 @@ + /* Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /* + * File: footer.S + */ + + .text + .align 2 + + /* + * Check to see if the thread needs to be suspended or debugger/profiler + * activity has begun. + * + * On entry: + * %ecx is reentry type, e.g. kInterpEntryInstr + * %edx is PC adjustment in bytes + */ + +common_periodicChecks: + movl %edx, -8(%esp) # save pc adjustments + movl rGLUE, %edx # %edx<- pMterpGlue + movl %ebx, -4(%esp) # save %ebx to the stack + movl offGlue_pSelfSuspendCount(%edx), %ebx # %ebx<- pSuspendCount (int) +4: + movl offGlue_pDebuggerActive(%edx), %eax # %eax<- pDebuggerActive + testl %eax, %eax + je 5f + movzbl (%eax), %eax # %eax<- get debuggerActive (boolean) +5: + cmp $$0, (%ebx) # check if suspend is pending + jne 2f # handle suspend + movl offGlue_pActiveProfilers(%edx), %ebx # %ebx<- activeProfilers (int) + orl (%ebx), %eax # %eax<- merge activeProfilers and debuggerActive + movl -8(%esp), %edx # %edx<- restore %edx + jne 3f # debugger or profiler active; switch interp + movl -4(%esp), %ebx # %ebx<- restore %ebx + ret # return +2: # check suspended + EXPORT_PC + movl offGlue_self(%edx), %eax # %eax<- glue->self + movl %eax, -12(%esp) # push parameter boolean + lea -12(%esp), %esp + call dvmCheckSuspendPending # call: (Thread* self) + # return: bool + movl 4(%esp), %edx # %edx<- restore %edx + movl 8(%esp), %ebx # %ebx<- restore %ebx + lea 12(%esp), %esp + ret +3: # debugger/profiler enabled, bail out + leal (rPC, %edx, 2), rPC # adjust pc to show target + movl rGLUE, %ecx # %ecx<- pMterpGlue + movb $$kInterpEntryInstr, offGlue_entryPoint(%ecx) + movl $$1, %edx # switch interpreter + jmp common_gotoBail # bail + + /* + * Check to see if the thread needs to be suspended or debugger/profiler + * activity has begun. With this variant, the reentry type is hard coded + * as kInterpEntryInstr. + * + * On entry: + * %edx is PC adjustment in bytes + */ + +common_periodicChecks_backwardBranch: + EXPORT_PC + movl rGLUE, %ecx # %ecx<- pMterpGlue + movl offGlue_pSelfSuspendCount(%ecx), rINST # %ebx<- pSuspendCount (int) +4: + movl offGlue_pDebuggerActive(%ecx), %eax # %eax<- pDebuggerActive + testl %eax, %eax # test for NULL pointer + je 5f + movzbl (%eax), %eax # %eax<- get debuggerActive count +5: + cmp $$0, (rINST) # check if suspend is pending + jne 2f # handle suspend + movl offGlue_pActiveProfilers(%ecx), rINST # %edx<- activeProfilers (int) + orl (rINST), %eax # %eax<- merge activeProfilers and debuggerActive + jne 3f # debugger or profiler active; switch interp + FINISH_RB %edx, %ecx # jump to next instruction +2: # check suspended + movl offGlue_self(%ecx), %eax# %eax<- glue->self + movl %edx, rINST + movl %eax, -12(%esp) # push parameter boolean + lea -12(%esp), %esp + call dvmCheckSuspendPending # call: (Thread* self) + # return: bool + movl rINST, %edx # %edx<- restore %edx + lea 12(%esp), %esp + FINISH_RB %edx, %ecx +3: # debugger/profiler enabled, bail out + leal (rPC, %edx, 2), rPC # adjust pc to show target + movb $$kInterpEntryInstr, offGlue_entryPoint(%ecx) + movl $$1, %edx # switch interpreter + jmp common_gotoBail # bail + + /* + * The equivalent of "goto bail", this calls through the "bail handler". + * State registers will be saved to the "glue" area before bailing. + * + * On entry: + * %edx is "bool changeInterp", indicating if we want to switch to the + * other interpreter or just bail all the way out + */ + +common_gotoBail: + SAVE_PC_FP_TO_GLUE %ecx # save program counter and frame pointer + + /* + * Inlined dvmMterpStdBail + */ + + lea 40(%ebp), %esp + movl %edx, %eax + movl 24(%ebp), %edi + movl 28(%ebp), %esi + movl 32(%ebp), %ebx + movl 36(%ebp), %ebp + ret + + /* + * Common code for method invocation with range. + * + * On entry: + * %ecx is "Method* methodToCall", the method we're trying to call + */ + +common_invokeMethodRange: +.LinvokeNewRange: + + /* + * prepare to copy args to "outs" area of current frame + */ + + SAVEAREA_FROM_FP %eax # %eax<- &outs; &StackSaveArea + test rINST, rINST # test for no args + movl rINST, sReg0 # sReg0<- AA + jz .LinvokeArgsDone # no args; jump to args done + FETCH 2, %edx # %edx<- CCCC + + /* + * %ecx=methodToCall, %edx=CCCC, sReg0=count, %eax=&outs (&stackSaveArea) + * (very few methods have > 10 args; could unroll for common cases) + */ + + movl %ebx, sReg1 # sReg1<- save %ebx + lea (rFP, %edx, 4), %edx # %edx<- &vCCCC + shll $$2, sReg0 # sReg0<- offset + subl sReg0, %eax # %eax<- update &outs + shrl $$2, sReg0 # sReg0<- offset +1: + movl (%edx), %ebx # %ebx<- vCCCC + lea 4(%edx), %edx # %edx<- &vCCCC++ + subl $$1, sReg0 # sReg<- sReg-- + movl %ebx, (%eax) # *outs<- vCCCC + lea 4(%eax), %eax # outs++ + jne 1b # loop if count (sReg0) not zero + movl sReg1, %ebx # %ebx<- restore %ebx + jmp .LinvokeArgsDone # continue + + /* + * %ecx is "Method* methodToCall", the method we're trying to call + * prepare to copy args to "outs" area of current frame + */ + +common_invokeMethodNoRange: +.LinvokeNewNoRange: + movl rINST, sReg0 # sReg0<- BA + shrl $$4, sReg0 # sReg0<- B + je .LinvokeArgsDone # no args; jump to args done + SAVEAREA_FROM_FP %eax # %eax<- &outs; &StackSaveArea + FETCH 2, %edx # %edx<- GFED + + /* + * %ecx=methodToCall, %edx=GFED, sReg0=count, %eax=outs + */ + +.LinvokeNonRange: + cmp $$2, sReg0 # compare sReg0 to 2 + movl %edx, sReg1 # sReg1<- GFED + jl 1f # handle 1 arg + je 2f # handle 2 args + cmp $$4, sReg0 # compare sReg0 to 4 + jl 3f # handle 3 args + je 4f # handle 4 args +5: + andl $$15, rINST # rINST<- A + lea -4(%eax), %eax # %eax<- update &outs; &outs-- + movl (rFP, rINST, 4), %edx # %edx<- vA + movl %edx, (%eax) # *outs<- vA + movl sReg1, %edx # %edx<- GFED +4: + shr $$12, %edx # %edx<- G + lea -4(%eax), %eax # %eax<- update &outs; &outs-- + movl (rFP, %edx, 4), %edx # %edx<- vG + movl %edx, (%eax) # *outs<- vG + movl sReg1, %edx # %edx<- GFED +3: + and $$0x0f00, %edx # %edx<- 0F00 + shr $$6, %edx # %edx<- F at correct offset + lea -4(%eax), %eax # %eax<- update &outs; &outs-- + movl (rFP, %edx), %edx # %edx<- vF + movl %edx, (%eax) # *outs<- vF + movl sReg1, %edx # %edx<- GFED +2: + and $$0x00f0, %edx # %edx<- 00E0 + shr $$2, %edx # %edx<- E at correct offset + lea -4(%eax), %eax # %eax<- update &outs; &outs-- + movl (rFP, %edx), %edx # %edx<- vE + movl %edx, (%eax) # *outs<- vE + movl sReg1, %edx # %edx<- GFED +1: + and $$0x000f, %edx # %edx<- 000D + movl (rFP, %edx, 4), %edx # %edx<- vD + movl %edx, -4(%eax) # *--outs<- vD +0: + + /* + * %ecx is "Method* methodToCall", the method we're trying to call + * find space for the new stack frame, check for overflow + */ + +.LinvokeArgsDone: + movzwl offMethod_registersSize(%ecx), %eax # %eax<- methodToCall->regsSize + movzwl offMethod_outsSize(%ecx), %edx # %edx<- methodToCall->outsSize + movl %ecx, sReg0 # sReg<- methodToCall + shl $$2, %eax # %eax<- update offset + SAVEAREA_FROM_FP %ecx # %ecx<- &outs; &StackSaveArea + subl %eax, %ecx # %ecx<- newFP; (old savearea - regsSize) + movl rGLUE, %eax # %eax<- pMterpGlue + movl %ecx, sReg1 # sReg1<- &outs + subl $$sizeofStackSaveArea, %ecx # %ecx<- newSaveArea (stack save area using newFP) + movl offGlue_interpStackEnd(%eax), %eax # %eax<- glue->interpStackEnd + movl %eax, sReg2 # sReg2<- glue->interpStackEnd + shl $$2, %edx # %edx<- update offset for outsSize + movl %ecx, %eax # %eax<- newSaveArea + sub %edx, %ecx # %ecx<- bottom; (newSaveArea - outsSize) + cmp sReg2, %ecx # compare interpStackEnd and bottom + movl sReg0, %ecx # %ecx<- restore methodToCall + jl .LstackOverflow # handle frame overflow + + /* + * set up newSaveArea + */ + +#ifdef EASY_GDB + SAVEAREA_FROM_FP %edx # %edx<- &outs; &StackSaveArea + movl %edx, offStackSaveArea_prevSave(%eax) # newSaveArea->prevSave<- &outs +#endif + movl rFP, offStackSaveArea_prevFrame(%eax) # newSaveArea->prevFrame<- rFP + movl rPC, offStackSaveArea_savedPc(%eax) # newSaveArea->savedPc<- rPC + testl $$ACC_NATIVE, offMethod_accessFlags(%ecx) # check for native call + movl %ecx, offStackSaveArea_method(%eax) # newSaveArea->method<- method to call + jne .LinvokeNative # handle native call + + /* + * Update "glue" values for the new method + * %ecx=methodToCall, sReg1=newFp + */ + + movl offMethod_clazz(%ecx), %edx # %edx<- method->clazz + movl rGLUE, %eax # %eax<- pMterpGlue + movl %ecx, offGlue_method(%eax) # glue->method<- methodToCall + movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex + movl offMethod_insns(%ecx), rPC # rPC<- methodToCall->insns + movl %edx, offGlue_methodClassDex(%eax) # glue->methodClassDex<- method->clazz->pDvmDex + movl offGlue_self(%eax), %ecx # %ecx<- glue->self + movl sReg1, rFP # rFP<- newFP + movl rFP, offThread_curFrame(%ecx) # glue->self->curFrame<- newFP + FINISH_A # jump to methodToCall->insns + + /* + * Prep for the native call + * %ecx=methodToCall, sReg1=newFP, %eax=newSaveArea + */ + +.LinvokeNative: + movl rGLUE, %edx # %edx<- pMterpGlue + movl %ecx, -20(%esp) # push parameter methodToCall + movl offGlue_self(%edx), %edx # %edx<- glue->self + movl offThread_jniLocal_topCookie(%edx), %ecx # %ecx<- glue->self->thread->refNext + movl %ecx, offStackSaveArea_localRefCookie(%eax) # newSaveArea->localRefCookie<- refNext + movl %eax, -4(%esp) # save newSaveArea + movl sReg1, %eax # %eax<- newFP + movl %eax, offThread_curFrame(%edx) # glue->self->curFrame<- newFP + movl %edx, -8(%esp) # save glue->self + movl %edx, -16(%esp) # push parameter glue->self + movl rGLUE, %edx # %edx<- pMterpGlue + movl -20(%esp), %ecx # %ecx<- methodToCall + lea offGlue_retval(%edx), %edx # %edx<- &retval + movl %edx, -24(%esp) # push parameter pMterpGlue + movl %eax, -28(%esp) # push parameter newFP + lea -28(%esp), %esp + +#ifdef ASSIST_DEBUGGER + jmp .Lskip + .type dalvik_mterp, %function +dalvik_mterp: + MTERP_ENTRY +.Lskip: +#endif + call *offMethod_nativeFunc(%ecx) # call methodToCall->nativeFunc + lea 28(%esp), %esp + movl -4(%esp), %edx # %edx<- newSaveArea + movl -8(%esp), %ecx # %ecx<- glue->self + movl offStackSaveArea_localRefCookie(%edx), %eax # %eax<- newSaveArea->localRefCookie + FFETCH_ADV 3, %edx # %edx<- next instruction hi; fetch, advance + cmp $$0, offThread_exception(%ecx) # check for exception + movl rFP, offThread_curFrame(%ecx) # glue->self->curFrame<- rFP + movl %eax, offThread_jniLocal_topCookie(%ecx) # glue->self<- newSaveArea->localRefCookie + jne common_exceptionThrown # handle exception + FGETOP_JMP 3, %edx # jump to next instruction; getop, jmp + +.LstackOverflow: + movl %ecx, -4(%esp) # push method to call + movl rGLUE, %ecx # %ecx<- pMterpGlue + movl offGlue_self(%ecx), %ecx # %ecx<- glue->self + movl %ecx, -8(%esp) # push parameter self + lea -8(%esp), %esp + call dvmHandleStackOverflow # call: (Thread* self, Method *meth) + # return: void + lea 8(%esp), %esp + jmp common_exceptionThrown # handle exception +#ifdef ASSIST_DEBUGGER +#endif + + /* + * Common code for handling a return instruction. + * + * This does not return. + */ + +common_returnFromMethod: +.LreturnNew: + + /* + * Inline common periodic checks + */ + + movl rGLUE, rINST # %ecx<- pMterpGlue + movl offGlue_pSelfSuspendCount(rINST), %edx # %ebx<- pSuspendCount (int) + movl offGlue_pDebuggerActive(rINST), %eax # %eax<- pDebuggerActive + movl (%eax), %eax # %eax<- get debuggerActive (boolean) + and $$7, %eax # %eax<- mask for boolean (just how many bits does it take?) + cmp $$0, (%edx) # check if suspend is pending + jne 2f # handle suspend + movl offGlue_pActiveProfilers(rINST), %edx # %edx<- activeProfilers (int) + or (%edx), %eax # %eax<- merge activeProfilers and debuggerActive + cmp $$0, %eax # check for debuggerActive + jne 3f # debugger or profiler active; switch interp + jmp 4f +2: # check suspended + movl offGlue_self(rINST), %eax# %eax<- glue->self + movl %eax, -12(%esp) # push parameter boolean + lea -12(%esp), %esp + call dvmCheckSuspendPending # call: (Thread* self) + # return: bool + lea 12(%esp), %esp + jmp 4f +3: # debugger/profiler enabled, bail out + movl $$kInterpEntryInstr, offGlue_entryPoint(rINST) # glue->entryPoint<- reentry type + movl $$1, %edx # switch to interp<- true + jmp common_gotoBail # bail + + + /* + * Get save area; rGLUE is %ebx, rFP is %eax + */ +4: + SAVEAREA_FROM_FP %ecx # %ecx<- saveArea(old) + movl offStackSaveArea_prevFrame(%ecx), rFP # rFP<- saveArea->PrevFrame + movl (offStackSaveArea_method - sizeofStackSaveArea)(rFP), %edx # %edx<- method we are returning to + cmpl $$0, %edx # check for break frame + je common_gotoBail # bail if break frame + movl offStackSaveArea_savedPc(%ecx), rPC # rPC<- saveAreaOld->savedPc + movl offGlue_self(rINST), %ecx # %eax<- glue->self + movl %edx, offGlue_method(rINST) # glue->method<- newSave->method + movl offMethod_clazz(%edx), %edx # %edx<- method->clazz + FFETCH_ADV 3, %eax # %ecx<- next instruction hi; fetch, advance + movl rFP, offThread_curFrame(%ecx) # glue->self->curFrame<- rFP + movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex + movl %edx, offGlue_methodClassDex(rINST) # glue->pDvmDex<- method->clazz->pDvmDex + FGETOP_JMP 3, %eax # jump to next instruction; getop, jmp + + /* + * Handle thrown an exception. If the exception processing code + * returns to us (instead of falling out of the interpreter), + * continue with whatever the next instruction now happens to be. + * This does not return. + */ + +common_exceptionThrown: +.LexceptionNew: + movl $$kInterpEntryThrow, %ecx # %ecx<- reentry type + movl $$0, %edx # %edx<- pc adjustment + call common_periodicChecks + movl rGLUE, %eax # %eax<- pMterpGlue + movl offGlue_self(%eax), %edx # %edx<- glue->self + movl offThread_exception(%edx), %ecx # %ecx<- pMterpGlue->self->exception + movl %edx, -4(%esp) # push parameter self + movl %ecx, -8(%esp) # push parameter obj + lea -8(%esp), %esp + call dvmAddTrackedAlloc # don't allow the exception to be GC'd + # call: (Object* obj, Thread* self) + # return: void + movl 4(%esp), %edx # %edx<- glue->self + movl $$0, offThread_exception(%edx) # glue->self->exception<- NULL + + /* + * set up args and a local for &fp + */ + + movl rFP, -4(%esp) # move fp to stack + lea -4(%esp), %esp # update %esp + movl %esp, -4(%esp) # push parameter 4<- &fp + movl $$0, -8(%esp) # push parameter 3<- false + movl 4(%esp), %edx + movl %edx, -12(%esp) # push parameter 2<- glue->self->exception + movl rGLUE, %eax # %eax<- pMterpGlue + movl offGlue_method(%eax), %edx # %edx<- glue->method + movl offMethod_insns(%edx), %edx # %edx<- glue->method->insns + movl rPC, %ecx # %ecx<- rPC + subl %edx, %ecx # %ecx<- pc - glue->method->insns + sar $$1, %ecx # %ecx<- adjust %ecx for offset + movl %ecx, -16(%esp) # push parameter 1<- glue->method->insns + movl 8(%esp), %edx + movl %edx, -20(%esp) # push parameter 0<- glue->self + lea -20(%esp), %esp + + /* + * call dvmFindCatchBlock, %eax gets catchRelPc (a code-unit offset) + */ + + call dvmFindCatchBlock # call: (Thread* self, int relPc, Object* exception, + # bool doUnroll, void** newFrame) + # return: int + lea 32(%esp), %esp + movl -12(%esp), rFP # rFP<- updated rFP + cmp $$0, %eax # check for catchRelPc < 0 + jl .LnotCaughtLocally # handle not caught locally + + /* + * fix stack overflow if necessary + */ + + movl -4(%esp), %ecx # %ecx<- glue->self + cmp $$0, offThread_stackOverflowed(%ecx) + je 1f + movl %eax, -4(%esp) # save %eax for later + movl %ecx, -12(%esp) # push parameter 2 glue->self + lea -12(%esp), %esp + call dvmCleanupStackOverflow # call: (Thread* self, Object* exception) + # return: void + lea 12(%esp), %esp + movl -4(%esp), %eax # %eax<- restore %eax + jmp 2f +1: + movl %ecx, -12(%esp) # push parameter 2 glue->self +2: + + /* + * adjust locals to match self->curFrame and updated PC + * + */ + + SAVEAREA_FROM_FP %edx # %edx<- get newSaveArea + movl rGLUE, %ecx # %ecx<- pMterpGlue + movl offStackSaveArea_method(%edx), rPC # rPC<- newMethod + movl rPC, offGlue_method(%ecx) # glue->method<- newMethod + movl offMethod_clazz(rPC), %edx # %edx<- method->clazz + movl offMethod_insns(rPC), rPC # rPC<- method->insns + movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex + lea (rPC, %eax, 2), rPC # rPC<- method->insns + catchRelPc + movl %edx, offGlue_methodClassDex(%ecx) # glue->pDvmDex<- method->clazz->pDvmDex + movl -8(%esp), %eax + movl %eax, -16(%esp) # push parameter 1 obj + lea -16(%esp), %esp + call dvmReleaseTrackedAlloc # call: (Object* obj, Thread* self) + # return: void + lea 16(%esp), %esp + FINISH_FETCH %eax + cmp $$OP_MOVE_EXCEPTION, %eax # is it a move exception + jne 1f + movl -12(%esp), %edx # %edx<- glue->self + movl -8(%esp), %ecx # %ecx<- exception + movl %ecx, offThread_exception(%edx) # restore the exception +1: + FINISH_JMP %eax + + /* + * -8(%esp) = exception, -4(%esp) = self + */ + +.LnotCaughtLocally: + movl -4(%esp), %edx # %edx<- glue->self + movzb offThread_stackOverflowed(%edx), %eax # %eax<- self->stackOverflowed + cmp $$0, %eax # check for stack overflow; + # maybe should use cmpb + je 1f # + movl %edx, -12(%esp) # push parameter 1 glue->self + lea -12(%esp), %esp + call dvmCleanupStackOverflow # call: (Thread* self, Object* exception) + # return: void + lea 12(%esp), %esp + + /* + * Release the exception + * -8(%esp) = exception, -4(%esp) = self + */ +1: + movl -8(%esp), %ecx # %ecx<- exception + movl -4(%esp), %edx # %edx<- glue->self + movl %ecx, offThread_exception(%edx) # glue->self<- exception + lea -8(%esp), %esp + call dvmReleaseTrackedAlloc # call: (Object* obj, Thread* self) + # return: void + lea 8(%esp), %esp + movl $$0, %edx # switch to interp<- false + jmp common_gotoBail # bail + + /* + * After returning from a "glued" function, pull out the updated + * values and start executing at the next instruction. + */ + +common_resumeAfterGlueCall: + LOAD_PC_FP_FROM_GLUE # pull rPC and rFP out of glue + FINISH_A # jump to next instruction + + /* + * For debugging, cause an immediate fault. + */ + +common_abort: + jmp .LdeadFood + +.LdeadFood: +.int 0xdeadf00d + + /* + * Invalid array index. + */ + +common_errArrayIndex: + EXPORT_PC + movl $$.LstrArrayIndexException, -8(%esp) # push parameter description + movl $$0, -4(%esp) # push parameter msg paramter + lea -8(%esp), %esp + call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) + # return: void + lea 8(%esp), %esp + jmp common_exceptionThrown # handle exception + + /* + * Invalid array value. + */ + +common_errArrayStore: + EXPORT_PC + movl $$.LstrArrayStoreException, -8(%esp) # push parameter description + movl $$0, -4(%esp) # push parameter msg paramter + lea -8(%esp), %esp + call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) + # return: void + lea 8(%esp), %esp + jmp common_exceptionThrown # handle exception + + /* + * Integer divide or mod by zero. + */ + +common_errDivideByZero: + EXPORT_PC + movl $$.LstrArithmeticException, -8(%esp) # push parameter description + movl $$.LstrDivideByZero, -4(%esp) # push parameter msg paramter + lea -8(%esp), %esp + call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) + # return: void + lea 8(%esp), %esp + jmp common_exceptionThrown # handle exception + + /* + * Attempt to allocate an array with a negative size. + */ + +common_errNegativeArraySize: + EXPORT_PC + movl $$.LstrNegativeArraySizeException, -8(%esp) # push parameter description + movl $$0, -4(%esp) # push parameter msg paramter + lea -8(%esp), %esp + call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) + # return: void + lea 8(%esp), %esp + jmp common_exceptionThrown # handle exception + + /* + * Invocation of a non-existent method. + */ + +common_errNoSuchMethod: + EXPORT_PC + movl $$.LstrNoSuchMethodError, -8(%esp) # push parameter description + movl $$0, -4(%esp) # push parameter msg paramter + lea -8(%esp), %esp + call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) + # return: void + lea 8(%esp), %esp + jmp common_exceptionThrown # handle exception + + /* + * Unexpected null object. + */ + +common_errNullObject: + EXPORT_PC + movl $$.LstrNullPointerException, -8(%esp) # push parameter description + movl $$0, -4(%esp) # push parameter msg paramter + lea -8(%esp), %esp + call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) + # return: void + lea 8(%esp), %esp + jmp common_exceptionThrown # handle exception + + /* + * String references + */ + + .align 4 + .section .rodata +.LstrArithmeticException: + .asciz "Ljava/lang/ArithmeticException;" +.LstrArrayIndexException: + .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" +.LstrArrayStoreException: + .asciz "Ljava/lang/ArrayStoreException;" +.LstrClassCastException: + .asciz "Ljava/lang/ClassCastException;" +.LstrDivideByZero: + .asciz "divide by zero" +.LstrInstantiationError: + .asciz "Ljava/lang/InstantiationError;" +.LstrNegativeArraySizeException: + .asciz "Ljava/lang/NegativeArraySizeException;" +.LstrNoSuchMethodError: + .asciz "Ljava/lang/NoSuchMethodError;" +.LstrNullPointerException: + .asciz "Ljava/lang/NullPointerException;" +.LstrExceptionNotCaughtLocally: + .asciz "Exception %s from %s:%d not caught locally\n" |