1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16/* 17 * Common subroutines and data. 18 */ 19 20#if defined(WITH_JIT) 21/* 22 * JIT-related re-entries into the interpreter. In general, if the 23 * exit from a translation can at some point be chained, the entry 24 * here requires that control arrived via a call, and that the "rp" 25 * on TOS is actually a pointer to a 32-bit cell containing the Dalvik PC 26 * of the next insn to handle. If no chaining will happen, the entry 27 * should be reached via a direct jump and rPC set beforehand. 28 */ 29 30 .global dvmJitToInterpPunt 31/* 32 * The compiler will generate a jump to this entry point when it is 33 * having difficulty translating a Dalvik instruction. We must skip 34 * the code cache lookup & prevent chaining to avoid bouncing between 35 * the interpreter and code cache. rPC must be set on entry. 36 */ 37dvmJitToInterpPunt: 38#if defined(WITH_JIT_TUNING) 39 movl rPC, OUT_ARG0(%esp) 40 call dvmBumpPunt 41#endif 42 movl rSELF, %ecx 43 movl offThread_curHandlerTable(%ecx),rIBASE 44 FETCH_INST_R %ecx 45 GOTO_NEXT_R %ecx 46 47 .global dvmJitToInterpSingleStep 48/* 49 * Return to the interpreter to handle a single instruction. 50 * Should be reached via a call. 51 * On entry: 52 * 0(%esp) <= native return address within trace 53 * rPC <= Dalvik PC of this instruction 54 * OUT_ARG0+4(%esp) <= Dalvik PC of next instruction 55 */ 56dvmJitToInterpSingleStep: 57/* TODO */ 58 call dvmAbort 59#if 0 60 pop %eax 61 movl rSELF, %ecx 62 movl OUT_ARG0(%esp), %edx 63 movl %eax,offThread_jitResumeNPC(%ecx) 64 movl %edx,offThread_jitResumeDPC(%ecx) 65 movl $$kInterpEntryInstr,offThread_entryPoint(%ecx) 66 movl $$1,rINST # changeInterp <= true 67 jmp common_gotoBail 68#endif 69 70 .global dvmJitToInterpNoChainNoProfile 71/* 72 * Return from the translation cache to the interpreter to do method 73 * invocation. Check if the translation exists for the callee, but don't 74 * chain to it. rPC must be set on entry. 75 */ 76dvmJitToInterpNoChainNoProfile: 77#if defined(WITH_JIT_TUNING) 78 call dvmBumpNoChain 79#endif 80 movl rSELF, %eax 81 movl rPC,OUT_ARG0(%esp) 82 movl %eax,OUT_ARG1(%esp) 83 call dvmJitGetTraceAddrThread # (pc, self) 84 movl rSELF,%ecx # ecx <- self 85 movl %eax,offThread_inJitCodeCache(%ecx) # set inJitCodeCache flag 86 cmpl $$0, %eax 87 jz 1f 88 call *%eax # exec translation if we've got one 89 # won't return 901: 91 movl rSELF, %ecx 92 movl offThread_curHandlerTable(%ecx),rIBASE 93 FETCH_INST_R %ecx 94 GOTO_NEXT_R %ecx 95 96/* 97 * Return from the translation cache and immediately request a 98 * translation fro the exit target, but don't attempt to chain. 99 * rPC set on entry. 100 */ 101 .global dvmJitToInterpTraceSelectNoChain 102dvmJitToInterpTraceSelectNoChain: 103#if defined(WITH_JIT_TUNING) 104 call dvmBumpNoChain 105#endif 106 movl rSELF, %eax 107 movl rPC,OUT_ARG0(%esp) 108 movl %eax,OUT_ARG1(%esp) 109 call dvmJitGetTraceAddrThread # (pc, self) 110 movl rSELF,%ecx 111 cmpl $$0,%eax 112 movl %eax,offThread_inJitCodeCache(%ecx) # set inJitCodeCache flag 113 jz 1f 114 call *%eax # jump to tranlation 115 # won't return 116 117/* No Translation - request one */ 1181: 119 GET_JIT_PROF_TABLE %ecx %eax 120 cmpl $$0, %eax # JIT enabled? 121 jnz 2f # Request one if so 122 movl rSELF, %ecx 123 movl offThread_curHandlerTable(%ecx),rIBASE 124 FETCH_INST_R %ecx # Continue interpreting if not 125 GOTO_NEXT_R %ecx 1262: 127 movl $$kJitTSelectRequestHot,rINST # ask for trace select 128 jmp common_selectTrace 129 130/* 131 * Return from the translation cache and immediately request a 132 * translation for the exit target. Reached via a call, and 133 * (TOS)->rPC. 134 */ 135 .global dvmJitToInterpTraceSelect 136dvmJitToInterpTraceSelect: 137 pop rINST # save chain cell address in callee save reg 138 movl (rINST),rPC 139 movl rSELF, %eax 140 movl rPC,OUT_ARG0(%esp) 141 movl %eax,OUT_ARG1(%esp) 142 call dvmJitGetTraceAddrThread # (pc, self) 143 cmpl $$0,%eax 144 jz 1b # no - ask for one 145 movl %eax,OUT_ARG0(%esp) 146# TODO - need to adjust rINST to beginning of sequence 147 movl rINST,OUT_ARG1(%esp) 148 call dvmJitChain # Attempt dvmJitChain(codeAddr,chainAddr) 149 cmpl $$0,%eax # Success? 150 jz toInterpreter # didn't chain - interpret 151 call *%eax 152 # won't return 153 154/* 155 * Placeholder entries for x86 JIT 156 */ 157 .global dvmJitToInterpBackwardBranch 158dvmJitToInterpBackwardBranch: 159 .global dvmJitToInterpNormal 160dvmJitToInterpNormal: 161 .global dvmJitToInterpNoChain 162dvmJitToInterpNoChain: 163toInterpreter: 164 jmp common_abort 165 166common_updateProfile: 167 # quick & dirty hash 168 movl rPC, %eax 169 shrl $$12, %eax 170 xorl rPC, %eax 171 andl $$((1<<JIT_PROF_SIZE_LOG_2)-1),%eax 172 decb (%edx,%eax) 173 jz 2f 1741: 175 GOTO_NEXT 1762: 177/* 178 * Here, we switch to the debug interpreter to request 179 * trace selection. First, though, check to see if there 180 * is already a native translation in place (and, if so, 181 * jump to it now. 182 */ 183 GET_JIT_THRESHOLD %ecx rINST # leaves rSELF in %ecx 184 EXPORT_PC 185 movb rINSTbl,(%edx,%eax) # reset counter 186 movl %ecx,rINST # preserve rSELF 187 movl rSELF, %eax 188 movl rPC,OUT_ARG0(%esp) 189 movl %eax,OUT_ARG1(%esp) 190 call dvmJitGetTraceAddr # (pc, self) 191 movl %eax,offThread_inJitCodeCache(rINST) # set the inJitCodeCache flag 192 cmpl $$0,%eax 193 jz 1f 194 call *%eax # TODO: decide call vs/ jmp!. No return either way 1951: 196 movl $$kJitTSelectRequest,%eax 197 # On entry, eax<- jitState, rPC valid 198common_selectTrace: 199/* TODO */ 200 call dvmAbort 201#if 0 202 movl rSELF,%ecx 203 movl %eax,offThread_jitState(%ecx) 204 movl $$kInterpEntryInstr,offThread_entryPoint(%ecx) 205 movl $$1,rINST 206 jmp common_gotoBail 207#endif 208#endif 209 210 211 212/* 213 * Common code for jumbo method invocation. 214 * 215 * On entry: 216 * eax = Method* methodToCall 217 * rINSTw trashed, must reload 218 * rIBASE trashed, must reload before resuming interpreter 219 */ 220 221common_invokeMethodJumbo: 222.LinvokeNewJumbo: 223 224 /* 225 * prepare to copy args to "outs" area of current frame 226 */ 227 movzwl 6(rPC),rINST # rINST<- BBBB 228 movzwl 8(rPC), %ecx # %ecx<- CCCC 229 ADVANCE_PC 2 # adjust pc to make return similar 230 SAVEAREA_FROM_FP %edx # %edx<- &StackSaveArea 231 test rINST, rINST 232 movl rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BBBB 233 jz .LinvokeArgsDone # no args; jump to args done 234 jmp .LinvokeRangeArgs # handle args like invoke range 235 236/* 237 * Common code for method invocation with range. 238 * 239 * On entry: 240 * eax = Method* methodToCall 241 * rINSTw trashed, must reload 242 * rIBASE trashed, must reload before resuming interpreter 243 */ 244 245common_invokeMethodRange: 246.LinvokeNewRange: 247 248 /* 249 * prepare to copy args to "outs" area of current frame 250 */ 251 252 movzbl 1(rPC),rINST # rINST<- AA 253 movzwl 4(rPC), %ecx # %ecx<- CCCC 254 SAVEAREA_FROM_FP %edx # %edx<- &StackSaveArea 255 test rINST, rINST 256 movl rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA 257 jz .LinvokeArgsDone # no args; jump to args done 258 259 260 /* 261 * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, 262 * %edx=&outs (&stackSaveArea). (very few methods have > 10 args; 263 * could unroll for common cases) 264 */ 265 266.LinvokeRangeArgs: 267 movl %ebx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- save %ebx 268 lea (rFP, %ecx, 4), %ecx # %ecx<- &vCCCC 269 shll $$2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 270 subl LOCAL0_OFFSET(%ebp), %edx # %edx<- update &outs 271 shrl $$2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 2721: 273 movl (%ecx), %ebx # %ebx<- vCCCC 274 lea 4(%ecx), %ecx # %ecx<- &vCCCC++ 275 subl $$1, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- LOCAL0_OFFSET-- 276 movl %ebx, (%edx) # *outs<- vCCCC 277 lea 4(%edx), %edx # outs++ 278 jne 1b # loop if count (LOCAL0_OFFSET(%ebp)) not zero 279 movl LOCAL1_OFFSET(%ebp), %ebx # %ebx<- restore %ebx 280 jmp .LinvokeArgsDone # continue 281 282 /* 283 * %eax is "Method* methodToCall", the method we're trying to call 284 * prepare to copy args to "outs" area of current frame 285 * rIBASE trashed, must reload before resuming interpreter 286 */ 287 288common_invokeMethodNoRange: 289.LinvokeNewNoRange: 290 movzbl 1(rPC),rINST # rINST<- BA 291 movl rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA 292 shrl $$4, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- B 293 je .LinvokeArgsDone # no args; jump to args done 294 movzwl 4(rPC), %ecx # %ecx<- GFED 295 SAVEAREA_FROM_FP %edx # %edx<- &StackSaveArea 296 297 /* 298 * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs 299 */ 300 301.LinvokeNonRange: 302 cmp $$2, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 2 303 movl %ecx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- GFED 304 jl 1f # handle 1 arg 305 je 2f # handle 2 args 306 cmp $$4, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 4 307 jl 3f # handle 3 args 308 je 4f # handle 4 args 3095: 310 andl $$15, rINST # rINSTw<- A 311 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 312 movl (rFP, rINST, 4), %ecx # %ecx<- vA 313 movl %ecx, (%edx) # *outs<- vA 314 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 3154: 316 shr $$12, %ecx # %ecx<- G 317 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 318 movl (rFP, %ecx, 4), %ecx # %ecx<- vG 319 movl %ecx, (%edx) # *outs<- vG 320 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 3213: 322 and $$0x0f00, %ecx # %ecx<- 0F00 323 shr $$8, %ecx # %ecx<- F 324 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 325 movl (rFP, %ecx, 4), %ecx # %ecx<- vF 326 movl %ecx, (%edx) # *outs<- vF 327 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 3282: 329 and $$0x00f0, %ecx # %ecx<- 00E0 330 shr $$4, %ecx # %ecx<- E 331 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 332 movl (rFP, %ecx, 4), %ecx # %ecx<- vE 333 movl %ecx, (%edx) # *outs<- vE 334 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 3351: 336 and $$0x000f, %ecx # %ecx<- 000D 337 movl (rFP, %ecx, 4), %ecx # %ecx<- vD 338 movl %ecx, -4(%edx) # *--outs<- vD 3390: 340 341 /* 342 * %eax is "Method* methodToCall", the method we're trying to call 343 * find space for the new stack frame, check for overflow 344 */ 345 346.LinvokeArgsDone: 347 movzwl offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize 348 movzwl offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize 349 movl %eax, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- methodToCall 350 shl $$2, %edx # %edx<- update offset 351 SAVEAREA_FROM_FP %eax # %eax<- &StackSaveArea 352 subl %edx, %eax # %eax<- newFP; (old savearea - regsSize) 353 movl rSELF,%edx # %edx<- pthread 354 movl %eax, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- &outs 355 subl $$sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP) 356 movl offThread_interpStackEnd(%edx), %edx # %edx<- self->interpStackEnd 357 movl %edx, TMP_SPILL1(%ebp) # spill self->interpStackEnd 358 shl $$2, %ecx # %ecx<- update offset for outsSize 359 movl %eax, %edx # %edx<- newSaveArea 360 sub %ecx, %eax # %eax<- bottom; (newSaveArea - outsSize) 361 cmp TMP_SPILL1(%ebp), %eax # compare interpStackEnd and bottom 362 movl LOCAL0_OFFSET(%ebp), %eax # %eax<- restore methodToCall 363 jl .LstackOverflow # handle frame overflow 364 365 /* 366 * set up newSaveArea 367 */ 368 369#ifdef EASY_GDB 370 SAVEAREA_FROM_FP %ecx # %ecx<- &StackSaveArea 371 movl %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs 372#endif 373 movl rSELF,%ecx # %ecx<- pthread 374 movl rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP 375 movl rPC, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC 376 377 /* Any special actions to take? */ 378 cmpw $$0, offThread_subMode(%ecx) 379 jne 2f # Yes - handle them 3801: 381 testl $$ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call 382 movl %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call 383 jne .LinvokeNative # handle native call 384 385 /* 386 * Update "self" values for the new method 387 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp 388 */ 389 movl offMethod_clazz(%eax), %edx # %edx<- method->clazz 390 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex 391 movl %eax, offThread_method(%ecx) # self->method<- methodToCall 392 movl %edx, offThread_methodClassDex(%ecx) # self->methodClassDex<- method->clazz->pDvmDex 393 movl offMethod_insns(%eax), rPC # rPC<- methodToCall->insns 394 movl $$1, offThread_debugIsMethodEntry(%ecx) 395 movl LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP 396 movl rFP, offThread_curFrame(%ecx) # curFrame<-newFP 397 movl offThread_curHandlerTable(%ecx),rIBASE 398 FETCH_INST 399 GOTO_NEXT # jump to methodToCall->insns 400 4012: 402 /* 403 * On entry, preserve all: 404 * %eax: method 405 * %ecx: self 406 * %edx: new save area 407 */ 408 SPILL_TMP1(%eax) # preserve methodToCall 409 SPILL_TMP2(%edx) # preserve newSaveArea 410 movl rPC, offThread_pc(%ecx) # update interpSave.pc 411 movl %ecx, OUT_ARG0(%esp) 412 movl %eax, OUT_ARG1(%esp) 413 call dvmReportInvoke # (self, method) 414 UNSPILL_TMP1(%eax) 415 UNSPILL_TMP2(%edx) 416 movl rSELF,%ecx # restore rSELF 417 jmp 1b 418 419 /* 420 * Prep for the native call 421 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea, %ecx=self 422 */ 423 424.LinvokeNative: 425 movl offThread_jniLocal_topCookie(%ecx), rINST # rINST<- self->localRef->... 426 movl rINST, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top 427 movl %edx, LOCAL2_OFFSET(%ebp) # save newSaveArea 428 movl LOCAL1_OFFSET(%ebp), rINST # rINST<- newFP 429 movl rINST, offThread_curFrame(%ecx) # curFrame<- newFP 430 cmpw $$0, offThread_subMode(%ecx) # Anything special going on? 431 jne 11f # yes - handle it 432 movl %ecx, OUT_ARG3(%esp) # push parameter self 433 movl %eax, OUT_ARG2(%esp) # push parameter methodToCall 434 lea offThread_retval(%ecx), %ecx # %ecx<- &retval 435 movl %ecx, OUT_ARG1(%esp) # push parameter &retval 436 movl rINST, OUT_ARG0(%esp) # push parameter newFP 437 call *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc 4387: 439 movl LOCAL2_OFFSET(%ebp), %ecx # %ecx<- newSaveArea 440 movl rSELF, %eax # %eax<- self 441 movl offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top 442 cmp $$0, offThread_exception(%eax) # check for exception 443 movl rFP, offThread_curFrame(%eax) # curFrame<- rFP 444 movl %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top 445 jne common_exceptionThrown # handle exception 446 movl offThread_curHandlerTable(%eax),rIBASE 447 FETCH_INST_OPCODE 3 %ecx 448 ADVANCE_PC 3 449 GOTO_NEXT_R %ecx # jump to next instruction 450 45111: 452 /* 453 * Handle any special subMode actions 454 * %eax=methodToCall, rINST=newFP, %ecx=self 455 */ 456 SPILL_TMP1(%eax) # save methodTocall 457 movl rPC, offThread_pc(%ecx) 458 movl %ecx, OUT_ARG0(%esp) 459 movl %eax, OUT_ARG1(%esp) 460 movl rFP, OUT_ARG2(%esp) 461 call dvmReportPreNativeInvoke # (self, methodToCall, fp) 462 UNSPILL_TMP1(%eax) # restore methodToCall 463 movl rSELF,%ecx # restore self 464 465 /* Do the native call */ 466 movl %ecx, OUT_ARG3(%esp) # push parameter self 467 lea offThread_retval(%ecx), %ecx # %ecx<- &retval 468 movl %eax, OUT_ARG2(%esp) # push parameter methodToCall 469 movl %ecx, OUT_ARG1(%esp) # push parameter &retval 470 movl rINST, OUT_ARG0(%esp) # push parameter newFP 471 call *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc 472 473 UNSPILL_TMP1(%eax) # restore methodToCall 474 movl rSELF, %ecx 475 movl %ecx, OUT_ARG0(%esp) 476 movl %eax, OUT_ARG1(%esp) 477 movl rFP, OUT_ARG2(%esp) 478 call dvmReportPostNativeInvoke # (self, methodToCall, fp) 479 jmp 7b # rejoin 480 481.LstackOverflow: # eax=methodToCall 482 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 483 movl rSELF,%eax # %eax<- self 484 movl %eax, OUT_ARG0(%esp) # push parameter self 485 call dvmHandleStackOverflow # call: (Thread* self, Method* meth) 486 jmp common_exceptionThrown # handle exception 487 488 489/* 490 * Common code for handling a return instruction 491 */ 492common_returnFromMethod: 493 movl rSELF,%ecx 494 SAVEAREA_FROM_FP %eax # eax<- saveArea (old) 495 cmpw $$0, offThread_subMode(%ecx) # special action needed? 496 jne 19f # go if so 49714: 498 movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame 499 movl (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST 500 cmpl $$0,rINST # break? 501 je common_gotoBail # break frame, bail out completely 502 503 movl offStackSaveArea_savedPc(%eax),rPC # pc<- saveArea->savedPC 504 movl rINST,offThread_method(%ecx) # self->method = newSave->meethod 505 movl rFP,offThread_curFrame(%ecx) # curFrame = fp 506 movl offMethod_clazz(rINST),%eax # eax<- method->clazz 507 movl offThread_curHandlerTable(%ecx),rIBASE 508 movl offClassObject_pDvmDex(%eax),rINST # rINST<- method->clazz->pDvmDex 509 FETCH_INST_OPCODE 3 %eax 510 movl rINST,offThread_methodClassDex(%ecx) 511 ADVANCE_PC 3 512 GOTO_NEXT_R %eax 513 51419: 515 /* 516 * Handle special subMode actions 517 * On entry, rFP: prevFP, %ecx: self, %eax: saveArea 518 */ 519 movl rFP, offThread_curFrame(%ecx) # update interpSave.curFrame 520 movl rPC, offThread_pc(%ecx) # update interpSave.pc 521 movl %ecx, OUT_ARG0(%esp) # parameter self 522 call dvmReportReturn # (self) 523 movl rSELF, %ecx # restore self 524 SAVEAREA_FROM_FP %eax # restore saveArea 525 jmp 14b 526 527 528/* 529 * Prepare to strip the current frame and "longjump" back to caller of 530 * dvmMterpStdRun. 531 * 532 * on entry: 533 * rINST holds changeInterp 534 * ecx holds self pointer 535 * 536 * expected profile: dvmMterpStdBail(Thread *self, bool changeInterp) 537 */ 538common_gotoBail: 539 movl rPC,offThread_pc(%ecx) # export state to self 540 movl rFP,offThread_curFrame(%ecx) 541 movl %ecx,OUT_ARG0(%esp) # self in arg0 542 movl rINST,OUT_ARG1(%esp) # changeInterp in arg1 543 call dvmMterpStdBail # bail out.... 544 545 546/* 547 * After returning from a "selfd" function, pull out the updated values 548 * and start executing at the next instruction. 549 */ 550 common_resumeAfterGlueCall: 551 movl rSELF, %eax 552 movl offThread_pc(%eax),rPC 553 movl offThread_curFrame(%eax),rFP 554 movl offThread_curHandlerTable(%eax),rIBASE 555 FETCH_INST 556 GOTO_NEXT 557 558/* 559 * Integer divide or mod by zero 560 */ 561common_errDivideByZero: 562 EXPORT_PC 563 movl $$.LstrDivideByZero,%eax 564 movl %eax,OUT_ARG0(%esp) 565 call dvmThrowArithmeticException 566 jmp common_exceptionThrown 567 568/* 569 * Attempt to allocate an array with a negative size. 570 * On entry, len in eax 571 */ 572common_errNegativeArraySize: 573 EXPORT_PC 574 movl %eax,OUT_ARG0(%esp) # arg0<- len 575 call dvmThrowNegativeArraySizeException # (len) 576 jmp common_exceptionThrown 577 578/* 579 * Attempt to allocate an array with a negative size. 580 * On entry, method name in eax 581 */ 582common_errNoSuchMethod: 583 584 EXPORT_PC 585 movl %eax,OUT_ARG0(%esp) 586 call dvmThrowNoSuchMethodError 587 jmp common_exceptionThrown 588 589/* 590 * Hit a null object when we weren't expecting one. Export the PC, throw a 591 * NullPointerException and goto the exception processing code. 592 */ 593common_errNullObject: 594 EXPORT_PC 595 xorl %eax,%eax 596 movl %eax,OUT_ARG0(%esp) 597 call dvmThrowNullPointerException 598 jmp common_exceptionThrown 599 600/* 601 * Array index exceeds max. 602 * On entry: 603 * eax <- array object 604 * ecx <- index 605 */ 606common_errArrayIndex: 607 EXPORT_PC 608 movl offArrayObject_length(%eax), %eax 609 movl %eax,OUT_ARG0(%esp) 610 movl %ecx,OUT_ARG1(%esp) 611 call dvmThrowArrayIndexOutOfBoundsException # args (length, index) 612 jmp common_exceptionThrown 613 614/* 615 * Somebody has thrown an exception. Handle it. 616 * 617 * If the exception processing code returns to us (instead of falling 618 * out of the interpreter), continue with whatever the next instruction 619 * now happens to be. 620 * 621 * NOTE: special subMode handling done in dvmMterp_exceptionThrown 622 * 623 * This does not return. 624 */ 625common_exceptionThrown: 626 movl rSELF,%ecx 627 movl rPC,offThread_pc(%ecx) 628 movl rFP,offThread_curFrame(%ecx) 629 movl %ecx,OUT_ARG0(%esp) 630 call dvmMterp_exceptionThrown 631 jmp common_resumeAfterGlueCall 632 633common_abort: 634 movl $$0xdeadf00d,%eax 635 call *%eax 636 637 638/* 639 * Strings 640 */ 641 642 .section .rodata 643.LstrDivideByZero: 644 .asciz "divide by zero" 645.LstrFilledNewArrayNotImplA: 646 .asciz "filled-new-array only implemented for 'int'" 647