1 /* Copyright (C) 2008 The Android Open Source Project 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 /* 17 * File: footer.S 18 */ 19 20 .text 21 .align 2 22 23 /* 24 * Check to see if the thread needs to be suspended or debugger/profiler 25 * activity has begun. 26 * 27 * On entry: 28 * %ecx is reentry type, e.g. kInterpEntryInstr 29 * %edx is PC adjustment in bytes 30 */ 31 32common_periodicChecks: 33 movl %edx, -8(%esp) # save pc adjustments 34 movl rGLUE, %edx # %edx<- pMterpGlue 35 movl %ebx, -4(%esp) # save %ebx to the stack 36 movl offGlue_pSelfSuspendCount(%edx), %ebx # %ebx<- pSuspendCount (int) 374: 38 movl offGlue_pDebuggerActive(%edx), %eax # %eax<- pDebuggerActive 39 testl %eax, %eax 40 je 5f 41 movzbl (%eax), %eax # %eax<- get debuggerActive (boolean) 425: 43 cmp $$0, (%ebx) # check if suspend is pending 44 jne 2f # handle suspend 45 movl offGlue_pActiveProfilers(%edx), %ebx # %ebx<- activeProfilers (int) 46 orl (%ebx), %eax # %eax<- merge activeProfilers and debuggerActive 47 movl -8(%esp), %edx # %edx<- restore %edx 48 jne 3f # debugger or profiler active; switch interp 49 movl -4(%esp), %ebx # %ebx<- restore %ebx 50 ret # return 512: # check suspended 52 EXPORT_PC 53 movl offGlue_self(%edx), %eax # %eax<- glue->self 54 movl %eax, -12(%esp) # push parameter boolean 55 lea -12(%esp), %esp 56 call dvmCheckSuspendPending # call: (Thread* self) 57 # return: bool 58 movl 4(%esp), %edx # %edx<- restore %edx 59 movl 8(%esp), %ebx # %ebx<- restore %ebx 60 lea 12(%esp), %esp 61 ret 623: # debugger/profiler enabled, bail out 63 leal (rPC, %edx, 2), rPC # adjust pc to show target 64 movl rGLUE, %ecx # %ecx<- pMterpGlue 65 movb $$kInterpEntryInstr, offGlue_entryPoint(%ecx) 66 movl $$1, %edx # switch interpreter 67 jmp common_gotoBail # bail 68 69 /* 70 * Check to see if the thread needs to be suspended or debugger/profiler 71 * activity has begun. With this variant, the reentry type is hard coded 72 * as kInterpEntryInstr. 73 * 74 * On entry: 75 * %edx is PC adjustment in bytes 76 */ 77 78common_periodicChecks_backwardBranch: 79 EXPORT_PC 80 movl rGLUE, %ecx # %ecx<- pMterpGlue 81 movl offGlue_pSelfSuspendCount(%ecx), rINST # %ebx<- pSuspendCount (int) 824: 83 movl offGlue_pDebuggerActive(%ecx), %eax # %eax<- pDebuggerActive 84 testl %eax, %eax # test for NULL pointer 85 je 5f 86 movzbl (%eax), %eax # %eax<- get debuggerActive count 875: 88 cmp $$0, (rINST) # check if suspend is pending 89 jne 2f # handle suspend 90 movl offGlue_pActiveProfilers(%ecx), rINST # %edx<- activeProfilers (int) 91 orl (rINST), %eax # %eax<- merge activeProfilers and debuggerActive 92 jne 3f # debugger or profiler active; switch interp 93 FINISH_RB %edx, %ecx # jump to next instruction 942: # check suspended 95 movl offGlue_self(%ecx), %eax# %eax<- glue->self 96 movl %edx, rINST 97 movl %eax, -12(%esp) # push parameter boolean 98 lea -12(%esp), %esp 99 call dvmCheckSuspendPending # call: (Thread* self) 100 # return: bool 101 movl rINST, %edx # %edx<- restore %edx 102 lea 12(%esp), %esp 103 FINISH_RB %edx, %ecx 1043: # debugger/profiler enabled, bail out 105 leal (rPC, %edx, 2), rPC # adjust pc to show target 106 movb $$kInterpEntryInstr, offGlue_entryPoint(%ecx) 107 movl $$1, %edx # switch interpreter 108 jmp common_gotoBail # bail 109 110 /* 111 * The equivalent of "goto bail", this calls through the "bail handler". 112 * State registers will be saved to the "glue" area before bailing. 113 * 114 * On entry: 115 * %edx is "bool changeInterp", indicating if we want to switch to the 116 * other interpreter or just bail all the way out 117 */ 118 119common_gotoBail: 120 SAVE_PC_FP_TO_GLUE %ecx # save program counter and frame pointer 121 122 /* 123 * Inlined dvmMterpStdBail 124 */ 125 126 lea 40(%ebp), %esp 127 movl %edx, %eax 128 movl 24(%ebp), %edi 129 movl 28(%ebp), %esi 130 movl 32(%ebp), %ebx 131 movl 36(%ebp), %ebp 132 ret 133 134 /* 135 * Common code for method invocation with range. 136 * 137 * On entry: 138 * %ecx is "Method* methodToCall", the method we're trying to call 139 */ 140 141common_invokeMethodRange: 142.LinvokeNewRange: 143 144 /* 145 * prepare to copy args to "outs" area of current frame 146 */ 147 148 SAVEAREA_FROM_FP %eax # %eax<- &outs; &StackSaveArea 149 test rINST, rINST # test for no args 150 movl rINST, sReg0 # sReg0<- AA 151 jz .LinvokeArgsDone # no args; jump to args done 152 FETCH 2, %edx # %edx<- CCCC 153 154 /* 155 * %ecx=methodToCall, %edx=CCCC, sReg0=count, %eax=&outs (&stackSaveArea) 156 * (very few methods have > 10 args; could unroll for common cases) 157 */ 158 159 movl %ebx, sReg1 # sReg1<- save %ebx 160 lea (rFP, %edx, 4), %edx # %edx<- &vCCCC 161 shll $$2, sReg0 # sReg0<- offset 162 subl sReg0, %eax # %eax<- update &outs 163 shrl $$2, sReg0 # sReg0<- offset 1641: 165 movl (%edx), %ebx # %ebx<- vCCCC 166 lea 4(%edx), %edx # %edx<- &vCCCC++ 167 subl $$1, sReg0 # sReg<- sReg-- 168 movl %ebx, (%eax) # *outs<- vCCCC 169 lea 4(%eax), %eax # outs++ 170 jne 1b # loop if count (sReg0) not zero 171 movl sReg1, %ebx # %ebx<- restore %ebx 172 jmp .LinvokeArgsDone # continue 173 174 /* 175 * %ecx is "Method* methodToCall", the method we're trying to call 176 * prepare to copy args to "outs" area of current frame 177 */ 178 179common_invokeMethodNoRange: 180.LinvokeNewNoRange: 181 movl rINST, sReg0 # sReg0<- BA 182 shrl $$4, sReg0 # sReg0<- B 183 je .LinvokeArgsDone # no args; jump to args done 184 SAVEAREA_FROM_FP %eax # %eax<- &outs; &StackSaveArea 185 FETCH 2, %edx # %edx<- GFED 186 187 /* 188 * %ecx=methodToCall, %edx=GFED, sReg0=count, %eax=outs 189 */ 190 191.LinvokeNonRange: 192 cmp $$2, sReg0 # compare sReg0 to 2 193 movl %edx, sReg1 # sReg1<- GFED 194 jl 1f # handle 1 arg 195 je 2f # handle 2 args 196 cmp $$4, sReg0 # compare sReg0 to 4 197 jl 3f # handle 3 args 198 je 4f # handle 4 args 1995: 200 andl $$15, rINST # rINST<- A 201 lea -4(%eax), %eax # %eax<- update &outs; &outs-- 202 movl (rFP, rINST, 4), %edx # %edx<- vA 203 movl %edx, (%eax) # *outs<- vA 204 movl sReg1, %edx # %edx<- GFED 2054: 206 shr $$12, %edx # %edx<- G 207 lea -4(%eax), %eax # %eax<- update &outs; &outs-- 208 movl (rFP, %edx, 4), %edx # %edx<- vG 209 movl %edx, (%eax) # *outs<- vG 210 movl sReg1, %edx # %edx<- GFED 2113: 212 and $$0x0f00, %edx # %edx<- 0F00 213 shr $$6, %edx # %edx<- F at correct offset 214 lea -4(%eax), %eax # %eax<- update &outs; &outs-- 215 movl (rFP, %edx), %edx # %edx<- vF 216 movl %edx, (%eax) # *outs<- vF 217 movl sReg1, %edx # %edx<- GFED 2182: 219 and $$0x00f0, %edx # %edx<- 00E0 220 shr $$2, %edx # %edx<- E at correct offset 221 lea -4(%eax), %eax # %eax<- update &outs; &outs-- 222 movl (rFP, %edx), %edx # %edx<- vE 223 movl %edx, (%eax) # *outs<- vE 224 movl sReg1, %edx # %edx<- GFED 2251: 226 and $$0x000f, %edx # %edx<- 000D 227 movl (rFP, %edx, 4), %edx # %edx<- vD 228 movl %edx, -4(%eax) # *--outs<- vD 2290: 230 231 /* 232 * %ecx is "Method* methodToCall", the method we're trying to call 233 * find space for the new stack frame, check for overflow 234 */ 235 236.LinvokeArgsDone: 237 movzwl offMethod_registersSize(%ecx), %eax # %eax<- methodToCall->regsSize 238 movzwl offMethod_outsSize(%ecx), %edx # %edx<- methodToCall->outsSize 239 movl %ecx, sReg0 # sReg<- methodToCall 240 shl $$2, %eax # %eax<- update offset 241 SAVEAREA_FROM_FP %ecx # %ecx<- &outs; &StackSaveArea 242 subl %eax, %ecx # %ecx<- newFP; (old savearea - regsSize) 243 movl rGLUE, %eax # %eax<- pMterpGlue 244 movl %ecx, sReg1 # sReg1<- &outs 245 subl $$sizeofStackSaveArea, %ecx # %ecx<- newSaveArea (stack save area using newFP) 246 movl offGlue_interpStackEnd(%eax), %eax # %eax<- glue->interpStackEnd 247 movl %eax, sReg2 # sReg2<- glue->interpStackEnd 248 shl $$2, %edx # %edx<- update offset for outsSize 249 movl %ecx, %eax # %eax<- newSaveArea 250 sub %edx, %ecx # %ecx<- bottom; (newSaveArea - outsSize) 251 cmp sReg2, %ecx # compare interpStackEnd and bottom 252 movl sReg0, %ecx # %ecx<- restore methodToCall 253 jl .LstackOverflow # handle frame overflow 254 255 /* 256 * set up newSaveArea 257 */ 258 259#ifdef EASY_GDB 260 SAVEAREA_FROM_FP %edx # %edx<- &outs; &StackSaveArea 261 movl %edx, offStackSaveArea_prevSave(%eax) # newSaveArea->prevSave<- &outs 262#endif 263 movl rFP, offStackSaveArea_prevFrame(%eax) # newSaveArea->prevFrame<- rFP 264 movl rPC, offStackSaveArea_savedPc(%eax) # newSaveArea->savedPc<- rPC 265 testl $$ACC_NATIVE, offMethod_accessFlags(%ecx) # check for native call 266 movl %ecx, offStackSaveArea_method(%eax) # newSaveArea->method<- method to call 267 jne .LinvokeNative # handle native call 268 269 /* 270 * Update "glue" values for the new method 271 * %ecx=methodToCall, sReg1=newFp 272 */ 273 274 movl offMethod_clazz(%ecx), %edx # %edx<- method->clazz 275 movl rGLUE, %eax # %eax<- pMterpGlue 276 movl %ecx, offGlue_method(%eax) # glue->method<- methodToCall 277 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex 278 movl offMethod_insns(%ecx), rPC # rPC<- methodToCall->insns 279 movl %edx, offGlue_methodClassDex(%eax) # glue->methodClassDex<- method->clazz->pDvmDex 280 movl offGlue_self(%eax), %ecx # %ecx<- glue->self 281 movl sReg1, rFP # rFP<- newFP 282 movl rFP, offThread_curFrame(%ecx) # glue->self->curFrame<- newFP 283 FINISH_A # jump to methodToCall->insns 284 285 /* 286 * Prep for the native call 287 * %ecx=methodToCall, sReg1=newFP, %eax=newSaveArea 288 */ 289 290.LinvokeNative: 291 movl rGLUE, %edx # %edx<- pMterpGlue 292 movl %ecx, -20(%esp) # push parameter methodToCall 293 movl offGlue_self(%edx), %edx # %edx<- glue->self 294 movl offThread_jniLocal_topCookie(%edx), %ecx # %ecx<- glue->self->thread->refNext 295 movl %ecx, offStackSaveArea_localRefCookie(%eax) # newSaveArea->localRefCookie<- refNext 296 movl %eax, -4(%esp) # save newSaveArea 297 movl sReg1, %eax # %eax<- newFP 298 movl %eax, offThread_curFrame(%edx) # glue->self->curFrame<- newFP 299 movl %edx, -8(%esp) # save glue->self 300 movl %edx, -16(%esp) # push parameter glue->self 301 movl rGLUE, %edx # %edx<- pMterpGlue 302 movl -20(%esp), %ecx # %ecx<- methodToCall 303 lea offGlue_retval(%edx), %edx # %edx<- &retval 304 movl %edx, -24(%esp) # push parameter pMterpGlue 305 movl %eax, -28(%esp) # push parameter newFP 306 lea -28(%esp), %esp 307 308#ifdef ASSIST_DEBUGGER 309 jmp .Lskip 310 .type dalvik_mterp, %function 311dalvik_mterp: 312 MTERP_ENTRY 313.Lskip: 314#endif 315 call *offMethod_nativeFunc(%ecx) # call methodToCall->nativeFunc 316 lea 28(%esp), %esp 317 movl -4(%esp), %edx # %edx<- newSaveArea 318 movl -8(%esp), %ecx # %ecx<- glue->self 319 movl offStackSaveArea_localRefCookie(%edx), %eax # %eax<- newSaveArea->localRefCookie 320 FFETCH_ADV 3, %edx # %edx<- next instruction hi; fetch, advance 321 cmp $$0, offThread_exception(%ecx) # check for exception 322 movl rFP, offThread_curFrame(%ecx) # glue->self->curFrame<- rFP 323 movl %eax, offThread_jniLocal_topCookie(%ecx) # glue->self<- newSaveArea->localRefCookie 324 jne common_exceptionThrown # handle exception 325 FGETOP_JMP 3, %edx # jump to next instruction; getop, jmp 326 327.LstackOverflow: 328 movl %ecx, -4(%esp) # push method to call 329 movl rGLUE, %ecx # %ecx<- pMterpGlue 330 movl offGlue_self(%ecx), %ecx # %ecx<- glue->self 331 movl %ecx, -8(%esp) # push parameter self 332 lea -8(%esp), %esp 333 call dvmHandleStackOverflow # call: (Thread* self, Method *meth) 334 # return: void 335 lea 8(%esp), %esp 336 jmp common_exceptionThrown # handle exception 337#ifdef ASSIST_DEBUGGER 338#endif 339 340 /* 341 * Common code for handling a return instruction. 342 * 343 * This does not return. 344 */ 345 346common_returnFromMethod: 347.LreturnNew: 348 349 /* 350 * Inline common periodic checks 351 */ 352 353 movl rGLUE, rINST # %ecx<- pMterpGlue 354 movl offGlue_pSelfSuspendCount(rINST), %edx # %ebx<- pSuspendCount (int) 355 movl offGlue_pDebuggerActive(rINST), %eax # %eax<- pDebuggerActive 356 movl (%eax), %eax # %eax<- get debuggerActive (boolean) 357 and $$7, %eax # %eax<- mask for boolean (just how many bits does it take?) 358 cmp $$0, (%edx) # check if suspend is pending 359 jne 2f # handle suspend 360 movl offGlue_pActiveProfilers(rINST), %edx # %edx<- activeProfilers (int) 361 or (%edx), %eax # %eax<- merge activeProfilers and debuggerActive 362 cmp $$0, %eax # check for debuggerActive 363 jne 3f # debugger or profiler active; switch interp 364 jmp 4f 3652: # check suspended 366 movl offGlue_self(rINST), %eax# %eax<- glue->self 367 movl %eax, -12(%esp) # push parameter boolean 368 lea -12(%esp), %esp 369 call dvmCheckSuspendPending # call: (Thread* self) 370 # return: bool 371 lea 12(%esp), %esp 372 jmp 4f 3733: # debugger/profiler enabled, bail out 374 movl $$kInterpEntryInstr, offGlue_entryPoint(rINST) # glue->entryPoint<- reentry type 375 movl $$1, %edx # switch to interp<- true 376 jmp common_gotoBail # bail 377 378 379 /* 380 * Get save area; rGLUE is %ebx, rFP is %eax 381 */ 3824: 383 SAVEAREA_FROM_FP %ecx # %ecx<- saveArea(old) 384 movl offStackSaveArea_prevFrame(%ecx), rFP # rFP<- saveArea->PrevFrame 385 movl (offStackSaveArea_method - sizeofStackSaveArea)(rFP), %edx # %edx<- method we are returning to 386 cmpl $$0, %edx # check for break frame 387 je common_gotoBail # bail if break frame 388 movl offStackSaveArea_savedPc(%ecx), rPC # rPC<- saveAreaOld->savedPc 389 movl offGlue_self(rINST), %ecx # %eax<- glue->self 390 movl %edx, offGlue_method(rINST) # glue->method<- newSave->method 391 movl offMethod_clazz(%edx), %edx # %edx<- method->clazz 392 FFETCH_ADV 3, %eax # %ecx<- next instruction hi; fetch, advance 393 movl rFP, offThread_curFrame(%ecx) # glue->self->curFrame<- rFP 394 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex 395 movl %edx, offGlue_methodClassDex(rINST) # glue->pDvmDex<- method->clazz->pDvmDex 396 FGETOP_JMP 3, %eax # jump to next instruction; getop, jmp 397 398 /* 399 * Handle thrown an exception. If the exception processing code 400 * returns to us (instead of falling out of the interpreter), 401 * continue with whatever the next instruction now happens to be. 402 * This does not return. 403 */ 404 405common_exceptionThrown: 406.LexceptionNew: 407 movl $$kInterpEntryThrow, %ecx # %ecx<- reentry type 408 movl $$0, %edx # %edx<- pc adjustment 409 call common_periodicChecks 410 movl rGLUE, %eax # %eax<- pMterpGlue 411 movl offGlue_self(%eax), %edx # %edx<- glue->self 412 movl offThread_exception(%edx), %ecx # %ecx<- pMterpGlue->self->exception 413 movl %edx, -4(%esp) # push parameter self 414 movl %ecx, -8(%esp) # push parameter obj 415 lea -8(%esp), %esp 416 call dvmAddTrackedAlloc # don't allow the exception to be GC'd 417 # call: (Object* obj, Thread* self) 418 # return: void 419 movl 4(%esp), %edx # %edx<- glue->self 420 movl $$0, offThread_exception(%edx) # glue->self->exception<- NULL 421 422 /* 423 * set up args and a local for &fp 424 */ 425 426 movl rFP, -4(%esp) # move fp to stack 427 lea -4(%esp), %esp # update %esp 428 movl %esp, -4(%esp) # push parameter 4<- &fp 429 movl $$0, -8(%esp) # push parameter 3<- false 430 movl 4(%esp), %edx 431 movl %edx, -12(%esp) # push parameter 2<- glue->self->exception 432 movl rGLUE, %eax # %eax<- pMterpGlue 433 movl offGlue_method(%eax), %edx # %edx<- glue->method 434 movl offMethod_insns(%edx), %edx # %edx<- glue->method->insns 435 movl rPC, %ecx # %ecx<- rPC 436 subl %edx, %ecx # %ecx<- pc - glue->method->insns 437 sar $$1, %ecx # %ecx<- adjust %ecx for offset 438 movl %ecx, -16(%esp) # push parameter 1<- glue->method->insns 439 movl 8(%esp), %edx 440 movl %edx, -20(%esp) # push parameter 0<- glue->self 441 lea -20(%esp), %esp 442 443 /* 444 * call dvmFindCatchBlock, %eax gets catchRelPc (a code-unit offset) 445 */ 446 447 call dvmFindCatchBlock # call: (Thread* self, int relPc, Object* exception, 448 # bool doUnroll, void** newFrame) 449 # return: int 450 lea 32(%esp), %esp 451 movl -12(%esp), rFP # rFP<- updated rFP 452 cmp $$0, %eax # check for catchRelPc < 0 453 jl .LnotCaughtLocally # handle not caught locally 454 455 /* 456 * fix stack overflow if necessary 457 */ 458 459 movl -4(%esp), %ecx # %ecx<- glue->self 460 cmp $$0, offThread_stackOverflowed(%ecx) 461 je 1f 462 movl %eax, -4(%esp) # save %eax for later 463 movl %ecx, -12(%esp) # push parameter 2 glue->self 464 lea -12(%esp), %esp 465 call dvmCleanupStackOverflow # call: (Thread* self, Object* exception) 466 # return: void 467 lea 12(%esp), %esp 468 movl -4(%esp), %eax # %eax<- restore %eax 469 jmp 2f 4701: 471 movl %ecx, -12(%esp) # push parameter 2 glue->self 4722: 473 474 /* 475 * adjust locals to match self->curFrame and updated PC 476 * 477 */ 478 479 SAVEAREA_FROM_FP %edx # %edx<- get newSaveArea 480 movl rGLUE, %ecx # %ecx<- pMterpGlue 481 movl offStackSaveArea_method(%edx), rPC # rPC<- newMethod 482 movl rPC, offGlue_method(%ecx) # glue->method<- newMethod 483 movl offMethod_clazz(rPC), %edx # %edx<- method->clazz 484 movl offMethod_insns(rPC), rPC # rPC<- method->insns 485 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex 486 lea (rPC, %eax, 2), rPC # rPC<- method->insns + catchRelPc 487 movl %edx, offGlue_methodClassDex(%ecx) # glue->pDvmDex<- method->clazz->pDvmDex 488 movl -8(%esp), %eax 489 movl %eax, -16(%esp) # push parameter 1 obj 490 lea -16(%esp), %esp 491 call dvmReleaseTrackedAlloc # call: (Object* obj, Thread* self) 492 # return: void 493 lea 16(%esp), %esp 494 FINISH_FETCH %eax 495 cmp $$OP_MOVE_EXCEPTION, %eax # is it a move exception 496 jne 1f 497 movl -12(%esp), %edx # %edx<- glue->self 498 movl -8(%esp), %ecx # %ecx<- exception 499 movl %ecx, offThread_exception(%edx) # restore the exception 5001: 501 FINISH_JMP %eax 502 503 /* 504 * -8(%esp) = exception, -4(%esp) = self 505 */ 506 507.LnotCaughtLocally: 508 movl -4(%esp), %edx # %edx<- glue->self 509 movzb offThread_stackOverflowed(%edx), %eax # %eax<- self->stackOverflowed 510 cmp $$0, %eax # check for stack overflow; 511 # maybe should use cmpb 512 je 1f # 513 movl %edx, -12(%esp) # push parameter 1 glue->self 514 lea -12(%esp), %esp 515 call dvmCleanupStackOverflow # call: (Thread* self, Object* exception) 516 # return: void 517 lea 12(%esp), %esp 518 519 /* 520 * Release the exception 521 * -8(%esp) = exception, -4(%esp) = self 522 */ 5231: 524 movl -8(%esp), %ecx # %ecx<- exception 525 movl -4(%esp), %edx # %edx<- glue->self 526 movl %ecx, offThread_exception(%edx) # glue->self<- exception 527 lea -8(%esp), %esp 528 call dvmReleaseTrackedAlloc # call: (Object* obj, Thread* self) 529 # return: void 530 lea 8(%esp), %esp 531 movl $$0, %edx # switch to interp<- false 532 jmp common_gotoBail # bail 533 534 /* 535 * After returning from a "glued" function, pull out the updated 536 * values and start executing at the next instruction. 537 */ 538 539common_resumeAfterGlueCall: 540 LOAD_PC_FP_FROM_GLUE # pull rPC and rFP out of glue 541 FINISH_A # jump to next instruction 542 543 /* 544 * For debugging, cause an immediate fault. 545 */ 546 547common_abort: 548 jmp .LdeadFood 549 550.LdeadFood: 551.int 0xdeadf00d 552 553 /* 554 * Invalid array index. 555 */ 556 557common_errArrayIndex: 558 EXPORT_PC 559 movl $$.LstrArrayIndexException, -8(%esp) # push parameter description 560 movl $$0, -4(%esp) # push parameter msg paramter 561 lea -8(%esp), %esp 562 call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) 563 # return: void 564 lea 8(%esp), %esp 565 jmp common_exceptionThrown # handle exception 566 567 /* 568 * Invalid array value. 569 */ 570 571common_errArrayStore: 572 EXPORT_PC 573 movl $$.LstrArrayStoreException, -8(%esp) # push parameter description 574 movl $$0, -4(%esp) # push parameter msg paramter 575 lea -8(%esp), %esp 576 call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) 577 # return: void 578 lea 8(%esp), %esp 579 jmp common_exceptionThrown # handle exception 580 581 /* 582 * Integer divide or mod by zero. 583 */ 584 585common_errDivideByZero: 586 EXPORT_PC 587 movl $$.LstrArithmeticException, -8(%esp) # push parameter description 588 movl $$.LstrDivideByZero, -4(%esp) # push parameter msg paramter 589 lea -8(%esp), %esp 590 call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) 591 # return: void 592 lea 8(%esp), %esp 593 jmp common_exceptionThrown # handle exception 594 595 /* 596 * Attempt to allocate an array with a negative size. 597 */ 598 599common_errNegativeArraySize: 600 EXPORT_PC 601 movl $$.LstrNegativeArraySizeException, -8(%esp) # push parameter description 602 movl $$0, -4(%esp) # push parameter msg paramter 603 lea -8(%esp), %esp 604 call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) 605 # return: void 606 lea 8(%esp), %esp 607 jmp common_exceptionThrown # handle exception 608 609 /* 610 * Invocation of a non-existent method. 611 */ 612 613common_errNoSuchMethod: 614 EXPORT_PC 615 movl $$.LstrNoSuchMethodError, -8(%esp) # push parameter description 616 movl $$0, -4(%esp) # push parameter msg paramter 617 lea -8(%esp), %esp 618 call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) 619 # return: void 620 lea 8(%esp), %esp 621 jmp common_exceptionThrown # handle exception 622 623 /* 624 * Unexpected null object. 625 */ 626 627common_errNullObject: 628 EXPORT_PC 629 movl $$.LstrNullPointerException, -8(%esp) # push parameter description 630 movl $$0, -4(%esp) # push parameter msg paramter 631 lea -8(%esp), %esp 632 call dvmThrowException # call: (const char* exceptionDescriptor, const char* msg) 633 # return: void 634 lea 8(%esp), %esp 635 jmp common_exceptionThrown # handle exception 636 637 /* 638 * String references 639 */ 640 641 .align 4 642 .section .rodata 643.LstrArithmeticException: 644 .asciz "Ljava/lang/ArithmeticException;" 645.LstrArrayIndexException: 646 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 647.LstrArrayStoreException: 648 .asciz "Ljava/lang/ArrayStoreException;" 649.LstrDivideByZero: 650 .asciz "divide by zero" 651.LstrInstantiationError: 652 .asciz "Ljava/lang/InstantiationError;" 653.LstrNegativeArraySizeException: 654 .asciz "Ljava/lang/NegativeArraySizeException;" 655.LstrNoSuchMethodError: 656 .asciz "Ljava/lang/NoSuchMethodError;" 657.LstrNullPointerException: 658 .asciz "Ljava/lang/NullPointerException;" 659.LstrExceptionNotCaughtLocally: 660 .asciz "Exception %s from %s:%d not caught locally\n" 661