footer.S revision 3185a41fe8b3223003a07685c1acdf44bfe148d0
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 method invocation with range. 214 * 215 * On entry: 216 * eax = Method* methodToCall 217 * rINSTw trashed, must reload 218 * rIBASE trashed, must reload before resuming interpreter 219 */ 220 221common_invokeMethodRange: 222.LinvokeNewRange: 223 224 /* 225 * prepare to copy args to "outs" area of current frame 226 */ 227 228 movzbl 1(rPC),rINST # rINST<- AA 229 movzwl 4(rPC), %ecx # %ecx<- CCCC 230 SAVEAREA_FROM_FP %edx # %edx<- &StackSaveArea 231 test rINST, rINST 232 movl rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA 233 jz .LinvokeArgsDone # no args; jump to args done 234 235 236 /* 237 * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, 238 * %edx=&outs (&stackSaveArea). (very few methods have > 10 args; 239 * could unroll for common cases) 240 */ 241 242.LinvokeRangeArgs: 243 movl %ebx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- save %ebx 244 lea (rFP, %ecx, 4), %ecx # %ecx<- &vCCCC 245 shll $$2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 246 subl LOCAL0_OFFSET(%ebp), %edx # %edx<- update &outs 247 shrl $$2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 2481: 249 movl (%ecx), %ebx # %ebx<- vCCCC 250 lea 4(%ecx), %ecx # %ecx<- &vCCCC++ 251 subl $$1, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- LOCAL0_OFFSET-- 252 movl %ebx, (%edx) # *outs<- vCCCC 253 lea 4(%edx), %edx # outs++ 254 jne 1b # loop if count (LOCAL0_OFFSET(%ebp)) not zero 255 movl LOCAL1_OFFSET(%ebp), %ebx # %ebx<- restore %ebx 256 jmp .LinvokeArgsDone # continue 257 258 /* 259 * %eax is "Method* methodToCall", the method we're trying to call 260 * prepare to copy args to "outs" area of current frame 261 * rIBASE trashed, must reload before resuming interpreter 262 */ 263 264common_invokeMethodNoRange: 265.LinvokeNewNoRange: 266 movzbl 1(rPC),rINST # rINST<- BA 267 movl rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA 268 shrl $$4, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- B 269 je .LinvokeArgsDone # no args; jump to args done 270 movzwl 4(rPC), %ecx # %ecx<- GFED 271 SAVEAREA_FROM_FP %edx # %edx<- &StackSaveArea 272 273 /* 274 * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs 275 */ 276 277.LinvokeNonRange: 278 cmp $$2, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 2 279 movl %ecx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- GFED 280 jl 1f # handle 1 arg 281 je 2f # handle 2 args 282 cmp $$4, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 4 283 jl 3f # handle 3 args 284 je 4f # handle 4 args 2855: 286 andl $$15, rINST # rINSTw<- A 287 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 288 movl (rFP, rINST, 4), %ecx # %ecx<- vA 289 movl %ecx, (%edx) # *outs<- vA 290 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 2914: 292 shr $$12, %ecx # %ecx<- G 293 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 294 movl (rFP, %ecx, 4), %ecx # %ecx<- vG 295 movl %ecx, (%edx) # *outs<- vG 296 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 2973: 298 and $$0x0f00, %ecx # %ecx<- 0F00 299 shr $$8, %ecx # %ecx<- F 300 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 301 movl (rFP, %ecx, 4), %ecx # %ecx<- vF 302 movl %ecx, (%edx) # *outs<- vF 303 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 3042: 305 and $$0x00f0, %ecx # %ecx<- 00E0 306 shr $$4, %ecx # %ecx<- E 307 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 308 movl (rFP, %ecx, 4), %ecx # %ecx<- vE 309 movl %ecx, (%edx) # *outs<- vE 310 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 3111: 312 and $$0x000f, %ecx # %ecx<- 000D 313 movl (rFP, %ecx, 4), %ecx # %ecx<- vD 314 movl %ecx, -4(%edx) # *--outs<- vD 3150: 316 317 /* 318 * %eax is "Method* methodToCall", the method we're trying to call 319 * find space for the new stack frame, check for overflow 320 */ 321 322.LinvokeArgsDone: 323 movzwl offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize 324 movzwl offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize 325 movl %eax, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- methodToCall 326 shl $$2, %edx # %edx<- update offset 327 SAVEAREA_FROM_FP %eax # %eax<- &StackSaveArea 328 subl %edx, %eax # %eax<- newFP; (old savearea - regsSize) 329 movl rSELF,%edx # %edx<- pthread 330 movl %eax, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- &outs 331 subl $$sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP) 332 movl offThread_interpStackEnd(%edx), %edx # %edx<- self->interpStackEnd 333 movl %edx, TMP_SPILL1(%ebp) # spill self->interpStackEnd 334 shl $$2, %ecx # %ecx<- update offset for outsSize 335 movl %eax, %edx # %edx<- newSaveArea 336 sub %ecx, %eax # %eax<- bottom; (newSaveArea - outsSize) 337 cmp TMP_SPILL1(%ebp), %eax # compare interpStackEnd and bottom 338 movl LOCAL0_OFFSET(%ebp), %eax # %eax<- restore methodToCall 339 jl .LstackOverflow # handle frame overflow 340 341 /* 342 * set up newSaveArea 343 */ 344 345#ifdef EASY_GDB 346 SAVEAREA_FROM_FP %ecx # %ecx<- &StackSaveArea 347 movl %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs 348#endif 349 movl rSELF,%ecx # %ecx<- pthread 350 movl rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP 351 movl rPC, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC 352 353 /* Any special actions to take? */ 354 cmpw $$0, offThread_subMode(%ecx) 355 jne 2f # Yes - handle them 3561: 357 testl $$ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call 358 movl %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call 359 jne .LinvokeNative # handle native call 360 361 /* 362 * Update "self" values for the new method 363 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp 364 */ 365 movl offMethod_clazz(%eax), %edx # %edx<- method->clazz 366 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex 367 movl %eax, offThread_method(%ecx) # self->method<- methodToCall 368 movl %edx, offThread_methodClassDex(%ecx) # self->methodClassDex<- method->clazz->pDvmDex 369 movl offMethod_insns(%eax), rPC # rPC<- methodToCall->insns 370 movl $$1, offThread_debugIsMethodEntry(%ecx) 371 movl LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP 372 movl rFP, offThread_curFrame(%ecx) # curFrame<-newFP 373 movl offThread_curHandlerTable(%ecx),rIBASE 374 FETCH_INST 375 GOTO_NEXT # jump to methodToCall->insns 376 3772: 378 /* 379 * On entry, preserve all: 380 * %eax: method 381 * %ecx: self 382 * %edx: new save area 383 */ 384 SPILL_TMP1(%eax) # preserve methodToCall 385 SPILL_TMP2(%edx) # preserve newSaveArea 386 movl rPC, offThread_pc(%ecx) # update interpSave.pc 387 movl %ecx, OUT_ARG0(%esp) 388 movl %eax, OUT_ARG1(%esp) 389 call dvmReportInvoke # (self, method) 390 UNSPILL_TMP1(%eax) 391 UNSPILL_TMP2(%edx) 392 movl rSELF,%ecx # restore rSELF 393 jmp 1b 394 395 /* 396 * Prep for the native call 397 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea, %ecx=self 398 */ 399 400.LinvokeNative: 401 movl offThread_jniLocal_topCookie(%ecx), rINST # rINST<- self->localRef->... 402 movl rINST, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top 403 movl %edx, LOCAL2_OFFSET(%ebp) # save newSaveArea 404 movl LOCAL1_OFFSET(%ebp), rINST # rINST<- newFP 405 movl rINST, offThread_curFrame(%ecx) # curFrame<- newFP 406 cmpw $$0, offThread_subMode(%ecx) # Anything special going on? 407 jne 11f # yes - handle it 408 movl %ecx, OUT_ARG3(%esp) # push parameter self 409 movl %eax, OUT_ARG2(%esp) # push parameter methodToCall 410 lea offThread_retval(%ecx), %ecx # %ecx<- &retval 411 movl %ecx, OUT_ARG1(%esp) # push parameter &retval 412 movl rINST, OUT_ARG0(%esp) # push parameter newFP 413 call *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc 4147: 415 movl LOCAL2_OFFSET(%ebp), %ecx # %ecx<- newSaveArea 416 movl rSELF, %eax # %eax<- self 417 movl offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top 418 cmp $$0, offThread_exception(%eax) # check for exception 419 movl rFP, offThread_curFrame(%eax) # curFrame<- rFP 420 movl %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top 421 jne common_exceptionThrown # handle exception 422 movl offThread_curHandlerTable(%eax),rIBASE 423 FETCH_INST_OPCODE 3 %ecx 424 ADVANCE_PC 3 425 GOTO_NEXT_R %ecx # jump to next instruction 426 42711: 428 /* 429 * Handle any special subMode actions 430 * %eax=methodToCall, rINST=newFP, %ecx=self 431 */ 432 SPILL_TMP1(%eax) # save methodTocall 433 movl rPC, offThread_pc(%ecx) 434 movl %eax, OUT_ARG0(%esp) 435 movl %ecx, OUT_ARG1(%esp) 436 movl rFP, OUT_ARG2(%esp) 437 call dvmReportPreNativeInvoke # (methodToCall, self, fp) 438 UNSPILL_TMP1(%eax) # restore methodToCall 439 movl rSELF,%ecx # restore self 440 441 /* Do the native call */ 442 movl %ecx, OUT_ARG3(%esp) # push parameter self 443 lea offThread_retval(%ecx), %ecx # %ecx<- &retval 444 movl %eax, OUT_ARG2(%esp) # push parameter methodToCall 445 movl %ecx, OUT_ARG1(%esp) # push parameter &retval 446 movl rINST, OUT_ARG0(%esp) # push parameter newFP 447 call *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc 448 449 UNSPILL_TMP1(%eax) # restore methodToCall 450 movl rSELF, %ecx 451 movl %eax, OUT_ARG0(%esp) 452 movl %ecx, OUT_ARG1(%esp) 453 movl rFP, OUT_ARG2(%esp) 454 call dvmReportPostNativeInvoke # (methodToCall, self, fp) 455 jmp 7b # rejoin 456 457.LstackOverflow: # eax=methodToCall 458 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 459 movl rSELF,%eax # %eax<- self 460 movl %eax, OUT_ARG0(%esp) # push parameter self 461 call dvmHandleStackOverflow # call: (Thread* self, Method* meth) 462 jmp common_exceptionThrown # handle exception 463 464 465/* 466 * Common code for handling a return instruction 467 */ 468common_returnFromMethod: 469 movl rSELF,%ecx 470 SAVEAREA_FROM_FP %eax # eax<- saveArea (old) 471 cmpw $$0, offThread_subMode(%ecx) # special action needed? 472 jne 19f # go if so 47314: 474 movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame 475 movl (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST 476 cmpl $$0,rINST # break? 477 je common_gotoBail # break frame, bail out completely 478 479 movl offStackSaveArea_savedPc(%eax),rPC # pc<- saveArea->savedPC 480 movl rINST,offThread_method(%ecx) # self->method = newSave->meethod 481 movl rFP,offThread_curFrame(%ecx) # curFrame = fp 482 movl offMethod_clazz(rINST),%eax # eax<- method->clazz 483 movl offThread_curHandlerTable(%ecx),rIBASE 484 movl offClassObject_pDvmDex(%eax),rINST # rINST<- method->clazz->pDvmDex 485 FETCH_INST_OPCODE 3 %eax 486 movl rINST,offThread_methodClassDex(%ecx) 487 ADVANCE_PC 3 488 GOTO_NEXT_R %eax 489 49019: 491 /* 492 * Handle special subMode actions 493 * On entry, rFP: prevFP, %ecx: self, %eax: saveArea 494 */ 495 movl rFP, offThread_curFrame(%ecx) # update interpSave.curFrame 496 movl rPC, offThread_pc(%ecx) # update interpSave.pc 497 movl %ecx, OUT_ARG0(%esp) # parameter self 498 call dvmReportReturn # (self) 499 movl rSELF, %ecx # restore self 500 SAVEAREA_FROM_FP %eax # restore saveArea 501 jmp 14b 502 503 504/* 505 * Prepare to strip the current frame and "longjump" back to caller of 506 * dvmMterpStdRun. 507 * 508 * on entry: 509 * rINST holds changeInterp 510 * ecx holds self pointer 511 * 512 * expected profile: dvmMterpStdBail(Thread *self, bool changeInterp) 513 */ 514common_gotoBail: 515 movl rPC,offThread_pc(%ecx) # export state to self 516 movl rFP,offThread_curFrame(%ecx) 517 movl %ecx,OUT_ARG0(%esp) # self in arg0 518 movl rINST,OUT_ARG1(%esp) # changeInterp in arg1 519 call dvmMterpStdBail # bail out.... 520 521 522/* 523 * After returning from a "selfd" function, pull out the updated values 524 * and start executing at the next instruction. 525 */ 526 common_resumeAfterGlueCall: 527 movl rSELF, %eax 528 movl offThread_pc(%eax),rPC 529 movl offThread_curFrame(%eax),rFP 530 movl offThread_curHandlerTable(%eax),rIBASE 531 FETCH_INST 532 GOTO_NEXT 533 534/* 535 * Integer divide or mod by zero 536 */ 537common_errDivideByZero: 538 EXPORT_PC 539 movl $$.LstrDivideByZero,%eax 540 movl %eax,OUT_ARG0(%esp) 541 call dvmThrowArithmeticException 542 jmp common_exceptionThrown 543 544/* 545 * Attempt to allocate an array with a negative size. 546 * On entry, len in eax 547 */ 548common_errNegativeArraySize: 549 EXPORT_PC 550 movl %eax,OUT_ARG0(%esp) # arg0<- len 551 call dvmThrowNegativeArraySizeException # (len) 552 jmp common_exceptionThrown 553 554/* 555 * Attempt to allocate an array with a negative size. 556 * On entry, method name in eax 557 */ 558common_errNoSuchMethod: 559 560 EXPORT_PC 561 movl %eax,OUT_ARG0(%esp) 562 call dvmThrowNoSuchMethodError 563 jmp common_exceptionThrown 564 565/* 566 * Hit a null object when we weren't expecting one. Export the PC, throw a 567 * NullPointerException and goto the exception processing code. 568 */ 569common_errNullObject: 570 EXPORT_PC 571 xorl %eax,%eax 572 movl %eax,OUT_ARG0(%esp) 573 call dvmThrowNullPointerException 574 jmp common_exceptionThrown 575 576/* 577 * Array index exceeds max. 578 * On entry: 579 * eax <- array object 580 * ecx <- index 581 */ 582common_errArrayIndex: 583 EXPORT_PC 584 movl offArrayObject_length(%eax), %eax 585 movl %eax,OUT_ARG0(%esp) 586 movl %ecx,OUT_ARG1(%esp) 587 call dvmThrowArrayIndexOutOfBoundsException # args (length, index) 588 jmp common_exceptionThrown 589 590/* 591 * Somebody has thrown an exception. Handle it. 592 * 593 * If the exception processing code returns to us (instead of falling 594 * out of the interpreter), continue with whatever the next instruction 595 * now happens to be. 596 * 597 * NOTE: special subMode handling done in dvmMterp_exceptionThrown 598 * 599 * This does not return. 600 */ 601common_exceptionThrown: 602 movl rSELF,%ecx 603 movl rPC,offThread_pc(%ecx) 604 movl rFP,offThread_curFrame(%ecx) 605 movl %ecx,OUT_ARG0(%esp) 606 call dvmMterp_exceptionThrown 607 jmp common_resumeAfterGlueCall 608 609common_abort: 610 movl $$0xdeadf00d,%eax 611 call *%eax 612 613 614/* 615 * Strings 616 */ 617 618 .section .rodata 619.LstrDivideByZero: 620 .asciz "divide by zero" 621.LstrFilledNewArrayNotImplA: 622 .asciz "filled-new-array only implemented for 'int'" 623