InterpAsm-x86.S revision dfd1bbf07d98c82a6072182f705f64a30ebf480b
1/* 2 * This file was generated automatically by gen-mterp.py for 'x86'. 3 * 4 * --> DO NOT EDIT <-- 5 */ 6 7/* File: x86/header.S */ 8/* 9 * Copyright (C) 2008 The Android Open Source Project 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 */ 23/* 24 * 32-bit x86 definitions and declarations. 25 */ 26 27/* 28386 ABI general notes: 29 30Caller save set: 31 eax, edx, ecx, st(0)-st(7) 32Callee save set: 33 ebx, esi, edi, ebp 34Return regs: 35 32-bit in eax 36 64-bit in edx:eax (low-order 32 in eax) 37 fp on top of fp stack st(0) 38 39Parameters passed on stack, pushed right-to-left. On entry to target, first 40parm is at 4(%esp). Traditional entry code is: 41 42functEntry: 43 push %ebp # save old frame pointer 44 mov %ebp,%esp # establish new frame pointer 45 sub FrameSize,%esp # Allocate storage for spill, locals & outs 46 47Once past the prologue, arguments are referenced at ((argno + 2)*4)(%ebp) 48 49Alignment of stack not strictly required, but should be for performance. We'll 50align frame sizes to 16-byte multiples. 51 52If we're not doing variable stack allocation (alloca), the frame pointer can be 53eliminated and all arg references adjusted to be esp relative. 54 55Mterp notes: 56 57Some key interpreter variables will be assigned to registers. Note that each 58will also have an associated spill location (mostly useful for those assigned 59to callee save registers). 60 61 nick reg purpose 62 rPC edi interpreted program counter, used for fetching instructions 63 rFP esi interpreted frame pointer, used for accessing locals and args 64 rINSTw bx first 16-bit code of current instruction 65 rINSTbl bl opcode portion of instruction word 66 rINSTbh bh high byte of inst word, usually contains src/tgt reg names 67 68Notes: 69 o High order 16 bits of ebx must be zero on entry to handler 70 o rPC, rFP, rINSTw/rINSTbl valid on handler entry and exit 71 o eax, edx and ecx are scratch, rINSTw/ebx sometimes scratch 72 73*/ 74 75#define rGLUE (%ebp) 76#define rPC %esi 77#define rFP %edi 78#define rINST %ebx 79#define rINSTw %bx 80#define rINSTbh %bh 81#define rINSTbl %bl 82 83 84/* Frame diagram while executing dvmMterpStdRun, high to low addresses */ 85#define IN_ARG0 ( 12) 86#define CALLER_RP ( 8) 87#define PREV_FP ( 4) 88#define rGLUE_SPILL ( 0) /* <- dvmMterpStdRun ebp */ 89/* Spill offsets relative to %ebp */ 90#define EDI_SPILL ( -4) 91#define ESI_SPILL ( -8) 92#define EBX_SPILL (-12) /* <- esp following dmMterpStdRun header */ 93#define rPC_SPILL (-16) 94#define rFP_SPILL (-20) 95#define rINST_SPILL (-24) 96#define TMP_SPILL1 (-28) 97#define TMP_SPILL2 (-32) 98#define TMP_SPILL3 (-36) 99#define LOCAL0_OFFSET (-40) 100#define LOCAL1_OFFSET (-44) 101#define LOCAL2_OFFSET (-48) 102#define LOCAL3_OFFSET (-52) 103/* Out Arg offsets, relative to %sp */ 104#define OUT_ARG4 ( 16) 105#define OUT_ARG3 ( 12) 106#define OUT_ARG2 ( 8) 107#define OUT_ARG1 ( 4) 108#define OUT_ARG0 ( 0) /* <- dvmMterpStdRun esp */ 109#define FRAME_SIZE 80 110 111#define SPILL(reg) movl reg##,reg##_SPILL(%ebp) 112#define UNSPILL(reg) movl reg##_SPILL(%ebp),reg 113#define SPILL_TMP1(reg) movl reg,TMP_SPILL1(%ebp) 114#define UNSPILL_TMP1(reg) movl TMP_SPILL1(%ebp),reg 115#define SPILL_TMP2(reg) movl reg,TMP_SPILL2(%ebp) 116#define UNSPILL_TMP2(reg) movl TMP_SPILL2(%ebp),reg 117#define SPILL_TMP3(reg) movl reg,TMP_SPILL3(%ebp) 118#define UNSPILL_TMP3(reg) movl TMP_SPILL3(%ebp),reg 119 120#if defined(WITH_JIT) 121.macro GET_JIT_PROF_TABLE _glue _reg 122 movl offGlue_pJitProfTable(\_glue),\_reg 123.endm 124.macro GET_JIT_THRESHOLD _glue _reg 125 movl offGlue_jitThreshold(\_glue),\_reg 126.endm 127#endif 128 129/* save/restore the PC and/or FP from the glue struct */ 130.macro SAVE_PC_FP_TO_GLUE _reg 131 movl rGLUE,\_reg 132 movl rPC,offGlue_pc(\_reg) 133 movl rFP,offGlue_fp(\_reg) 134.endm 135 136.macro LOAD_PC_FP_FROM_GLUE 137 movl rGLUE,rFP 138 movl offGlue_pc(rFP),rPC 139 movl offGlue_fp(rFP),rFP 140.endm 141 142/* The interpreter assumes a properly aligned stack on entry, and 143 * will preserve 16-byte alignment. 144 */ 145 146/* 147 * "export" the PC to the interpreted stack frame, f/b/o future exception 148 * objects. Must * be done *before* something calls dvmThrowException. 149 * 150 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e. 151 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc) 152 * 153 * It's okay to do this more than once. 154 */ 155.macro EXPORT_PC 156 movl rPC, (-sizeofStackSaveArea + offStackSaveArea_currentPc)(rFP) 157.endm 158 159/* 160 * Given a frame pointer, find the stack save area. 161 * 162 * In C this is "((StackSaveArea*)(_fp) -1)". 163 */ 164.macro SAVEAREA_FROM_FP _reg 165 leal -sizeofStackSaveArea(rFP), \_reg 166.endm 167 168/* 169 * Fetch the next instruction from rPC into rINSTw. Does not advance rPC. 170 */ 171.macro FETCH_INST 172 movzwl (rPC),rINST 173.endm 174 175/* 176 * Fetch the opcode byte and zero-extend it into _reg. Must be used 177 * in conjunction with GOTO_NEXT_R 178 */ 179.macro FETCH_INST_R _reg 180 movzbl (rPC),\_reg 181.endm 182 183/* 184 * Fetch the opcode byte at _count words offset from rPC and zero-extend 185 * it into _reg. Must be used in conjunction with GOTO_NEXT_R 186 */ 187.macro FETCH_INST_OPCODE _count _reg 188 movzbl \_count*2(rPC),\_reg 189.endm 190 191/* 192 * Fetch the nth instruction word from rPC into rINSTw. Does not advance 193 * rPC, and _count is in words 194 */ 195.macro FETCH_INST_WORD _count 196 movzwl \_count*2(rPC),rINST 197.endm 198 199/* 200 * Fetch instruction word indexed (used for branching). 201 * Index is in instruction word units. 202 */ 203.macro FETCH_INST_INDEXED _reg 204 movzwl (rPC,\_reg,2),rINST 205.endm 206 207/* 208 * Advance rPC by instruction count 209 */ 210.macro ADVANCE_PC _count 211 leal 2*\_count(rPC),rPC 212.endm 213 214/* 215 * Advance rPC by branch offset in register 216 */ 217.macro ADVANCE_PC_INDEXED _reg 218 leal (rPC,\_reg,2),rPC 219.endm 220 221.macro GOTO_NEXT 222 movzx rINSTbl,%eax 223 movzbl rINSTbh,rINST 224 jmp *dvmAsmInstructionJmpTable(,%eax,4) 225.endm 226 227 /* 228 * Version of GOTO_NEXT that assumes _reg preloaded with opcode. 229 * Should be paired with FETCH_INST_R 230 */ 231.macro GOTO_NEXT_R _reg 232 movzbl 1(rPC),rINST 233 jmp *dvmAsmInstructionJmpTable(,\_reg,4) 234.endm 235 236/* 237 * Get/set the 32-bit value from a Dalvik register. 238 */ 239.macro GET_VREG_R _reg _vreg 240 movl (rFP,\_vreg,4),\_reg 241.endm 242 243.macro SET_VREG _reg _vreg 244 movl \_reg,(rFP,\_vreg,4) 245.endm 246 247.macro GET_VREG_WORD _reg _vreg _offset 248 movl 4*(\_offset)(rFP,\_vreg,4),\_reg 249.endm 250 251.macro SET_VREG_WORD _reg _vreg _offset 252 movl \_reg,4*(\_offset)(rFP,\_vreg,4) 253.endm 254 255#if 1 256 257#define rFinish %edx 258 259/* Macros for x86-atom handlers */ 260 /* 261 * Get the 32-bit value from a dalvik register. 262 */ 263 264 .macro GET_VREG _vreg 265 movl (rFP,\_vreg, 4), \_vreg 266 .endm 267 268 /* 269 * Fetch the next instruction from the specified offset. Advances rPC 270 * to point to the next instruction. "_count" is in 16-bit code units. 271 * 272 * This must come AFTER anything that can throw an exception, or the 273 * exception catch may miss. (This also implies that it must come after 274 * EXPORT_PC()) 275 */ 276 277 .macro FETCH_ADVANCE_INST _count 278 add $(\_count*2), rPC 279 movzwl (rPC), rINST 280 .endm 281 282 /* 283 * Fetch the next instruction from an offset specified by _reg. Updates 284 * rPC to point to the next instruction. "_reg" must specify the distance 285 * in bytes, *not* 16-bit code units, and may be a signed value. 286 */ 287 288 .macro FETCH_ADVANCE_INST_RB _reg 289 addl \_reg, rPC 290 movzwl (rPC), rINST 291 .endm 292 293 /* 294 * Fetch a half-word code unit from an offset past the current PC. The 295 * "_count" value is in 16-bit code units. Does not advance rPC. 296 * For example, given instruction of format: AA|op BBBB, it 297 * fetches BBBB. 298 */ 299 300 .macro FETCH _count _reg 301 movzwl (\_count*2)(rPC), \_reg 302 .endm 303 304 /* 305 * Fetch a half-word code unit from an offset past the current PC. The 306 * "_count" value is in 16-bit code units. Does not advance rPC. 307 * This variant treats the value as signed. 308 */ 309 310 .macro FETCHs _count _reg 311 movswl (\_count*2)(rPC), \_reg 312 .endm 313 314 /* 315 * Fetch the first byte from an offset past the current PC. The 316 * "_count" value is in 16-bit code units. Does not advance rPC. 317 * For example, given instruction of format: AA|op CC|BB, it 318 * fetches BB. 319 */ 320 321 .macro FETCH_BB _count _reg 322 movzbl (\_count*2)(rPC), \_reg 323 .endm 324 325 /* 326 * Fetch the second byte from an offset past the current PC. The 327 * "_count" value is in 16-bit code units. Does not advance rPC. 328 * For example, given instruction of format: AA|op CC|BB, it 329 * fetches CC. 330 */ 331 332 .macro FETCH_CC _count _reg 333 movzbl (\_count*2 + 1)(rPC), \_reg 334 .endm 335 336 /* 337 * Fetch the second byte from an offset past the current PC. The 338 * "_count" value is in 16-bit code units. Does not advance rPC. 339 * This variant treats the value as signed. 340 */ 341 342 .macro FETCH_CCs _count _reg 343 movsbl (\_count*2 + 1)(rPC), \_reg 344 .endm 345 346 347 /* 348 * Fetch one byte from an offset past the current PC. Pass in the same 349 * "_count" as you would for FETCH, and an additional 0/1 indicating which 350 * byte of the halfword you want (lo/hi). 351 */ 352 353 .macro FETCH_B _reg _count _byte 354 movzbl (\_count*2+\_byte)(rPC), \_reg 355 .endm 356 357 /* 358 * Put the instruction's opcode field into the specified register. 359 */ 360 361 .macro GET_INST_OPCODE _reg 362 movzbl rINSTbl, \_reg 363 .endm 364 365 /* 366 * Begin executing the opcode in _reg. 367 */ 368 369 .macro GOTO_OPCODE _reg 370 shl $6, \_reg 371 addl $dvmAsmInstructionStart,\_reg 372 jmp *\_reg 373 .endm 374 375 376 377 /* 378 * Macros pair attempts to speed up FETCH_INST, GET_INST_OPCODE and GOTO_OPCODE 379 * by using a jump table. _rFinish should must be the same register for 380 * both macros. 381 */ 382 383 .macro FFETCH _rFinish 384 movzbl (rPC), \_rFinish 385 .endm 386 387 .macro FGETOP_JMPa _rFinish 388 movzbl 1(rPC), rINST 389 jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4) 390 .endm 391 392 /* 393 * Macro pair attempts to speed up FETCH_INST, GET_INST_OPCODE and GOTO_OPCODE 394 * by using a jump table. _rFinish and _count should must be the same register for 395 * both macros. 396 */ 397 398 .macro FFETCH_ADV _count _rFinish 399 movzbl (\_count*2)(rPC), \_rFinish 400 .endm 401 402 .macro FGETOP_JMP _count _rFinish 403 movzbl (\_count*2 + 1)(rPC), rINST 404 addl $(\_count*2), rPC 405 jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4) 406 .endm 407 408 .macro FGETOP_JMP2 _rFinish 409 movzbl 1(rPC), rINST 410 jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4) 411 .endm 412 413 .macro OLD_JMP_1 _count _rFinish 414 movzbl (\_count*2)(rPC), \_rFinish 415 shl $6, \_rFinish 416 .endm 417 418 .macro OLD_JMP_2 _rFinish 419 addl $dvmAsmInstructionStart,\_rFinish 420 .endm 421 422 .macro OLD_JMP_3 _count 423 addl $(\_count*2), rPC 424 .endm 425 426 .macro OLD_JMP_4 _rFinish 427 movzbl 1(rPC), rINST 428 jmp *\_rFinish 429 .endm 430 431 .macro OLD_JMP_A_1 _reg _rFinish 432 movzbl (rPC, \_reg), \_rFinish 433 shl $6, \_rFinish 434 .endm 435 436 .macro OLD_JMP_A_2 _rFinish 437 addl $dvmAsmInstructionStart,\_rFinish 438 .endm 439 440 .macro OLD_JMP_A_3 _reg _rFinish 441 addl \_reg, rPC 442 movzbl 1(rPC, \_reg), rINST 443 jmp *\_rFinish 444 .endm 445 446 /* 447 * Macro pair attempts to speed up FETCH_INST, GET_INST_OPCODE and GOTO_OPCODE 448 * by using a jump table. _rFinish and _reg should must be the same register for 449 * both macros. 450 */ 451 452 .macro FFETCH_ADV_RB _reg _rFinish 453 movzbl (\_reg, rPC), \_rFinish 454 .endm 455 456 .macro FGETOP_RB_JMP _reg _rFinish 457 movzbl 1(\_reg, rPC), rINST 458 addl \_reg, rPC 459 jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4) 460 .endm 461 462 /* 463 * Attempts to speed up FETCH_INST, GET_INST_OPCODE using 464 * a jump table. This macro should be called before FINISH_JMP where 465 * rFinish should be the same register containing the opcode value. 466 * This is an attempt to split up FINISH in order to reduce or remove 467 * potential stalls due to the wait for rFINISH. 468 */ 469 470 .macro FINISH_FETCH _rFinish 471 movzbl (rPC), \_rFinish 472 movzbl 1(rPC), rINST 473 .endm 474 475 476 /* 477 * Attempts to speed up FETCH_ADVANCE_INST, GET_INST_OPCODE using 478 * a jump table. This macro should be called before FINISH_JMP where 479 * rFinish should be the same register containing the opcode value. 480 * This is an attempt to split up FINISH in order to reduce or remove 481 * potential stalls due to the wait for rFINISH. 482 */ 483 484 .macro FINISH_FETCH_ADVANCE _count _rFinish 485 movzbl (\_count*2)(rPC), \_rFinish 486 movzbl (\_count*2 + 1)(rPC), rINST 487 addl $(\_count*2), rPC 488 .endm 489 490 /* 491 * Attempts to speed up FETCH_ADVANCE_INST_RB, GET_INST_OPCODE using 492 * a jump table. This macro should be called before FINISH_JMP where 493 * rFinish should be the same register containing the opcode value. 494 * This is an attempt to split up FINISH in order to reduce or remove 495 * potential stalls due to the wait for rFINISH. 496 */ 497 498 .macro FINISH_FETCH_ADVANCE_RB _reg _rFinish 499 movzbl (\_reg, rPC), \_rFinish 500 movzbl 1(\_reg, rPC), rINST 501 addl \_reg, rPC 502 .endm 503 504 /* 505 * Attempts to speed up GOTO_OPCODE using a jump table. This macro should 506 * be called after a FINISH_FETCH* instruction where rFinish should be the 507 * same register containing the opcode value. This is an attempt to split up 508 * FINISH in order to reduce or remove potential stalls due to the wait for rFINISH. 509 */ 510 511 .macro FINISH_JMP _rFinish 512 jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4) 513 .endm 514 515 /* 516 * Attempts to speed up FETCH_INST, GET_INST_OPCODE, GOTO_OPCODE by using 517 * a jump table. Uses a single macro - but it should be faster if we 518 * split up the fetch for rFinish and the jump using rFinish. 519 */ 520 521 .macro FINISH_A 522 movzbl (rPC), rFinish 523 movzbl 1(rPC), rINST 524 jmp *dvmAsmInstructionJmpTable(,rFinish, 4) 525 .endm 526 527 /* 528 * Attempts to speed up FETCH_ADVANCE_INST, GET_INST_OPCODE, 529 * GOTO_OPCODE by using a jump table. Uses a single macro - 530 * but it should be faster if we split up the fetch for rFinish 531 * and the jump using rFinish. 532 */ 533 534 .macro FINISH _count 535 movzbl (\_count*2)(rPC), rFinish 536 movzbl (\_count*2 + 1)(rPC), rINST 537 addl $(\_count*2), rPC 538 jmp *dvmAsmInstructionJmpTable(,rFinish, 4) 539 .endm 540 541 /* 542 * Attempts to speed up FETCH_ADVANCE_INST_RB, GET_INST_OPCODE, 543 * GOTO_OPCODE by using a jump table. Uses a single macro - 544 * but it should be faster if we split up the fetch for rFinish 545 * and the jump using rFinish. 546 */ 547 548 .macro FINISH_RB _reg _rFinish 549 movzbl (\_reg, rPC), \_rFinish 550 movzbl 1(\_reg, rPC), rINST 551 addl \_reg, rPC 552 jmp *dvmAsmInstructionJmpTable(,\_rFinish, 4) 553 .endm 554 555#define sReg0 LOCAL0_OFFSET(%ebp) 556#define sReg1 LOCAL1_OFFSET(%ebp) 557#define sReg2 LOCAL2_OFFSET(%ebp) 558#define sReg3 LOCAL3_OFFSET(%ebp) 559 560 /* 561 * Hard coded helper values. 562 */ 563 564.balign 16 565 566.LdoubNeg: 567 .quad 0x8000000000000000 568 569.L64bits: 570 .quad 0xFFFFFFFFFFFFFFFF 571 572.LshiftMask2: 573 .quad 0x0000000000000000 574.LshiftMask: 575 .quad 0x000000000000003F 576 577.Lvalue64: 578 .quad 0x0000000000000040 579 580.LvaluePosInfLong: 581 .quad 0x7FFFFFFFFFFFFFFF 582 583.LvalueNegInfLong: 584 .quad 0x8000000000000000 585 586.LvalueNanLong: 587 .quad 0x0000000000000000 588 589.LintMin: 590.long 0x80000000 591 592.LintMax: 593.long 0x7FFFFFFF 594#endif 595 596 597/* 598 * This is a #include, not a %include, because we want the C pre-processor 599 * to expand the macros into assembler assignment statements. 600 */ 601#include "../common/asm-constants.h" 602 603#if defined(WITH_JIT) 604#include "../common/jit-config.h" 605#endif 606 607 608 .global dvmAsmInstructionStart 609 .type dvmAsmInstructionStart, %function 610dvmAsmInstructionStart = .L_OP_NOP 611 .text 612 613/* ------------------------------ */ 614 .balign 64 615.L_OP_NOP: /* 0x00 */ 616/* File: x86/OP_NOP.S */ 617 FETCH_INST_OPCODE 1 %edx 618 ADVANCE_PC 1 619 GOTO_NEXT_R %edx 620 621/* ------------------------------ */ 622 .balign 64 623.L_OP_MOVE: /* 0x01 */ 624/* File: x86/OP_MOVE.S */ 625 /* for move, move-object, long-to-int */ 626 /* op vA, vB */ 627 movzbl rINSTbl,%eax # eax<- BA 628 andb $0xf,%al # eax<- A 629 shrl $4,rINST # rINST<- B 630 GET_VREG_R %ecx rINST 631 FETCH_INST_OPCODE 1 %edx 632 ADVANCE_PC 1 633 SET_VREG %ecx %eax # fp[A]<-fp[B] 634 GOTO_NEXT_R %edx 635 636/* ------------------------------ */ 637 .balign 64 638.L_OP_MOVE_FROM16: /* 0x02 */ 639/* File: x86/OP_MOVE_FROM16.S */ 640 /* for: move/from16, move-object/from16 */ 641 /* op vAA, vBBBB */ 642 movzx rINSTbl,%eax # eax <= AA 643 movw 2(rPC),rINSTw # rINSTw <= BBBB 644 GET_VREG_R %ecx rINST # ecx<- fp[BBBB] 645 FETCH_INST_OPCODE 2 %edx 646 ADVANCE_PC 2 647 SET_VREG %ecx %eax # fp[AA]<- ecx] 648 GOTO_NEXT_R %edx 649 650/* ------------------------------ */ 651 .balign 64 652.L_OP_MOVE_16: /* 0x03 */ 653/* File: x86/OP_MOVE_16.S */ 654 /* for: move/16, move-object/16 */ 655 /* op vAAAA, vBBBB */ 656 movzwl 4(rPC),%ecx # ecx<- BBBB 657 movzwl 2(rPC),%eax # eax<- AAAA 658 GET_VREG_R %ecx %ecx 659 FETCH_INST_OPCODE 3 %edx 660 ADVANCE_PC 3 661 SET_VREG %ecx %eax 662 GOTO_NEXT_R %edx 663 664/* ------------------------------ */ 665 .balign 64 666.L_OP_MOVE_WIDE: /* 0x04 */ 667/* File: x86/OP_MOVE_WIDE.S */ 668 /* move-wide vA, vB */ 669 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 670 movzbl rINSTbl,%ecx # ecx <- BA 671 sarl $4,rINST # rINST<- B 672 GET_VREG_WORD %eax rINST 0 # eax<- v[B+0] 673 GET_VREG_WORD rINST rINST 1 # rINST<- v[B+1] 674 andb $0xf,%cl # ecx <- A 675 FETCH_INST_OPCODE 1 %edx 676 SET_VREG_WORD rINST %ecx 1 # v[A+1]<- rINST 677 ADVANCE_PC 1 678 SET_VREG_WORD %eax %ecx 0 # v[A+0]<- eax 679 GOTO_NEXT_R %edx 680 681/* ------------------------------ */ 682 .balign 64 683.L_OP_MOVE_WIDE_FROM16: /* 0x05 */ 684/* File: x86/OP_MOVE_WIDE_FROM16.S */ 685 /* move-wide/from16 vAA, vBBBB */ 686 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 687 movzwl 2(rPC),%ecx # ecx<- BBBB 688 movzbl rINSTbl,%eax # eax<- AAAA 689 GET_VREG_WORD rINST %ecx 0 # rINST<- v[BBBB+0] 690 GET_VREG_WORD %ecx %ecx 1 # ecx<- v[BBBB+1] 691 FETCH_INST_OPCODE 2 %edx 692 ADVANCE_PC 2 693 SET_VREG_WORD rINST %eax 0 # v[AAAA+0]<- rINST 694 SET_VREG_WORD %ecx %eax 1 # v[AAAA+1]<- eax 695 GOTO_NEXT_R %edx 696 697/* ------------------------------ */ 698 .balign 64 699.L_OP_MOVE_WIDE_16: /* 0x06 */ 700/* File: x86/OP_MOVE_WIDE_16.S */ 701 /* move-wide/16 vAAAA, vBBBB */ 702 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 703 movzwl 4(rPC),%ecx # ecx<- BBBB 704 movzwl 2(rPC),%eax # eax<- AAAA 705 GET_VREG_WORD rINST %ecx 0 # rINSTw_WORD<- v[BBBB+0] 706 GET_VREG_WORD %ecx %ecx 1 # ecx<- v[BBBB+1] 707 FETCH_INST_OPCODE 3 %edx 708 SET_VREG_WORD rINST %eax 0 # v[AAAA+0]<- rINST 709 ADVANCE_PC 3 710 SET_VREG_WORD %ecx %eax 1 # v[AAAA+1]<- ecx 711 GOTO_NEXT_R %edx 712 713/* ------------------------------ */ 714 .balign 64 715.L_OP_MOVE_OBJECT: /* 0x07 */ 716/* File: x86/OP_MOVE_OBJECT.S */ 717/* File: x86/OP_MOVE.S */ 718 /* for move, move-object, long-to-int */ 719 /* op vA, vB */ 720 movzbl rINSTbl,%eax # eax<- BA 721 andb $0xf,%al # eax<- A 722 shrl $4,rINST # rINST<- B 723 GET_VREG_R %ecx rINST 724 FETCH_INST_OPCODE 1 %edx 725 ADVANCE_PC 1 726 SET_VREG %ecx %eax # fp[A]<-fp[B] 727 GOTO_NEXT_R %edx 728 729 730/* ------------------------------ */ 731 .balign 64 732.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */ 733/* File: x86/OP_MOVE_OBJECT_FROM16.S */ 734/* File: x86/OP_MOVE_FROM16.S */ 735 /* for: move/from16, move-object/from16 */ 736 /* op vAA, vBBBB */ 737 movzx rINSTbl,%eax # eax <= AA 738 movw 2(rPC),rINSTw # rINSTw <= BBBB 739 GET_VREG_R %ecx rINST # ecx<- fp[BBBB] 740 FETCH_INST_OPCODE 2 %edx 741 ADVANCE_PC 2 742 SET_VREG %ecx %eax # fp[AA]<- ecx] 743 GOTO_NEXT_R %edx 744 745 746/* ------------------------------ */ 747 .balign 64 748.L_OP_MOVE_OBJECT_16: /* 0x09 */ 749/* File: x86/OP_MOVE_OBJECT_16.S */ 750/* File: x86/OP_MOVE_16.S */ 751 /* for: move/16, move-object/16 */ 752 /* op vAAAA, vBBBB */ 753 movzwl 4(rPC),%ecx # ecx<- BBBB 754 movzwl 2(rPC),%eax # eax<- AAAA 755 GET_VREG_R %ecx %ecx 756 FETCH_INST_OPCODE 3 %edx 757 ADVANCE_PC 3 758 SET_VREG %ecx %eax 759 GOTO_NEXT_R %edx 760 761 762/* ------------------------------ */ 763 .balign 64 764.L_OP_MOVE_RESULT: /* 0x0a */ 765/* File: x86/OP_MOVE_RESULT.S */ 766 /* for: move-result, move-result-object */ 767 /* op vAA */ 768 movl rGLUE,%eax # eax<- rGLUE 769 movzx rINSTbl,%ecx # ecx<- AA 770 movl offGlue_retval(%eax),%eax # eax<- glue->retval.l 771 FETCH_INST_OPCODE 1 %edx 772 ADVANCE_PC 1 773 SET_VREG %eax %ecx # fp[AA]<- retval.l 774 GOTO_NEXT_R %edx 775 776/* ------------------------------ */ 777 .balign 64 778.L_OP_MOVE_RESULT_WIDE: /* 0x0b */ 779/* File: x86/OP_MOVE_RESULT_WIDE.S */ 780 /* move-result-wide vAA */ 781 movl rGLUE,%ecx 782 movl offGlue_retval(%ecx),%eax 783 movl 4+offGlue_retval(%ecx),%ecx 784 FETCH_INST_OPCODE 1 %edx 785 SET_VREG_WORD %eax rINST 0 # v[AA+0] <- eax 786 SET_VREG_WORD %ecx rINST 1 # v[AA+1] <- ecx 787 ADVANCE_PC 1 788 GOTO_NEXT_R %edx 789 790/* ------------------------------ */ 791 .balign 64 792.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */ 793/* File: x86/OP_MOVE_RESULT_OBJECT.S */ 794/* File: x86/OP_MOVE_RESULT.S */ 795 /* for: move-result, move-result-object */ 796 /* op vAA */ 797 movl rGLUE,%eax # eax<- rGLUE 798 movzx rINSTbl,%ecx # ecx<- AA 799 movl offGlue_retval(%eax),%eax # eax<- glue->retval.l 800 FETCH_INST_OPCODE 1 %edx 801 ADVANCE_PC 1 802 SET_VREG %eax %ecx # fp[AA]<- retval.l 803 GOTO_NEXT_R %edx 804 805 806/* ------------------------------ */ 807 .balign 64 808.L_OP_MOVE_EXCEPTION: /* 0x0d */ 809/* File: x86/OP_MOVE_EXCEPTION.S */ 810 /* move-exception vAA */ 811 movl rGLUE,%ecx 812 movl offGlue_self(%ecx),%ecx # ecx<- glue->self 813 movl offThread_exception(%ecx),%eax # eax<- dvmGetException bypass 814 SET_VREG %eax rINST # fp[AA]<- exception object 815 FETCH_INST_OPCODE 1 %edx 816 ADVANCE_PC 1 817 movl $0,offThread_exception(%ecx) # dvmClearException bypass 818 GOTO_NEXT_R %edx 819 820/* ------------------------------ */ 821 .balign 64 822.L_OP_RETURN_VOID: /* 0x0e */ 823/* File: x86/OP_RETURN_VOID.S */ 824 jmp common_returnFromMethod 825 826/* ------------------------------ */ 827 .balign 64 828.L_OP_RETURN: /* 0x0f */ 829/* File: x86/OP_RETURN.S */ 830 /* 831 * Return a 32-bit value. Copies the return value into the "glue" 832 * structure, then jumps to the return handler. 833 * 834 * for: return, return-object 835 */ 836 /* op vAA */ 837 movl rGLUE,%ecx 838 GET_VREG_R %eax rINST # eax<- vAA 839 movl %eax,offGlue_retval(%ecx) # retval.i <- AA 840 jmp common_returnFromMethod 841 842/* ------------------------------ */ 843 .balign 64 844.L_OP_RETURN_WIDE: /* 0x10 */ 845/* File: x86/OP_RETURN_WIDE.S */ 846 /* 847 * Return a 64-bit value. Copies the return value into the "glue" 848 * structure, then jumps to the return handler. 849 */ 850 /* return-wide vAA */ 851 movl rGLUE,%ecx 852 GET_VREG_WORD %eax rINST 0 # eax<- v[AA+0] 853 GET_VREG_WORD rINST rINST 1 # rINST<- v[AA+1] 854 movl %eax,offGlue_retval(%ecx) 855 movl rINST,4+offGlue_retval(%ecx) 856 jmp common_returnFromMethod 857 858/* ------------------------------ */ 859 .balign 64 860.L_OP_RETURN_OBJECT: /* 0x11 */ 861/* File: x86/OP_RETURN_OBJECT.S */ 862/* File: x86/OP_RETURN.S */ 863 /* 864 * Return a 32-bit value. Copies the return value into the "glue" 865 * structure, then jumps to the return handler. 866 * 867 * for: return, return-object 868 */ 869 /* op vAA */ 870 movl rGLUE,%ecx 871 GET_VREG_R %eax rINST # eax<- vAA 872 movl %eax,offGlue_retval(%ecx) # retval.i <- AA 873 jmp common_returnFromMethod 874 875 876/* ------------------------------ */ 877 .balign 64 878.L_OP_CONST_4: /* 0x12 */ 879/* File: x86/OP_CONST_4.S */ 880 /* const/4 vA, #+B */ 881 movsx rINSTbl,%eax # eax<-ssssssBx 882 movl $0xf,%ecx 883 andl %eax,%ecx # ecx<- A 884 FETCH_INST_OPCODE 1 %edx 885 ADVANCE_PC 1 886 sarl $4,%eax 887 SET_VREG %eax %ecx 888 GOTO_NEXT_R %edx 889 890/* ------------------------------ */ 891 .balign 64 892.L_OP_CONST_16: /* 0x13 */ 893/* File: x86/OP_CONST_16.S */ 894 /* const/16 vAA, #+BBBB */ 895 movswl 2(rPC),%ecx # ecx<- ssssBBBB 896 movl rINST,%eax # eax<- AA 897 FETCH_INST_OPCODE 2 %edx 898 ADVANCE_PC 2 899 SET_VREG %ecx %eax # vAA<- ssssBBBB 900 GOTO_NEXT_R %edx 901 902/* ------------------------------ */ 903 .balign 64 904.L_OP_CONST: /* 0x14 */ 905/* File: x86/OP_CONST.S */ 906 /* const vAA, #+BBBBbbbb */ 907 movl 2(rPC),%eax # grab all 32 bits at once 908 movl rINST,%ecx # ecx<- AA 909 FETCH_INST_OPCODE 3 %edx 910 ADVANCE_PC 3 911 SET_VREG %eax %ecx # vAA<- eax 912 GOTO_NEXT_R %edx 913 914/* ------------------------------ */ 915 .balign 64 916.L_OP_CONST_HIGH16: /* 0x15 */ 917/* File: x86/OP_CONST_HIGH16.S */ 918 /* const/high16 vAA, #+BBBB0000 */ 919 movzwl 2(rPC),%eax # eax<- 0000BBBB 920 movl rINST,%ecx # ecx<- AA 921 FETCH_INST_OPCODE 2 %edx 922 ADVANCE_PC 2 923 sall $16,%eax # eax<- BBBB0000 924 SET_VREG %eax %ecx # vAA<- eax 925 GOTO_NEXT_R %edx 926 927/* ------------------------------ */ 928 .balign 64 929.L_OP_CONST_WIDE_16: /* 0x16 */ 930/* File: x86/OP_CONST_WIDE_16.S */ 931 /* const-wide/16 vAA, #+BBBB */ 932 movswl 2(rPC),%eax # eax<- ssssBBBB 933 cltd # rPC:eax<- ssssssssssssBBBB 934 SET_VREG_WORD %edx rINST 1 # store msw 935 FETCH_INST_OPCODE 2 %edx 936 SET_VREG_WORD %eax rINST 0 # store lsw 937 ADVANCE_PC 2 938 GOTO_NEXT_R %edx 939 940/* ------------------------------ */ 941 .balign 64 942.L_OP_CONST_WIDE_32: /* 0x17 */ 943/* File: x86/OP_CONST_WIDE_32.S */ 944 /* const-wide/32 vAA, #+BBBBbbbb */ 945 movl 2(rPC),%eax # eax<- BBBBbbbb 946 cltd # rPC:eax<- ssssssssssssBBBB 947 SET_VREG_WORD %edx rINST,1 # store msw 948 FETCH_INST_OPCODE 3 %edx 949 SET_VREG_WORD %eax rINST 0 # store lsw 950 ADVANCE_PC 3 951 GOTO_NEXT_R %edx 952 953/* ------------------------------ */ 954 .balign 64 955.L_OP_CONST_WIDE: /* 0x18 */ 956/* File: x86/OP_CONST_WIDE.S */ 957 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 958 movl 2(rPC),%eax # eax<- lsw 959 movzbl rINSTbl,%ecx # ecx<- AA 960 movl 6(rPC),rINST # rINST<- msw 961 leal (rFP,%ecx,4),%ecx # dst addr 962 movl rINST,4(%ecx) 963 FETCH_INST_OPCODE 5 %edx 964 movl %eax,(%ecx) 965 ADVANCE_PC 5 966 GOTO_NEXT_R %edx 967 968/* ------------------------------ */ 969 .balign 64 970.L_OP_CONST_WIDE_HIGH16: /* 0x19 */ 971/* File: x86/OP_CONST_WIDE_HIGH16.S */ 972 /* const-wide/high16 vAA, #+BBBB000000000000 */ 973 movzwl 2(rPC),%eax # eax<- 0000BBBB 974 FETCH_INST_OPCODE 2 %edx 975 ADVANCE_PC 2 976 sall $16,%eax # eax<- BBBB0000 977 SET_VREG_WORD %eax rINST 1 # v[AA+1]<- eax 978 xorl %eax,%eax 979 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax 980 GOTO_NEXT_R %edx 981 982/* ------------------------------ */ 983 .balign 64 984.L_OP_CONST_STRING: /* 0x1a */ 985/* File: x86/OP_CONST_STRING.S */ 986 987 /* const/string vAA, String@BBBB */ 988 movl rGLUE,%ecx 989 movzwl 2(rPC),%eax # eax<- BBBB 990 movl offGlue_methodClassDex(%ecx),%ecx# ecx<- glue->methodClassDex 991 movl offDvmDex_pResStrings(%ecx),%ecx # ecx<- dvmDex->pResStrings 992 movl (%ecx,%eax,4),%eax # eax<- rResString[BBBB] 993 movl rINST,%ecx 994 FETCH_INST_OPCODE 2 %edx 995 testl %eax,%eax # resolved yet? 996 je .LOP_CONST_STRING_resolve 997 SET_VREG %eax %ecx # vAA<- rResString[BBBB] 998 ADVANCE_PC 2 999 GOTO_NEXT_R %edx 1000 1001/* ------------------------------ */ 1002 .balign 64 1003.L_OP_CONST_STRING_JUMBO: /* 0x1b */ 1004/* File: x86/OP_CONST_STRING_JUMBO.S */ 1005 1006 /* const/string vAA, String@BBBBBBBB */ 1007 movl rGLUE,%ecx 1008 movl 2(rPC),%eax # eax<- BBBBBBBB 1009 movl offGlue_methodClassDex(%ecx),%ecx# ecx<- glue->methodClassDex 1010 movl offDvmDex_pResStrings(%ecx),%ecx # ecx<- dvmDex->pResStrings 1011 movl (%ecx,%eax,4),%eax # eax<- rResString[BBBB] 1012 movl rINST,%ecx 1013 FETCH_INST_OPCODE 3 %edx 1014 testl %eax,%eax # resolved yet? 1015 je .LOP_CONST_STRING_JUMBO_resolve 1016 SET_VREG %eax %ecx # vAA<- rResString[BBBB] 1017 ADVANCE_PC 3 1018 GOTO_NEXT_R %edx 1019 1020/* ------------------------------ */ 1021 .balign 64 1022.L_OP_CONST_CLASS: /* 0x1c */ 1023/* File: x86/OP_CONST_CLASS.S */ 1024 1025 /* const/class vAA, Class@BBBB */ 1026 movl rGLUE,%ecx 1027 movzwl 2(rPC),%eax # eax<- BBBB 1028 movl offGlue_methodClassDex(%ecx),%ecx# ecx<- glue->methodClassDex 1029 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- dvmDex->pResClasses 1030 movl (%ecx,%eax,4),%eax # eax<- rResClasses[BBBB] 1031 movl rINST,%ecx 1032 FETCH_INST_OPCODE 2 %edx 1033 testl %eax,%eax # resolved yet? 1034 je .LOP_CONST_CLASS_resolve 1035 SET_VREG %eax %ecx # vAA<- rResClasses[BBBB] 1036 ADVANCE_PC 2 1037 GOTO_NEXT_R %edx 1038 1039/* ------------------------------ */ 1040 .balign 64 1041.L_OP_MONITOR_ENTER: /* 0x1d */ 1042/* File: x86/OP_MONITOR_ENTER.S */ 1043 /* 1044 * Synchronize on an object. 1045 */ 1046 /* monitor-enter vAA */ 1047 movl rGLUE,%ecx 1048 GET_VREG_R %eax rINST # eax<- vAA 1049 movl offGlue_self(%ecx),%ecx # ecx<- glue->self 1050 FETCH_INST_WORD 1 1051 testl %eax,%eax # null object? 1052 EXPORT_PC # need for precise GC, MONITOR_TRACKING 1053 jne .LOP_MONITOR_ENTER_continue 1054 jmp common_errNullObject 1055 1056/* ------------------------------ */ 1057 .balign 64 1058.L_OP_MONITOR_EXIT: /* 0x1e */ 1059/* File: x86/OP_MONITOR_EXIT.S */ 1060 /* 1061 * Unlock an object. 1062 * 1063 * Exceptions that occur when unlocking a monitor need to appear as 1064 * if they happened at the following instruction. See the Dalvik 1065 * instruction spec. 1066 */ 1067 /* monitor-exit vAA */ 1068 GET_VREG_R %eax rINST 1069 movl rGLUE,%ecx 1070 EXPORT_PC 1071 testl %eax,%eax # null object? 1072 je .LOP_MONITOR_EXIT_errNullObject # go if so 1073 movl offGlue_self(%ecx),%ecx # ecx<- glue->self 1074 movl %eax,OUT_ARG1(%esp) 1075 movl %ecx,OUT_ARG0(%esp) 1076 jmp .LOP_MONITOR_EXIT_continue 1077 1078/* ------------------------------ */ 1079 .balign 64 1080.L_OP_CHECK_CAST: /* 0x1f */ 1081/* File: x86/OP_CHECK_CAST.S */ 1082 /* 1083 * Check to see if a cast from one class to another is allowed. 1084 */ 1085 /* check-cast vAA, class@BBBB */ 1086 movl rGLUE,%ecx 1087 GET_VREG_R rINST,rINST # rINST<- vAA (object) 1088 movzwl 2(rPC),%eax # eax<- BBBB 1089 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 1090 testl rINST,rINST # is oject null? 1091 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses 1092 je .LOP_CHECK_CAST_okay # null obj, cast always succeeds 1093 movl (%ecx,%eax,4),%eax # eax<- resolved class 1094 movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz 1095 testl %eax,%eax # have we resolved this before? 1096 je .LOP_CHECK_CAST_resolve # no, go do it now 1097.LOP_CHECK_CAST_resolved: 1098 cmpl %eax,%ecx # same class (trivial success)? 1099 jne .LOP_CHECK_CAST_fullcheck # no, do full check 1100.LOP_CHECK_CAST_okay: 1101 FETCH_INST_OPCODE 2 %edx 1102 ADVANCE_PC 2 1103 GOTO_NEXT_R %edx 1104 1105/* ------------------------------ */ 1106 .balign 64 1107.L_OP_INSTANCE_OF: /* 0x20 */ 1108/* File: x86/OP_INSTANCE_OF.S */ 1109 /* 1110 * Check to see if an object reference is an instance of a class. 1111 * 1112 * Most common situation is a non-null object, being compared against 1113 * an already-resolved class. 1114 */ 1115 /* instance-of vA, vB, class@CCCC */ 1116 movl rINST,%eax # eax<- BA 1117 sarl $4,%eax # eax<- B 1118 GET_VREG_R %eax %eax # eax<- vB (obj) 1119 movl rGLUE,%ecx 1120 testl %eax,%eax # object null? 1121 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 1122 je .LOP_INSTANCE_OF_store # null obj, not instance, store it 1123 movzwl 2(rPC),%edx # edx<- CCCC 1124 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses 1125 movl (%ecx,%edx,4),%ecx # ecx<- resolved class 1126 movl offObject_clazz(%eax),%eax # eax<- obj->clazz 1127 testl %ecx,%ecx # have we resolved this before? 1128 je .LOP_INSTANCE_OF_resolve # not resolved, do it now 1129.LOP_INSTANCE_OF_resolved: # eax<- obj->clazz, ecx<- resolved class 1130 cmpl %eax,%ecx # same class (trivial success)? 1131 je .LOP_INSTANCE_OF_trivial # yes, trivial finish 1132 jmp .LOP_INSTANCE_OF_fullcheck # no, do full check 1133 1134/* ------------------------------ */ 1135 .balign 64 1136.L_OP_ARRAY_LENGTH: /* 0x21 */ 1137/* File: x86/OP_ARRAY_LENGTH.S */ 1138 /* 1139 * Return the length of an array. 1140 */ 1141 mov rINST,%eax # eax<- BA 1142 sarl $4,rINST # rINST<- B 1143 GET_VREG_R %ecx rINST # ecx<- vB (object ref) 1144 andb $0xf,%al # eax<- A 1145 testl %ecx,%ecx # is null? 1146 je common_errNullObject 1147 FETCH_INST_OPCODE 1 %edx 1148 movl offArrayObject_length(%ecx),%ecx 1149 ADVANCE_PC 1 1150 SET_VREG %ecx %eax 1151 GOTO_NEXT_R %edx 1152 1153/* ------------------------------ */ 1154 .balign 64 1155.L_OP_NEW_INSTANCE: /* 0x22 */ 1156/* File: x86/OP_NEW_INSTANCE.S */ 1157 /* 1158 * Create a new instance of a class. 1159 */ 1160 /* new-instance vAA, class@BBBB */ 1161 movl rGLUE,%ecx 1162 movzwl 2(rPC),%eax # eax<- BBBB 1163 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 1164 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses 1165 EXPORT_PC 1166 movl (%ecx,%eax,4),%ecx # ecx<- resolved class 1167 testl %ecx,%ecx # resolved? 1168 je .LOP_NEW_INSTANCE_resolve # no, go do it 1169.LOP_NEW_INSTANCE_resolved: # on entry, ecx<- class 1170 cmpb $CLASS_INITIALIZED,offClassObject_status(%ecx) 1171 je .LOP_NEW_INSTANCE_initialized 1172 jmp .LOP_NEW_INSTANCE_needinit 1173 1174/* ------------------------------ */ 1175 .balign 64 1176.L_OP_NEW_ARRAY: /* 0x23 */ 1177/* File: x86/OP_NEW_ARRAY.S */ 1178 /* 1179 * Allocate an array of objects, specified with the array class 1180 * and a count. 1181 * 1182 * The verifier guarantees that this is an array class, so we don't 1183 * check for it here. 1184 */ 1185 /* new-array vA, vB, class@CCCC */ 1186 movl rGLUE,%ecx 1187 EXPORT_PC 1188 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 1189 movzwl 2(rPC),%eax # eax<- CCCC 1190 movl offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses 1191 movl (%ecx,%eax,4),%ecx # ecx<- resolved class 1192 movzbl rINSTbl,%eax 1193 sarl $4,%eax # eax<- B 1194 GET_VREG_R %eax %eax # eax<- vB (array length) 1195 andb $0xf,rINSTbl # rINST<- A 1196 testl %eax,%eax 1197 js common_errNegativeArraySize # bail 1198 testl %ecx,%ecx # already resolved? 1199 jne .LOP_NEW_ARRAY_finish # yes, fast path 1200 jmp .LOP_NEW_ARRAY_resolve # resolve now 1201 1202/* ------------------------------ */ 1203 .balign 64 1204.L_OP_FILLED_NEW_ARRAY: /* 0x24 */ 1205/* File: x86/OP_FILLED_NEW_ARRAY.S */ 1206 /* 1207 * Create a new array with elements filled from registers. 1208 * 1209 * for: filled-new-array, filled-new-array/range 1210 */ 1211 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1212 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1213 movl rGLUE,%eax 1214 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex 1215 movzwl 2(rPC),%ecx # ecx<- BBBB 1216 movl offDvmDex_pResClasses(%eax),%eax # eax<- pDvmDex->pResClasses 1217 movl (%eax,%ecx,4),%eax # eax<- resolved class 1218 EXPORT_PC 1219 testl %eax,%eax # already resolved? 1220 jne .LOP_FILLED_NEW_ARRAY_continue # yes, continue 1221 # less frequent path, so we'll redo some work 1222 movl rGLUE,%eax 1223 movl $0,OUT_ARG2(%esp) # arg2<- false 1224 movl %ecx,OUT_ARG1(%esp) # arg1<- BBBB 1225 movl offGlue_method(%eax),%eax # eax<- glue->method 1226 jmp .LOP_FILLED_NEW_ARRAY_more 1227 1228/* ------------------------------ */ 1229 .balign 64 1230.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */ 1231/* File: x86/OP_FILLED_NEW_ARRAY_RANGE.S */ 1232/* File: x86/OP_FILLED_NEW_ARRAY.S */ 1233 /* 1234 * Create a new array with elements filled from registers. 1235 * 1236 * for: filled-new-array, filled-new-array/range 1237 */ 1238 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 1239 /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */ 1240 movl rGLUE,%eax 1241 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex 1242 movzwl 2(rPC),%ecx # ecx<- BBBB 1243 movl offDvmDex_pResClasses(%eax),%eax # eax<- pDvmDex->pResClasses 1244 movl (%eax,%ecx,4),%eax # eax<- resolved class 1245 EXPORT_PC 1246 testl %eax,%eax # already resolved? 1247 jne .LOP_FILLED_NEW_ARRAY_RANGE_continue # yes, continue 1248 # less frequent path, so we'll redo some work 1249 movl rGLUE,%eax 1250 movl $0,OUT_ARG2(%esp) # arg2<- false 1251 movl %ecx,OUT_ARG1(%esp) # arg1<- BBBB 1252 movl offGlue_method(%eax),%eax # eax<- glue->method 1253 jmp .LOP_FILLED_NEW_ARRAY_RANGE_more 1254 1255 1256/* ------------------------------ */ 1257 .balign 64 1258.L_OP_FILL_ARRAY_DATA: /* 0x26 */ 1259/* File: x86/OP_FILL_ARRAY_DATA.S */ 1260 /* fill-array-data vAA, +BBBBBBBB */ 1261 movl 2(rPC),%ecx # ecx<- BBBBbbbb 1262 leal (rPC,%ecx,2),%ecx # ecx<- PC + BBBBbbbb*2 1263 GET_VREG_R %eax rINST 1264 EXPORT_PC 1265 movl %eax,OUT_ARG0(%esp) 1266 movl %ecx,OUT_ARG1(%esp) 1267 call dvmInterpHandleFillArrayData 1268 FETCH_INST_OPCODE 3 %edx 1269 testl %eax,%eax # exception thrown? 1270 je common_exceptionThrown 1271 ADVANCE_PC 3 1272 GOTO_NEXT_R %edx 1273 1274/* ------------------------------ */ 1275 .balign 64 1276.L_OP_THROW: /* 0x27 */ 1277/* File: x86/OP_THROW.S */ 1278 /* 1279 * Throw an exception object in the current thread. 1280 */ 1281 /* throw vAA */ 1282 movl rGLUE,%ecx 1283 EXPORT_PC 1284 GET_VREG_R %eax rINST # eax<- exception object 1285 movl offGlue_self(%ecx),%ecx # ecx<- glue->self 1286 testl %eax,%eax # null object? 1287 je common_errNullObject 1288 movl %eax,offThread_exception(%ecx) # thread->exception<- obj 1289 jmp common_exceptionThrown 1290 1291/* ------------------------------ */ 1292 .balign 64 1293.L_OP_GOTO: /* 0x28 */ 1294/* File: x86/OP_GOTO.S */ 1295 /* 1296 * Unconditional branch, 8-bit offset. 1297 * 1298 * The branch distance is a signed code-unit offset, which we need to 1299 * double to get a byte offset. 1300 */ 1301 /* goto +AA */ 1302 movsbl rINSTbl,rINST # ebx<- ssssssAA 1303 testl rINST,rINST # test for <0 1304 js common_backwardBranch 1305 movl rINST,%eax 1306 FETCH_INST_INDEXED %eax 1307 ADVANCE_PC_INDEXED %eax 1308 GOTO_NEXT 1309 1310/* ------------------------------ */ 1311 .balign 64 1312.L_OP_GOTO_16: /* 0x29 */ 1313/* File: x86/OP_GOTO_16.S */ 1314 /* 1315 * Unconditional branch, 16-bit offset. 1316 * 1317 * The branch distance is a signed code-unit offset 1318 */ 1319 /* goto/16 +AAAA */ 1320 movswl 2(rPC),rINST # rINST<- ssssAAAA 1321 testl rINST,rINST # test for <0 1322 js common_backwardBranch 1323 movl rINST,%eax 1324 FETCH_INST_INDEXED %eax 1325 ADVANCE_PC_INDEXED %eax 1326 GOTO_NEXT 1327 1328/* ------------------------------ */ 1329 .balign 64 1330.L_OP_GOTO_32: /* 0x2a */ 1331/* File: x86/OP_GOTO_32.S */ 1332 /* 1333 * Unconditional branch, 32-bit offset. 1334 * 1335 * The branch distance is a signed code-unit offset. 1336 * 1337 * Unlike most opcodes, this one is allowed to branch to itself, so 1338 * our "backward branch" test must be "<=0" instead of "<0". 1339 */ 1340 /* goto/32 AAAAAAAA */ 1341 movl 2(rPC),rINST # rINST<- AAAAAAAA 1342 cmpl $0,rINST # test for <= 0 1343 jle common_backwardBranch 1344 movl rINST,%eax 1345 FETCH_INST_INDEXED %eax 1346 ADVANCE_PC_INDEXED %eax 1347 GOTO_NEXT 1348 1349/* ------------------------------ */ 1350 .balign 64 1351.L_OP_PACKED_SWITCH: /* 0x2b */ 1352/* File: x86/OP_PACKED_SWITCH.S */ 1353 /* 1354 * Handle a packed-switch or sparse-switch instruction. In both cases 1355 * we decode it and hand it off to a helper function. 1356 * 1357 * We don't really expect backward branches in a switch statement, but 1358 * they're perfectly legal, so we check for them here. 1359 * 1360 * for: packed-switch, sparse-switch 1361 */ 1362 /* op vAA, +BBBB */ 1363 movl 2(rPC),%ecx # ecx<- BBBBbbbb 1364 GET_VREG_R %eax rINST # eax<- vAA 1365 leal (rPC,%ecx,2),%ecx # ecx<- PC + BBBBbbbb*2 1366 movl %eax,OUT_ARG1(%esp) # ARG1<- vAA 1367 movl %ecx,OUT_ARG0(%esp) # ARG0<- switchData 1368 call dvmInterpHandlePackedSwitch 1369 testl %eax,%eax 1370 movl %eax,rINST # set up word offset 1371 jle common_backwardBranch # check on special actions 1372 ADVANCE_PC_INDEXED rINST 1373 FETCH_INST 1374 GOTO_NEXT 1375 1376/* ------------------------------ */ 1377 .balign 64 1378.L_OP_SPARSE_SWITCH: /* 0x2c */ 1379/* File: x86/OP_SPARSE_SWITCH.S */ 1380/* File: x86/OP_PACKED_SWITCH.S */ 1381 /* 1382 * Handle a packed-switch or sparse-switch instruction. In both cases 1383 * we decode it and hand it off to a helper function. 1384 * 1385 * We don't really expect backward branches in a switch statement, but 1386 * they're perfectly legal, so we check for them here. 1387 * 1388 * for: packed-switch, sparse-switch 1389 */ 1390 /* op vAA, +BBBB */ 1391 movl 2(rPC),%ecx # ecx<- BBBBbbbb 1392 GET_VREG_R %eax rINST # eax<- vAA 1393 leal (rPC,%ecx,2),%ecx # ecx<- PC + BBBBbbbb*2 1394 movl %eax,OUT_ARG1(%esp) # ARG1<- vAA 1395 movl %ecx,OUT_ARG0(%esp) # ARG0<- switchData 1396 call dvmInterpHandleSparseSwitch 1397 testl %eax,%eax 1398 movl %eax,rINST # set up word offset 1399 jle common_backwardBranch # check on special actions 1400 ADVANCE_PC_INDEXED rINST 1401 FETCH_INST 1402 GOTO_NEXT 1403 1404 1405/* ------------------------------ */ 1406 .balign 64 1407.L_OP_CMPL_FLOAT: /* 0x2d */ 1408/* File: x86/OP_CMPL_FLOAT.S */ 1409/* File: x86/OP_CMPG_DOUBLE.S */ 1410 /* float/double_cmp[gl] vAA, vBB, vCC */ 1411 movzbl 3(rPC),%eax # eax<- CC 1412 movzbl 2(rPC),%ecx # ecx<- BB 1413 .if 0 1414 fldl (rFP,%eax,4) 1415 fldl (rFP,%ecx,4) 1416 .else 1417 flds (rFP,%eax,4) 1418 flds (rFP,%ecx,4) 1419 .endif 1420 xorl %ecx,%ecx 1421 fucompp # z if equal, p set if NaN, c set if st0 < st1 1422 fnstsw %ax 1423 sahf 1424 movl rINST,%eax 1425 FETCH_INST_OPCODE 2 %edx 1426 jp .LOP_CMPL_FLOAT_isNaN 1427 je .LOP_CMPL_FLOAT_finish 1428 sbbl %ecx,%ecx 1429 jb .LOP_CMPL_FLOAT_finish 1430 incl %ecx 1431.LOP_CMPL_FLOAT_finish: 1432 SET_VREG %ecx %eax 1433 ADVANCE_PC 2 1434 GOTO_NEXT_R %edx 1435 1436 1437/* ------------------------------ */ 1438 .balign 64 1439.L_OP_CMPG_FLOAT: /* 0x2e */ 1440/* File: x86/OP_CMPG_FLOAT.S */ 1441/* File: x86/OP_CMPG_DOUBLE.S */ 1442 /* float/double_cmp[gl] vAA, vBB, vCC */ 1443 movzbl 3(rPC),%eax # eax<- CC 1444 movzbl 2(rPC),%ecx # ecx<- BB 1445 .if 0 1446 fldl (rFP,%eax,4) 1447 fldl (rFP,%ecx,4) 1448 .else 1449 flds (rFP,%eax,4) 1450 flds (rFP,%ecx,4) 1451 .endif 1452 xorl %ecx,%ecx 1453 fucompp # z if equal, p set if NaN, c set if st0 < st1 1454 fnstsw %ax 1455 sahf 1456 movl rINST,%eax 1457 FETCH_INST_OPCODE 2 %edx 1458 jp .LOP_CMPG_FLOAT_isNaN 1459 je .LOP_CMPG_FLOAT_finish 1460 sbbl %ecx,%ecx 1461 jb .LOP_CMPG_FLOAT_finish 1462 incl %ecx 1463.LOP_CMPG_FLOAT_finish: 1464 SET_VREG %ecx %eax 1465 ADVANCE_PC 2 1466 GOTO_NEXT_R %edx 1467 1468 1469/* ------------------------------ */ 1470 .balign 64 1471.L_OP_CMPL_DOUBLE: /* 0x2f */ 1472/* File: x86/OP_CMPL_DOUBLE.S */ 1473/* File: x86/OP_CMPG_DOUBLE.S */ 1474 /* float/double_cmp[gl] vAA, vBB, vCC */ 1475 movzbl 3(rPC),%eax # eax<- CC 1476 movzbl 2(rPC),%ecx # ecx<- BB 1477 .if 1 1478 fldl (rFP,%eax,4) 1479 fldl (rFP,%ecx,4) 1480 .else 1481 flds (rFP,%eax,4) 1482 flds (rFP,%ecx,4) 1483 .endif 1484 xorl %ecx,%ecx 1485 fucompp # z if equal, p set if NaN, c set if st0 < st1 1486 fnstsw %ax 1487 sahf 1488 movl rINST,%eax 1489 FETCH_INST_OPCODE 2 %edx 1490 jp .LOP_CMPL_DOUBLE_isNaN 1491 je .LOP_CMPL_DOUBLE_finish 1492 sbbl %ecx,%ecx 1493 jb .LOP_CMPL_DOUBLE_finish 1494 incl %ecx 1495.LOP_CMPL_DOUBLE_finish: 1496 SET_VREG %ecx %eax 1497 ADVANCE_PC 2 1498 GOTO_NEXT_R %edx 1499 1500 1501/* ------------------------------ */ 1502 .balign 64 1503.L_OP_CMPG_DOUBLE: /* 0x30 */ 1504/* File: x86/OP_CMPG_DOUBLE.S */ 1505 /* float/double_cmp[gl] vAA, vBB, vCC */ 1506 movzbl 3(rPC),%eax # eax<- CC 1507 movzbl 2(rPC),%ecx # ecx<- BB 1508 .if 1 1509 fldl (rFP,%eax,4) 1510 fldl (rFP,%ecx,4) 1511 .else 1512 flds (rFP,%eax,4) 1513 flds (rFP,%ecx,4) 1514 .endif 1515 xorl %ecx,%ecx 1516 fucompp # z if equal, p set if NaN, c set if st0 < st1 1517 fnstsw %ax 1518 sahf 1519 movl rINST,%eax 1520 FETCH_INST_OPCODE 2 %edx 1521 jp .LOP_CMPG_DOUBLE_isNaN 1522 je .LOP_CMPG_DOUBLE_finish 1523 sbbl %ecx,%ecx 1524 jb .LOP_CMPG_DOUBLE_finish 1525 incl %ecx 1526.LOP_CMPG_DOUBLE_finish: 1527 SET_VREG %ecx %eax 1528 ADVANCE_PC 2 1529 GOTO_NEXT_R %edx 1530 1531/* ------------------------------ */ 1532 .balign 64 1533.L_OP_CMP_LONG: /* 0x31 */ 1534/* File: x86/OP_CMP_LONG.S */ 1535 /* 1536 * Compare two 64-bit values. Puts 0, 1, or -1 into the destination 1537 * register based on the results of the comparison. 1538 */ 1539 /* cmp-long vAA, vBB, vCC */ 1540 movzbl 2(rPC),%ecx # ecx<- BB 1541 movzbl 3(rPC),%edx # edx<- CC 1542 GET_VREG_WORD %eax %ecx,1 # eax<- v[BB+1] 1543 GET_VREG_WORD %ecx %ecx 0 # ecx<- v[BB+0] 1544 cmpl 4(rFP,%edx,4),%eax 1545 jl .LOP_CMP_LONG_smaller 1546 jg .LOP_CMP_LONG_bigger 1547 sub (rFP,%edx,4),%ecx 1548 ja .LOP_CMP_LONG_bigger 1549 jb .LOP_CMP_LONG_smaller 1550 jmp .LOP_CMP_LONG_finish 1551 1552/* ------------------------------ */ 1553 .balign 64 1554.L_OP_IF_EQ: /* 0x32 */ 1555/* File: x86/OP_IF_EQ.S */ 1556/* File: x86/bincmp.S */ 1557 /* 1558 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1559 * fragment that specifies the *reverse* comparison to perform, e.g. 1560 * for "if-le" you would use "gt". 1561 * 1562 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1563 */ 1564 /* if-cmp vA, vB, +CCCC */ 1565 movzx rINSTbl,%ecx # ecx <- A+ 1566 andb $0xf,%cl # ecx <- A 1567 GET_VREG_R %eax %ecx # eax <- vA 1568 sarl $4,rINST # rINST<- B 1569 cmpl (rFP,rINST,4),%eax # compare (vA, vB) 1570 movswl 2(rPC),rINST # Get signed branch offset 1571 movl $2,%eax # assume not taken 1572 jne 1f 1573 testl rINST,rINST 1574 js common_backwardBranch 1575 movl rINST,%eax 15761: 1577 FETCH_INST_INDEXED %eax 1578 ADVANCE_PC_INDEXED %eax 1579 GOTO_NEXT 1580 1581 1582/* ------------------------------ */ 1583 .balign 64 1584.L_OP_IF_NE: /* 0x33 */ 1585/* File: x86/OP_IF_NE.S */ 1586/* File: x86/bincmp.S */ 1587 /* 1588 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1589 * fragment that specifies the *reverse* comparison to perform, e.g. 1590 * for "if-le" you would use "gt". 1591 * 1592 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1593 */ 1594 /* if-cmp vA, vB, +CCCC */ 1595 movzx rINSTbl,%ecx # ecx <- A+ 1596 andb $0xf,%cl # ecx <- A 1597 GET_VREG_R %eax %ecx # eax <- vA 1598 sarl $4,rINST # rINST<- B 1599 cmpl (rFP,rINST,4),%eax # compare (vA, vB) 1600 movswl 2(rPC),rINST # Get signed branch offset 1601 movl $2,%eax # assume not taken 1602 je 1f 1603 testl rINST,rINST 1604 js common_backwardBranch 1605 movl rINST,%eax 16061: 1607 FETCH_INST_INDEXED %eax 1608 ADVANCE_PC_INDEXED %eax 1609 GOTO_NEXT 1610 1611 1612/* ------------------------------ */ 1613 .balign 64 1614.L_OP_IF_LT: /* 0x34 */ 1615/* File: x86/OP_IF_LT.S */ 1616/* File: x86/bincmp.S */ 1617 /* 1618 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1619 * fragment that specifies the *reverse* comparison to perform, e.g. 1620 * for "if-le" you would use "gt". 1621 * 1622 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1623 */ 1624 /* if-cmp vA, vB, +CCCC */ 1625 movzx rINSTbl,%ecx # ecx <- A+ 1626 andb $0xf,%cl # ecx <- A 1627 GET_VREG_R %eax %ecx # eax <- vA 1628 sarl $4,rINST # rINST<- B 1629 cmpl (rFP,rINST,4),%eax # compare (vA, vB) 1630 movswl 2(rPC),rINST # Get signed branch offset 1631 movl $2,%eax # assume not taken 1632 jge 1f 1633 testl rINST,rINST 1634 js common_backwardBranch 1635 movl rINST,%eax 16361: 1637 FETCH_INST_INDEXED %eax 1638 ADVANCE_PC_INDEXED %eax 1639 GOTO_NEXT 1640 1641 1642/* ------------------------------ */ 1643 .balign 64 1644.L_OP_IF_GE: /* 0x35 */ 1645/* File: x86/OP_IF_GE.S */ 1646/* File: x86/bincmp.S */ 1647 /* 1648 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1649 * fragment that specifies the *reverse* comparison to perform, e.g. 1650 * for "if-le" you would use "gt". 1651 * 1652 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1653 */ 1654 /* if-cmp vA, vB, +CCCC */ 1655 movzx rINSTbl,%ecx # ecx <- A+ 1656 andb $0xf,%cl # ecx <- A 1657 GET_VREG_R %eax %ecx # eax <- vA 1658 sarl $4,rINST # rINST<- B 1659 cmpl (rFP,rINST,4),%eax # compare (vA, vB) 1660 movswl 2(rPC),rINST # Get signed branch offset 1661 movl $2,%eax # assume not taken 1662 jl 1f 1663 testl rINST,rINST 1664 js common_backwardBranch 1665 movl rINST,%eax 16661: 1667 FETCH_INST_INDEXED %eax 1668 ADVANCE_PC_INDEXED %eax 1669 GOTO_NEXT 1670 1671 1672/* ------------------------------ */ 1673 .balign 64 1674.L_OP_IF_GT: /* 0x36 */ 1675/* File: x86/OP_IF_GT.S */ 1676/* File: x86/bincmp.S */ 1677 /* 1678 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1679 * fragment that specifies the *reverse* comparison to perform, e.g. 1680 * for "if-le" you would use "gt". 1681 * 1682 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1683 */ 1684 /* if-cmp vA, vB, +CCCC */ 1685 movzx rINSTbl,%ecx # ecx <- A+ 1686 andb $0xf,%cl # ecx <- A 1687 GET_VREG_R %eax %ecx # eax <- vA 1688 sarl $4,rINST # rINST<- B 1689 cmpl (rFP,rINST,4),%eax # compare (vA, vB) 1690 movswl 2(rPC),rINST # Get signed branch offset 1691 movl $2,%eax # assume not taken 1692 jle 1f 1693 testl rINST,rINST 1694 js common_backwardBranch 1695 movl rINST,%eax 16961: 1697 FETCH_INST_INDEXED %eax 1698 ADVANCE_PC_INDEXED %eax 1699 GOTO_NEXT 1700 1701 1702/* ------------------------------ */ 1703 .balign 64 1704.L_OP_IF_LE: /* 0x37 */ 1705/* File: x86/OP_IF_LE.S */ 1706/* File: x86/bincmp.S */ 1707 /* 1708 * Generic two-operand compare-and-branch operation. Provide a "revcmp" 1709 * fragment that specifies the *reverse* comparison to perform, e.g. 1710 * for "if-le" you would use "gt". 1711 * 1712 * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le 1713 */ 1714 /* if-cmp vA, vB, +CCCC */ 1715 movzx rINSTbl,%ecx # ecx <- A+ 1716 andb $0xf,%cl # ecx <- A 1717 GET_VREG_R %eax %ecx # eax <- vA 1718 sarl $4,rINST # rINST<- B 1719 cmpl (rFP,rINST,4),%eax # compare (vA, vB) 1720 movswl 2(rPC),rINST # Get signed branch offset 1721 movl $2,%eax # assume not taken 1722 jg 1f 1723 testl rINST,rINST 1724 js common_backwardBranch 1725 movl rINST,%eax 17261: 1727 FETCH_INST_INDEXED %eax 1728 ADVANCE_PC_INDEXED %eax 1729 GOTO_NEXT 1730 1731 1732/* ------------------------------ */ 1733 .balign 64 1734.L_OP_IF_EQZ: /* 0x38 */ 1735/* File: x86/OP_IF_EQZ.S */ 1736/* File: x86/zcmp.S */ 1737 /* 1738 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1739 * fragment that specifies the *reverse* comparison to perform, e.g. 1740 * for "if-le" you would use "gt". 1741 * 1742 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1743 */ 1744 /* if-cmp vAA, +BBBB */ 1745 cmpl $0,(rFP,rINST,4) # compare (vA, 0) 1746 movswl 2(rPC),rINST # fetch signed displacement 1747 movl $2,%eax # assume branch not taken 1748 jne 1f 1749 testl rINST,rINST 1750 js common_backwardBranch 1751 movl rINST,%eax 17521: 1753 FETCH_INST_INDEXED %eax 1754 ADVANCE_PC_INDEXED %eax 1755 GOTO_NEXT 1756 1757 1758/* ------------------------------ */ 1759 .balign 64 1760.L_OP_IF_NEZ: /* 0x39 */ 1761/* File: x86/OP_IF_NEZ.S */ 1762/* File: x86/zcmp.S */ 1763 /* 1764 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1765 * fragment that specifies the *reverse* comparison to perform, e.g. 1766 * for "if-le" you would use "gt". 1767 * 1768 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1769 */ 1770 /* if-cmp vAA, +BBBB */ 1771 cmpl $0,(rFP,rINST,4) # compare (vA, 0) 1772 movswl 2(rPC),rINST # fetch signed displacement 1773 movl $2,%eax # assume branch not taken 1774 je 1f 1775 testl rINST,rINST 1776 js common_backwardBranch 1777 movl rINST,%eax 17781: 1779 FETCH_INST_INDEXED %eax 1780 ADVANCE_PC_INDEXED %eax 1781 GOTO_NEXT 1782 1783 1784/* ------------------------------ */ 1785 .balign 64 1786.L_OP_IF_LTZ: /* 0x3a */ 1787/* File: x86/OP_IF_LTZ.S */ 1788/* File: x86/zcmp.S */ 1789 /* 1790 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1791 * fragment that specifies the *reverse* comparison to perform, e.g. 1792 * for "if-le" you would use "gt". 1793 * 1794 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1795 */ 1796 /* if-cmp vAA, +BBBB */ 1797 cmpl $0,(rFP,rINST,4) # compare (vA, 0) 1798 movswl 2(rPC),rINST # fetch signed displacement 1799 movl $2,%eax # assume branch not taken 1800 jge 1f 1801 testl rINST,rINST 1802 js common_backwardBranch 1803 movl rINST,%eax 18041: 1805 FETCH_INST_INDEXED %eax 1806 ADVANCE_PC_INDEXED %eax 1807 GOTO_NEXT 1808 1809 1810/* ------------------------------ */ 1811 .balign 64 1812.L_OP_IF_GEZ: /* 0x3b */ 1813/* File: x86/OP_IF_GEZ.S */ 1814/* File: x86/zcmp.S */ 1815 /* 1816 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1817 * fragment that specifies the *reverse* comparison to perform, e.g. 1818 * for "if-le" you would use "gt". 1819 * 1820 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1821 */ 1822 /* if-cmp vAA, +BBBB */ 1823 cmpl $0,(rFP,rINST,4) # compare (vA, 0) 1824 movswl 2(rPC),rINST # fetch signed displacement 1825 movl $2,%eax # assume branch not taken 1826 jl 1f 1827 testl rINST,rINST 1828 js common_backwardBranch 1829 movl rINST,%eax 18301: 1831 FETCH_INST_INDEXED %eax 1832 ADVANCE_PC_INDEXED %eax 1833 GOTO_NEXT 1834 1835 1836/* ------------------------------ */ 1837 .balign 64 1838.L_OP_IF_GTZ: /* 0x3c */ 1839/* File: x86/OP_IF_GTZ.S */ 1840/* File: x86/zcmp.S */ 1841 /* 1842 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1843 * fragment that specifies the *reverse* comparison to perform, e.g. 1844 * for "if-le" you would use "gt". 1845 * 1846 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1847 */ 1848 /* if-cmp vAA, +BBBB */ 1849 cmpl $0,(rFP,rINST,4) # compare (vA, 0) 1850 movswl 2(rPC),rINST # fetch signed displacement 1851 movl $2,%eax # assume branch not taken 1852 jle 1f 1853 testl rINST,rINST 1854 js common_backwardBranch 1855 movl rINST,%eax 18561: 1857 FETCH_INST_INDEXED %eax 1858 ADVANCE_PC_INDEXED %eax 1859 GOTO_NEXT 1860 1861 1862/* ------------------------------ */ 1863 .balign 64 1864.L_OP_IF_LEZ: /* 0x3d */ 1865/* File: x86/OP_IF_LEZ.S */ 1866/* File: x86/zcmp.S */ 1867 /* 1868 * Generic one-operand compare-and-branch operation. Provide a "revcmp" 1869 * fragment that specifies the *reverse* comparison to perform, e.g. 1870 * for "if-le" you would use "gt". 1871 * 1872 * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez 1873 */ 1874 /* if-cmp vAA, +BBBB */ 1875 cmpl $0,(rFP,rINST,4) # compare (vA, 0) 1876 movswl 2(rPC),rINST # fetch signed displacement 1877 movl $2,%eax # assume branch not taken 1878 jg 1f 1879 testl rINST,rINST 1880 js common_backwardBranch 1881 movl rINST,%eax 18821: 1883 FETCH_INST_INDEXED %eax 1884 ADVANCE_PC_INDEXED %eax 1885 GOTO_NEXT 1886 1887 1888/* ------------------------------ */ 1889 .balign 64 1890.L_OP_UNUSED_3E: /* 0x3e */ 1891/* File: x86/OP_UNUSED_3E.S */ 1892/* File: x86/unused.S */ 1893 jmp common_abort 1894 1895 1896/* ------------------------------ */ 1897 .balign 64 1898.L_OP_UNUSED_3F: /* 0x3f */ 1899/* File: x86/OP_UNUSED_3F.S */ 1900/* File: x86/unused.S */ 1901 jmp common_abort 1902 1903 1904/* ------------------------------ */ 1905 .balign 64 1906.L_OP_UNUSED_40: /* 0x40 */ 1907/* File: x86/OP_UNUSED_40.S */ 1908/* File: x86/unused.S */ 1909 jmp common_abort 1910 1911 1912/* ------------------------------ */ 1913 .balign 64 1914.L_OP_UNUSED_41: /* 0x41 */ 1915/* File: x86/OP_UNUSED_41.S */ 1916/* File: x86/unused.S */ 1917 jmp common_abort 1918 1919 1920/* ------------------------------ */ 1921 .balign 64 1922.L_OP_UNUSED_42: /* 0x42 */ 1923/* File: x86/OP_UNUSED_42.S */ 1924/* File: x86/unused.S */ 1925 jmp common_abort 1926 1927 1928/* ------------------------------ */ 1929 .balign 64 1930.L_OP_UNUSED_43: /* 0x43 */ 1931/* File: x86/OP_UNUSED_43.S */ 1932/* File: x86/unused.S */ 1933 jmp common_abort 1934 1935 1936/* ------------------------------ */ 1937 .balign 64 1938.L_OP_AGET: /* 0x44 */ 1939/* File: x86/OP_AGET.S */ 1940 /* 1941 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1942 * 1943 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1944 */ 1945 /* op vAA, vBB, vCC */ 1946 movzbl 2(rPC),%eax # eax<- BB 1947 movzbl 3(rPC),%ecx # ecx<- CC 1948 GET_VREG_R %eax %eax # eax<- vBB (array object) 1949 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 1950 testl %eax,%eax # null array object? 1951 je common_errNullObject # bail if so 1952 cmpl offArrayObject_length(%eax),%ecx 1953 jae common_errArrayIndex # index >= length, bail. Expects 1954 # arrayObj in eax 1955 # index in ecx 1956 movl offArrayObject_contents(%eax,%ecx,4),%eax 1957.LOP_AGET_finish: 1958 FETCH_INST_OPCODE 2 %edx 1959 SET_VREG %eax rINST 1960 ADVANCE_PC 2 1961 GOTO_NEXT_R %edx 1962 1963/* ------------------------------ */ 1964 .balign 64 1965.L_OP_AGET_WIDE: /* 0x45 */ 1966/* File: x86/OP_AGET_WIDE.S */ 1967 /* 1968 * Array get, 64 bits. vAA <- vBB[vCC]. 1969 * 1970 */ 1971 /* op vAA, vBB, vCC */ 1972 movzbl 2(rPC),%eax # eax<- BB 1973 movzbl 3(rPC),%ecx # ecx<- CC 1974 GET_VREG_R %eax %eax # eax<- vBB (array object) 1975 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 1976 testl %eax,%eax # null array object? 1977 je common_errNullObject # bail if so 1978 cmpl offArrayObject_length(%eax),%ecx 1979 jb .LOP_AGET_WIDE_finish # index < length, OK 1980 jmp common_errArrayIndex # index >= length, bail. Expects 1981 # arrayObj in eax 1982 # index in ecx 1983 1984/* ------------------------------ */ 1985 .balign 64 1986.L_OP_AGET_OBJECT: /* 0x46 */ 1987/* File: x86/OP_AGET_OBJECT.S */ 1988/* File: x86/OP_AGET.S */ 1989 /* 1990 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1991 * 1992 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1993 */ 1994 /* op vAA, vBB, vCC */ 1995 movzbl 2(rPC),%eax # eax<- BB 1996 movzbl 3(rPC),%ecx # ecx<- CC 1997 GET_VREG_R %eax %eax # eax<- vBB (array object) 1998 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 1999 testl %eax,%eax # null array object? 2000 je common_errNullObject # bail if so 2001 cmpl offArrayObject_length(%eax),%ecx 2002 jae common_errArrayIndex # index >= length, bail. Expects 2003 # arrayObj in eax 2004 # index in ecx 2005 movl offArrayObject_contents(%eax,%ecx,4),%eax 2006.LOP_AGET_OBJECT_finish: 2007 FETCH_INST_OPCODE 2 %edx 2008 SET_VREG %eax rINST 2009 ADVANCE_PC 2 2010 GOTO_NEXT_R %edx 2011 2012 2013/* ------------------------------ */ 2014 .balign 64 2015.L_OP_AGET_BOOLEAN: /* 0x47 */ 2016/* File: x86/OP_AGET_BOOLEAN.S */ 2017/* File: x86/OP_AGET.S */ 2018 /* 2019 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2020 * 2021 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2022 */ 2023 /* op vAA, vBB, vCC */ 2024 movzbl 2(rPC),%eax # eax<- BB 2025 movzbl 3(rPC),%ecx # ecx<- CC 2026 GET_VREG_R %eax %eax # eax<- vBB (array object) 2027 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2028 testl %eax,%eax # null array object? 2029 je common_errNullObject # bail if so 2030 cmpl offArrayObject_length(%eax),%ecx 2031 jae common_errArrayIndex # index >= length, bail. Expects 2032 # arrayObj in eax 2033 # index in ecx 2034 movzbl offArrayObject_contents(%eax,%ecx,1),%eax 2035.LOP_AGET_BOOLEAN_finish: 2036 FETCH_INST_OPCODE 2 %edx 2037 SET_VREG %eax rINST 2038 ADVANCE_PC 2 2039 GOTO_NEXT_R %edx 2040 2041 2042/* ------------------------------ */ 2043 .balign 64 2044.L_OP_AGET_BYTE: /* 0x48 */ 2045/* File: x86/OP_AGET_BYTE.S */ 2046/* File: x86/OP_AGET.S */ 2047 /* 2048 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2049 * 2050 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2051 */ 2052 /* op vAA, vBB, vCC */ 2053 movzbl 2(rPC),%eax # eax<- BB 2054 movzbl 3(rPC),%ecx # ecx<- CC 2055 GET_VREG_R %eax %eax # eax<- vBB (array object) 2056 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2057 testl %eax,%eax # null array object? 2058 je common_errNullObject # bail if so 2059 cmpl offArrayObject_length(%eax),%ecx 2060 jae common_errArrayIndex # index >= length, bail. Expects 2061 # arrayObj in eax 2062 # index in ecx 2063 movsbl offArrayObject_contents(%eax,%ecx,1),%eax 2064.LOP_AGET_BYTE_finish: 2065 FETCH_INST_OPCODE 2 %edx 2066 SET_VREG %eax rINST 2067 ADVANCE_PC 2 2068 GOTO_NEXT_R %edx 2069 2070 2071/* ------------------------------ */ 2072 .balign 64 2073.L_OP_AGET_CHAR: /* 0x49 */ 2074/* File: x86/OP_AGET_CHAR.S */ 2075/* File: x86/OP_AGET.S */ 2076 /* 2077 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2078 * 2079 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2080 */ 2081 /* op vAA, vBB, vCC */ 2082 movzbl 2(rPC),%eax # eax<- BB 2083 movzbl 3(rPC),%ecx # ecx<- CC 2084 GET_VREG_R %eax %eax # eax<- vBB (array object) 2085 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2086 testl %eax,%eax # null array object? 2087 je common_errNullObject # bail if so 2088 cmpl offArrayObject_length(%eax),%ecx 2089 jae common_errArrayIndex # index >= length, bail. Expects 2090 # arrayObj in eax 2091 # index in ecx 2092 movzwl offArrayObject_contents(%eax,%ecx,2),%eax 2093.LOP_AGET_CHAR_finish: 2094 FETCH_INST_OPCODE 2 %edx 2095 SET_VREG %eax rINST 2096 ADVANCE_PC 2 2097 GOTO_NEXT_R %edx 2098 2099 2100/* ------------------------------ */ 2101 .balign 64 2102.L_OP_AGET_SHORT: /* 0x4a */ 2103/* File: x86/OP_AGET_SHORT.S */ 2104/* File: x86/OP_AGET.S */ 2105 /* 2106 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2107 * 2108 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2109 */ 2110 /* op vAA, vBB, vCC */ 2111 movzbl 2(rPC),%eax # eax<- BB 2112 movzbl 3(rPC),%ecx # ecx<- CC 2113 GET_VREG_R %eax %eax # eax<- vBB (array object) 2114 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2115 testl %eax,%eax # null array object? 2116 je common_errNullObject # bail if so 2117 cmpl offArrayObject_length(%eax),%ecx 2118 jae common_errArrayIndex # index >= length, bail. Expects 2119 # arrayObj in eax 2120 # index in ecx 2121 movswl offArrayObject_contents(%eax,%ecx,2),%eax 2122.LOP_AGET_SHORT_finish: 2123 FETCH_INST_OPCODE 2 %edx 2124 SET_VREG %eax rINST 2125 ADVANCE_PC 2 2126 GOTO_NEXT_R %edx 2127 2128 2129/* ------------------------------ */ 2130 .balign 64 2131.L_OP_APUT: /* 0x4b */ 2132/* File: x86/OP_APUT.S */ 2133 /* 2134 * Array put, 32 bits or less. vBB[vCC] <- vAA 2135 * 2136 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short 2137 */ 2138 /* op vAA, vBB, vCC */ 2139 movzbl 2(rPC),%eax # eax<- BB 2140 movzbl 3(rPC),%ecx # ecx<- CC 2141 GET_VREG_R %eax %eax # eax<- vBB (array object) 2142 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2143 testl %eax,%eax # null array object? 2144 je common_errNullObject # bail if so 2145 cmpl offArrayObject_length(%eax),%ecx 2146 jae common_errArrayIndex # index >= length, bail. Expects: 2147 # arrayObj in eax 2148 # index in ecx 2149 leal offArrayObject_contents(%eax,%ecx,4),%eax 2150.LOP_APUT_finish: 2151 GET_VREG_R %ecx rINST 2152 FETCH_INST_OPCODE 2 %edx 2153 movl %ecx,(%eax) 2154 ADVANCE_PC 2 2155 GOTO_NEXT_R %edx 2156 2157/* ------------------------------ */ 2158 .balign 64 2159.L_OP_APUT_WIDE: /* 0x4c */ 2160/* File: x86/OP_APUT_WIDE.S */ 2161 /* 2162 * Array put, 64 bits. vBB[vCC]<-vAA. 2163 * 2164 */ 2165 /* op vAA, vBB, vCC */ 2166 movzbl 2(rPC),%eax # eax<- BB 2167 movzbl 3(rPC),%ecx # ecx<- CC 2168 GET_VREG_R %eax %eax # eax<- vBB (array object) 2169 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2170 testl %eax,%eax # null array object? 2171 je common_errNullObject # bail if so 2172 cmpl offArrayObject_length(%eax),%ecx 2173 jb .LOP_APUT_WIDE_finish # index < length, OK 2174 jmp common_errArrayIndex # index >= length, bail. Expects: 2175 # arrayObj in eax 2176 # index in ecx 2177 2178/* ------------------------------ */ 2179 .balign 64 2180.L_OP_APUT_OBJECT: /* 0x4d */ 2181/* File: x86/OP_APUT_OBJECT.S */ 2182 /* 2183 * Array put, 32 bits or less. vBB[vCC] <- vAA 2184 * 2185 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short 2186 */ 2187 /* op vAA, vBB, vCC */ 2188 movzbl 2(rPC),%eax # eax<- BB 2189 movzbl 3(rPC),%ecx # ecx<- CC 2190 GET_VREG_R %eax %eax # eax<- vBB (array object) 2191 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2192 GET_VREG_R rINST rINST # rINST<- vAA 2193 testl %eax,%eax # null array object? 2194 je common_errNullObject # bail if so 2195 cmpl offArrayObject_length(%eax),%ecx 2196 jb .LOP_APUT_OBJECT_continue 2197 jmp common_errArrayIndex # index >= length, bail. Expects 2198 # arrayObj in eax 2199 # index in ecx 2200 2201/* ------------------------------ */ 2202 .balign 64 2203.L_OP_APUT_BOOLEAN: /* 0x4e */ 2204/* File: x86/OP_APUT_BOOLEAN.S */ 2205/* File: x86/OP_APUT.S */ 2206 /* 2207 * Array put, 32 bits or less. vBB[vCC] <- vAA 2208 * 2209 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short 2210 */ 2211 /* op vAA, vBB, vCC */ 2212 movzbl 2(rPC),%eax # eax<- BB 2213 movzbl 3(rPC),%ecx # ecx<- CC 2214 GET_VREG_R %eax %eax # eax<- vBB (array object) 2215 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2216 testl %eax,%eax # null array object? 2217 je common_errNullObject # bail if so 2218 cmpl offArrayObject_length(%eax),%ecx 2219 jae common_errArrayIndex # index >= length, bail. Expects: 2220 # arrayObj in eax 2221 # index in ecx 2222 leal offArrayObject_contents(%eax,%ecx,1),%eax 2223.LOP_APUT_BOOLEAN_finish: 2224 GET_VREG_R %ecx rINST 2225 FETCH_INST_OPCODE 2 %edx 2226 movb %cl,(%eax) 2227 ADVANCE_PC 2 2228 GOTO_NEXT_R %edx 2229 2230 2231/* ------------------------------ */ 2232 .balign 64 2233.L_OP_APUT_BYTE: /* 0x4f */ 2234/* File: x86/OP_APUT_BYTE.S */ 2235/* File: x86/OP_APUT.S */ 2236 /* 2237 * Array put, 32 bits or less. vBB[vCC] <- vAA 2238 * 2239 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short 2240 */ 2241 /* op vAA, vBB, vCC */ 2242 movzbl 2(rPC),%eax # eax<- BB 2243 movzbl 3(rPC),%ecx # ecx<- CC 2244 GET_VREG_R %eax %eax # eax<- vBB (array object) 2245 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2246 testl %eax,%eax # null array object? 2247 je common_errNullObject # bail if so 2248 cmpl offArrayObject_length(%eax),%ecx 2249 jae common_errArrayIndex # index >= length, bail. Expects: 2250 # arrayObj in eax 2251 # index in ecx 2252 leal offArrayObject_contents(%eax,%ecx,1),%eax 2253.LOP_APUT_BYTE_finish: 2254 GET_VREG_R %ecx rINST 2255 FETCH_INST_OPCODE 2 %edx 2256 movb %cl,(%eax) 2257 ADVANCE_PC 2 2258 GOTO_NEXT_R %edx 2259 2260 2261/* ------------------------------ */ 2262 .balign 64 2263.L_OP_APUT_CHAR: /* 0x50 */ 2264/* File: x86/OP_APUT_CHAR.S */ 2265/* File: x86/OP_APUT.S */ 2266 /* 2267 * Array put, 32 bits or less. vBB[vCC] <- vAA 2268 * 2269 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short 2270 */ 2271 /* op vAA, vBB, vCC */ 2272 movzbl 2(rPC),%eax # eax<- BB 2273 movzbl 3(rPC),%ecx # ecx<- CC 2274 GET_VREG_R %eax %eax # eax<- vBB (array object) 2275 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2276 testl %eax,%eax # null array object? 2277 je common_errNullObject # bail if so 2278 cmpl offArrayObject_length(%eax),%ecx 2279 jae common_errArrayIndex # index >= length, bail. Expects: 2280 # arrayObj in eax 2281 # index in ecx 2282 leal offArrayObject_contents(%eax,%ecx,2),%eax 2283.LOP_APUT_CHAR_finish: 2284 GET_VREG_R %ecx rINST 2285 FETCH_INST_OPCODE 2 %edx 2286 movw %cx,(%eax) 2287 ADVANCE_PC 2 2288 GOTO_NEXT_R %edx 2289 2290 2291/* ------------------------------ */ 2292 .balign 64 2293.L_OP_APUT_SHORT: /* 0x51 */ 2294/* File: x86/OP_APUT_SHORT.S */ 2295/* File: x86/OP_APUT.S */ 2296 /* 2297 * Array put, 32 bits or less. vBB[vCC] <- vAA 2298 * 2299 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short 2300 */ 2301 /* op vAA, vBB, vCC */ 2302 movzbl 2(rPC),%eax # eax<- BB 2303 movzbl 3(rPC),%ecx # ecx<- CC 2304 GET_VREG_R %eax %eax # eax<- vBB (array object) 2305 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2306 testl %eax,%eax # null array object? 2307 je common_errNullObject # bail if so 2308 cmpl offArrayObject_length(%eax),%ecx 2309 jae common_errArrayIndex # index >= length, bail. Expects: 2310 # arrayObj in eax 2311 # index in ecx 2312 leal offArrayObject_contents(%eax,%ecx,2),%eax 2313.LOP_APUT_SHORT_finish: 2314 GET_VREG_R %ecx rINST 2315 FETCH_INST_OPCODE 2 %edx 2316 movw %cx,(%eax) 2317 ADVANCE_PC 2 2318 GOTO_NEXT_R %edx 2319 2320 2321/* ------------------------------ */ 2322 .balign 64 2323.L_OP_IGET: /* 0x52 */ 2324/* File: x86/OP_IGET.S */ 2325 /* 2326 * General 32-bit instance field get. 2327 * 2328 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2329 */ 2330 /* op vA, vB, field@CCCC */ 2331 movl rGLUE,%ecx 2332 movzwl 2(rPC),%edx # edx<- 0000CCCC 2333 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2334 movzbl rINSTbl,%ecx # ecx<- BA 2335 sarl $4,%ecx # ecx<- B 2336 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2337 andb $0xf,rINSTbl # rINST<- A 2338 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2339 movl (%eax,%edx,4),%eax # resolved entry 2340 testl %eax,%eax # is resolved entry null? 2341 jne .LOP_IGET_finish # no, already resolved 2342 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 2343 movl rGLUE,%edx 2344 jmp .LOP_IGET_resolve 2345 2346/* ------------------------------ */ 2347 .balign 64 2348.L_OP_IGET_WIDE: /* 0x53 */ 2349/* File: x86/OP_IGET_WIDE.S */ 2350 /* 2351 * 64-bit instance field get. 2352 * 2353 */ 2354 /* op vA, vB, field@CCCC */ 2355 movl rGLUE,%ecx 2356 movzwl 2(rPC),%edx # edx<- 0000CCCC 2357 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2358 movzbl rINSTbl,%ecx # ecx<- BA 2359 sarl $4,%ecx # ecx<- B 2360 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2361 andb $0xf,rINSTbl # rINST<- A 2362 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2363 movl (%eax,%edx,4),%eax # resolved entry 2364 testl %eax,%eax # is resolved entry null? 2365 jne .LOP_IGET_WIDE_finish # no, already resolved 2366 movl %edx,OUT_ARG1(%esp) # for dvmResolveInstField 2367 movl rGLUE,%edx 2368 jmp .LOP_IGET_WIDE_resolve 2369 2370/* ------------------------------ */ 2371 .balign 64 2372.L_OP_IGET_OBJECT: /* 0x54 */ 2373/* File: x86/OP_IGET_OBJECT.S */ 2374/* File: x86/OP_IGET.S */ 2375 /* 2376 * General 32-bit instance field get. 2377 * 2378 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2379 */ 2380 /* op vA, vB, field@CCCC */ 2381 movl rGLUE,%ecx 2382 movzwl 2(rPC),%edx # edx<- 0000CCCC 2383 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2384 movzbl rINSTbl,%ecx # ecx<- BA 2385 sarl $4,%ecx # ecx<- B 2386 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2387 andb $0xf,rINSTbl # rINST<- A 2388 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2389 movl (%eax,%edx,4),%eax # resolved entry 2390 testl %eax,%eax # is resolved entry null? 2391 jne .LOP_IGET_OBJECT_finish # no, already resolved 2392 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 2393 movl rGLUE,%edx 2394 jmp .LOP_IGET_OBJECT_resolve 2395 2396 2397/* ------------------------------ */ 2398 .balign 64 2399.L_OP_IGET_BOOLEAN: /* 0x55 */ 2400/* File: x86/OP_IGET_BOOLEAN.S */ 2401/* File: x86/OP_IGET.S */ 2402 /* 2403 * General 32-bit instance field get. 2404 * 2405 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2406 */ 2407 /* op vA, vB, field@CCCC */ 2408 movl rGLUE,%ecx 2409 movzwl 2(rPC),%edx # edx<- 0000CCCC 2410 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2411 movzbl rINSTbl,%ecx # ecx<- BA 2412 sarl $4,%ecx # ecx<- B 2413 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2414 andb $0xf,rINSTbl # rINST<- A 2415 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2416 movl (%eax,%edx,4),%eax # resolved entry 2417 testl %eax,%eax # is resolved entry null? 2418 jne .LOP_IGET_BOOLEAN_finish # no, already resolved 2419 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 2420 movl rGLUE,%edx 2421 jmp .LOP_IGET_BOOLEAN_resolve 2422 2423 2424/* ------------------------------ */ 2425 .balign 64 2426.L_OP_IGET_BYTE: /* 0x56 */ 2427/* File: x86/OP_IGET_BYTE.S */ 2428/* File: x86/OP_IGET.S */ 2429 /* 2430 * General 32-bit instance field get. 2431 * 2432 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2433 */ 2434 /* op vA, vB, field@CCCC */ 2435 movl rGLUE,%ecx 2436 movzwl 2(rPC),%edx # edx<- 0000CCCC 2437 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2438 movzbl rINSTbl,%ecx # ecx<- BA 2439 sarl $4,%ecx # ecx<- B 2440 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2441 andb $0xf,rINSTbl # rINST<- A 2442 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2443 movl (%eax,%edx,4),%eax # resolved entry 2444 testl %eax,%eax # is resolved entry null? 2445 jne .LOP_IGET_BYTE_finish # no, already resolved 2446 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 2447 movl rGLUE,%edx 2448 jmp .LOP_IGET_BYTE_resolve 2449 2450 2451/* ------------------------------ */ 2452 .balign 64 2453.L_OP_IGET_CHAR: /* 0x57 */ 2454/* File: x86/OP_IGET_CHAR.S */ 2455/* File: x86/OP_IGET.S */ 2456 /* 2457 * General 32-bit instance field get. 2458 * 2459 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2460 */ 2461 /* op vA, vB, field@CCCC */ 2462 movl rGLUE,%ecx 2463 movzwl 2(rPC),%edx # edx<- 0000CCCC 2464 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2465 movzbl rINSTbl,%ecx # ecx<- BA 2466 sarl $4,%ecx # ecx<- B 2467 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2468 andb $0xf,rINSTbl # rINST<- A 2469 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2470 movl (%eax,%edx,4),%eax # resolved entry 2471 testl %eax,%eax # is resolved entry null? 2472 jne .LOP_IGET_CHAR_finish # no, already resolved 2473 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 2474 movl rGLUE,%edx 2475 jmp .LOP_IGET_CHAR_resolve 2476 2477 2478/* ------------------------------ */ 2479 .balign 64 2480.L_OP_IGET_SHORT: /* 0x58 */ 2481/* File: x86/OP_IGET_SHORT.S */ 2482/* File: x86/OP_IGET.S */ 2483 /* 2484 * General 32-bit instance field get. 2485 * 2486 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2487 */ 2488 /* op vA, vB, field@CCCC */ 2489 movl rGLUE,%ecx 2490 movzwl 2(rPC),%edx # edx<- 0000CCCC 2491 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2492 movzbl rINSTbl,%ecx # ecx<- BA 2493 sarl $4,%ecx # ecx<- B 2494 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2495 andb $0xf,rINSTbl # rINST<- A 2496 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2497 movl (%eax,%edx,4),%eax # resolved entry 2498 testl %eax,%eax # is resolved entry null? 2499 jne .LOP_IGET_SHORT_finish # no, already resolved 2500 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 2501 movl rGLUE,%edx 2502 jmp .LOP_IGET_SHORT_resolve 2503 2504 2505/* ------------------------------ */ 2506 .balign 64 2507.L_OP_IPUT: /* 0x59 */ 2508/* File: x86/OP_IPUT.S */ 2509 2510 /* 2511 * General 32-bit instance field put. 2512 * 2513 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2514 */ 2515 /* op vA, vB, field@CCCC */ 2516 movl rGLUE,%ecx 2517 movzwl 2(rPC),%edx # %edx<- 0000CCCC 2518 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2519 movzbl rINSTbl,%ecx # ecx<- BA 2520 sarl $4,%ecx # ecx<- B 2521 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2522 andb $0xf,rINSTbl # rINST<- A 2523 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2524 movl (%eax,%edx,4),%eax # resolved entry 2525 testl %eax,%eax # is resolved entry null? 2526 jne .LOP_IPUT_finish # no, already resolved 2527 movl %edx,OUT_ARG1(%esp) 2528 movl rGLUE,%edx 2529 jmp .LOP_IPUT_resolve 2530 2531/* ------------------------------ */ 2532 .balign 64 2533.L_OP_IPUT_WIDE: /* 0x5a */ 2534/* File: x86/OP_IPUT_WIDE.S */ 2535 /* 2536 * 64-bit instance field put. 2537 * 2538 */ 2539 /* op vA, vB, field@CCCC */ 2540 movl rGLUE,%ecx 2541 movzwl 2(rPC),%edx # edx<- 0000CCCC 2542 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2543 movzbl rINSTbl,%ecx # ecx<- BA 2544 sarl $4,%ecx # ecx<- B 2545 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2546 andb $0xf,rINSTbl # rINST<- A 2547 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2548 movl (%eax,%edx,4),%eax # resolved entry 2549 testl %eax,%eax # is resolved entry null? 2550 jne .LOP_IPUT_WIDE_finish # no, already resolved 2551 movl %edx,OUT_ARG1(%esp) 2552 movl rGLUE,%edx 2553 jmp .LOP_IPUT_WIDE_resolve 2554 2555/* ------------------------------ */ 2556 .balign 64 2557.L_OP_IPUT_OBJECT: /* 0x5b */ 2558/* File: x86/OP_IPUT_OBJECT.S */ 2559 /* 2560 * Object field put. 2561 * 2562 * for: iput-object 2563 */ 2564 /* op vA, vB, field@CCCC */ 2565 movl rGLUE,%ecx 2566 movzwl 2(rPC),%edx # edx<- 0000CCCC 2567 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2568 movzbl rINSTbl,%ecx # ecx<- BA 2569 sarl $4,%ecx # ecx<- B 2570 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2571 andb $0xf,rINSTbl # rINST<- A 2572 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2573 movl (%eax,%edx,4),%eax # resolved entry 2574 testl %eax,%eax # is resolved entry null? 2575 jne .LOP_IPUT_OBJECT_finish # no, already resolved 2576 movl %edx,OUT_ARG1(%esp) 2577 movl rGLUE,%edx 2578 jmp .LOP_IPUT_OBJECT_resolve 2579 2580/* ------------------------------ */ 2581 .balign 64 2582.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2583/* File: x86/OP_IPUT_BOOLEAN.S */ 2584/* File: x86/OP_IPUT.S */ 2585 2586 /* 2587 * General 32-bit instance field put. 2588 * 2589 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2590 */ 2591 /* op vA, vB, field@CCCC */ 2592 movl rGLUE,%ecx 2593 movzwl 2(rPC),%edx # %edx<- 0000CCCC 2594 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2595 movzbl rINSTbl,%ecx # ecx<- BA 2596 sarl $4,%ecx # ecx<- B 2597 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2598 andb $0xf,rINSTbl # rINST<- A 2599 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2600 movl (%eax,%edx,4),%eax # resolved entry 2601 testl %eax,%eax # is resolved entry null? 2602 jne .LOP_IPUT_BOOLEAN_finish # no, already resolved 2603 movl %edx,OUT_ARG1(%esp) 2604 movl rGLUE,%edx 2605 jmp .LOP_IPUT_BOOLEAN_resolve 2606 2607 2608/* ------------------------------ */ 2609 .balign 64 2610.L_OP_IPUT_BYTE: /* 0x5d */ 2611/* File: x86/OP_IPUT_BYTE.S */ 2612/* File: x86/OP_IPUT.S */ 2613 2614 /* 2615 * General 32-bit instance field put. 2616 * 2617 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2618 */ 2619 /* op vA, vB, field@CCCC */ 2620 movl rGLUE,%ecx 2621 movzwl 2(rPC),%edx # %edx<- 0000CCCC 2622 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2623 movzbl rINSTbl,%ecx # ecx<- BA 2624 sarl $4,%ecx # ecx<- B 2625 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2626 andb $0xf,rINSTbl # rINST<- A 2627 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2628 movl (%eax,%edx,4),%eax # resolved entry 2629 testl %eax,%eax # is resolved entry null? 2630 jne .LOP_IPUT_BYTE_finish # no, already resolved 2631 movl %edx,OUT_ARG1(%esp) 2632 movl rGLUE,%edx 2633 jmp .LOP_IPUT_BYTE_resolve 2634 2635 2636/* ------------------------------ */ 2637 .balign 64 2638.L_OP_IPUT_CHAR: /* 0x5e */ 2639/* File: x86/OP_IPUT_CHAR.S */ 2640/* File: x86/OP_IPUT.S */ 2641 2642 /* 2643 * General 32-bit instance field put. 2644 * 2645 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2646 */ 2647 /* op vA, vB, field@CCCC */ 2648 movl rGLUE,%ecx 2649 movzwl 2(rPC),%edx # %edx<- 0000CCCC 2650 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2651 movzbl rINSTbl,%ecx # ecx<- BA 2652 sarl $4,%ecx # ecx<- B 2653 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2654 andb $0xf,rINSTbl # rINST<- A 2655 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2656 movl (%eax,%edx,4),%eax # resolved entry 2657 testl %eax,%eax # is resolved entry null? 2658 jne .LOP_IPUT_CHAR_finish # no, already resolved 2659 movl %edx,OUT_ARG1(%esp) 2660 movl rGLUE,%edx 2661 jmp .LOP_IPUT_CHAR_resolve 2662 2663 2664/* ------------------------------ */ 2665 .balign 64 2666.L_OP_IPUT_SHORT: /* 0x5f */ 2667/* File: x86/OP_IPUT_SHORT.S */ 2668/* File: x86/OP_IPUT.S */ 2669 2670 /* 2671 * General 32-bit instance field put. 2672 * 2673 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2674 */ 2675 /* op vA, vB, field@CCCC */ 2676 movl rGLUE,%ecx 2677 movzwl 2(rPC),%edx # %edx<- 0000CCCC 2678 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2679 movzbl rINSTbl,%ecx # ecx<- BA 2680 sarl $4,%ecx # ecx<- B 2681 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2682 andb $0xf,rINSTbl # rINST<- A 2683 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2684 movl (%eax,%edx,4),%eax # resolved entry 2685 testl %eax,%eax # is resolved entry null? 2686 jne .LOP_IPUT_SHORT_finish # no, already resolved 2687 movl %edx,OUT_ARG1(%esp) 2688 movl rGLUE,%edx 2689 jmp .LOP_IPUT_SHORT_resolve 2690 2691 2692/* ------------------------------ */ 2693 .balign 64 2694.L_OP_SGET: /* 0x60 */ 2695/* File: x86/OP_SGET.S */ 2696 /* 2697 * General 32-bit SGET handler. 2698 * 2699 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2700 */ 2701 /* op vAA, field@BBBB */ 2702 movl rGLUE,%ecx 2703 movzwl 2(rPC),%eax # eax<- field ref BBBB 2704 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2705 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2706 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2707 testl %eax,%eax # resolved entry null? 2708 je .LOP_SGET_resolve # if not, make it so 2709.LOP_SGET_finish: # field ptr in eax 2710 movl offStaticField_value(%eax),%eax 2711 FETCH_INST_OPCODE 2 %edx 2712 ADVANCE_PC 2 2713 SET_VREG %eax rINST 2714 GOTO_NEXT_R %edx 2715 2716/* ------------------------------ */ 2717 .balign 64 2718.L_OP_SGET_WIDE: /* 0x61 */ 2719/* File: x86/OP_SGET_WIDE.S */ 2720 /* 2721 * 64-bit SGET handler. 2722 * 2723 */ 2724 /* sget-wide vAA, field@BBBB */ 2725 movl rGLUE,%ecx 2726 movzwl 2(rPC),%eax # eax<- field ref BBBB 2727 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2728 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2729 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2730 testl %eax,%eax # resolved entry null? 2731 je .LOP_SGET_WIDE_resolve # if not, make it so 2732.LOP_SGET_WIDE_finish: # field ptr in eax 2733 movl offStaticField_value(%eax),%ecx # ecx<- lsw 2734 movl 4+offStaticField_value(%eax),%eax # eax<- msw 2735 FETCH_INST_OPCODE 2 %edx 2736 ADVANCE_PC 2 2737 SET_VREG_WORD %ecx rINST 0 2738 SET_VREG_WORD %eax rINST 1 2739 GOTO_NEXT_R %edx 2740 2741/* ------------------------------ */ 2742 .balign 64 2743.L_OP_SGET_OBJECT: /* 0x62 */ 2744/* File: x86/OP_SGET_OBJECT.S */ 2745/* File: x86/OP_SGET.S */ 2746 /* 2747 * General 32-bit SGET handler. 2748 * 2749 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2750 */ 2751 /* op vAA, field@BBBB */ 2752 movl rGLUE,%ecx 2753 movzwl 2(rPC),%eax # eax<- field ref BBBB 2754 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2755 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2756 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2757 testl %eax,%eax # resolved entry null? 2758 je .LOP_SGET_OBJECT_resolve # if not, make it so 2759.LOP_SGET_OBJECT_finish: # field ptr in eax 2760 movl offStaticField_value(%eax),%eax 2761 FETCH_INST_OPCODE 2 %edx 2762 ADVANCE_PC 2 2763 SET_VREG %eax rINST 2764 GOTO_NEXT_R %edx 2765 2766 2767/* ------------------------------ */ 2768 .balign 64 2769.L_OP_SGET_BOOLEAN: /* 0x63 */ 2770/* File: x86/OP_SGET_BOOLEAN.S */ 2771/* File: x86/OP_SGET.S */ 2772 /* 2773 * General 32-bit SGET handler. 2774 * 2775 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2776 */ 2777 /* op vAA, field@BBBB */ 2778 movl rGLUE,%ecx 2779 movzwl 2(rPC),%eax # eax<- field ref BBBB 2780 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2781 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2782 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2783 testl %eax,%eax # resolved entry null? 2784 je .LOP_SGET_BOOLEAN_resolve # if not, make it so 2785.LOP_SGET_BOOLEAN_finish: # field ptr in eax 2786 movl offStaticField_value(%eax),%eax 2787 FETCH_INST_OPCODE 2 %edx 2788 ADVANCE_PC 2 2789 SET_VREG %eax rINST 2790 GOTO_NEXT_R %edx 2791 2792 2793/* ------------------------------ */ 2794 .balign 64 2795.L_OP_SGET_BYTE: /* 0x64 */ 2796/* File: x86/OP_SGET_BYTE.S */ 2797/* File: x86/OP_SGET.S */ 2798 /* 2799 * General 32-bit SGET handler. 2800 * 2801 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2802 */ 2803 /* op vAA, field@BBBB */ 2804 movl rGLUE,%ecx 2805 movzwl 2(rPC),%eax # eax<- field ref BBBB 2806 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2807 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2808 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2809 testl %eax,%eax # resolved entry null? 2810 je .LOP_SGET_BYTE_resolve # if not, make it so 2811.LOP_SGET_BYTE_finish: # field ptr in eax 2812 movl offStaticField_value(%eax),%eax 2813 FETCH_INST_OPCODE 2 %edx 2814 ADVANCE_PC 2 2815 SET_VREG %eax rINST 2816 GOTO_NEXT_R %edx 2817 2818 2819/* ------------------------------ */ 2820 .balign 64 2821.L_OP_SGET_CHAR: /* 0x65 */ 2822/* File: x86/OP_SGET_CHAR.S */ 2823/* File: x86/OP_SGET.S */ 2824 /* 2825 * General 32-bit SGET handler. 2826 * 2827 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2828 */ 2829 /* op vAA, field@BBBB */ 2830 movl rGLUE,%ecx 2831 movzwl 2(rPC),%eax # eax<- field ref BBBB 2832 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2833 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2834 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2835 testl %eax,%eax # resolved entry null? 2836 je .LOP_SGET_CHAR_resolve # if not, make it so 2837.LOP_SGET_CHAR_finish: # field ptr in eax 2838 movl offStaticField_value(%eax),%eax 2839 FETCH_INST_OPCODE 2 %edx 2840 ADVANCE_PC 2 2841 SET_VREG %eax rINST 2842 GOTO_NEXT_R %edx 2843 2844 2845/* ------------------------------ */ 2846 .balign 64 2847.L_OP_SGET_SHORT: /* 0x66 */ 2848/* File: x86/OP_SGET_SHORT.S */ 2849/* File: x86/OP_SGET.S */ 2850 /* 2851 * General 32-bit SGET handler. 2852 * 2853 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2854 */ 2855 /* op vAA, field@BBBB */ 2856 movl rGLUE,%ecx 2857 movzwl 2(rPC),%eax # eax<- field ref BBBB 2858 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2859 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2860 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2861 testl %eax,%eax # resolved entry null? 2862 je .LOP_SGET_SHORT_resolve # if not, make it so 2863.LOP_SGET_SHORT_finish: # field ptr in eax 2864 movl offStaticField_value(%eax),%eax 2865 FETCH_INST_OPCODE 2 %edx 2866 ADVANCE_PC 2 2867 SET_VREG %eax rINST 2868 GOTO_NEXT_R %edx 2869 2870 2871/* ------------------------------ */ 2872 .balign 64 2873.L_OP_SPUT: /* 0x67 */ 2874/* File: x86/OP_SPUT.S */ 2875 /* 2876 * General 32-bit SPUT handler. 2877 * 2878 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2879 */ 2880 /* op vAA, field@BBBB */ 2881 movl rGLUE,%ecx 2882 movzwl 2(rPC),%eax # eax<- field ref BBBB 2883 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2884 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2885 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2886 testl %eax,%eax # resolved entry null? 2887 je .LOP_SPUT_resolve # if not, make it so 2888.LOP_SPUT_finish: # field ptr in eax 2889 GET_VREG_R %ecx rINST 2890 FETCH_INST_OPCODE 2 %edx 2891 ADVANCE_PC 2 2892 movl %ecx,offStaticField_value(%eax) 2893 GOTO_NEXT_R %edx 2894 2895/* ------------------------------ */ 2896 .balign 64 2897.L_OP_SPUT_WIDE: /* 0x68 */ 2898/* File: x86/OP_SPUT_WIDE.S */ 2899 /* 2900 * General 32-bit SPUT handler. 2901 * 2902 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2903 */ 2904 /* op vAA, field@BBBB */ 2905 movl rGLUE,%ecx 2906 movzwl 2(rPC),%eax # eax<- field ref BBBB 2907 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2908 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2909 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2910 testl %eax,%eax # resolved entry null? 2911 je .LOP_SPUT_WIDE_resolve # if not, make it so 2912.LOP_SPUT_WIDE_finish: # field ptr in eax 2913 GET_VREG_WORD %ecx rINST 0 # rINST<- lsw 2914 GET_VREG_WORD rINST rINST 1 # ecx<- msw 2915 FETCH_INST_OPCODE 2 %edx 2916 ADVANCE_PC 2 2917 movl %ecx,offStaticField_value(%eax) 2918 movl rINST,4+offStaticField_value(%eax) 2919 GOTO_NEXT_R %edx 2920 2921/* ------------------------------ */ 2922 .balign 64 2923.L_OP_SPUT_OBJECT: /* 0x69 */ 2924/* File: x86/OP_SPUT_OBJECT.S */ 2925 /* 2926 * SPUT object handler. 2927 */ 2928 /* op vAA, field@BBBB */ 2929 movl rGLUE,%ecx 2930 movzwl 2(rPC),%eax # eax<- field ref BBBB 2931 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2932 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2933 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField 2934 testl %eax,%eax # resolved entry null? 2935 je .LOP_SPUT_OBJECT_resolve # if not, make it so 2936.LOP_SPUT_OBJECT_finish: # field ptr in eax 2937 movzbl rINSTbl,%ecx # ecx<- AA 2938 GET_VREG_R %ecx %ecx 2939 jmp .LOP_SPUT_OBJECT_continue 2940 2941/* ------------------------------ */ 2942 .balign 64 2943.L_OP_SPUT_BOOLEAN: /* 0x6a */ 2944/* File: x86/OP_SPUT_BOOLEAN.S */ 2945/* File: x86/OP_SPUT.S */ 2946 /* 2947 * General 32-bit SPUT handler. 2948 * 2949 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2950 */ 2951 /* op vAA, field@BBBB */ 2952 movl rGLUE,%ecx 2953 movzwl 2(rPC),%eax # eax<- field ref BBBB 2954 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2955 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2956 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2957 testl %eax,%eax # resolved entry null? 2958 je .LOP_SPUT_BOOLEAN_resolve # if not, make it so 2959.LOP_SPUT_BOOLEAN_finish: # field ptr in eax 2960 GET_VREG_R %ecx rINST 2961 FETCH_INST_OPCODE 2 %edx 2962 ADVANCE_PC 2 2963 movl %ecx,offStaticField_value(%eax) 2964 GOTO_NEXT_R %edx 2965 2966 2967/* ------------------------------ */ 2968 .balign 64 2969.L_OP_SPUT_BYTE: /* 0x6b */ 2970/* File: x86/OP_SPUT_BYTE.S */ 2971/* File: x86/OP_SPUT.S */ 2972 /* 2973 * General 32-bit SPUT handler. 2974 * 2975 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2976 */ 2977 /* op vAA, field@BBBB */ 2978 movl rGLUE,%ecx 2979 movzwl 2(rPC),%eax # eax<- field ref BBBB 2980 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2981 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2982 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2983 testl %eax,%eax # resolved entry null? 2984 je .LOP_SPUT_BYTE_resolve # if not, make it so 2985.LOP_SPUT_BYTE_finish: # field ptr in eax 2986 GET_VREG_R %ecx rINST 2987 FETCH_INST_OPCODE 2 %edx 2988 ADVANCE_PC 2 2989 movl %ecx,offStaticField_value(%eax) 2990 GOTO_NEXT_R %edx 2991 2992 2993/* ------------------------------ */ 2994 .balign 64 2995.L_OP_SPUT_CHAR: /* 0x6c */ 2996/* File: x86/OP_SPUT_CHAR.S */ 2997/* File: x86/OP_SPUT.S */ 2998 /* 2999 * General 32-bit SPUT handler. 3000 * 3001 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3002 */ 3003 /* op vAA, field@BBBB */ 3004 movl rGLUE,%ecx 3005 movzwl 2(rPC),%eax # eax<- field ref BBBB 3006 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 3007 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 3008 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 3009 testl %eax,%eax # resolved entry null? 3010 je .LOP_SPUT_CHAR_resolve # if not, make it so 3011.LOP_SPUT_CHAR_finish: # field ptr in eax 3012 GET_VREG_R %ecx rINST 3013 FETCH_INST_OPCODE 2 %edx 3014 ADVANCE_PC 2 3015 movl %ecx,offStaticField_value(%eax) 3016 GOTO_NEXT_R %edx 3017 3018 3019/* ------------------------------ */ 3020 .balign 64 3021.L_OP_SPUT_SHORT: /* 0x6d */ 3022/* File: x86/OP_SPUT_SHORT.S */ 3023/* File: x86/OP_SPUT.S */ 3024 /* 3025 * General 32-bit SPUT handler. 3026 * 3027 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 3028 */ 3029 /* op vAA, field@BBBB */ 3030 movl rGLUE,%ecx 3031 movzwl 2(rPC),%eax # eax<- field ref BBBB 3032 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 3033 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 3034 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 3035 testl %eax,%eax # resolved entry null? 3036 je .LOP_SPUT_SHORT_resolve # if not, make it so 3037.LOP_SPUT_SHORT_finish: # field ptr in eax 3038 GET_VREG_R %ecx rINST 3039 FETCH_INST_OPCODE 2 %edx 3040 ADVANCE_PC 2 3041 movl %ecx,offStaticField_value(%eax) 3042 GOTO_NEXT_R %edx 3043 3044 3045/* ------------------------------ */ 3046 .balign 64 3047.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3048/* File: x86/OP_INVOKE_VIRTUAL.S */ 3049 3050 /* 3051 * Handle a virtual method call. 3052 * 3053 * for: invoke-virtual, invoke-virtual/range 3054 */ 3055 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3056 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3057 movl rGLUE,%eax 3058 movzwl 2(rPC),%ecx # ecx<- BBBB 3059 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex 3060 EXPORT_PC 3061 movl offDvmDex_pResMethods(%eax),%eax # eax<- pDvmDex->pResMethods 3062 movl (%eax,%ecx,4),%eax # eax<- resolved baseMethod 3063 testl %eax,%eax # already resolved? 3064 jne .LOP_INVOKE_VIRTUAL_continue # yes, continue 3065 movl rGLUE,%eax 3066 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 3067 movl offGlue_method(%eax),%eax # eax<- glue->method 3068 jmp .LOP_INVOKE_VIRTUAL_more 3069 3070/* ------------------------------ */ 3071 .balign 64 3072.L_OP_INVOKE_SUPER: /* 0x6f */ 3073/* File: x86/OP_INVOKE_SUPER.S */ 3074 /* 3075 * Handle a "super" method call. 3076 * 3077 * for: invoke-super, invoke-super/range 3078 */ 3079 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3080 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3081 movl rGLUE,rINST 3082 movzwl 2(rPC),%eax # eax<- BBBB 3083 movl offGlue_methodClassDex(rINST),%ecx # ecx<- pDvmDex 3084 EXPORT_PC 3085 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 3086 movl (%ecx,%eax,4),%ecx # ecx<- resolved baseMethod 3087 movl offGlue_method(rINST),%eax # eax<- method 3088 movzwl 4(rPC),rINST # rINST<- GFED or CCCC 3089 .if (!0) 3090 andl $0xf,rINST # rINST<- D (or stays CCCC) 3091 .endif 3092 GET_VREG_R rINST rINST # rINST<- "this" ptr 3093 testl rINST,rINST # null "this"? 3094 je common_errNullObject # yes, throw 3095 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 3096 testl %ecx,%ecx # already resolved? 3097 jne .LOP_INVOKE_SUPER_continue # yes - go on 3098 jmp .LOP_INVOKE_SUPER_resolve 3099 3100/* ------------------------------ */ 3101 .balign 64 3102.L_OP_INVOKE_DIRECT: /* 0x70 */ 3103/* File: x86/OP_INVOKE_DIRECT.S */ 3104 /* 3105 * Handle a direct method call. 3106 * 3107 * (We could defer the "is 'this' pointer null" test to the common 3108 * method invocation code, and use a flag to indicate that static 3109 * calls don't count. If we do this as part of copying the arguments 3110 * out we could avoiding loading the first arg twice.) 3111 * 3112 * for: invoke-direct, invoke-direct/range 3113 */ 3114 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3115 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3116 movl rGLUE,%ecx 3117 movzwl 2(rPC),%eax # eax<- BBBB 3118 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 3119 EXPORT_PC 3120 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 3121 movzwl 4(rPC),%edx # edx<- GFED or CCCC 3122 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall 3123 .if (!0) 3124 andl $0xf,%edx # edx<- D (or stays CCCC) 3125 .endif 3126 testl %eax,%eax # already resolved? 3127 GET_VREG_R %ecx %edx # ecx<- "this" ptr 3128 je .LOP_INVOKE_DIRECT_resolve # not resolved, do it now 3129.LOP_INVOKE_DIRECT_finish: 3130 testl %ecx,%ecx # null "this"? 3131 jne common_invokeMethodNoRange # no, continue on 3132 jmp common_errNullObject 3133 3134/* ------------------------------ */ 3135 .balign 64 3136.L_OP_INVOKE_STATIC: /* 0x71 */ 3137/* File: x86/OP_INVOKE_STATIC.S */ 3138 /* 3139 * Handle a static method call. 3140 * 3141 * for: invoke-static, invoke-static/range 3142 */ 3143 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3144 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3145 movl rGLUE,%ecx 3146 movzwl 2(rPC),%eax # eax<- BBBB 3147 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 3148 EXPORT_PC 3149 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 3150 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall 3151 testl %eax,%eax 3152 jne common_invokeMethodNoRange 3153 movl rGLUE,%ecx 3154 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 3155 movzwl 2(rPC),%eax 3156 movl offMethod_clazz(%ecx),%ecx# ecx<- method->clazz 3157 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 3158 movl %ecx,OUT_ARG0(%esp) # arg0<- clazz 3159 jmp .LOP_INVOKE_STATIC_continue 3160 3161/* ------------------------------ */ 3162 .balign 64 3163.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3164/* File: x86/OP_INVOKE_INTERFACE.S */ 3165 /* 3166 * Handle an interface method call. 3167 * 3168 * for: invoke-interface, invoke-interface/range 3169 */ 3170 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3171 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3172 movzwl 4(rPC),%eax # eax<- FEDC or CCCC 3173 movl rGLUE,%ecx 3174 .if (!0) 3175 andl $0xf,%eax # eax<- C (or stays CCCC) 3176 .endif 3177 GET_VREG_R %eax %eax # eax<- "this" 3178 EXPORT_PC 3179 testl %eax,%eax # null this? 3180 je common_errNullObject # yes, fail 3181 movl offObject_clazz(%eax),%eax# eax<- thisPtr->clazz 3182 movl %eax,OUT_ARG0(%esp) # arg0<- class 3183 movl offGlue_methodClassDex(%ecx),%eax # eax<- methodClassDex 3184 movl offGlue_method(%ecx),%ecx # ecx<- method 3185 movl %eax,OUT_ARG3(%esp) # arg3<- dex 3186 movzwl 2(rPC),%eax # eax<- BBBB 3187 movl %ecx,OUT_ARG2(%esp) # arg2<- method 3188 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 3189 jmp .LOP_INVOKE_INTERFACE_continue 3190 3191/* ------------------------------ */ 3192 .balign 64 3193.L_OP_UNUSED_73: /* 0x73 */ 3194/* File: x86/OP_UNUSED_73.S */ 3195/* File: x86/unused.S */ 3196 jmp common_abort 3197 3198 3199/* ------------------------------ */ 3200 .balign 64 3201.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3202/* File: x86/OP_INVOKE_VIRTUAL_RANGE.S */ 3203/* File: x86/OP_INVOKE_VIRTUAL.S */ 3204 3205 /* 3206 * Handle a virtual method call. 3207 * 3208 * for: invoke-virtual, invoke-virtual/range 3209 */ 3210 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3211 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3212 movl rGLUE,%eax 3213 movzwl 2(rPC),%ecx # ecx<- BBBB 3214 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex 3215 EXPORT_PC 3216 movl offDvmDex_pResMethods(%eax),%eax # eax<- pDvmDex->pResMethods 3217 movl (%eax,%ecx,4),%eax # eax<- resolved baseMethod 3218 testl %eax,%eax # already resolved? 3219 jne .LOP_INVOKE_VIRTUAL_RANGE_continue # yes, continue 3220 movl rGLUE,%eax 3221 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 3222 movl offGlue_method(%eax),%eax # eax<- glue->method 3223 jmp .LOP_INVOKE_VIRTUAL_RANGE_more 3224 3225 3226/* ------------------------------ */ 3227 .balign 64 3228.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3229/* File: x86/OP_INVOKE_SUPER_RANGE.S */ 3230/* File: x86/OP_INVOKE_SUPER.S */ 3231 /* 3232 * Handle a "super" method call. 3233 * 3234 * for: invoke-super, invoke-super/range 3235 */ 3236 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3237 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3238 movl rGLUE,rINST 3239 movzwl 2(rPC),%eax # eax<- BBBB 3240 movl offGlue_methodClassDex(rINST),%ecx # ecx<- pDvmDex 3241 EXPORT_PC 3242 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 3243 movl (%ecx,%eax,4),%ecx # ecx<- resolved baseMethod 3244 movl offGlue_method(rINST),%eax # eax<- method 3245 movzwl 4(rPC),rINST # rINST<- GFED or CCCC 3246 .if (!1) 3247 andl $0xf,rINST # rINST<- D (or stays CCCC) 3248 .endif 3249 GET_VREG_R rINST rINST # rINST<- "this" ptr 3250 testl rINST,rINST # null "this"? 3251 je common_errNullObject # yes, throw 3252 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 3253 testl %ecx,%ecx # already resolved? 3254 jne .LOP_INVOKE_SUPER_RANGE_continue # yes - go on 3255 jmp .LOP_INVOKE_SUPER_RANGE_resolve 3256 3257 3258/* ------------------------------ */ 3259 .balign 64 3260.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3261/* File: x86/OP_INVOKE_DIRECT_RANGE.S */ 3262/* File: x86/OP_INVOKE_DIRECT.S */ 3263 /* 3264 * Handle a direct method call. 3265 * 3266 * (We could defer the "is 'this' pointer null" test to the common 3267 * method invocation code, and use a flag to indicate that static 3268 * calls don't count. If we do this as part of copying the arguments 3269 * out we could avoiding loading the first arg twice.) 3270 * 3271 * for: invoke-direct, invoke-direct/range 3272 */ 3273 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3274 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3275 movl rGLUE,%ecx 3276 movzwl 2(rPC),%eax # eax<- BBBB 3277 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 3278 EXPORT_PC 3279 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 3280 movzwl 4(rPC),%edx # edx<- GFED or CCCC 3281 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall 3282 .if (!1) 3283 andl $0xf,%edx # edx<- D (or stays CCCC) 3284 .endif 3285 testl %eax,%eax # already resolved? 3286 GET_VREG_R %ecx %edx # ecx<- "this" ptr 3287 je .LOP_INVOKE_DIRECT_RANGE_resolve # not resolved, do it now 3288.LOP_INVOKE_DIRECT_RANGE_finish: 3289 testl %ecx,%ecx # null "this"? 3290 jne common_invokeMethodRange # no, continue on 3291 jmp common_errNullObject 3292 3293 3294/* ------------------------------ */ 3295 .balign 64 3296.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3297/* File: x86/OP_INVOKE_STATIC_RANGE.S */ 3298/* File: x86/OP_INVOKE_STATIC.S */ 3299 /* 3300 * Handle a static method call. 3301 * 3302 * for: invoke-static, invoke-static/range 3303 */ 3304 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3305 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3306 movl rGLUE,%ecx 3307 movzwl 2(rPC),%eax # eax<- BBBB 3308 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 3309 EXPORT_PC 3310 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 3311 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall 3312 testl %eax,%eax 3313 jne common_invokeMethodRange 3314 movl rGLUE,%ecx 3315 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 3316 movzwl 2(rPC),%eax 3317 movl offMethod_clazz(%ecx),%ecx# ecx<- method->clazz 3318 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 3319 movl %ecx,OUT_ARG0(%esp) # arg0<- clazz 3320 jmp .LOP_INVOKE_STATIC_RANGE_continue 3321 3322 3323/* ------------------------------ */ 3324 .balign 64 3325.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3326/* File: x86/OP_INVOKE_INTERFACE_RANGE.S */ 3327/* File: x86/OP_INVOKE_INTERFACE.S */ 3328 /* 3329 * Handle an interface method call. 3330 * 3331 * for: invoke-interface, invoke-interface/range 3332 */ 3333 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3334 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3335 movzwl 4(rPC),%eax # eax<- FEDC or CCCC 3336 movl rGLUE,%ecx 3337 .if (!1) 3338 andl $0xf,%eax # eax<- C (or stays CCCC) 3339 .endif 3340 GET_VREG_R %eax %eax # eax<- "this" 3341 EXPORT_PC 3342 testl %eax,%eax # null this? 3343 je common_errNullObject # yes, fail 3344 movl offObject_clazz(%eax),%eax# eax<- thisPtr->clazz 3345 movl %eax,OUT_ARG0(%esp) # arg0<- class 3346 movl offGlue_methodClassDex(%ecx),%eax # eax<- methodClassDex 3347 movl offGlue_method(%ecx),%ecx # ecx<- method 3348 movl %eax,OUT_ARG3(%esp) # arg3<- dex 3349 movzwl 2(rPC),%eax # eax<- BBBB 3350 movl %ecx,OUT_ARG2(%esp) # arg2<- method 3351 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 3352 jmp .LOP_INVOKE_INTERFACE_RANGE_continue 3353 3354 3355/* ------------------------------ */ 3356 .balign 64 3357.L_OP_UNUSED_79: /* 0x79 */ 3358/* File: x86/OP_UNUSED_79.S */ 3359/* File: x86/unused.S */ 3360 jmp common_abort 3361 3362 3363/* ------------------------------ */ 3364 .balign 64 3365.L_OP_UNUSED_7A: /* 0x7a */ 3366/* File: x86/OP_UNUSED_7A.S */ 3367/* File: x86/unused.S */ 3368 jmp common_abort 3369 3370 3371/* ------------------------------ */ 3372 .balign 64 3373.L_OP_NEG_INT: /* 0x7b */ 3374/* File: x86/OP_NEG_INT.S */ 3375/* File: x86/unop.S */ 3376 /* 3377 * Generic 32-bit unary operation. Provide an "instr" line that 3378 * specifies an instruction that performs "result = op eax". 3379 */ 3380 /* unop vA, vB */ 3381 movzbl rINSTbl,%ecx # ecx<- A+ 3382 sarl $4,rINST # rINST<- B 3383 GET_VREG_R %eax rINST # eax<- vB 3384 andb $0xf,%cl # ecx<- A 3385 FETCH_INST_OPCODE 1 %edx 3386 ADVANCE_PC 1 3387 3388 3389 negl %eax 3390 SET_VREG %eax %ecx 3391 GOTO_NEXT_R %edx 3392 3393 3394/* ------------------------------ */ 3395 .balign 64 3396.L_OP_NOT_INT: /* 0x7c */ 3397/* File: x86/OP_NOT_INT.S */ 3398/* File: x86/unop.S */ 3399 /* 3400 * Generic 32-bit unary operation. Provide an "instr" line that 3401 * specifies an instruction that performs "result = op eax". 3402 */ 3403 /* unop vA, vB */ 3404 movzbl rINSTbl,%ecx # ecx<- A+ 3405 sarl $4,rINST # rINST<- B 3406 GET_VREG_R %eax rINST # eax<- vB 3407 andb $0xf,%cl # ecx<- A 3408 FETCH_INST_OPCODE 1 %edx 3409 ADVANCE_PC 1 3410 3411 3412 notl %eax 3413 SET_VREG %eax %ecx 3414 GOTO_NEXT_R %edx 3415 3416 3417/* ------------------------------ */ 3418 .balign 64 3419.L_OP_NEG_LONG: /* 0x7d */ 3420/* File: x86/OP_NEG_LONG.S */ 3421 /* unop vA, vB */ 3422 movzbl rINSTbl,%ecx # ecx<- BA 3423 sarl $4,%ecx # ecx<- B 3424 andb $0xf,rINSTbl # rINST<- A 3425 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0] 3426 GET_VREG_WORD %ecx %ecx 1 # ecx<- v[B+1] 3427 negl %eax 3428 adcl $0,%ecx 3429 negl %ecx 3430 FETCH_INST_OPCODE 1 %edx 3431 SET_VREG_WORD %eax rINST 0 # v[A+0]<- eax 3432 SET_VREG_WORD %ecx rINST 1 # v[A+1]<- ecx 3433 ADVANCE_PC 1 3434 GOTO_NEXT_R %edx 3435 3436/* ------------------------------ */ 3437 .balign 64 3438.L_OP_NOT_LONG: /* 0x7e */ 3439/* File: x86/OP_NOT_LONG.S */ 3440 /* unop vA, vB */ 3441 movzbl rINSTbl,%ecx # ecx<- BA 3442 sarl $4,%ecx # ecx<- B 3443 andb $0xf,rINSTbl # rINST<- A 3444 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0] 3445 GET_VREG_WORD %ecx %ecx 1 # ecx<- v[B+1] 3446 FETCH_INST_OPCODE 1 %edx 3447 notl %eax 3448 notl %ecx 3449 SET_VREG_WORD %eax rINST 0 # v[A+0]<- eax 3450 SET_VREG_WORD %ecx rINST 1 # v[A+1]<- ecx 3451 ADVANCE_PC 1 3452 GOTO_NEXT_R %edx 3453 3454/* ------------------------------ */ 3455 .balign 64 3456.L_OP_NEG_FLOAT: /* 0x7f */ 3457/* File: x86/OP_NEG_FLOAT.S */ 3458/* File: x86/fpcvt.S */ 3459 /* 3460 * Generic 32-bit FP conversion operation. 3461 */ 3462 /* unop vA, vB */ 3463 movzbl rINSTbl,%ecx # ecx<- A+ 3464 sarl $4,rINST # rINST<- B 3465 flds (rFP,rINST,4) # %st0<- vB 3466 andb $0xf,%cl # ecx<- A 3467 FETCH_INST_OPCODE 1 %edx 3468 ADVANCE_PC 1 3469 fchs 3470 fstps (rFP,%ecx,4) # vA<- %st0 3471 GOTO_NEXT_R %edx 3472 3473 3474/* ------------------------------ */ 3475 .balign 64 3476.L_OP_NEG_DOUBLE: /* 0x80 */ 3477/* File: x86/OP_NEG_DOUBLE.S */ 3478/* File: x86/fpcvt.S */ 3479 /* 3480 * Generic 32-bit FP conversion operation. 3481 */ 3482 /* unop vA, vB */ 3483 movzbl rINSTbl,%ecx # ecx<- A+ 3484 sarl $4,rINST # rINST<- B 3485 fldl (rFP,rINST,4) # %st0<- vB 3486 andb $0xf,%cl # ecx<- A 3487 FETCH_INST_OPCODE 1 %edx 3488 ADVANCE_PC 1 3489 fchs 3490 fstpl (rFP,%ecx,4) # vA<- %st0 3491 GOTO_NEXT_R %edx 3492 3493 3494/* ------------------------------ */ 3495 .balign 64 3496.L_OP_INT_TO_LONG: /* 0x81 */ 3497/* File: x86/OP_INT_TO_LONG.S */ 3498 /* int to long vA, vB */ 3499 movzbl rINSTbl,%eax # eax<- +A 3500 sarl $4,%eax # eax<- B 3501 GET_VREG_R %eax %eax # eax<- vB 3502 andb $0xf,rINSTbl # rINST<- A 3503 cltd # edx:eax<- sssssssBBBBBBBB 3504 SET_VREG_WORD %edx rINST 1 # v[A+1]<- edx/rPC 3505 FETCH_INST_OPCODE 1 %edx 3506 SET_VREG_WORD %eax rINST 0 # v[A+0]<- %eax 3507 ADVANCE_PC 1 3508 GOTO_NEXT_R %edx 3509 3510/* ------------------------------ */ 3511 .balign 64 3512.L_OP_INT_TO_FLOAT: /* 0x82 */ 3513/* File: x86/OP_INT_TO_FLOAT.S */ 3514/* File: x86/fpcvt.S */ 3515 /* 3516 * Generic 32-bit FP conversion operation. 3517 */ 3518 /* unop vA, vB */ 3519 movzbl rINSTbl,%ecx # ecx<- A+ 3520 sarl $4,rINST # rINST<- B 3521 fildl (rFP,rINST,4) # %st0<- vB 3522 andb $0xf,%cl # ecx<- A 3523 FETCH_INST_OPCODE 1 %edx 3524 ADVANCE_PC 1 3525 3526 fstps (rFP,%ecx,4) # vA<- %st0 3527 GOTO_NEXT_R %edx 3528 3529 3530/* ------------------------------ */ 3531 .balign 64 3532.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3533/* File: x86/OP_INT_TO_DOUBLE.S */ 3534/* File: x86/fpcvt.S */ 3535 /* 3536 * Generic 32-bit FP conversion operation. 3537 */ 3538 /* unop vA, vB */ 3539 movzbl rINSTbl,%ecx # ecx<- A+ 3540 sarl $4,rINST # rINST<- B 3541 fildl (rFP,rINST,4) # %st0<- vB 3542 andb $0xf,%cl # ecx<- A 3543 FETCH_INST_OPCODE 1 %edx 3544 ADVANCE_PC 1 3545 3546 fstpl (rFP,%ecx,4) # vA<- %st0 3547 GOTO_NEXT_R %edx 3548 3549 3550/* ------------------------------ */ 3551 .balign 64 3552.L_OP_LONG_TO_INT: /* 0x84 */ 3553/* File: x86/OP_LONG_TO_INT.S */ 3554/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3555/* File: x86/OP_MOVE.S */ 3556 /* for move, move-object, long-to-int */ 3557 /* op vA, vB */ 3558 movzbl rINSTbl,%eax # eax<- BA 3559 andb $0xf,%al # eax<- A 3560 shrl $4,rINST # rINST<- B 3561 GET_VREG_R %ecx rINST 3562 FETCH_INST_OPCODE 1 %edx 3563 ADVANCE_PC 1 3564 SET_VREG %ecx %eax # fp[A]<-fp[B] 3565 GOTO_NEXT_R %edx 3566 3567 3568/* ------------------------------ */ 3569 .balign 64 3570.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3571/* File: x86/OP_LONG_TO_FLOAT.S */ 3572/* File: x86/fpcvt.S */ 3573 /* 3574 * Generic 32-bit FP conversion operation. 3575 */ 3576 /* unop vA, vB */ 3577 movzbl rINSTbl,%ecx # ecx<- A+ 3578 sarl $4,rINST # rINST<- B 3579 fildll (rFP,rINST,4) # %st0<- vB 3580 andb $0xf,%cl # ecx<- A 3581 FETCH_INST_OPCODE 1 %edx 3582 ADVANCE_PC 1 3583 3584 fstps (rFP,%ecx,4) # vA<- %st0 3585 GOTO_NEXT_R %edx 3586 3587 3588/* ------------------------------ */ 3589 .balign 64 3590.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3591/* File: x86/OP_LONG_TO_DOUBLE.S */ 3592/* File: x86/fpcvt.S */ 3593 /* 3594 * Generic 32-bit FP conversion operation. 3595 */ 3596 /* unop vA, vB */ 3597 movzbl rINSTbl,%ecx # ecx<- A+ 3598 sarl $4,rINST # rINST<- B 3599 fildll (rFP,rINST,4) # %st0<- vB 3600 andb $0xf,%cl # ecx<- A 3601 FETCH_INST_OPCODE 1 %edx 3602 ADVANCE_PC 1 3603 3604 fstpl (rFP,%ecx,4) # vA<- %st0 3605 GOTO_NEXT_R %edx 3606 3607 3608/* ------------------------------ */ 3609 .balign 64 3610.L_OP_FLOAT_TO_INT: /* 0x87 */ 3611/* File: x86/OP_FLOAT_TO_INT.S */ 3612/* File: x86/cvtfp_int.S */ 3613/* On fp to int conversions, Java requires that 3614 * if the result > maxint, it should be clamped to maxint. If it is less 3615 * than minint, it should be clamped to minint. If it is a nan, the result 3616 * should be zero. Further, the rounding mode is to truncate. This model 3617 * differs from what is delivered normally via the x86 fpu, so we have 3618 * to play some games. 3619 */ 3620 /* float/double to int/long vA, vB */ 3621 movzbl rINSTbl,%ecx # ecx<- A+ 3622 sarl $4,rINST # rINST<- B 3623 .if 0 3624 fldl (rFP,rINST,4) # %st0<- vB 3625 .else 3626 flds (rFP,rINST,4) # %st0<- vB 3627 .endif 3628 ftst 3629 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode 3630 movzwl LOCAL0_OFFSET(%ebp),%eax 3631 movb $0xc,%ah 3632 movw %ax,LOCAL0_OFFSET+2(%ebp) 3633 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode 3634 FETCH_INST_OPCODE 1 %edx 3635 andb $0xf,%cl # ecx<- A 3636 .if 0 3637 fistpll (rFP,%ecx,4) # convert and store 3638 .else 3639 fistpl (rFP,%ecx,4) # convert and store 3640 .endif 3641 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode 3642 jmp .LOP_FLOAT_TO_INT_continue 3643 3644 3645/* ------------------------------ */ 3646 .balign 64 3647.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3648/* File: x86/OP_FLOAT_TO_LONG.S */ 3649/* File: x86/cvtfp_int.S */ 3650/* On fp to int conversions, Java requires that 3651 * if the result > maxint, it should be clamped to maxint. If it is less 3652 * than minint, it should be clamped to minint. If it is a nan, the result 3653 * should be zero. Further, the rounding mode is to truncate. This model 3654 * differs from what is delivered normally via the x86 fpu, so we have 3655 * to play some games. 3656 */ 3657 /* float/double to int/long vA, vB */ 3658 movzbl rINSTbl,%ecx # ecx<- A+ 3659 sarl $4,rINST # rINST<- B 3660 .if 0 3661 fldl (rFP,rINST,4) # %st0<- vB 3662 .else 3663 flds (rFP,rINST,4) # %st0<- vB 3664 .endif 3665 ftst 3666 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode 3667 movzwl LOCAL0_OFFSET(%ebp),%eax 3668 movb $0xc,%ah 3669 movw %ax,LOCAL0_OFFSET+2(%ebp) 3670 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode 3671 FETCH_INST_OPCODE 1 %edx 3672 andb $0xf,%cl # ecx<- A 3673 .if 1 3674 fistpll (rFP,%ecx,4) # convert and store 3675 .else 3676 fistpl (rFP,%ecx,4) # convert and store 3677 .endif 3678 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode 3679 jmp .LOP_FLOAT_TO_LONG_continue 3680 3681 3682/* ------------------------------ */ 3683 .balign 64 3684.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3685/* File: x86/OP_FLOAT_TO_DOUBLE.S */ 3686/* File: x86/fpcvt.S */ 3687 /* 3688 * Generic 32-bit FP conversion operation. 3689 */ 3690 /* unop vA, vB */ 3691 movzbl rINSTbl,%ecx # ecx<- A+ 3692 sarl $4,rINST # rINST<- B 3693 flds (rFP,rINST,4) # %st0<- vB 3694 andb $0xf,%cl # ecx<- A 3695 FETCH_INST_OPCODE 1 %edx 3696 ADVANCE_PC 1 3697 3698 fstpl (rFP,%ecx,4) # vA<- %st0 3699 GOTO_NEXT_R %edx 3700 3701 3702/* ------------------------------ */ 3703 .balign 64 3704.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3705/* File: x86/OP_DOUBLE_TO_INT.S */ 3706/* File: x86/cvtfp_int.S */ 3707/* On fp to int conversions, Java requires that 3708 * if the result > maxint, it should be clamped to maxint. If it is less 3709 * than minint, it should be clamped to minint. If it is a nan, the result 3710 * should be zero. Further, the rounding mode is to truncate. This model 3711 * differs from what is delivered normally via the x86 fpu, so we have 3712 * to play some games. 3713 */ 3714 /* float/double to int/long vA, vB */ 3715 movzbl rINSTbl,%ecx # ecx<- A+ 3716 sarl $4,rINST # rINST<- B 3717 .if 1 3718 fldl (rFP,rINST,4) # %st0<- vB 3719 .else 3720 flds (rFP,rINST,4) # %st0<- vB 3721 .endif 3722 ftst 3723 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode 3724 movzwl LOCAL0_OFFSET(%ebp),%eax 3725 movb $0xc,%ah 3726 movw %ax,LOCAL0_OFFSET+2(%ebp) 3727 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode 3728 FETCH_INST_OPCODE 1 %edx 3729 andb $0xf,%cl # ecx<- A 3730 .if 0 3731 fistpll (rFP,%ecx,4) # convert and store 3732 .else 3733 fistpl (rFP,%ecx,4) # convert and store 3734 .endif 3735 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode 3736 jmp .LOP_DOUBLE_TO_INT_continue 3737 3738 3739/* ------------------------------ */ 3740 .balign 64 3741.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3742/* File: x86/OP_DOUBLE_TO_LONG.S */ 3743/* File: x86/cvtfp_int.S */ 3744/* On fp to int conversions, Java requires that 3745 * if the result > maxint, it should be clamped to maxint. If it is less 3746 * than minint, it should be clamped to minint. If it is a nan, the result 3747 * should be zero. Further, the rounding mode is to truncate. This model 3748 * differs from what is delivered normally via the x86 fpu, so we have 3749 * to play some games. 3750 */ 3751 /* float/double to int/long vA, vB */ 3752 movzbl rINSTbl,%ecx # ecx<- A+ 3753 sarl $4,rINST # rINST<- B 3754 .if 1 3755 fldl (rFP,rINST,4) # %st0<- vB 3756 .else 3757 flds (rFP,rINST,4) # %st0<- vB 3758 .endif 3759 ftst 3760 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode 3761 movzwl LOCAL0_OFFSET(%ebp),%eax 3762 movb $0xc,%ah 3763 movw %ax,LOCAL0_OFFSET+2(%ebp) 3764 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode 3765 FETCH_INST_OPCODE 1 %edx 3766 andb $0xf,%cl # ecx<- A 3767 .if 1 3768 fistpll (rFP,%ecx,4) # convert and store 3769 .else 3770 fistpl (rFP,%ecx,4) # convert and store 3771 .endif 3772 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode 3773 jmp .LOP_DOUBLE_TO_LONG_continue 3774 3775 3776/* ------------------------------ */ 3777 .balign 64 3778.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3779/* File: x86/OP_DOUBLE_TO_FLOAT.S */ 3780/* File: x86/fpcvt.S */ 3781 /* 3782 * Generic 32-bit FP conversion operation. 3783 */ 3784 /* unop vA, vB */ 3785 movzbl rINSTbl,%ecx # ecx<- A+ 3786 sarl $4,rINST # rINST<- B 3787 fldl (rFP,rINST,4) # %st0<- vB 3788 andb $0xf,%cl # ecx<- A 3789 FETCH_INST_OPCODE 1 %edx 3790 ADVANCE_PC 1 3791 3792 fstps (rFP,%ecx,4) # vA<- %st0 3793 GOTO_NEXT_R %edx 3794 3795 3796/* ------------------------------ */ 3797 .balign 64 3798.L_OP_INT_TO_BYTE: /* 0x8d */ 3799/* File: x86/OP_INT_TO_BYTE.S */ 3800/* File: x86/unop.S */ 3801 /* 3802 * Generic 32-bit unary operation. Provide an "instr" line that 3803 * specifies an instruction that performs "result = op eax". 3804 */ 3805 /* unop vA, vB */ 3806 movzbl rINSTbl,%ecx # ecx<- A+ 3807 sarl $4,rINST # rINST<- B 3808 GET_VREG_R %eax rINST # eax<- vB 3809 andb $0xf,%cl # ecx<- A 3810 FETCH_INST_OPCODE 1 %edx 3811 ADVANCE_PC 1 3812 3813 3814 movsbl %al,%eax 3815 SET_VREG %eax %ecx 3816 GOTO_NEXT_R %edx 3817 3818 3819/* ------------------------------ */ 3820 .balign 64 3821.L_OP_INT_TO_CHAR: /* 0x8e */ 3822/* File: x86/OP_INT_TO_CHAR.S */ 3823/* File: x86/unop.S */ 3824 /* 3825 * Generic 32-bit unary operation. Provide an "instr" line that 3826 * specifies an instruction that performs "result = op eax". 3827 */ 3828 /* unop vA, vB */ 3829 movzbl rINSTbl,%ecx # ecx<- A+ 3830 sarl $4,rINST # rINST<- B 3831 GET_VREG_R %eax rINST # eax<- vB 3832 andb $0xf,%cl # ecx<- A 3833 FETCH_INST_OPCODE 1 %edx 3834 ADVANCE_PC 1 3835 3836 3837 movzwl %ax,%eax 3838 SET_VREG %eax %ecx 3839 GOTO_NEXT_R %edx 3840 3841 3842/* ------------------------------ */ 3843 .balign 64 3844.L_OP_INT_TO_SHORT: /* 0x8f */ 3845/* File: x86/OP_INT_TO_SHORT.S */ 3846/* File: x86/unop.S */ 3847 /* 3848 * Generic 32-bit unary operation. Provide an "instr" line that 3849 * specifies an instruction that performs "result = op eax". 3850 */ 3851 /* unop vA, vB */ 3852 movzbl rINSTbl,%ecx # ecx<- A+ 3853 sarl $4,rINST # rINST<- B 3854 GET_VREG_R %eax rINST # eax<- vB 3855 andb $0xf,%cl # ecx<- A 3856 FETCH_INST_OPCODE 1 %edx 3857 ADVANCE_PC 1 3858 3859 3860 movswl %ax,%eax 3861 SET_VREG %eax %ecx 3862 GOTO_NEXT_R %edx 3863 3864 3865/* ------------------------------ */ 3866 .balign 64 3867.L_OP_ADD_INT: /* 0x90 */ 3868/* File: x86/OP_ADD_INT.S */ 3869/* File: x86/binop.S */ 3870 /* 3871 * Generic 32-bit binary operation. Provide an "instr" line that 3872 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 3873 * This could be an x86 instruction or a function call. (If the result 3874 * comes back in a register other than eax, you can override "result".) 3875 * 3876 * For: add-int, sub-int, and-int, or-int, 3877 * xor-int, shl-int, shr-int, ushr-int 3878 */ 3879 /* binop vAA, vBB, vCC */ 3880 movzbl 2(rPC),%eax # eax<- BB 3881 movzbl 3(rPC),%ecx # ecx<- CC 3882 GET_VREG_R %eax %eax # eax<- vBB 3883 addl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax 3884 FETCH_INST_OPCODE 2 %edx 3885 ADVANCE_PC 2 3886 SET_VREG %eax rINST 3887 GOTO_NEXT_R %edx 3888 3889 3890/* ------------------------------ */ 3891 .balign 64 3892.L_OP_SUB_INT: /* 0x91 */ 3893/* File: x86/OP_SUB_INT.S */ 3894/* File: x86/binop.S */ 3895 /* 3896 * Generic 32-bit binary operation. Provide an "instr" line that 3897 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 3898 * This could be an x86 instruction or a function call. (If the result 3899 * comes back in a register other than eax, you can override "result".) 3900 * 3901 * For: add-int, sub-int, and-int, or-int, 3902 * xor-int, shl-int, shr-int, ushr-int 3903 */ 3904 /* binop vAA, vBB, vCC */ 3905 movzbl 2(rPC),%eax # eax<- BB 3906 movzbl 3(rPC),%ecx # ecx<- CC 3907 GET_VREG_R %eax %eax # eax<- vBB 3908 subl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax 3909 FETCH_INST_OPCODE 2 %edx 3910 ADVANCE_PC 2 3911 SET_VREG %eax rINST 3912 GOTO_NEXT_R %edx 3913 3914 3915/* ------------------------------ */ 3916 .balign 64 3917.L_OP_MUL_INT: /* 0x92 */ 3918/* File: x86/OP_MUL_INT.S */ 3919 /* 3920 * 32-bit binary multiplication. 3921 */ 3922 /* mul vAA, vBB, vCC */ 3923 movzbl 2(rPC),%eax # eax<- BB 3924 movzbl 3(rPC),%ecx # ecx<- CC 3925 GET_VREG_R %eax %eax # eax<- vBB 3926 imull (rFP,%ecx,4),%eax # trashes edx 3927 FETCH_INST_OPCODE 2 %edx 3928 ADVANCE_PC 2 3929 SET_VREG %eax rINST 3930 GOTO_NEXT_R %edx 3931 3932/* ------------------------------ */ 3933 .balign 64 3934.L_OP_DIV_INT: /* 0x93 */ 3935/* File: x86/OP_DIV_INT.S */ 3936/* File: x86/bindiv.S */ 3937 3938 /* 3939 * 32-bit binary div/rem operation. Handles special case of op0=minint and 3940 * op1=-1. 3941 */ 3942 /* binop vAA, vBB, vCC */ 3943 movzbl 2(rPC),%eax # eax<- BB 3944 movzbl 3(rPC),%ecx # ecx<- CC 3945 GET_VREG_R %eax %eax # eax<- vBB 3946 GET_VREG_R %ecx %ecx # eax<- vBB 3947 cmpl $0,%ecx 3948 je common_errDivideByZero 3949 cmpl $-1,%ecx 3950 jne .LOP_DIV_INT_continue_div 3951 cmpl $0x80000000,%eax 3952 jne .LOP_DIV_INT_continue_div 3953 movl $0x80000000,%eax 3954 jmp .LOP_DIV_INT_finish_div 3955 3956 3957 3958/* ------------------------------ */ 3959 .balign 64 3960.L_OP_REM_INT: /* 0x94 */ 3961/* File: x86/OP_REM_INT.S */ 3962/* File: x86/bindiv.S */ 3963 3964 /* 3965 * 32-bit binary div/rem operation. Handles special case of op0=minint and 3966 * op1=-1. 3967 */ 3968 /* binop vAA, vBB, vCC */ 3969 movzbl 2(rPC),%eax # eax<- BB 3970 movzbl 3(rPC),%ecx # ecx<- CC 3971 GET_VREG_R %eax %eax # eax<- vBB 3972 GET_VREG_R %ecx %ecx # eax<- vBB 3973 cmpl $0,%ecx 3974 je common_errDivideByZero 3975 cmpl $-1,%ecx 3976 jne .LOP_REM_INT_continue_div 3977 cmpl $0x80000000,%eax 3978 jne .LOP_REM_INT_continue_div 3979 movl $0,%edx 3980 jmp .LOP_REM_INT_finish_div 3981 3982 3983 3984/* ------------------------------ */ 3985 .balign 64 3986.L_OP_AND_INT: /* 0x95 */ 3987/* File: x86/OP_AND_INT.S */ 3988/* File: x86/binop.S */ 3989 /* 3990 * Generic 32-bit binary operation. Provide an "instr" line that 3991 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 3992 * This could be an x86 instruction or a function call. (If the result 3993 * comes back in a register other than eax, you can override "result".) 3994 * 3995 * For: add-int, sub-int, and-int, or-int, 3996 * xor-int, shl-int, shr-int, ushr-int 3997 */ 3998 /* binop vAA, vBB, vCC */ 3999 movzbl 2(rPC),%eax # eax<- BB 4000 movzbl 3(rPC),%ecx # ecx<- CC 4001 GET_VREG_R %eax %eax # eax<- vBB 4002 andl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax 4003 FETCH_INST_OPCODE 2 %edx 4004 ADVANCE_PC 2 4005 SET_VREG %eax rINST 4006 GOTO_NEXT_R %edx 4007 4008 4009/* ------------------------------ */ 4010 .balign 64 4011.L_OP_OR_INT: /* 0x96 */ 4012/* File: x86/OP_OR_INT.S */ 4013/* File: x86/binop.S */ 4014 /* 4015 * Generic 32-bit binary operation. Provide an "instr" line that 4016 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 4017 * This could be an x86 instruction or a function call. (If the result 4018 * comes back in a register other than eax, you can override "result".) 4019 * 4020 * For: add-int, sub-int, and-int, or-int, 4021 * xor-int, shl-int, shr-int, ushr-int 4022 */ 4023 /* binop vAA, vBB, vCC */ 4024 movzbl 2(rPC),%eax # eax<- BB 4025 movzbl 3(rPC),%ecx # ecx<- CC 4026 GET_VREG_R %eax %eax # eax<- vBB 4027 orl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax 4028 FETCH_INST_OPCODE 2 %edx 4029 ADVANCE_PC 2 4030 SET_VREG %eax rINST 4031 GOTO_NEXT_R %edx 4032 4033 4034/* ------------------------------ */ 4035 .balign 64 4036.L_OP_XOR_INT: /* 0x97 */ 4037/* File: x86/OP_XOR_INT.S */ 4038/* File: x86/binop.S */ 4039 /* 4040 * Generic 32-bit binary operation. Provide an "instr" line that 4041 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 4042 * This could be an x86 instruction or a function call. (If the result 4043 * comes back in a register other than eax, you can override "result".) 4044 * 4045 * For: add-int, sub-int, and-int, or-int, 4046 * xor-int, shl-int, shr-int, ushr-int 4047 */ 4048 /* binop vAA, vBB, vCC */ 4049 movzbl 2(rPC),%eax # eax<- BB 4050 movzbl 3(rPC),%ecx # ecx<- CC 4051 GET_VREG_R %eax %eax # eax<- vBB 4052 xorl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax 4053 FETCH_INST_OPCODE 2 %edx 4054 ADVANCE_PC 2 4055 SET_VREG %eax rINST 4056 GOTO_NEXT_R %edx 4057 4058 4059/* ------------------------------ */ 4060 .balign 64 4061.L_OP_SHL_INT: /* 0x98 */ 4062/* File: x86/OP_SHL_INT.S */ 4063/* File: x86/binop1.S */ 4064 /* 4065 * Generic 32-bit binary operation in which both operands loaded to 4066 * registers (op0 in eax, op1 in ecx). 4067 */ 4068 /* binop vAA, vBB, vCC */ 4069 movzbl 2(rPC),%eax # eax<- BB 4070 movzbl 3(rPC),%ecx # ecx<- CC 4071 GET_VREG_R %eax %eax # eax<- vBB 4072 GET_VREG_R %ecx %ecx # eax<- vBB 4073 sall %cl,%eax # ex: addl %ecx,%eax 4074 FETCH_INST_OPCODE 2 %edx 4075 ADVANCE_PC 2 4076 SET_VREG %eax rINST 4077 GOTO_NEXT_R %edx 4078 4079 4080/* ------------------------------ */ 4081 .balign 64 4082.L_OP_SHR_INT: /* 0x99 */ 4083/* File: x86/OP_SHR_INT.S */ 4084/* File: x86/binop1.S */ 4085 /* 4086 * Generic 32-bit binary operation in which both operands loaded to 4087 * registers (op0 in eax, op1 in ecx). 4088 */ 4089 /* binop vAA, vBB, vCC */ 4090 movzbl 2(rPC),%eax # eax<- BB 4091 movzbl 3(rPC),%ecx # ecx<- CC 4092 GET_VREG_R %eax %eax # eax<- vBB 4093 GET_VREG_R %ecx %ecx # eax<- vBB 4094 sarl %cl,%eax # ex: addl %ecx,%eax 4095 FETCH_INST_OPCODE 2 %edx 4096 ADVANCE_PC 2 4097 SET_VREG %eax rINST 4098 GOTO_NEXT_R %edx 4099 4100 4101/* ------------------------------ */ 4102 .balign 64 4103.L_OP_USHR_INT: /* 0x9a */ 4104/* File: x86/OP_USHR_INT.S */ 4105/* File: x86/binop1.S */ 4106 /* 4107 * Generic 32-bit binary operation in which both operands loaded to 4108 * registers (op0 in eax, op1 in ecx). 4109 */ 4110 /* binop vAA, vBB, vCC */ 4111 movzbl 2(rPC),%eax # eax<- BB 4112 movzbl 3(rPC),%ecx # ecx<- CC 4113 GET_VREG_R %eax %eax # eax<- vBB 4114 GET_VREG_R %ecx %ecx # eax<- vBB 4115 shrl %cl,%eax # ex: addl %ecx,%eax 4116 FETCH_INST_OPCODE 2 %edx 4117 ADVANCE_PC 2 4118 SET_VREG %eax rINST 4119 GOTO_NEXT_R %edx 4120 4121 4122/* ------------------------------ */ 4123 .balign 64 4124.L_OP_ADD_LONG: /* 0x9b */ 4125/* File: x86/OP_ADD_LONG.S */ 4126/* File: x86/binopWide.S */ 4127 /* 4128 * Generic 64-bit binary operation. 4129 */ 4130 /* binop vAA, vBB, vCC */ 4131 4132 movzbl 2(rPC),%eax # eax<- BB 4133 movzbl 3(rPC),%ecx # ecx<- CC 4134 GET_VREG_WORD %edx %eax 0 # edx<- v[BB+0] 4135 GET_VREG_WORD %eax %eax 1 # eax<- v[BB+1] 4136 addl (rFP,%ecx,4),%edx # ex: addl (rFP,%ecx,4),%edx 4137 adcl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax 4138 SET_VREG_WORD %edx rINST 0 # v[AA+0] <- edx 4139 FETCH_INST_OPCODE 2 %edx 4140 SET_VREG_WORD %eax rINST 1 # v[AA+1] <- eax 4141 ADVANCE_PC 2 4142 GOTO_NEXT_R %edx 4143 4144 4145/* ------------------------------ */ 4146 .balign 64 4147.L_OP_SUB_LONG: /* 0x9c */ 4148/* File: x86/OP_SUB_LONG.S */ 4149/* File: x86/binopWide.S */ 4150 /* 4151 * Generic 64-bit binary operation. 4152 */ 4153 /* binop vAA, vBB, vCC */ 4154 4155 movzbl 2(rPC),%eax # eax<- BB 4156 movzbl 3(rPC),%ecx # ecx<- CC 4157 GET_VREG_WORD %edx %eax 0 # edx<- v[BB+0] 4158 GET_VREG_WORD %eax %eax 1 # eax<- v[BB+1] 4159 subl (rFP,%ecx,4),%edx # ex: addl (rFP,%ecx,4),%edx 4160 sbbl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax 4161 SET_VREG_WORD %edx rINST 0 # v[AA+0] <- edx 4162 FETCH_INST_OPCODE 2 %edx 4163 SET_VREG_WORD %eax rINST 1 # v[AA+1] <- eax 4164 ADVANCE_PC 2 4165 GOTO_NEXT_R %edx 4166 4167 4168/* ------------------------------ */ 4169 .balign 64 4170.L_OP_MUL_LONG: /* 0x9d */ 4171/* File: x86/OP_MUL_LONG.S */ 4172 /* 4173 * Signed 64-bit integer multiply. 4174 * 4175 * We could definately use more free registers for 4176 * this code. We spill rINSTw (ebx), 4177 * giving us eax, ebc, ecx and edx as computational 4178 * temps. On top of that, we'll spill edi (rFP) 4179 * for use as the vB pointer and esi (rPC) for use 4180 * as the vC pointer. Yuck. 4181 */ 4182 /* mul-long vAA, vBB, vCC */ 4183 movzbl 2(rPC),%eax # eax<- B 4184 movzbl 3(rPC),%ecx # ecx<- C 4185 SPILL_TMP2(%esi) # save Dalvik PC 4186 SPILL(rFP) 4187 SPILL(rINST) 4188 leal (rFP,%eax,4),%esi # esi<- &v[B] 4189 leal (rFP,%ecx,4),rFP # rFP<- &v[C] 4190 movl 4(%esi),%ecx # ecx<- Bmsw 4191 imull (rFP),%ecx # ecx<- (Bmsw*Clsw) 4192 movl 4(rFP),%eax # eax<- Cmsw 4193 imull (%esi),%eax # eax<- (Cmsw*Blsw) 4194 addl %eax,%ecx # ecx<- (Bmsw*Clsw)+(Cmsw*Blsw) 4195 movl (rFP),%eax # eax<- Clsw 4196 mull (%esi) # eax<- (Clsw*Alsw) 4197 UNSPILL(rINST) 4198 UNSPILL(rFP) 4199 jmp .LOP_MUL_LONG_continue 4200 4201/* ------------------------------ */ 4202 .balign 64 4203.L_OP_DIV_LONG: /* 0x9e */ 4204/* File: x86/OP_DIV_LONG.S */ 4205 /* div vAA, vBB, vCC */ 4206 movzbl 3(rPC),%eax # eax<- CC 4207 movzbl 2(rPC),%ecx # ecx<- BB 4208 GET_VREG_WORD %edx %eax 0 4209 GET_VREG_WORD %eax %eax 1 4210 movl %edx,OUT_ARG2(%esp) 4211 testl %eax,%eax 4212 je .LOP_DIV_LONG_check_zero 4213 cmpl $-1,%eax 4214 je .LOP_DIV_LONG_check_neg1 4215.LOP_DIV_LONG_notSpecial: 4216 GET_VREG_WORD %edx %ecx 0 4217 GET_VREG_WORD %ecx %ecx 1 4218.LOP_DIV_LONG_notSpecial1: 4219 movl %eax,OUT_ARG3(%esp) 4220 movl %edx,OUT_ARG0(%esp) 4221 movl %ecx,OUT_ARG1(%esp) 4222 jmp .LOP_DIV_LONG_continue 4223 4224/* ------------------------------ */ 4225 .balign 64 4226.L_OP_REM_LONG: /* 0x9f */ 4227/* File: x86/OP_REM_LONG.S */ 4228/* File: x86/OP_DIV_LONG.S */ 4229 /* div vAA, vBB, vCC */ 4230 movzbl 3(rPC),%eax # eax<- CC 4231 movzbl 2(rPC),%ecx # ecx<- BB 4232 GET_VREG_WORD %edx %eax 0 4233 GET_VREG_WORD %eax %eax 1 4234 movl %edx,OUT_ARG2(%esp) 4235 testl %eax,%eax 4236 je .LOP_REM_LONG_check_zero 4237 cmpl $-1,%eax 4238 je .LOP_REM_LONG_check_neg1 4239.LOP_REM_LONG_notSpecial: 4240 GET_VREG_WORD %edx %ecx 0 4241 GET_VREG_WORD %ecx %ecx 1 4242.LOP_REM_LONG_notSpecial1: 4243 movl %eax,OUT_ARG3(%esp) 4244 movl %edx,OUT_ARG0(%esp) 4245 movl %ecx,OUT_ARG1(%esp) 4246 jmp .LOP_REM_LONG_continue 4247 4248 4249/* ------------------------------ */ 4250 .balign 64 4251.L_OP_AND_LONG: /* 0xa0 */ 4252/* File: x86/OP_AND_LONG.S */ 4253/* File: x86/binopWide.S */ 4254 /* 4255 * Generic 64-bit binary operation. 4256 */ 4257 /* binop vAA, vBB, vCC */ 4258 4259 movzbl 2(rPC),%eax # eax<- BB 4260 movzbl 3(rPC),%ecx # ecx<- CC 4261 GET_VREG_WORD %edx %eax 0 # edx<- v[BB+0] 4262 GET_VREG_WORD %eax %eax 1 # eax<- v[BB+1] 4263 andl (rFP,%ecx,4),%edx # ex: addl (rFP,%ecx,4),%edx 4264 andl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax 4265 SET_VREG_WORD %edx rINST 0 # v[AA+0] <- edx 4266 FETCH_INST_OPCODE 2 %edx 4267 SET_VREG_WORD %eax rINST 1 # v[AA+1] <- eax 4268 ADVANCE_PC 2 4269 GOTO_NEXT_R %edx 4270 4271 4272/* ------------------------------ */ 4273 .balign 64 4274.L_OP_OR_LONG: /* 0xa1 */ 4275/* File: x86/OP_OR_LONG.S */ 4276/* File: x86/binopWide.S */ 4277 /* 4278 * Generic 64-bit binary operation. 4279 */ 4280 /* binop vAA, vBB, vCC */ 4281 4282 movzbl 2(rPC),%eax # eax<- BB 4283 movzbl 3(rPC),%ecx # ecx<- CC 4284 GET_VREG_WORD %edx %eax 0 # edx<- v[BB+0] 4285 GET_VREG_WORD %eax %eax 1 # eax<- v[BB+1] 4286 orl (rFP,%ecx,4),%edx # ex: addl (rFP,%ecx,4),%edx 4287 orl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax 4288 SET_VREG_WORD %edx rINST 0 # v[AA+0] <- edx 4289 FETCH_INST_OPCODE 2 %edx 4290 SET_VREG_WORD %eax rINST 1 # v[AA+1] <- eax 4291 ADVANCE_PC 2 4292 GOTO_NEXT_R %edx 4293 4294 4295/* ------------------------------ */ 4296 .balign 64 4297.L_OP_XOR_LONG: /* 0xa2 */ 4298/* File: x86/OP_XOR_LONG.S */ 4299/* File: x86/binopWide.S */ 4300 /* 4301 * Generic 64-bit binary operation. 4302 */ 4303 /* binop vAA, vBB, vCC */ 4304 4305 movzbl 2(rPC),%eax # eax<- BB 4306 movzbl 3(rPC),%ecx # ecx<- CC 4307 GET_VREG_WORD %edx %eax 0 # edx<- v[BB+0] 4308 GET_VREG_WORD %eax %eax 1 # eax<- v[BB+1] 4309 xorl (rFP,%ecx,4),%edx # ex: addl (rFP,%ecx,4),%edx 4310 xorl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax 4311 SET_VREG_WORD %edx rINST 0 # v[AA+0] <- edx 4312 FETCH_INST_OPCODE 2 %edx 4313 SET_VREG_WORD %eax rINST 1 # v[AA+1] <- eax 4314 ADVANCE_PC 2 4315 GOTO_NEXT_R %edx 4316 4317 4318/* ------------------------------ */ 4319 .balign 64 4320.L_OP_SHL_LONG: /* 0xa3 */ 4321/* File: x86/OP_SHL_LONG.S */ 4322 /* 4323 * Long integer shift. This is different from the generic 32/64-bit 4324 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4325 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4326 * 6 bits of the shift distance. x86 shifts automatically mask off 4327 * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31 4328 * case specially. 4329 */ 4330 /* shl-long vAA, vBB, vCC */ 4331 /* ecx gets shift count */ 4332 /* Need to spill edx */ 4333 /* rINSTw gets AA */ 4334 movzbl 2(rPC),%eax # eax<- BB 4335 movzbl 3(rPC),%ecx # ecx<- CC 4336 GET_VREG_WORD %edx %eax 1 # ecx<- v[BB+1] 4337 GET_VREG_R %ecx %ecx # ecx<- vCC 4338 GET_VREG_WORD %eax %eax 0 # eax<- v[BB+0] 4339 shldl %eax,%edx 4340 sall %cl,%eax 4341 testb $32,%cl 4342 je 2f 4343 movl %eax,%edx 4344 xorl %eax,%eax 43452: 4346 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- %edx 4347 FETCH_INST_OPCODE 2 %edx 4348 jmp .LOP_SHL_LONG_finish 4349 4350/* ------------------------------ */ 4351 .balign 64 4352.L_OP_SHR_LONG: /* 0xa4 */ 4353/* File: x86/OP_SHR_LONG.S */ 4354 /* 4355 * Long integer shift. This is different from the generic 32/64-bit 4356 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4357 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4358 * 6 bits of the shift distance. x86 shifts automatically mask off 4359 * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31 4360 * case specially. 4361 */ 4362 /* shr-long vAA, vBB, vCC */ 4363 /* ecx gets shift count */ 4364 /* Need to spill edx */ 4365 /* rINSTw gets AA */ 4366 movzbl 2(rPC),%eax # eax<- BB 4367 movzbl 3(rPC),%ecx # ecx<- CC 4368 GET_VREG_WORD %edx %eax 1 # edx<- v[BB+1] 4369 GET_VREG_R %ecx %ecx # ecx<- vCC 4370 GET_VREG_WORD %eax %eax 0 # eax<- v[BB+0] 4371 shrdl %edx,%eax 4372 sarl %cl,%edx 4373 testb $32,%cl 4374 je 2f 4375 movl %edx,%eax 4376 sarl $31,%edx 43772: 4378 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- edx 4379 FETCH_INST_OPCODE 2 %edx 4380 jmp .LOP_SHR_LONG_finish 4381 4382/* ------------------------------ */ 4383 .balign 64 4384.L_OP_USHR_LONG: /* 0xa5 */ 4385/* File: x86/OP_USHR_LONG.S */ 4386 /* 4387 * Long integer shift. This is different from the generic 32/64-bit 4388 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4389 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4390 * 6 bits of the shift distance. x86 shifts automatically mask off 4391 * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31 4392 * case specially. 4393 */ 4394 /* shr-long vAA, vBB, vCC */ 4395 /* ecx gets shift count */ 4396 /* Need to spill edx */ 4397 /* rINSTw gets AA */ 4398 movzbl 2(rPC),%eax # eax<- BB 4399 movzbl 3(rPC),%ecx # ecx<- CC 4400 GET_VREG_WORD %edx %eax 1 # edx<- v[BB+1] 4401 GET_VREG_R %ecx %ecx # ecx<- vCC 4402 GET_VREG_WORD %eax %eax 0 # eax<- v[BB+0] 4403 shrdl %edx,%eax 4404 shrl %cl,%edx 4405 testb $32,%cl 4406 je 2f 4407 movl %edx,%eax 4408 xorl %edx,%edx 44092: 4410 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- edx 4411 FETCH_INST_OPCODE 2 %edx 4412 jmp .LOP_USHR_LONG_finish 4413 4414/* ------------------------------ */ 4415 .balign 64 4416.L_OP_ADD_FLOAT: /* 0xa6 */ 4417/* File: x86/OP_ADD_FLOAT.S */ 4418/* File: x86/binflop.S */ 4419 /* 4420 * Generic 32-bit binary float operation. 4421 * 4422 * For: add-fp, sub-fp, mul-fp, div-fp 4423 */ 4424 /* binop vAA, vBB, vCC */ 4425 movzbl 2(rPC),%eax # eax<- CC 4426 movzbl 3(rPC),%ecx # ecx<- BB 4427 flds (rFP,%eax,4) # vCC to fp stack 4428 fadds (rFP,%ecx,4) # ex: faddp 4429 FETCH_INST_OPCODE 2 %edx 4430 ADVANCE_PC 2 4431 fstps (rFP,rINST,4) # %st to vAA 4432 GOTO_NEXT_R %edx 4433 4434 4435/* ------------------------------ */ 4436 .balign 64 4437.L_OP_SUB_FLOAT: /* 0xa7 */ 4438/* File: x86/OP_SUB_FLOAT.S */ 4439/* File: x86/binflop.S */ 4440 /* 4441 * Generic 32-bit binary float operation. 4442 * 4443 * For: add-fp, sub-fp, mul-fp, div-fp 4444 */ 4445 /* binop vAA, vBB, vCC */ 4446 movzbl 2(rPC),%eax # eax<- CC 4447 movzbl 3(rPC),%ecx # ecx<- BB 4448 flds (rFP,%eax,4) # vCC to fp stack 4449 fsubs (rFP,%ecx,4) # ex: faddp 4450 FETCH_INST_OPCODE 2 %edx 4451 ADVANCE_PC 2 4452 fstps (rFP,rINST,4) # %st to vAA 4453 GOTO_NEXT_R %edx 4454 4455 4456/* ------------------------------ */ 4457 .balign 64 4458.L_OP_MUL_FLOAT: /* 0xa8 */ 4459/* File: x86/OP_MUL_FLOAT.S */ 4460/* File: x86/binflop.S */ 4461 /* 4462 * Generic 32-bit binary float operation. 4463 * 4464 * For: add-fp, sub-fp, mul-fp, div-fp 4465 */ 4466 /* binop vAA, vBB, vCC */ 4467 movzbl 2(rPC),%eax # eax<- CC 4468 movzbl 3(rPC),%ecx # ecx<- BB 4469 flds (rFP,%eax,4) # vCC to fp stack 4470 fmuls (rFP,%ecx,4) # ex: faddp 4471 FETCH_INST_OPCODE 2 %edx 4472 ADVANCE_PC 2 4473 fstps (rFP,rINST,4) # %st to vAA 4474 GOTO_NEXT_R %edx 4475 4476 4477/* ------------------------------ */ 4478 .balign 64 4479.L_OP_DIV_FLOAT: /* 0xa9 */ 4480/* File: x86/OP_DIV_FLOAT.S */ 4481/* File: x86/binflop.S */ 4482 /* 4483 * Generic 32-bit binary float operation. 4484 * 4485 * For: add-fp, sub-fp, mul-fp, div-fp 4486 */ 4487 /* binop vAA, vBB, vCC */ 4488 movzbl 2(rPC),%eax # eax<- CC 4489 movzbl 3(rPC),%ecx # ecx<- BB 4490 flds (rFP,%eax,4) # vCC to fp stack 4491 fdivs (rFP,%ecx,4) # ex: faddp 4492 FETCH_INST_OPCODE 2 %edx 4493 ADVANCE_PC 2 4494 fstps (rFP,rINST,4) # %st to vAA 4495 GOTO_NEXT_R %edx 4496 4497 4498/* ------------------------------ */ 4499 .balign 64 4500.L_OP_REM_FLOAT: /* 0xaa */ 4501/* File: x86/OP_REM_FLOAT.S */ 4502 /* rem_float vAA, vBB, vCC */ 4503 movzbl 3(rPC),%ecx # ecx<- BB 4504 movzbl 2(rPC),%eax # eax<- CC 4505 flds (rFP,%ecx,4) # vCC to fp stack 4506 flds (rFP,%eax,4) # vCC to fp stack 4507 movzbl rINSTbl,%ecx # ecx<- AA 4508 FETCH_INST_OPCODE 2 %edx 45091: 4510 fprem 4511 fstsw %ax 4512 sahf 4513 jp 1b 4514 fstp %st(1) 4515 ADVANCE_PC 2 4516 fstps (rFP,%ecx,4) # %st to vAA 4517 GOTO_NEXT_R %edx 4518 4519/* ------------------------------ */ 4520 .balign 64 4521.L_OP_ADD_DOUBLE: /* 0xab */ 4522/* File: x86/OP_ADD_DOUBLE.S */ 4523/* File: x86/binflop.S */ 4524 /* 4525 * Generic 32-bit binary float operation. 4526 * 4527 * For: add-fp, sub-fp, mul-fp, div-fp 4528 */ 4529 /* binop vAA, vBB, vCC */ 4530 movzbl 2(rPC),%eax # eax<- CC 4531 movzbl 3(rPC),%ecx # ecx<- BB 4532 fldl (rFP,%eax,4) # vCC to fp stack 4533 faddl (rFP,%ecx,4) # ex: faddp 4534 FETCH_INST_OPCODE 2 %edx 4535 ADVANCE_PC 2 4536 fstpl (rFP,rINST,4) # %st to vAA 4537 GOTO_NEXT_R %edx 4538 4539 4540/* ------------------------------ */ 4541 .balign 64 4542.L_OP_SUB_DOUBLE: /* 0xac */ 4543/* File: x86/OP_SUB_DOUBLE.S */ 4544/* File: x86/binflop.S */ 4545 /* 4546 * Generic 32-bit binary float operation. 4547 * 4548 * For: add-fp, sub-fp, mul-fp, div-fp 4549 */ 4550 /* binop vAA, vBB, vCC */ 4551 movzbl 2(rPC),%eax # eax<- CC 4552 movzbl 3(rPC),%ecx # ecx<- BB 4553 fldl (rFP,%eax,4) # vCC to fp stack 4554 fsubl (rFP,%ecx,4) # ex: faddp 4555 FETCH_INST_OPCODE 2 %edx 4556 ADVANCE_PC 2 4557 fstpl (rFP,rINST,4) # %st to vAA 4558 GOTO_NEXT_R %edx 4559 4560 4561/* ------------------------------ */ 4562 .balign 64 4563.L_OP_MUL_DOUBLE: /* 0xad */ 4564/* File: x86/OP_MUL_DOUBLE.S */ 4565/* File: x86/binflop.S */ 4566 /* 4567 * Generic 32-bit binary float operation. 4568 * 4569 * For: add-fp, sub-fp, mul-fp, div-fp 4570 */ 4571 /* binop vAA, vBB, vCC */ 4572 movzbl 2(rPC),%eax # eax<- CC 4573 movzbl 3(rPC),%ecx # ecx<- BB 4574 fldl (rFP,%eax,4) # vCC to fp stack 4575 fmull (rFP,%ecx,4) # ex: faddp 4576 FETCH_INST_OPCODE 2 %edx 4577 ADVANCE_PC 2 4578 fstpl (rFP,rINST,4) # %st to vAA 4579 GOTO_NEXT_R %edx 4580 4581 4582/* ------------------------------ */ 4583 .balign 64 4584.L_OP_DIV_DOUBLE: /* 0xae */ 4585/* File: x86/OP_DIV_DOUBLE.S */ 4586/* File: x86/binflop.S */ 4587 /* 4588 * Generic 32-bit binary float operation. 4589 * 4590 * For: add-fp, sub-fp, mul-fp, div-fp 4591 */ 4592 /* binop vAA, vBB, vCC */ 4593 movzbl 2(rPC),%eax # eax<- CC 4594 movzbl 3(rPC),%ecx # ecx<- BB 4595 fldl (rFP,%eax,4) # vCC to fp stack 4596 fdivl (rFP,%ecx,4) # ex: faddp 4597 FETCH_INST_OPCODE 2 %edx 4598 ADVANCE_PC 2 4599 fstpl (rFP,rINST,4) # %st to vAA 4600 GOTO_NEXT_R %edx 4601 4602 4603/* ------------------------------ */ 4604 .balign 64 4605.L_OP_REM_DOUBLE: /* 0xaf */ 4606/* File: x86/OP_REM_DOUBLE.S */ 4607 /* rem_float vAA, vBB, vCC */ 4608 movzbl 3(rPC),%ecx # ecx<- BB 4609 movzbl 2(rPC),%eax # eax<- CC 4610 fldl (rFP,%ecx,4) # vCC to fp stack 4611 fldl (rFP,%eax,4) # vCC to fp stack 4612 movzbl rINSTbl,%ecx # ecx<- AA 4613 FETCH_INST_OPCODE 2 %edx 46141: 4615 fprem 4616 fstsw %ax 4617 sahf 4618 jp 1b 4619 fstp %st(1) 4620 ADVANCE_PC 2 4621 fstpl (rFP,%ecx,4) # %st to vAA 4622 GOTO_NEXT_R %edx 4623 4624/* ------------------------------ */ 4625 .balign 64 4626.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 4627/* File: x86/OP_ADD_INT_2ADDR.S */ 4628/* File: x86/binop2addr.S */ 4629 /* 4630 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 4631 * that specifies an instruction that performs "result = r0 op r1". 4632 * This could be an ARM instruction or a function call. (If the result 4633 * comes back in a register other than r0, you can override "result".) 4634 * 4635 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4636 * vCC (r1). Useful for integer division and modulus. 4637 * 4638 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 4639 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 4640 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 4641 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 4642 */ 4643 /* binop/2addr vA, vB */ 4644 movzx rINSTbl,%ecx # ecx<- A+ 4645 sarl $4,rINST # rINST<- B 4646 GET_VREG_R %eax rINST # eax<- vB 4647 FETCH_INST_OPCODE 1 %edx 4648 andb $0xf,%cl # ecx<- A 4649 addl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4) 4650 ADVANCE_PC 1 4651 GOTO_NEXT_R %edx 4652 4653 4654/* ------------------------------ */ 4655 .balign 64 4656.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 4657/* File: x86/OP_SUB_INT_2ADDR.S */ 4658/* File: x86/binop2addr.S */ 4659 /* 4660 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 4661 * that specifies an instruction that performs "result = r0 op r1". 4662 * This could be an ARM instruction or a function call. (If the result 4663 * comes back in a register other than r0, you can override "result".) 4664 * 4665 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4666 * vCC (r1). Useful for integer division and modulus. 4667 * 4668 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 4669 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 4670 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 4671 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 4672 */ 4673 /* binop/2addr vA, vB */ 4674 movzx rINSTbl,%ecx # ecx<- A+ 4675 sarl $4,rINST # rINST<- B 4676 GET_VREG_R %eax rINST # eax<- vB 4677 FETCH_INST_OPCODE 1 %edx 4678 andb $0xf,%cl # ecx<- A 4679 subl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4) 4680 ADVANCE_PC 1 4681 GOTO_NEXT_R %edx 4682 4683 4684/* ------------------------------ */ 4685 .balign 64 4686.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 4687/* File: x86/OP_MUL_INT_2ADDR.S */ 4688 /* mul vA, vB */ 4689 movzx rINSTbl,%ecx # ecx<- A+ 4690 sarl $4,rINST # rINST<- B 4691 GET_VREG_R %eax rINST # eax<- vB 4692 andb $0xf,%cl # ecx<- A 4693 imull (rFP,%ecx,4),%eax 4694 FETCH_INST_OPCODE 1 %edx 4695 SET_VREG %eax %ecx 4696 ADVANCE_PC 1 4697 GOTO_NEXT_R %edx 4698 4699/* ------------------------------ */ 4700 .balign 64 4701.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 4702/* File: x86/OP_DIV_INT_2ADDR.S */ 4703/* File: x86/bindiv2addr.S */ 4704 /* 4705 * 32-bit binary div/rem operation. Handles special case of op0=minint and 4706 * op1=-1. 4707 */ 4708 /* div/rem/2addr vA, vB */ 4709 movzx rINSTbl,%ecx # eax<- BA 4710 sarl $4,%ecx # ecx<- B 4711 GET_VREG_R %ecx %ecx # eax<- vBB 4712 andb $0xf,rINSTbl # rINST<- A 4713 GET_VREG_R %eax rINST # eax<- vBB 4714 cmpl $0,%ecx 4715 je common_errDivideByZero 4716 cmpl $-1,%ecx 4717 jne .LOP_DIV_INT_2ADDR_continue_div2addr 4718 cmpl $0x80000000,%eax 4719 jne .LOP_DIV_INT_2ADDR_continue_div2addr 4720 movl $0x80000000,%eax 4721 jmp .LOP_DIV_INT_2ADDR_finish_div2addr 4722 4723 4724 4725/* ------------------------------ */ 4726 .balign 64 4727.L_OP_REM_INT_2ADDR: /* 0xb4 */ 4728/* File: x86/OP_REM_INT_2ADDR.S */ 4729/* File: x86/bindiv2addr.S */ 4730 /* 4731 * 32-bit binary div/rem operation. Handles special case of op0=minint and 4732 * op1=-1. 4733 */ 4734 /* div/rem/2addr vA, vB */ 4735 movzx rINSTbl,%ecx # eax<- BA 4736 sarl $4,%ecx # ecx<- B 4737 GET_VREG_R %ecx %ecx # eax<- vBB 4738 andb $0xf,rINSTbl # rINST<- A 4739 GET_VREG_R %eax rINST # eax<- vBB 4740 cmpl $0,%ecx 4741 je common_errDivideByZero 4742 cmpl $-1,%ecx 4743 jne .LOP_REM_INT_2ADDR_continue_div2addr 4744 cmpl $0x80000000,%eax 4745 jne .LOP_REM_INT_2ADDR_continue_div2addr 4746 movl $0,%edx 4747 jmp .LOP_REM_INT_2ADDR_finish_div2addr 4748 4749 4750 4751/* ------------------------------ */ 4752 .balign 64 4753.L_OP_AND_INT_2ADDR: /* 0xb5 */ 4754/* File: x86/OP_AND_INT_2ADDR.S */ 4755/* File: x86/binop2addr.S */ 4756 /* 4757 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 4758 * that specifies an instruction that performs "result = r0 op r1". 4759 * This could be an ARM instruction or a function call. (If the result 4760 * comes back in a register other than r0, you can override "result".) 4761 * 4762 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4763 * vCC (r1). Useful for integer division and modulus. 4764 * 4765 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 4766 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 4767 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 4768 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 4769 */ 4770 /* binop/2addr vA, vB */ 4771 movzx rINSTbl,%ecx # ecx<- A+ 4772 sarl $4,rINST # rINST<- B 4773 GET_VREG_R %eax rINST # eax<- vB 4774 FETCH_INST_OPCODE 1 %edx 4775 andb $0xf,%cl # ecx<- A 4776 andl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4) 4777 ADVANCE_PC 1 4778 GOTO_NEXT_R %edx 4779 4780 4781/* ------------------------------ */ 4782 .balign 64 4783.L_OP_OR_INT_2ADDR: /* 0xb6 */ 4784/* File: x86/OP_OR_INT_2ADDR.S */ 4785/* File: x86/binop2addr.S */ 4786 /* 4787 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 4788 * that specifies an instruction that performs "result = r0 op r1". 4789 * This could be an ARM instruction or a function call. (If the result 4790 * comes back in a register other than r0, you can override "result".) 4791 * 4792 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4793 * vCC (r1). Useful for integer division and modulus. 4794 * 4795 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 4796 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 4797 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 4798 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 4799 */ 4800 /* binop/2addr vA, vB */ 4801 movzx rINSTbl,%ecx # ecx<- A+ 4802 sarl $4,rINST # rINST<- B 4803 GET_VREG_R %eax rINST # eax<- vB 4804 FETCH_INST_OPCODE 1 %edx 4805 andb $0xf,%cl # ecx<- A 4806 orl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4) 4807 ADVANCE_PC 1 4808 GOTO_NEXT_R %edx 4809 4810 4811/* ------------------------------ */ 4812 .balign 64 4813.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 4814/* File: x86/OP_XOR_INT_2ADDR.S */ 4815/* File: x86/binop2addr.S */ 4816 /* 4817 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 4818 * that specifies an instruction that performs "result = r0 op r1". 4819 * This could be an ARM instruction or a function call. (If the result 4820 * comes back in a register other than r0, you can override "result".) 4821 * 4822 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4823 * vCC (r1). Useful for integer division and modulus. 4824 * 4825 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 4826 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 4827 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 4828 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 4829 */ 4830 /* binop/2addr vA, vB */ 4831 movzx rINSTbl,%ecx # ecx<- A+ 4832 sarl $4,rINST # rINST<- B 4833 GET_VREG_R %eax rINST # eax<- vB 4834 FETCH_INST_OPCODE 1 %edx 4835 andb $0xf,%cl # ecx<- A 4836 xorl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4) 4837 ADVANCE_PC 1 4838 GOTO_NEXT_R %edx 4839 4840 4841/* ------------------------------ */ 4842 .balign 64 4843.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 4844/* File: x86/OP_SHL_INT_2ADDR.S */ 4845/* File: x86/shop2addr.S */ 4846 /* 4847 * Generic 32-bit "shift/2addr" operation. 4848 */ 4849 /* shift/2addr vA, vB */ 4850 movzx rINSTbl,%ecx # eax<- BA 4851 sarl $4,%ecx # ecx<- B 4852 GET_VREG_R %ecx %ecx # eax<- vBB 4853 andb $0xf,rINSTbl # rINST<- A 4854 GET_VREG_R %eax rINST # eax<- vAA 4855 sall %cl,%eax # ex: sarl %cl,%eax 4856 FETCH_INST_OPCODE 1 %edx 4857 SET_VREG %eax rINST 4858 ADVANCE_PC 1 4859 GOTO_NEXT_R %edx 4860 4861 4862/* ------------------------------ */ 4863 .balign 64 4864.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 4865/* File: x86/OP_SHR_INT_2ADDR.S */ 4866/* File: x86/shop2addr.S */ 4867 /* 4868 * Generic 32-bit "shift/2addr" operation. 4869 */ 4870 /* shift/2addr vA, vB */ 4871 movzx rINSTbl,%ecx # eax<- BA 4872 sarl $4,%ecx # ecx<- B 4873 GET_VREG_R %ecx %ecx # eax<- vBB 4874 andb $0xf,rINSTbl # rINST<- A 4875 GET_VREG_R %eax rINST # eax<- vAA 4876 sarl %cl,%eax # ex: sarl %cl,%eax 4877 FETCH_INST_OPCODE 1 %edx 4878 SET_VREG %eax rINST 4879 ADVANCE_PC 1 4880 GOTO_NEXT_R %edx 4881 4882 4883/* ------------------------------ */ 4884 .balign 64 4885.L_OP_USHR_INT_2ADDR: /* 0xba */ 4886/* File: x86/OP_USHR_INT_2ADDR.S */ 4887/* File: x86/shop2addr.S */ 4888 /* 4889 * Generic 32-bit "shift/2addr" operation. 4890 */ 4891 /* shift/2addr vA, vB */ 4892 movzx rINSTbl,%ecx # eax<- BA 4893 sarl $4,%ecx # ecx<- B 4894 GET_VREG_R %ecx %ecx # eax<- vBB 4895 andb $0xf,rINSTbl # rINST<- A 4896 GET_VREG_R %eax rINST # eax<- vAA 4897 shrl %cl,%eax # ex: sarl %cl,%eax 4898 FETCH_INST_OPCODE 1 %edx 4899 SET_VREG %eax rINST 4900 ADVANCE_PC 1 4901 GOTO_NEXT_R %edx 4902 4903 4904/* ------------------------------ */ 4905 .balign 64 4906.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 4907/* File: x86/OP_ADD_LONG_2ADDR.S */ 4908/* File: x86/binopWide2addr.S */ 4909 /* 4910 * Generic 64-bit binary operation. 4911 */ 4912 /* binop/2addr vA, vB */ 4913 movzbl rINSTbl,%ecx # ecx<- BA 4914 sarl $4,%ecx # ecx<- B 4915 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0] 4916 GET_VREG_WORD %ecx %ecx 1 # eax<- v[B+1] 4917 andb $0xF,rINSTbl # rINST<- A 4918 addl %eax,(rFP,rINST,4) # example: addl %eax,(rFP,rINST,4) 4919 adcl %ecx,4(rFP,rINST,4) # example: adcl %ecx,4(rFP,rINST,4) 4920 FETCH_INST_OPCODE 1 %edx 4921 ADVANCE_PC 1 4922 GOTO_NEXT_R %edx 4923 4924 4925/* ------------------------------ */ 4926 .balign 64 4927.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 4928/* File: x86/OP_SUB_LONG_2ADDR.S */ 4929/* File: x86/binopWide2addr.S */ 4930 /* 4931 * Generic 64-bit binary operation. 4932 */ 4933 /* binop/2addr vA, vB */ 4934 movzbl rINSTbl,%ecx # ecx<- BA 4935 sarl $4,%ecx # ecx<- B 4936 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0] 4937 GET_VREG_WORD %ecx %ecx 1 # eax<- v[B+1] 4938 andb $0xF,rINSTbl # rINST<- A 4939 subl %eax,(rFP,rINST,4) # example: addl %eax,(rFP,rINST,4) 4940 sbbl %ecx,4(rFP,rINST,4) # example: adcl %ecx,4(rFP,rINST,4) 4941 FETCH_INST_OPCODE 1 %edx 4942 ADVANCE_PC 1 4943 GOTO_NEXT_R %edx 4944 4945 4946/* ------------------------------ */ 4947 .balign 64 4948.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 4949/* File: x86/OP_MUL_LONG_2ADDR.S */ 4950 /* 4951 * Signed 64-bit integer multiply, 2-addr version 4952 * 4953 * We could definately use more free registers for 4954 * this code. We must spill %edx (edx) because it 4955 * is used by imul. We'll also spill rINST (ebx), 4956 * giving us eax, ebc, ecx and edx as computational 4957 * temps. On top of that, we'll spill %esi (edi) 4958 * for use as the vA pointer and rFP (esi) for use 4959 * as the vB pointer. Yuck. 4960 */ 4961 /* mul-long/2addr vA, vB */ 4962 movzbl rINSTbl,%eax # eax<- BA 4963 andb $0xf,%al # eax<- A 4964 sarl $4,rINST # rINST<- B 4965 SPILL_TMP2(%esi) 4966 SPILL(rFP) 4967 leal (rFP,%eax,4),%esi # %esi<- &v[A] 4968 leal (rFP,rINST,4),rFP # rFP<- &v[B] 4969 movl 4(%esi),%ecx # ecx<- Amsw 4970 imull (rFP),%ecx # ecx<- (Amsw*Blsw) 4971 movl 4(rFP),%eax # eax<- Bmsw 4972 imull (%esi),%eax # eax<- (Bmsw*Alsw) 4973 addl %eax,%ecx # ecx<- (Amsw*Blsw)+(Bmsw*Alsw) 4974 movl (rFP),%eax # eax<- Blsw 4975 mull (%esi) # eax<- (Blsw*Alsw) 4976 jmp .LOP_MUL_LONG_2ADDR_continue 4977 4978/* ------------------------------ */ 4979 .balign 64 4980.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 4981/* File: x86/OP_DIV_LONG_2ADDR.S */ 4982 /* div/2addr vA, vB */ 4983 movzbl rINSTbl,%eax 4984 shrl $4,%eax # eax<- B 4985 andb $0xf,rINSTbl # rINST<- A 4986 GET_VREG_WORD %edx %eax 0 4987 GET_VREG_WORD %eax %eax 1 4988 movl %edx,OUT_ARG2(%esp) 4989 testl %eax,%eax 4990 je .LOP_DIV_LONG_2ADDR_check_zero 4991 cmpl $-1,%eax 4992 je .LOP_DIV_LONG_2ADDR_check_neg1 4993.LOP_DIV_LONG_2ADDR_notSpecial: 4994 GET_VREG_WORD %edx rINST 0 4995 GET_VREG_WORD %ecx rINST 1 4996.LOP_DIV_LONG_2ADDR_notSpecial1: 4997 jmp .LOP_DIV_LONG_2ADDR_continue 4998 4999/* ------------------------------ */ 5000 .balign 64 5001.L_OP_REM_LONG_2ADDR: /* 0xbf */ 5002/* File: x86/OP_REM_LONG_2ADDR.S */ 5003/* File: x86/OP_DIV_LONG_2ADDR.S */ 5004 /* div/2addr vA, vB */ 5005 movzbl rINSTbl,%eax 5006 shrl $4,%eax # eax<- B 5007 andb $0xf,rINSTbl # rINST<- A 5008 GET_VREG_WORD %edx %eax 0 5009 GET_VREG_WORD %eax %eax 1 5010 movl %edx,OUT_ARG2(%esp) 5011 testl %eax,%eax 5012 je .LOP_REM_LONG_2ADDR_check_zero 5013 cmpl $-1,%eax 5014 je .LOP_REM_LONG_2ADDR_check_neg1 5015.LOP_REM_LONG_2ADDR_notSpecial: 5016 GET_VREG_WORD %edx rINST 0 5017 GET_VREG_WORD %ecx rINST 1 5018.LOP_REM_LONG_2ADDR_notSpecial1: 5019 jmp .LOP_REM_LONG_2ADDR_continue 5020 5021 5022/* ------------------------------ */ 5023 .balign 64 5024.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 5025/* File: x86/OP_AND_LONG_2ADDR.S */ 5026/* File: x86/binopWide2addr.S */ 5027 /* 5028 * Generic 64-bit binary operation. 5029 */ 5030 /* binop/2addr vA, vB */ 5031 movzbl rINSTbl,%ecx # ecx<- BA 5032 sarl $4,%ecx # ecx<- B 5033 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0] 5034 GET_VREG_WORD %ecx %ecx 1 # eax<- v[B+1] 5035 andb $0xF,rINSTbl # rINST<- A 5036 andl %eax,(rFP,rINST,4) # example: addl %eax,(rFP,rINST,4) 5037 andl %ecx,4(rFP,rINST,4) # example: adcl %ecx,4(rFP,rINST,4) 5038 FETCH_INST_OPCODE 1 %edx 5039 ADVANCE_PC 1 5040 GOTO_NEXT_R %edx 5041 5042 5043/* ------------------------------ */ 5044 .balign 64 5045.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5046/* File: x86/OP_OR_LONG_2ADDR.S */ 5047/* File: x86/binopWide2addr.S */ 5048 /* 5049 * Generic 64-bit binary operation. 5050 */ 5051 /* binop/2addr vA, vB */ 5052 movzbl rINSTbl,%ecx # ecx<- BA 5053 sarl $4,%ecx # ecx<- B 5054 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0] 5055 GET_VREG_WORD %ecx %ecx 1 # eax<- v[B+1] 5056 andb $0xF,rINSTbl # rINST<- A 5057 orl %eax,(rFP,rINST,4) # example: addl %eax,(rFP,rINST,4) 5058 orl %ecx,4(rFP,rINST,4) # example: adcl %ecx,4(rFP,rINST,4) 5059 FETCH_INST_OPCODE 1 %edx 5060 ADVANCE_PC 1 5061 GOTO_NEXT_R %edx 5062 5063 5064/* ------------------------------ */ 5065 .balign 64 5066.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 5067/* File: x86/OP_XOR_LONG_2ADDR.S */ 5068/* File: x86/binopWide2addr.S */ 5069 /* 5070 * Generic 64-bit binary operation. 5071 */ 5072 /* binop/2addr vA, vB */ 5073 movzbl rINSTbl,%ecx # ecx<- BA 5074 sarl $4,%ecx # ecx<- B 5075 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0] 5076 GET_VREG_WORD %ecx %ecx 1 # eax<- v[B+1] 5077 andb $0xF,rINSTbl # rINST<- A 5078 xorl %eax,(rFP,rINST,4) # example: addl %eax,(rFP,rINST,4) 5079 xorl %ecx,4(rFP,rINST,4) # example: adcl %ecx,4(rFP,rINST,4) 5080 FETCH_INST_OPCODE 1 %edx 5081 ADVANCE_PC 1 5082 GOTO_NEXT_R %edx 5083 5084 5085/* ------------------------------ */ 5086 .balign 64 5087.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 5088/* File: x86/OP_SHL_LONG_2ADDR.S */ 5089 /* 5090 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 5091 * 32-bit shift distance. 5092 */ 5093 /* shl-long/2addr vA, vB */ 5094 /* ecx gets shift count */ 5095 /* Need to spill edx */ 5096 /* rINSTw gets AA */ 5097 movzbl rINSTbl,%ecx # ecx<- BA 5098 andb $0xf,rINSTbl # rINST<- A 5099 GET_VREG_WORD %eax rINST 0 # eax<- v[AA+0] 5100 sarl $4,%ecx # ecx<- B 5101 GET_VREG_WORD %edx rINST 1 # edx<- v[AA+1] 5102 GET_VREG_R %ecx %ecx # ecx<- vBB 5103 shldl %eax,%edx 5104 sall %cl,%eax 5105 testb $32,%cl 5106 je 2f 5107 movl %eax,%edx 5108 xorl %eax,%eax 51092: 5110 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- edx 5111 jmp .LOP_SHL_LONG_2ADDR_finish 5112 5113/* ------------------------------ */ 5114 .balign 64 5115.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 5116/* File: x86/OP_SHR_LONG_2ADDR.S */ 5117 /* 5118 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 5119 * 32-bit shift distance. 5120 */ 5121 /* shl-long/2addr vA, vB */ 5122 /* ecx gets shift count */ 5123 /* Need to spill edx */ 5124 /* rINSTw gets AA */ 5125 movzbl rINSTbl,%ecx # ecx<- BA 5126 andb $0xf,rINSTbl # rINST<- A 5127 GET_VREG_WORD %eax rINST 0 # eax<- v[AA+0] 5128 sarl $4,%ecx # ecx<- B 5129 GET_VREG_WORD %edx rINST 1 # edx<- v[AA+1] 5130 GET_VREG_R %ecx %ecx # ecx<- vBB 5131 shrdl %edx,%eax 5132 sarl %cl,%edx 5133 testb $32,%cl 5134 je 2f 5135 movl %edx,%eax 5136 sarl $31,%edx 51372: 5138 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- edx 5139 jmp .LOP_SHR_LONG_2ADDR_finish 5140 5141/* ------------------------------ */ 5142 .balign 64 5143.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 5144/* File: x86/OP_USHR_LONG_2ADDR.S */ 5145 /* 5146 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 5147 * 32-bit shift distance. 5148 */ 5149 /* shl-long/2addr vA, vB */ 5150 /* ecx gets shift count */ 5151 /* Need to spill edx */ 5152 /* rINSTw gets AA */ 5153 movzbl rINSTbl,%ecx # ecx<- BA 5154 andb $0xf,rINSTbl # rINST<- A 5155 GET_VREG_WORD %eax rINST 0 # eax<- v[AA+0] 5156 sarl $4,%ecx # ecx<- B 5157 GET_VREG_WORD %edx rINST 1 # edx<- v[AA+1] 5158 GET_VREG_R %ecx %ecx # ecx<- vBB 5159 shrdl %edx,%eax 5160 shrl %cl,%edx 5161 testb $32,%cl 5162 je 2f 5163 movl %edx,%eax 5164 xorl %edx,%edx 51652: 5166 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- edx 5167 jmp .LOP_USHR_LONG_2ADDR_finish 5168 5169/* ------------------------------ */ 5170 .balign 64 5171.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 5172/* File: x86/OP_ADD_FLOAT_2ADDR.S */ 5173/* File: x86/binflop2addr.S */ 5174 /* 5175 * Generic 32-bit binary float operation. 5176 * 5177 * For: add-fp, sub-fp, mul-fp, div-fp 5178 */ 5179 5180 /* binop/2addr vA, vB */ 5181 movzx rINSTbl,%ecx # ecx<- A+ 5182 andb $0xf,%cl # ecx<- A 5183 flds (rFP,%ecx,4) # vAA to fp stack 5184 sarl $4,rINST # rINST<- B 5185 fadds (rFP,rINST,4) # ex: faddp 5186 FETCH_INST_OPCODE 1 %edx 5187 ADVANCE_PC 1 5188 fstps (rFP,%ecx,4) # %st to vA 5189 GOTO_NEXT_R %edx 5190 5191 5192/* ------------------------------ */ 5193 .balign 64 5194.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 5195/* File: x86/OP_SUB_FLOAT_2ADDR.S */ 5196/* File: x86/binflop2addr.S */ 5197 /* 5198 * Generic 32-bit binary float operation. 5199 * 5200 * For: add-fp, sub-fp, mul-fp, div-fp 5201 */ 5202 5203 /* binop/2addr vA, vB */ 5204 movzx rINSTbl,%ecx # ecx<- A+ 5205 andb $0xf,%cl # ecx<- A 5206 flds (rFP,%ecx,4) # vAA to fp stack 5207 sarl $4,rINST # rINST<- B 5208 fsubs (rFP,rINST,4) # ex: faddp 5209 FETCH_INST_OPCODE 1 %edx 5210 ADVANCE_PC 1 5211 fstps (rFP,%ecx,4) # %st to vA 5212 GOTO_NEXT_R %edx 5213 5214 5215/* ------------------------------ */ 5216 .balign 64 5217.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 5218/* File: x86/OP_MUL_FLOAT_2ADDR.S */ 5219/* File: x86/binflop2addr.S */ 5220 /* 5221 * Generic 32-bit binary float operation. 5222 * 5223 * For: add-fp, sub-fp, mul-fp, div-fp 5224 */ 5225 5226 /* binop/2addr vA, vB */ 5227 movzx rINSTbl,%ecx # ecx<- A+ 5228 andb $0xf,%cl # ecx<- A 5229 flds (rFP,%ecx,4) # vAA to fp stack 5230 sarl $4,rINST # rINST<- B 5231 fmuls (rFP,rINST,4) # ex: faddp 5232 FETCH_INST_OPCODE 1 %edx 5233 ADVANCE_PC 1 5234 fstps (rFP,%ecx,4) # %st to vA 5235 GOTO_NEXT_R %edx 5236 5237 5238/* ------------------------------ */ 5239 .balign 64 5240.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 5241/* File: x86/OP_DIV_FLOAT_2ADDR.S */ 5242/* File: x86/binflop2addr.S */ 5243 /* 5244 * Generic 32-bit binary float operation. 5245 * 5246 * For: add-fp, sub-fp, mul-fp, div-fp 5247 */ 5248 5249 /* binop/2addr vA, vB */ 5250 movzx rINSTbl,%ecx # ecx<- A+ 5251 andb $0xf,%cl # ecx<- A 5252 flds (rFP,%ecx,4) # vAA to fp stack 5253 sarl $4,rINST # rINST<- B 5254 fdivs (rFP,rINST,4) # ex: faddp 5255 FETCH_INST_OPCODE 1 %edx 5256 ADVANCE_PC 1 5257 fstps (rFP,%ecx,4) # %st to vA 5258 GOTO_NEXT_R %edx 5259 5260 5261/* ------------------------------ */ 5262 .balign 64 5263.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 5264/* File: x86/OP_REM_FLOAT_2ADDR.S */ 5265 /* rem_float/2addr vA, vB */ 5266 movzx rINSTbl,%ecx # ecx<- A+ 5267 sarl $4,rINST # rINST<- B 5268 flds (rFP,rINST,4) # vBB to fp stack 5269 andb $0xf,%cl # ecx<- A 5270 flds (rFP,%ecx,4) # vAA to fp stack 5271 FETCH_INST_OPCODE 1 %edx 52721: 5273 fprem 5274 fstsw %ax 5275 sahf 5276 jp 1b 5277 fstp %st(1) 5278 ADVANCE_PC 1 5279 fstps (rFP,%ecx,4) # %st to vA 5280 GOTO_NEXT_R %edx 5281 5282/* ------------------------------ */ 5283 .balign 64 5284.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 5285/* File: x86/OP_ADD_DOUBLE_2ADDR.S */ 5286/* File: x86/binflop2addr.S */ 5287 /* 5288 * Generic 32-bit binary float operation. 5289 * 5290 * For: add-fp, sub-fp, mul-fp, div-fp 5291 */ 5292 5293 /* binop/2addr vA, vB */ 5294 movzx rINSTbl,%ecx # ecx<- A+ 5295 andb $0xf,%cl # ecx<- A 5296 fldl (rFP,%ecx,4) # vAA to fp stack 5297 sarl $4,rINST # rINST<- B 5298 faddl (rFP,rINST,4) # ex: faddp 5299 FETCH_INST_OPCODE 1 %edx 5300 ADVANCE_PC 1 5301 fstpl (rFP,%ecx,4) # %st to vA 5302 GOTO_NEXT_R %edx 5303 5304 5305/* ------------------------------ */ 5306 .balign 64 5307.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 5308/* File: x86/OP_SUB_DOUBLE_2ADDR.S */ 5309/* File: x86/binflop2addr.S */ 5310 /* 5311 * Generic 32-bit binary float operation. 5312 * 5313 * For: add-fp, sub-fp, mul-fp, div-fp 5314 */ 5315 5316 /* binop/2addr vA, vB */ 5317 movzx rINSTbl,%ecx # ecx<- A+ 5318 andb $0xf,%cl # ecx<- A 5319 fldl (rFP,%ecx,4) # vAA to fp stack 5320 sarl $4,rINST # rINST<- B 5321 fsubl (rFP,rINST,4) # ex: faddp 5322 FETCH_INST_OPCODE 1 %edx 5323 ADVANCE_PC 1 5324 fstpl (rFP,%ecx,4) # %st to vA 5325 GOTO_NEXT_R %edx 5326 5327 5328/* ------------------------------ */ 5329 .balign 64 5330.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 5331/* File: x86/OP_MUL_DOUBLE_2ADDR.S */ 5332/* File: x86/binflop2addr.S */ 5333 /* 5334 * Generic 32-bit binary float operation. 5335 * 5336 * For: add-fp, sub-fp, mul-fp, div-fp 5337 */ 5338 5339 /* binop/2addr vA, vB */ 5340 movzx rINSTbl,%ecx # ecx<- A+ 5341 andb $0xf,%cl # ecx<- A 5342 fldl (rFP,%ecx,4) # vAA to fp stack 5343 sarl $4,rINST # rINST<- B 5344 fmull (rFP,rINST,4) # ex: faddp 5345 FETCH_INST_OPCODE 1 %edx 5346 ADVANCE_PC 1 5347 fstpl (rFP,%ecx,4) # %st to vA 5348 GOTO_NEXT_R %edx 5349 5350 5351/* ------------------------------ */ 5352 .balign 64 5353.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 5354/* File: x86/OP_DIV_DOUBLE_2ADDR.S */ 5355/* File: x86/binflop2addr.S */ 5356 /* 5357 * Generic 32-bit binary float operation. 5358 * 5359 * For: add-fp, sub-fp, mul-fp, div-fp 5360 */ 5361 5362 /* binop/2addr vA, vB */ 5363 movzx rINSTbl,%ecx # ecx<- A+ 5364 andb $0xf,%cl # ecx<- A 5365 fldl (rFP,%ecx,4) # vAA to fp stack 5366 sarl $4,rINST # rINST<- B 5367 fdivl (rFP,rINST,4) # ex: faddp 5368 FETCH_INST_OPCODE 1 %edx 5369 ADVANCE_PC 1 5370 fstpl (rFP,%ecx,4) # %st to vA 5371 GOTO_NEXT_R %edx 5372 5373 5374/* ------------------------------ */ 5375 .balign 64 5376.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 5377/* File: x86/OP_REM_DOUBLE_2ADDR.S */ 5378 /* rem_float/2addr vA, vB */ 5379 movzx rINSTbl,%ecx # ecx<- A+ 5380 sarl $4,rINST # rINST<- B 5381 fldl (rFP,rINST,4) # vBB to fp stack 5382 andb $0xf,%cl # ecx<- A 5383 fldl (rFP,%ecx,4) # vAA to fp stack 5384 FETCH_INST_OPCODE 1 %edx 53851: 5386 fprem 5387 fstsw %ax 5388 sahf 5389 jp 1b 5390 fstp %st(1) 5391 ADVANCE_PC 1 5392 fstpl (rFP,%ecx,4) # %st to vA 5393 GOTO_NEXT_R %edx 5394 5395/* ------------------------------ */ 5396 .balign 64 5397.L_OP_ADD_INT_LIT16: /* 0xd0 */ 5398/* File: x86/OP_ADD_INT_LIT16.S */ 5399/* File: x86/binopLit16.S */ 5400 /* 5401 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 5402 * that specifies an instruction that performs "result = eax op ecx". 5403 * This could be an x86 instruction or a function call. (If the result 5404 * comes back in a register other than eax, you can override "result".) 5405 * 5406 * For: add-int/lit16, rsub-int, 5407 * and-int/lit16, or-int/lit16, xor-int/lit16 5408 */ 5409 /* binop/lit16 vA, vB, #+CCCC */ 5410 movzbl rINSTbl,%eax # eax<- 000000BA 5411 sarl $4,%eax # eax<- B 5412 GET_VREG_R %eax %eax # eax<- vB 5413 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5414 andb $0xf,rINSTbl # rINST<- A 5415 addl %ecx,%eax # for example: addl %ecx, %eax 5416 SET_VREG %eax rINST 5417 FETCH_INST_OPCODE 2 %edx 5418 ADVANCE_PC 2 5419 GOTO_NEXT_R %edx 5420 5421 5422/* ------------------------------ */ 5423 .balign 64 5424.L_OP_RSUB_INT: /* 0xd1 */ 5425/* File: x86/OP_RSUB_INT.S */ 5426/* File: x86/binopLit16.S */ 5427 /* 5428 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 5429 * that specifies an instruction that performs "result = eax op ecx". 5430 * This could be an x86 instruction or a function call. (If the result 5431 * comes back in a register other than eax, you can override "result".) 5432 * 5433 * For: add-int/lit16, rsub-int, 5434 * and-int/lit16, or-int/lit16, xor-int/lit16 5435 */ 5436 /* binop/lit16 vA, vB, #+CCCC */ 5437 movzbl rINSTbl,%eax # eax<- 000000BA 5438 sarl $4,%eax # eax<- B 5439 GET_VREG_R %eax %eax # eax<- vB 5440 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5441 andb $0xf,rINSTbl # rINST<- A 5442 subl %eax,%ecx # for example: addl %ecx, %eax 5443 SET_VREG %ecx rINST 5444 FETCH_INST_OPCODE 2 %edx 5445 ADVANCE_PC 2 5446 GOTO_NEXT_R %edx 5447 5448 5449/* ------------------------------ */ 5450 .balign 64 5451.L_OP_MUL_INT_LIT16: /* 0xd2 */ 5452/* File: x86/OP_MUL_INT_LIT16.S */ 5453 /* mul/lit16 vA, vB, #+CCCC */ 5454 /* Need A in rINST, ssssCCCC in ecx, vB in eax */ 5455 movzbl rINSTbl,%eax # eax<- 000000BA 5456 sarl $4,%eax # eax<- B 5457 GET_VREG_R %eax %eax # eax<- vB 5458 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5459 andb $0xf,rINSTbl # rINST<- A 5460 imull %ecx,%eax # trashes edx 5461 FETCH_INST_OPCODE 2 %edx 5462 ADVANCE_PC 2 5463 SET_VREG %eax rINST 5464 GOTO_NEXT_R %edx 5465 5466/* ------------------------------ */ 5467 .balign 64 5468.L_OP_DIV_INT_LIT16: /* 0xd3 */ 5469/* File: x86/OP_DIV_INT_LIT16.S */ 5470/* File: x86/bindivLit16.S */ 5471 /* 5472 * 32-bit binary div/rem operation. Handles special case of op0=minint and 5473 * op1=-1. 5474 */ 5475 /* div/rem/lit16 vA, vB, #+CCCC */ 5476 /* Need A in rINST, ssssCCCC in ecx, vB in eax */ 5477 movzbl rINSTbl,%eax # eax<- 000000BA 5478 sarl $4,%eax # eax<- B 5479 GET_VREG_R %eax %eax # eax<- vB 5480 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5481 andb $0xf,rINSTbl # rINST<- A 5482 cmpl $0,%ecx 5483 je common_errDivideByZero 5484 cmpl $-1,%ecx 5485 jne .LOP_DIV_INT_LIT16_continue_div 5486 cmpl $0x80000000,%eax 5487 jne .LOP_DIV_INT_LIT16_continue_div 5488 movl $0x80000000,%eax 5489 jmp .LOP_DIV_INT_LIT16_finish_div 5490 5491 5492 5493/* ------------------------------ */ 5494 .balign 64 5495.L_OP_REM_INT_LIT16: /* 0xd4 */ 5496/* File: x86/OP_REM_INT_LIT16.S */ 5497/* File: x86/bindivLit16.S */ 5498 /* 5499 * 32-bit binary div/rem operation. Handles special case of op0=minint and 5500 * op1=-1. 5501 */ 5502 /* div/rem/lit16 vA, vB, #+CCCC */ 5503 /* Need A in rINST, ssssCCCC in ecx, vB in eax */ 5504 movzbl rINSTbl,%eax # eax<- 000000BA 5505 sarl $4,%eax # eax<- B 5506 GET_VREG_R %eax %eax # eax<- vB 5507 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5508 andb $0xf,rINSTbl # rINST<- A 5509 cmpl $0,%ecx 5510 je common_errDivideByZero 5511 cmpl $-1,%ecx 5512 jne .LOP_REM_INT_LIT16_continue_div 5513 cmpl $0x80000000,%eax 5514 jne .LOP_REM_INT_LIT16_continue_div 5515 movl $0,%edx 5516 jmp .LOP_REM_INT_LIT16_finish_div 5517 5518 5519 5520/* ------------------------------ */ 5521 .balign 64 5522.L_OP_AND_INT_LIT16: /* 0xd5 */ 5523/* File: x86/OP_AND_INT_LIT16.S */ 5524/* File: x86/binopLit16.S */ 5525 /* 5526 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 5527 * that specifies an instruction that performs "result = eax op ecx". 5528 * This could be an x86 instruction or a function call. (If the result 5529 * comes back in a register other than eax, you can override "result".) 5530 * 5531 * For: add-int/lit16, rsub-int, 5532 * and-int/lit16, or-int/lit16, xor-int/lit16 5533 */ 5534 /* binop/lit16 vA, vB, #+CCCC */ 5535 movzbl rINSTbl,%eax # eax<- 000000BA 5536 sarl $4,%eax # eax<- B 5537 GET_VREG_R %eax %eax # eax<- vB 5538 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5539 andb $0xf,rINSTbl # rINST<- A 5540 andl %ecx,%eax # for example: addl %ecx, %eax 5541 SET_VREG %eax rINST 5542 FETCH_INST_OPCODE 2 %edx 5543 ADVANCE_PC 2 5544 GOTO_NEXT_R %edx 5545 5546 5547/* ------------------------------ */ 5548 .balign 64 5549.L_OP_OR_INT_LIT16: /* 0xd6 */ 5550/* File: x86/OP_OR_INT_LIT16.S */ 5551/* File: x86/binopLit16.S */ 5552 /* 5553 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 5554 * that specifies an instruction that performs "result = eax op ecx". 5555 * This could be an x86 instruction or a function call. (If the result 5556 * comes back in a register other than eax, you can override "result".) 5557 * 5558 * For: add-int/lit16, rsub-int, 5559 * and-int/lit16, or-int/lit16, xor-int/lit16 5560 */ 5561 /* binop/lit16 vA, vB, #+CCCC */ 5562 movzbl rINSTbl,%eax # eax<- 000000BA 5563 sarl $4,%eax # eax<- B 5564 GET_VREG_R %eax %eax # eax<- vB 5565 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5566 andb $0xf,rINSTbl # rINST<- A 5567 orl %ecx,%eax # for example: addl %ecx, %eax 5568 SET_VREG %eax rINST 5569 FETCH_INST_OPCODE 2 %edx 5570 ADVANCE_PC 2 5571 GOTO_NEXT_R %edx 5572 5573 5574/* ------------------------------ */ 5575 .balign 64 5576.L_OP_XOR_INT_LIT16: /* 0xd7 */ 5577/* File: x86/OP_XOR_INT_LIT16.S */ 5578/* File: x86/binopLit16.S */ 5579 /* 5580 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 5581 * that specifies an instruction that performs "result = eax op ecx". 5582 * This could be an x86 instruction or a function call. (If the result 5583 * comes back in a register other than eax, you can override "result".) 5584 * 5585 * For: add-int/lit16, rsub-int, 5586 * and-int/lit16, or-int/lit16, xor-int/lit16 5587 */ 5588 /* binop/lit16 vA, vB, #+CCCC */ 5589 movzbl rINSTbl,%eax # eax<- 000000BA 5590 sarl $4,%eax # eax<- B 5591 GET_VREG_R %eax %eax # eax<- vB 5592 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5593 andb $0xf,rINSTbl # rINST<- A 5594 xor %ecx,%eax # for example: addl %ecx, %eax 5595 SET_VREG %eax rINST 5596 FETCH_INST_OPCODE 2 %edx 5597 ADVANCE_PC 2 5598 GOTO_NEXT_R %edx 5599 5600 5601/* ------------------------------ */ 5602 .balign 64 5603.L_OP_ADD_INT_LIT8: /* 0xd8 */ 5604/* File: x86/OP_ADD_INT_LIT8.S */ 5605/* File: x86/binopLit8.S */ 5606 /* 5607 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5608 * that specifies an instruction that performs "result = eax op ecx". 5609 * This could be an x86 instruction or a function call. (If the result 5610 * comes back in a register other than r0, you can override "result".) 5611 * 5612 * For: add-int/lit8, rsub-int/lit8 5613 * and-int/lit8, or-int/lit8, xor-int/lit8, 5614 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5615 */ 5616 /* binop/lit8 vAA, vBB, #+CC */ 5617 movzbl 2(rPC),%eax # eax<- BB 5618 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5619 GET_VREG_R %eax %eax # eax<- rBB 5620 addl %ecx,%eax # ex: addl %ecx,%eax 5621 FETCH_INST_OPCODE 2 %edx 5622 SET_VREG %eax rINST 5623 ADVANCE_PC 2 5624 GOTO_NEXT_R %edx 5625 5626 5627/* ------------------------------ */ 5628 .balign 64 5629.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 5630/* File: x86/OP_RSUB_INT_LIT8.S */ 5631/* File: x86/binopLit8.S */ 5632 /* 5633 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5634 * that specifies an instruction that performs "result = eax op ecx". 5635 * This could be an x86 instruction or a function call. (If the result 5636 * comes back in a register other than r0, you can override "result".) 5637 * 5638 * For: add-int/lit8, rsub-int/lit8 5639 * and-int/lit8, or-int/lit8, xor-int/lit8, 5640 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5641 */ 5642 /* binop/lit8 vAA, vBB, #+CC */ 5643 movzbl 2(rPC),%eax # eax<- BB 5644 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5645 GET_VREG_R %eax %eax # eax<- rBB 5646 subl %eax,%ecx # ex: addl %ecx,%eax 5647 FETCH_INST_OPCODE 2 %edx 5648 SET_VREG %ecx rINST 5649 ADVANCE_PC 2 5650 GOTO_NEXT_R %edx 5651 5652 5653/* ------------------------------ */ 5654 .balign 64 5655.L_OP_MUL_INT_LIT8: /* 0xda */ 5656/* File: x86/OP_MUL_INT_LIT8.S */ 5657 /* mul/lit8 vAA, vBB, #+CC */ 5658 movzbl 2(rPC),%eax # eax<- BB 5659 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5660 GET_VREG_R %eax %eax # eax<- rBB 5661 imull %ecx,%eax # trashes edx 5662 FETCH_INST_OPCODE 2 %edx 5663 ADVANCE_PC 2 5664 SET_VREG %eax rINST 5665 GOTO_NEXT_R %edx 5666 5667/* ------------------------------ */ 5668 .balign 64 5669.L_OP_DIV_INT_LIT8: /* 0xdb */ 5670/* File: x86/OP_DIV_INT_LIT8.S */ 5671/* File: x86/bindivLit8.S */ 5672 /* 5673 * 32-bit div/rem "lit8" binary operation. Handles special case of 5674 * op0=minint & op1=-1 5675 */ 5676 /* div/rem/lit8 vAA, vBB, #+CC */ 5677 movzbl 2(rPC),%eax # eax<- BB 5678 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5679 GET_VREG_R %eax %eax # eax<- rBB 5680 cmpl $0,%ecx 5681 je common_errDivideByZero 5682 cmpl $0x80000000,%eax 5683 jne .LOP_DIV_INT_LIT8_continue_div 5684 cmpl $-1,%ecx 5685 jne .LOP_DIV_INT_LIT8_continue_div 5686 movl $0x80000000,%eax 5687 jmp .LOP_DIV_INT_LIT8_finish_div 5688 5689 5690 5691/* ------------------------------ */ 5692 .balign 64 5693.L_OP_REM_INT_LIT8: /* 0xdc */ 5694/* File: x86/OP_REM_INT_LIT8.S */ 5695/* File: x86/bindivLit8.S */ 5696 /* 5697 * 32-bit div/rem "lit8" binary operation. Handles special case of 5698 * op0=minint & op1=-1 5699 */ 5700 /* div/rem/lit8 vAA, vBB, #+CC */ 5701 movzbl 2(rPC),%eax # eax<- BB 5702 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5703 GET_VREG_R %eax %eax # eax<- rBB 5704 cmpl $0,%ecx 5705 je common_errDivideByZero 5706 cmpl $0x80000000,%eax 5707 jne .LOP_REM_INT_LIT8_continue_div 5708 cmpl $-1,%ecx 5709 jne .LOP_REM_INT_LIT8_continue_div 5710 movl $0,%edx 5711 jmp .LOP_REM_INT_LIT8_finish_div 5712 5713 5714 5715/* ------------------------------ */ 5716 .balign 64 5717.L_OP_AND_INT_LIT8: /* 0xdd */ 5718/* File: x86/OP_AND_INT_LIT8.S */ 5719/* File: x86/binopLit8.S */ 5720 /* 5721 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5722 * that specifies an instruction that performs "result = eax op ecx". 5723 * This could be an x86 instruction or a function call. (If the result 5724 * comes back in a register other than r0, you can override "result".) 5725 * 5726 * For: add-int/lit8, rsub-int/lit8 5727 * and-int/lit8, or-int/lit8, xor-int/lit8, 5728 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5729 */ 5730 /* binop/lit8 vAA, vBB, #+CC */ 5731 movzbl 2(rPC),%eax # eax<- BB 5732 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5733 GET_VREG_R %eax %eax # eax<- rBB 5734 andl %ecx,%eax # ex: addl %ecx,%eax 5735 FETCH_INST_OPCODE 2 %edx 5736 SET_VREG %eax rINST 5737 ADVANCE_PC 2 5738 GOTO_NEXT_R %edx 5739 5740 5741/* ------------------------------ */ 5742 .balign 64 5743.L_OP_OR_INT_LIT8: /* 0xde */ 5744/* File: x86/OP_OR_INT_LIT8.S */ 5745/* File: x86/binopLit8.S */ 5746 /* 5747 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5748 * that specifies an instruction that performs "result = eax op ecx". 5749 * This could be an x86 instruction or a function call. (If the result 5750 * comes back in a register other than r0, you can override "result".) 5751 * 5752 * For: add-int/lit8, rsub-int/lit8 5753 * and-int/lit8, or-int/lit8, xor-int/lit8, 5754 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5755 */ 5756 /* binop/lit8 vAA, vBB, #+CC */ 5757 movzbl 2(rPC),%eax # eax<- BB 5758 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5759 GET_VREG_R %eax %eax # eax<- rBB 5760 orl %ecx,%eax # ex: addl %ecx,%eax 5761 FETCH_INST_OPCODE 2 %edx 5762 SET_VREG %eax rINST 5763 ADVANCE_PC 2 5764 GOTO_NEXT_R %edx 5765 5766 5767/* ------------------------------ */ 5768 .balign 64 5769.L_OP_XOR_INT_LIT8: /* 0xdf */ 5770/* File: x86/OP_XOR_INT_LIT8.S */ 5771/* File: x86/binopLit8.S */ 5772 /* 5773 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5774 * that specifies an instruction that performs "result = eax op ecx". 5775 * This could be an x86 instruction or a function call. (If the result 5776 * comes back in a register other than r0, you can override "result".) 5777 * 5778 * For: add-int/lit8, rsub-int/lit8 5779 * and-int/lit8, or-int/lit8, xor-int/lit8, 5780 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5781 */ 5782 /* binop/lit8 vAA, vBB, #+CC */ 5783 movzbl 2(rPC),%eax # eax<- BB 5784 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5785 GET_VREG_R %eax %eax # eax<- rBB 5786 xor %ecx,%eax # ex: addl %ecx,%eax 5787 FETCH_INST_OPCODE 2 %edx 5788 SET_VREG %eax rINST 5789 ADVANCE_PC 2 5790 GOTO_NEXT_R %edx 5791 5792 5793/* ------------------------------ */ 5794 .balign 64 5795.L_OP_SHL_INT_LIT8: /* 0xe0 */ 5796/* File: x86/OP_SHL_INT_LIT8.S */ 5797/* File: x86/binopLit8.S */ 5798 /* 5799 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5800 * that specifies an instruction that performs "result = eax op ecx". 5801 * This could be an x86 instruction or a function call. (If the result 5802 * comes back in a register other than r0, you can override "result".) 5803 * 5804 * For: add-int/lit8, rsub-int/lit8 5805 * and-int/lit8, or-int/lit8, xor-int/lit8, 5806 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5807 */ 5808 /* binop/lit8 vAA, vBB, #+CC */ 5809 movzbl 2(rPC),%eax # eax<- BB 5810 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5811 GET_VREG_R %eax %eax # eax<- rBB 5812 sall %cl,%eax # ex: addl %ecx,%eax 5813 FETCH_INST_OPCODE 2 %edx 5814 SET_VREG %eax rINST 5815 ADVANCE_PC 2 5816 GOTO_NEXT_R %edx 5817 5818 5819/* ------------------------------ */ 5820 .balign 64 5821.L_OP_SHR_INT_LIT8: /* 0xe1 */ 5822/* File: x86/OP_SHR_INT_LIT8.S */ 5823/* File: x86/binopLit8.S */ 5824 /* 5825 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5826 * that specifies an instruction that performs "result = eax op ecx". 5827 * This could be an x86 instruction or a function call. (If the result 5828 * comes back in a register other than r0, you can override "result".) 5829 * 5830 * For: add-int/lit8, rsub-int/lit8 5831 * and-int/lit8, or-int/lit8, xor-int/lit8, 5832 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5833 */ 5834 /* binop/lit8 vAA, vBB, #+CC */ 5835 movzbl 2(rPC),%eax # eax<- BB 5836 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5837 GET_VREG_R %eax %eax # eax<- rBB 5838 sarl %cl,%eax # ex: addl %ecx,%eax 5839 FETCH_INST_OPCODE 2 %edx 5840 SET_VREG %eax rINST 5841 ADVANCE_PC 2 5842 GOTO_NEXT_R %edx 5843 5844 5845/* ------------------------------ */ 5846 .balign 64 5847.L_OP_USHR_INT_LIT8: /* 0xe2 */ 5848/* File: x86/OP_USHR_INT_LIT8.S */ 5849/* File: x86/binopLit8.S */ 5850 /* 5851 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5852 * that specifies an instruction that performs "result = eax op ecx". 5853 * This could be an x86 instruction or a function call. (If the result 5854 * comes back in a register other than r0, you can override "result".) 5855 * 5856 * For: add-int/lit8, rsub-int/lit8 5857 * and-int/lit8, or-int/lit8, xor-int/lit8, 5858 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5859 */ 5860 /* binop/lit8 vAA, vBB, #+CC */ 5861 movzbl 2(rPC),%eax # eax<- BB 5862 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5863 GET_VREG_R %eax %eax # eax<- rBB 5864 shrl %cl,%eax # ex: addl %ecx,%eax 5865 FETCH_INST_OPCODE 2 %edx 5866 SET_VREG %eax rINST 5867 ADVANCE_PC 2 5868 GOTO_NEXT_R %edx 5869 5870 5871/* ------------------------------ */ 5872 .balign 64 5873.L_OP_IGET_VOLATILE: /* 0xe3 */ 5874/* File: x86/OP_IGET_VOLATILE.S */ 5875/* File: x86/OP_IGET.S */ 5876 /* 5877 * General 32-bit instance field get. 5878 * 5879 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 5880 */ 5881 /* op vA, vB, field@CCCC */ 5882 movl rGLUE,%ecx 5883 movzwl 2(rPC),%edx # edx<- 0000CCCC 5884 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 5885 movzbl rINSTbl,%ecx # ecx<- BA 5886 sarl $4,%ecx # ecx<- B 5887 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 5888 andb $0xf,rINSTbl # rINST<- A 5889 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 5890 movl (%eax,%edx,4),%eax # resolved entry 5891 testl %eax,%eax # is resolved entry null? 5892 jne .LOP_IGET_VOLATILE_finish # no, already resolved 5893 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 5894 movl rGLUE,%edx 5895 jmp .LOP_IGET_VOLATILE_resolve 5896 5897 5898/* ------------------------------ */ 5899 .balign 64 5900.L_OP_IPUT_VOLATILE: /* 0xe4 */ 5901/* File: x86/OP_IPUT_VOLATILE.S */ 5902/* File: x86/OP_IPUT.S */ 5903 5904 /* 5905 * General 32-bit instance field put. 5906 * 5907 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 5908 */ 5909 /* op vA, vB, field@CCCC */ 5910 movl rGLUE,%ecx 5911 movzwl 2(rPC),%edx # %edx<- 0000CCCC 5912 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 5913 movzbl rINSTbl,%ecx # ecx<- BA 5914 sarl $4,%ecx # ecx<- B 5915 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 5916 andb $0xf,rINSTbl # rINST<- A 5917 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 5918 movl (%eax,%edx,4),%eax # resolved entry 5919 testl %eax,%eax # is resolved entry null? 5920 jne .LOP_IPUT_VOLATILE_finish # no, already resolved 5921 movl %edx,OUT_ARG1(%esp) 5922 movl rGLUE,%edx 5923 jmp .LOP_IPUT_VOLATILE_resolve 5924 5925 5926/* ------------------------------ */ 5927 .balign 64 5928.L_OP_SGET_VOLATILE: /* 0xe5 */ 5929/* File: x86/OP_SGET_VOLATILE.S */ 5930/* File: x86/OP_SGET.S */ 5931 /* 5932 * General 32-bit SGET handler. 5933 * 5934 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 5935 */ 5936 /* op vAA, field@BBBB */ 5937 movl rGLUE,%ecx 5938 movzwl 2(rPC),%eax # eax<- field ref BBBB 5939 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 5940 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 5941 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 5942 testl %eax,%eax # resolved entry null? 5943 je .LOP_SGET_VOLATILE_resolve # if not, make it so 5944.LOP_SGET_VOLATILE_finish: # field ptr in eax 5945 movl offStaticField_value(%eax),%eax 5946 FETCH_INST_OPCODE 2 %edx 5947 ADVANCE_PC 2 5948 SET_VREG %eax rINST 5949 GOTO_NEXT_R %edx 5950 5951 5952/* ------------------------------ */ 5953 .balign 64 5954.L_OP_SPUT_VOLATILE: /* 0xe6 */ 5955/* File: x86/OP_SPUT_VOLATILE.S */ 5956/* File: x86/OP_SPUT.S */ 5957 /* 5958 * General 32-bit SPUT handler. 5959 * 5960 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 5961 */ 5962 /* op vAA, field@BBBB */ 5963 movl rGLUE,%ecx 5964 movzwl 2(rPC),%eax # eax<- field ref BBBB 5965 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 5966 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 5967 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 5968 testl %eax,%eax # resolved entry null? 5969 je .LOP_SPUT_VOLATILE_resolve # if not, make it so 5970.LOP_SPUT_VOLATILE_finish: # field ptr in eax 5971 GET_VREG_R %ecx rINST 5972 FETCH_INST_OPCODE 2 %edx 5973 ADVANCE_PC 2 5974 movl %ecx,offStaticField_value(%eax) 5975 GOTO_NEXT_R %edx 5976 5977 5978/* ------------------------------ */ 5979 .balign 64 5980.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ 5981/* File: x86/OP_IGET_OBJECT_VOLATILE.S */ 5982/* File: x86/OP_IGET.S */ 5983 /* 5984 * General 32-bit instance field get. 5985 * 5986 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 5987 */ 5988 /* op vA, vB, field@CCCC */ 5989 movl rGLUE,%ecx 5990 movzwl 2(rPC),%edx # edx<- 0000CCCC 5991 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 5992 movzbl rINSTbl,%ecx # ecx<- BA 5993 sarl $4,%ecx # ecx<- B 5994 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 5995 andb $0xf,rINSTbl # rINST<- A 5996 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 5997 movl (%eax,%edx,4),%eax # resolved entry 5998 testl %eax,%eax # is resolved entry null? 5999 jne .LOP_IGET_OBJECT_VOLATILE_finish # no, already resolved 6000 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 6001 movl rGLUE,%edx 6002 jmp .LOP_IGET_OBJECT_VOLATILE_resolve 6003 6004 6005/* ------------------------------ */ 6006 .balign 64 6007.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 6008 /* (stub) */ 6009 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx 6010 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 6011 call dvmMterp_OP_IGET_WIDE_VOLATILE # do the real work 6012 mov rGLUE,%ecx 6013 LOAD_PC_FP_FROM_GLUE # retrieve updated values 6014 FETCH_INST 6015 GOTO_NEXT 6016/* ------------------------------ */ 6017 .balign 64 6018.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 6019 /* (stub) */ 6020 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx 6021 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 6022 call dvmMterp_OP_IPUT_WIDE_VOLATILE # do the real work 6023 mov rGLUE,%ecx 6024 LOAD_PC_FP_FROM_GLUE # retrieve updated values 6025 FETCH_INST 6026 GOTO_NEXT 6027/* ------------------------------ */ 6028 .balign 64 6029.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 6030 /* (stub) */ 6031 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx 6032 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 6033 call dvmMterp_OP_SGET_WIDE_VOLATILE # do the real work 6034 mov rGLUE,%ecx 6035 LOAD_PC_FP_FROM_GLUE # retrieve updated values 6036 FETCH_INST 6037 GOTO_NEXT 6038/* ------------------------------ */ 6039 .balign 64 6040.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 6041 /* (stub) */ 6042 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx 6043 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 6044 call dvmMterp_OP_SPUT_WIDE_VOLATILE # do the real work 6045 mov rGLUE,%ecx 6046 LOAD_PC_FP_FROM_GLUE # retrieve updated values 6047 FETCH_INST 6048 GOTO_NEXT 6049/* ------------------------------ */ 6050 .balign 64 6051.L_OP_BREAKPOINT: /* 0xec */ 6052/* File: x86/OP_BREAKPOINT.S */ 6053/* File: x86/unused.S */ 6054 jmp common_abort 6055 6056 6057/* ------------------------------ */ 6058 .balign 64 6059.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 6060/* File: x86/OP_THROW_VERIFICATION_ERROR.S */ 6061 /* 6062 * Handle a throw-verification-error instruction. This throws an 6063 * exception for an error discovered during verification. The 6064 * exception is indicated by AA, with some detail provided by BBBB. 6065 */ 6066 /* op AA, ref@BBBB */ 6067 movl rGLUE,%ecx 6068 movzwl 2(rPC),%eax # eax<- BBBB 6069 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6070 EXPORT_PC 6071 movl %eax,OUT_ARG2(%esp) # arg2<- BBBB 6072 movl rINST,OUT_ARG1(%esp) # arg1<- AA 6073 movl %ecx,OUT_ARG0(%esp) # arg0<- method 6074 call dvmThrowVerificationError # call(method, kind, ref) 6075 jmp common_exceptionThrown # handle exception 6076 6077/* ------------------------------ */ 6078 .balign 64 6079.L_OP_EXECUTE_INLINE: /* 0xee */ 6080/* File: x86/OP_EXECUTE_INLINE.S */ 6081 /* 6082 * Execute a "native inline" instruction. 6083 * 6084 * We will be calling through a function table: 6085 * 6086 * (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, pResult) 6087 * 6088 * Ignores argument count - always loads 4. 6089 * 6090 */ 6091 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 6092 movl rGLUE,%ecx 6093 EXPORT_PC 6094 movzwl 2(rPC),%eax # eax<- BBBB 6095 leal offGlue_retval(%ecx),%ecx # ecx<- & glue->retval 6096 movl %ecx,OUT_ARG4(%esp) 6097 call .LOP_EXECUTE_INLINE_continue # make call; will return after 6098 testl %eax,%eax # successful? 6099 FETCH_INST_OPCODE 3 %edx 6100 je common_exceptionThrown # no, handle exception 6101 ADVANCE_PC 3 6102 GOTO_NEXT_R %edx 6103 6104/* ------------------------------ */ 6105 .balign 64 6106.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 6107 /* (stub) */ 6108 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx 6109 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 6110 call dvmMterp_OP_EXECUTE_INLINE_RANGE # do the real work 6111 mov rGLUE,%ecx 6112 LOAD_PC_FP_FROM_GLUE # retrieve updated values 6113 FETCH_INST 6114 GOTO_NEXT 6115/* ------------------------------ */ 6116 .balign 64 6117.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 6118/* File: x86/OP_INVOKE_DIRECT_EMPTY.S */ 6119 /* 6120 * invoke-direct-empty is a no-op in a "standard" interpreter. 6121 */ 6122 FETCH_INST_WORD 3 6123 ADVANCE_PC 3 6124 GOTO_NEXT 6125 6126/* ------------------------------ */ 6127 .balign 64 6128.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */ 6129 /* (stub) */ 6130 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx 6131 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 6132 call dvmMterp_OP_RETURN_VOID_BARRIER # do the real work 6133 mov rGLUE,%ecx 6134 LOAD_PC_FP_FROM_GLUE # retrieve updated values 6135 FETCH_INST 6136 GOTO_NEXT 6137/* ------------------------------ */ 6138 .balign 64 6139.L_OP_IGET_QUICK: /* 0xf2 */ 6140/* File: x86/OP_IGET_QUICK.S */ 6141 /* For: iget-quick, iget-object-quick */ 6142 /* op vA, vB, offset@CCCC */ 6143 movzbl rINSTbl,%ecx # ecx<- BA 6144 sarl $4,%ecx # ecx<- B 6145 GET_VREG_R %ecx %ecx # vB (object we're operating on) 6146 movzwl 2(rPC),%eax # eax<- field byte offset 6147 cmpl $0,%ecx # is object null? 6148 je common_errNullObject 6149 movl (%ecx,%eax,1),%eax 6150 FETCH_INST_OPCODE 2 %edx 6151 ADVANCE_PC 2 6152 andb $0xf,rINSTbl # rINST<- A 6153 SET_VREG %eax rINST # fp[A]<- result 6154 GOTO_NEXT_R %edx 6155 6156/* ------------------------------ */ 6157 .balign 64 6158.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 6159/* File: x86/OP_IGET_WIDE_QUICK.S */ 6160 /* For: iget-wide-quick */ 6161 /* op vA, vB, offset@CCCC */ 6162 movzbl rINSTbl,%ecx # ecx<- BA 6163 sarl $4,%ecx # ecx<- B 6164 GET_VREG_R %ecx %ecx # vB (object we're operating on) 6165 movzwl 2(rPC),%eax # eax<- field byte offset 6166 cmpl $0,%ecx # is object null? 6167 je common_errNullObject 6168 leal (%ecx,%eax,1),%eax # eax<- address of 64-bit source 6169 movl (%eax),%ecx # ecx<- lsw 6170 movl 4(%eax),%eax # eax<- msw 6171 andb $0xf,rINSTbl # rINST<- A 6172 FETCH_INST_OPCODE 2 %edx 6173 SET_VREG_WORD %ecx rINST 0 # v[A+0]<- lsw 6174 SET_VREG_WORD %eax rINST 1 # v[A+1]<- msw 6175 ADVANCE_PC 2 6176 GOTO_NEXT_R %edx 6177 6178/* ------------------------------ */ 6179 .balign 64 6180.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 6181/* File: x86/OP_IGET_OBJECT_QUICK.S */ 6182/* File: x86/OP_IGET_QUICK.S */ 6183 /* For: iget-quick, iget-object-quick */ 6184 /* op vA, vB, offset@CCCC */ 6185 movzbl rINSTbl,%ecx # ecx<- BA 6186 sarl $4,%ecx # ecx<- B 6187 GET_VREG_R %ecx %ecx # vB (object we're operating on) 6188 movzwl 2(rPC),%eax # eax<- field byte offset 6189 cmpl $0,%ecx # is object null? 6190 je common_errNullObject 6191 movl (%ecx,%eax,1),%eax 6192 FETCH_INST_OPCODE 2 %edx 6193 ADVANCE_PC 2 6194 andb $0xf,rINSTbl # rINST<- A 6195 SET_VREG %eax rINST # fp[A]<- result 6196 GOTO_NEXT_R %edx 6197 6198 6199/* ------------------------------ */ 6200 .balign 64 6201.L_OP_IPUT_QUICK: /* 0xf5 */ 6202/* File: x86/OP_IPUT_QUICK.S */ 6203 /* For: iput-quick */ 6204 /* op vA, vB, offset@CCCC */ 6205 movzbl rINSTbl,%ecx # ecx<- BA 6206 sarl $4,%ecx # ecx<- B 6207 GET_VREG_R %ecx %ecx # vB (object we're operating on) 6208 andb $0xf,rINSTbl # rINST<- A 6209 GET_VREG_R rINST,rINST # rINST<- v[A] 6210 movzwl 2(rPC),%eax # eax<- field byte offset 6211 testl %ecx,%ecx # is object null? 6212 FETCH_INST_OPCODE 2 %edx 6213 je common_errNullObject 6214 movl rINST,(%ecx,%eax,1) 6215 ADVANCE_PC 2 6216 GOTO_NEXT_R %edx 6217 6218/* ------------------------------ */ 6219 .balign 64 6220.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 6221/* File: x86/OP_IPUT_WIDE_QUICK.S */ 6222 /* For: iput-wide-quick */ 6223 /* op vA, vB, offset@CCCC */ 6224 movzbl rINSTbl,%ecx # ecx<- BA 6225 sarl $4,%ecx # ecx<- B 6226 GET_VREG_R %ecx %ecx # vB (object we're operating on) 6227 movzwl 2(rPC),%eax # eax<- field byte offset 6228 testl %ecx,%ecx # is object null? 6229 je common_errNullObject 6230 leal (%ecx,%eax,1),%ecx # ecx<- Address of 64-bit target 6231 andb $0xf,rINSTbl # rINST<- A 6232 GET_VREG_WORD %eax rINST 0 # eax<- lsw 6233 GET_VREG_WORD rINST rINST 1 # rINST<- msw 6234 FETCH_INST_OPCODE 2 %edx 6235 movl %eax,(%ecx) 6236 movl rINST,4(%ecx) 6237 ADVANCE_PC 2 6238 GOTO_NEXT_R %edx 6239 6240/* ------------------------------ */ 6241 .balign 64 6242.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 6243/* File: x86/OP_IPUT_OBJECT_QUICK.S */ 6244 /* For: iput-object-quick */ 6245 /* op vA, vB, offset@CCCC */ 6246 movzbl rINSTbl,%ecx # ecx<- BA 6247 sarl $4,%ecx # ecx<- B 6248 GET_VREG_R %ecx %ecx # vB (object we're operating on) 6249 andb $0xf,rINSTbl # rINST<- A 6250 GET_VREG_R rINST rINST # rINST<- v[A] 6251 movzwl 2(rPC),%eax # eax<- field byte offset 6252 testl %ecx,%ecx # is object null? 6253 je common_errNullObject 6254 movl rINST,(%ecx,%eax,1) 6255 movl rGLUE,%eax 6256 jmp .LOP_IPUT_OBJECT_QUICK_finish 6257 6258/* ------------------------------ */ 6259 .balign 64 6260.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 6261/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */ 6262 /* 6263 * Handle an optimized virtual method call. 6264 * 6265 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 6266 */ 6267 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6268 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6269 movzwl 4(rPC),%eax # eax<- FEDC or CCCC 6270 movzwl 2(rPC),%ecx # ecx<- BBBB 6271 .if (!0) 6272 andl $0xf,%eax # eax<- C (or stays CCCC) 6273 .endif 6274 GET_VREG_R %eax %eax # eax<- vC ("this" ptr) 6275 testl %eax,%eax # null? 6276 je common_errNullObject # yep, throw exception 6277 movl offObject_clazz(%eax),%eax # eax<- thisPtr->clazz 6278 movl offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable 6279 EXPORT_PC # might throw later - get ready 6280 movl (%eax,%ecx,4),%eax # eax<- vtable[BBBB] 6281 jmp common_invokeMethodNoRange 6282 6283/* ------------------------------ */ 6284 .balign 64 6285.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 6286/* File: x86/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 6287/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */ 6288 /* 6289 * Handle an optimized virtual method call. 6290 * 6291 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 6292 */ 6293 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6294 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6295 movzwl 4(rPC),%eax # eax<- FEDC or CCCC 6296 movzwl 2(rPC),%ecx # ecx<- BBBB 6297 .if (!1) 6298 andl $0xf,%eax # eax<- C (or stays CCCC) 6299 .endif 6300 GET_VREG_R %eax %eax # eax<- vC ("this" ptr) 6301 testl %eax,%eax # null? 6302 je common_errNullObject # yep, throw exception 6303 movl offObject_clazz(%eax),%eax # eax<- thisPtr->clazz 6304 movl offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable 6305 EXPORT_PC # might throw later - get ready 6306 movl (%eax,%ecx,4),%eax # eax<- vtable[BBBB] 6307 jmp common_invokeMethodRange 6308 6309 6310/* ------------------------------ */ 6311 .balign 64 6312.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 6313/* File: x86/OP_INVOKE_SUPER_QUICK.S */ 6314 /* 6315 * Handle an optimized "super" method call. 6316 * 6317 * for: [opt] invoke-super-quick, invoke-super-quick/range 6318 */ 6319 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6320 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6321 movl rGLUE,%ecx 6322 movzwl 4(rPC),%eax # eax<- GFED or CCCC 6323 movl offGlue_method(%ecx),%ecx # ecx<- current method 6324 .if (!0) 6325 andl $0xf,%eax # eax<- D (or stays CCCC) 6326 .endif 6327 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6328 GET_VREG_R %eax %eax # eax<- "this" 6329 movl offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super 6330 testl %eax,%eax # null "this"? 6331 je common_errNullObject # "this" is null, throw exception 6332 movzwl 2(rPC),%eax # eax<- BBBB 6333 movl offClassObject_vtable(%ecx),%ecx # ecx<- vtable 6334 EXPORT_PC 6335 movl (%ecx,%eax,4),%eax # eax<- super->vtable[BBBB] 6336 jmp common_invokeMethodNoRange 6337 6338/* ------------------------------ */ 6339 .balign 64 6340.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 6341/* File: x86/OP_INVOKE_SUPER_QUICK_RANGE.S */ 6342/* File: x86/OP_INVOKE_SUPER_QUICK.S */ 6343 /* 6344 * Handle an optimized "super" method call. 6345 * 6346 * for: [opt] invoke-super-quick, invoke-super-quick/range 6347 */ 6348 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6349 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6350 movl rGLUE,%ecx 6351 movzwl 4(rPC),%eax # eax<- GFED or CCCC 6352 movl offGlue_method(%ecx),%ecx # ecx<- current method 6353 .if (!1) 6354 andl $0xf,%eax # eax<- D (or stays CCCC) 6355 .endif 6356 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6357 GET_VREG_R %eax %eax # eax<- "this" 6358 movl offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super 6359 testl %eax,%eax # null "this"? 6360 je common_errNullObject # "this" is null, throw exception 6361 movzwl 2(rPC),%eax # eax<- BBBB 6362 movl offClassObject_vtable(%ecx),%ecx # ecx<- vtable 6363 EXPORT_PC 6364 movl (%ecx,%eax,4),%eax # eax<- super->vtable[BBBB] 6365 jmp common_invokeMethodRange 6366 6367 6368/* ------------------------------ */ 6369 .balign 64 6370.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 6371/* File: x86/OP_IPUT_OBJECT_VOLATILE.S */ 6372/* File: x86/OP_IPUT_OBJECT.S */ 6373 /* 6374 * Object field put. 6375 * 6376 * for: iput-object 6377 */ 6378 /* op vA, vB, field@CCCC */ 6379 movl rGLUE,%ecx 6380 movzwl 2(rPC),%edx # edx<- 0000CCCC 6381 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 6382 movzbl rINSTbl,%ecx # ecx<- BA 6383 sarl $4,%ecx # ecx<- B 6384 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 6385 andb $0xf,rINSTbl # rINST<- A 6386 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 6387 movl (%eax,%edx,4),%eax # resolved entry 6388 testl %eax,%eax # is resolved entry null? 6389 jne .LOP_IPUT_OBJECT_VOLATILE_finish # no, already resolved 6390 movl %edx,OUT_ARG1(%esp) 6391 movl rGLUE,%edx 6392 jmp .LOP_IPUT_OBJECT_VOLATILE_resolve 6393 6394 6395/* ------------------------------ */ 6396 .balign 64 6397.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 6398/* File: x86/OP_SGET_OBJECT_VOLATILE.S */ 6399/* File: x86/OP_SGET.S */ 6400 /* 6401 * General 32-bit SGET handler. 6402 * 6403 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 6404 */ 6405 /* op vAA, field@BBBB */ 6406 movl rGLUE,%ecx 6407 movzwl 2(rPC),%eax # eax<- field ref BBBB 6408 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 6409 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 6410 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 6411 testl %eax,%eax # resolved entry null? 6412 je .LOP_SGET_OBJECT_VOLATILE_resolve # if not, make it so 6413.LOP_SGET_OBJECT_VOLATILE_finish: # field ptr in eax 6414 movl offStaticField_value(%eax),%eax 6415 FETCH_INST_OPCODE 2 %edx 6416 ADVANCE_PC 2 6417 SET_VREG %eax rINST 6418 GOTO_NEXT_R %edx 6419 6420 6421/* ------------------------------ */ 6422 .balign 64 6423.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 6424/* File: x86/OP_SPUT_OBJECT_VOLATILE.S */ 6425/* File: x86/OP_SPUT_OBJECT.S */ 6426 /* 6427 * SPUT object handler. 6428 */ 6429 /* op vAA, field@BBBB */ 6430 movl rGLUE,%ecx 6431 movzwl 2(rPC),%eax # eax<- field ref BBBB 6432 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 6433 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 6434 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField 6435 testl %eax,%eax # resolved entry null? 6436 je .LOP_SPUT_OBJECT_VOLATILE_resolve # if not, make it so 6437.LOP_SPUT_OBJECT_VOLATILE_finish: # field ptr in eax 6438 movzbl rINSTbl,%ecx # ecx<- AA 6439 GET_VREG_R %ecx %ecx 6440 jmp .LOP_SPUT_OBJECT_VOLATILE_continue 6441 6442 6443/* ------------------------------ */ 6444 .balign 64 6445.L_OP_DISPATCH_FF: /* 0xff */ 6446/* File: x86/OP_DISPATCH_FF.S */ 6447/* File: x86/unused.S */ 6448 jmp common_abort 6449 6450 6451 6452 .balign 64 6453 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 6454 .global dvmAsmInstructionEnd 6455dvmAsmInstructionEnd: 6456 6457/* 6458 * =========================================================================== 6459 * Sister implementations 6460 * =========================================================================== 6461 */ 6462 .global dvmAsmSisterStart 6463 .type dvmAsmSisterStart, %function 6464 .text 6465 .balign 4 6466dvmAsmSisterStart: 6467 6468/* continuation for OP_CONST_STRING */ 6469 6470/* This is the less common path, so we'll redo some work 6471 here rather than force spills on the common path */ 6472.LOP_CONST_STRING_resolve: 6473 movl rGLUE,%eax 6474 movl %ecx,rINST # rINST<- AA 6475 EXPORT_PC 6476 movl offGlue_method(%eax),%eax # eax<- glue->method 6477 movzwl 2(rPC),%ecx # ecx<- BBBB 6478 movl offMethod_clazz(%eax),%eax 6479 movl %ecx,OUT_ARG1(%esp) 6480 movl %eax,OUT_ARG0(%esp) 6481 call dvmResolveString # go resolve 6482 testl %eax,%eax # failed? 6483 je common_exceptionThrown 6484 SET_VREG %eax rINST 6485 FETCH_INST_OPCODE 2 %edx 6486 ADVANCE_PC 2 6487 GOTO_NEXT_R %edx 6488 6489/* continuation for OP_CONST_STRING_JUMBO */ 6490 6491/* This is the less common path, so we'll redo some work 6492 here rather than force spills on the common path */ 6493.LOP_CONST_STRING_JUMBO_resolve: 6494 movl rGLUE,%eax 6495 movl %ecx,rINST # rINST<- AA 6496 EXPORT_PC 6497 movl offGlue_method(%eax),%eax # eax<- glue->method 6498 movl 2(rPC),%ecx # ecx<- BBBBBBBB 6499 movl offMethod_clazz(%eax),%eax 6500 movl %ecx,OUT_ARG1(%esp) 6501 movl %eax,OUT_ARG0(%esp) 6502 call dvmResolveString # go resolve 6503 testl %eax,%eax # failed? 6504 je common_exceptionThrown 6505 SET_VREG %eax rINST 6506 FETCH_INST_OPCODE 3 %edx 6507 ADVANCE_PC 3 6508 GOTO_NEXT_R %edx 6509 6510/* continuation for OP_CONST_CLASS */ 6511 6512/* This is the less common path, so we'll redo some work 6513 here rather than force spills on the common path */ 6514.LOP_CONST_CLASS_resolve: 6515 movl rGLUE,%eax 6516 movl %ecx,rINST # rINST<- AA 6517 EXPORT_PC 6518 movl offGlue_method(%eax),%eax # eax<- glue->method 6519 movl $1,OUT_ARG2(%esp) # true 6520 movzwl 2(rPC),%ecx # ecx<- BBBB 6521 movl offMethod_clazz(%eax),%eax 6522 movl %ecx,OUT_ARG1(%esp) 6523 movl %eax,OUT_ARG0(%esp) 6524 call dvmResolveClass # go resolve 6525 testl %eax,%eax # failed? 6526 je common_exceptionThrown 6527 SET_VREG %eax rINST 6528 FETCH_INST_OPCODE 2 %edx 6529 ADVANCE_PC 2 6530 GOTO_NEXT_R %edx 6531 6532/* continuation for OP_MONITOR_ENTER */ 6533 6534.LOP_MONITOR_ENTER_continue: 6535 movl %ecx,OUT_ARG0(%esp) 6536 movl %eax,OUT_ARG1(%esp) 6537 call dvmLockObject # dvmLockObject(self,object) 6538#ifdef WITH_DEADLOCK_PREDICTION 6539 movl rGLUE,%ecx 6540 movl offGlueSelf(%ecx),%ecx # ecx<- glue->self 6541 movl offThread_exception(%ecx),%eax 6542 testl %eax,%eax 6543 jne common_exceptionThrown 6544#endif 6545 ADVANCE_PC 1 6546 GOTO_NEXT 6547 6548/* continuation for OP_MONITOR_EXIT */ 6549 6550.LOP_MONITOR_EXIT_continue: 6551 call dvmUnlockObject # unlock(self,obj) 6552 FETCH_INST_OPCODE 1 %edx 6553 testl %eax,%eax # success? 6554 ADVANCE_PC 1 6555 je common_exceptionThrown # no, exception pending 6556 GOTO_NEXT_R %edx 6557.LOP_MONITOR_EXIT_errNullObject: 6558 ADVANCE_PC 1 # advance before throw 6559 jmp common_errNullObject 6560 6561/* continuation for OP_CHECK_CAST */ 6562 6563 /* 6564 * Trivial test failed, need to perform full check. This is common. 6565 * ecx holds obj->clazz 6566 * eax holds class resolved from BBBB 6567 * rINST holds object 6568 */ 6569.LOP_CHECK_CAST_fullcheck: 6570 movl %eax,sReg0 # we'll need the desired class on failure 6571 movl %eax,OUT_ARG1(%esp) 6572 movl %ecx,OUT_ARG0(%esp) 6573 call dvmInstanceofNonTrivial # eax<- boolean result 6574 testl %eax,%eax # failed? 6575 jne .LOP_CHECK_CAST_okay # no, success 6576 6577 # A cast has failed. We need to throw a ClassCastException. 6578 EXPORT_PC 6579 movl offObject_clazz(rINST),%eax 6580 movl %eax,OUT_ARG0(%esp) # arg0<- obj->clazz 6581 movl sReg0,%ecx 6582 movl %ecx,OUT_ARG1(%esp) # arg1<- desired class 6583 call dvmThrowClassCastException 6584 jmp common_exceptionThrown 6585 6586 /* 6587 * Resolution required. This is the least-likely path, and we're 6588 * going to have to recreate some data. 6589 * 6590 * rINST holds object 6591 */ 6592.LOP_CHECK_CAST_resolve: 6593 movl rGLUE,%ecx 6594 EXPORT_PC 6595 movzwl 2(rPC),%eax # eax<- BBBB 6596 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6597 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 6598 movl offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz 6599 movl $0,OUT_ARG2(%esp) # arg2<- false 6600 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz 6601 call dvmResolveClass # eax<- resolved ClassObject ptr 6602 testl %eax,%eax # got null? 6603 je common_exceptionThrown # yes, handle exception 6604 movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz 6605 jmp .LOP_CHECK_CAST_resolved # pick up where we left off 6606 6607/* continuation for OP_INSTANCE_OF */ 6608 6609 /* 6610 * Trivial test failed, need to perform full check. This is common. 6611 * eax holds obj->clazz 6612 * ecx holds class resolved from BBBB 6613 * rINST has BA 6614 */ 6615.LOP_INSTANCE_OF_fullcheck: 6616 movl %eax,OUT_ARG0(%esp) 6617 movl %ecx,OUT_ARG1(%esp) 6618 call dvmInstanceofNonTrivial # eax<- boolean result 6619 # fall through to OP_INSTANCE_OF_store 6620 6621 /* 6622 * eax holds boolean result 6623 * rINST holds BA 6624 */ 6625.LOP_INSTANCE_OF_store: 6626 FETCH_INST_OPCODE 2 %edx 6627 andb $0xf,rINSTbl # <- A 6628 ADVANCE_PC 2 6629 SET_VREG %eax rINST # vA<- eax 6630 GOTO_NEXT_R %edx 6631 6632 /* 6633 * Trivial test succeeded, save and bail. 6634 * r9 holds A 6635 */ 6636.LOP_INSTANCE_OF_trivial: 6637 FETCH_INST_OPCODE 2 %edx 6638 andb $0xf,rINSTbl # <- A 6639 ADVANCE_PC 2 6640 movl $1,%eax 6641 SET_VREG %eax rINST # vA<- true 6642 GOTO_NEXT_R %edx 6643 6644 /* 6645 * Resolution required. This is the least-likely path. 6646 * 6647 * edx holds BBBB 6648 * rINST holds BA 6649 */ 6650.LOP_INSTANCE_OF_resolve: 6651 movl %edx,OUT_ARG1(%esp) # arg1<- BBBB 6652 movl rGLUE,%ecx 6653 movl offGlue_method(%ecx),%ecx 6654 movl $1,OUT_ARG2(%esp) # arg2<- true 6655 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6656 EXPORT_PC 6657 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz 6658 call dvmResolveClass # eax<- resolved ClassObject ptr 6659 testl %eax,%eax # success? 6660 je common_exceptionThrown # no, handle exception 6661/* Now, we need to sync up with fast path. We need eax to 6662 * hold the obj->clazz, and ecx to hold the resolved class 6663 */ 6664 movl %eax,%ecx # ecx<- resolved class 6665 movl rINST,%eax # eax<- BA 6666 sarl $4,%eax # eax<- B 6667 GET_VREG_R %eax %eax # eax<- vB (obj) 6668 movl offObject_clazz(%eax),%eax # eax<- obj->clazz 6669 jmp .LOP_INSTANCE_OF_resolved 6670 6671/* continuation for OP_NEW_INSTANCE */ 6672 6673.LOP_NEW_INSTANCE_initialized: # on entry, ecx<- class 6674 /* TODO: remove test for interface/abstract, now done in verifier */ 6675 testl $(ACC_INTERFACE|ACC_ABSTRACT),offClassObject_accessFlags(%ecx) 6676 movl $ALLOC_DONT_TRACK,OUT_ARG1(%esp) 6677 jne .LOP_NEW_INSTANCE_abstract 6678.LOP_NEW_INSTANCE_finish: # ecx=class 6679 movl %ecx,OUT_ARG0(%esp) 6680 call dvmAllocObject # eax<- new object 6681 FETCH_INST_OPCODE 2 %edx 6682 testl %eax,%eax # success? 6683 je common_exceptionThrown # no, bail out 6684 SET_VREG %eax rINST 6685 ADVANCE_PC 2 6686 GOTO_NEXT_R %edx 6687 6688 /* 6689 * Class initialization required. 6690 * 6691 * ecx holds class object 6692 */ 6693.LOP_NEW_INSTANCE_needinit: 6694 SPILL_TMP1(%ecx) # save object 6695 movl %ecx,OUT_ARG0(%esp) 6696 call dvmInitClass # initialize class 6697 UNSPILL_TMP1(%ecx) # restore object 6698 testl %eax,%eax # success? 6699 jne .LOP_NEW_INSTANCE_initialized # success, continue 6700 jmp common_exceptionThrown # go deal with init exception 6701 6702 /* 6703 * Resolution required. This is the least-likely path. 6704 * 6705 */ 6706.LOP_NEW_INSTANCE_resolve: 6707 movl rGLUE,%ecx 6708 movzwl 2(rPC),%eax 6709 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6710 movl %eax,OUT_ARG1(%esp) 6711 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6712 movl $0,OUT_ARG2(%esp) 6713 movl %ecx,OUT_ARG0(%esp) 6714 call dvmResolveClass # call(clazz,off,flags) 6715 movl %eax,%ecx # ecx<- resolved ClassObject ptr 6716 testl %ecx,%ecx # success? 6717 jne .LOP_NEW_INSTANCE_resolved # good to go 6718 jmp common_exceptionThrown # no, handle exception 6719 6720 /* 6721 * TODO: remove this 6722 * We can't instantiate an abstract class or interface, so throw an 6723 * InstantiationError with the class descriptor as the message. 6724 * 6725 * ecx holds class object 6726 */ 6727.LOP_NEW_INSTANCE_abstract: 6728 movl offClassObject_descriptor(%ecx),%eax 6729 movl $.LstrInstantiationError,OUT_ARG0(%esp) 6730 movl %eax,OUT_ARG1(%esp) 6731 call dvmThrowExceptionWithClassMessage 6732 jmp common_exceptionThrown 6733 6734/* continuation for OP_NEW_ARRAY */ 6735 6736 /* 6737 * Resolve class. (This is an uncommon case.) 6738 * ecx holds class (null here) 6739 * eax holds array length (vB) 6740 */ 6741.LOP_NEW_ARRAY_resolve: 6742 movl rGLUE,%ecx 6743 SPILL_TMP1(%eax) # save array length 6744 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6745 movzwl 2(rPC),%eax # eax<- CCCC 6746 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6747 movl %eax,OUT_ARG1(%esp) 6748 movl $0,OUT_ARG2(%esp) 6749 movl %ecx,OUT_ARG0(%esp) 6750 call dvmResolveClass # eax<- call(clazz,ref,flag) 6751 movl %eax,%ecx 6752 UNSPILL_TMP1(%eax) 6753 testl %ecx,%ecx # successful resolution? 6754 je common_exceptionThrown # no, bail. 6755# fall through to OP_NEW_ARRAY_finish 6756 6757 /* 6758 * Finish allocation 6759 * 6760 * ecx holds class 6761 * eax holds array length (vB) 6762 */ 6763.LOP_NEW_ARRAY_finish: 6764 movl %ecx,OUT_ARG0(%esp) 6765 movl %eax,OUT_ARG1(%esp) 6766 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) 6767 call dvmAllocArrayByClass # eax<- call(clazz,length,flags) 6768 FETCH_INST_OPCODE 2 %edx 6769 testl %eax,%eax # failed? 6770 je common_exceptionThrown # yup - go handle 6771 SET_VREG %eax rINST 6772 ADVANCE_PC 2 6773 GOTO_NEXT_R %edx 6774 6775/* continuation for OP_FILLED_NEW_ARRAY */ 6776 6777.LOP_FILLED_NEW_ARRAY_more: 6778 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 6779 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 6780 call dvmResolveClass # eax<- call(clazz,ref,flag) 6781 testl %eax,%eax # null? 6782 je common_exceptionThrown # yes, handle it 6783 6784 # note: fall through to .LOP_FILLED_NEW_ARRAY_continue 6785 6786 /* 6787 * On entry: 6788 * eax holds array class [r0] 6789 * rINST holds AA or BB [r10] 6790 * ecx is scratch 6791 */ 6792.LOP_FILLED_NEW_ARRAY_continue: 6793 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor 6794 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags 6795 movzbl 1(%ecx),%ecx # ecx<- descriptor[1] 6796 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass 6797 movl rGLUE,%eax 6798 cmpb $'I',%cl # supported? 6799 je 1f 6800 cmpb $'L',%cl 6801 je 1f 6802 cmpb $'[',%cl 6803 jne .LOP_FILLED_NEW_ARRAY_notimpl # no, not handled yet 68041: 6805 movl %ecx,offGlue_retval+4(%eax) # save type 6806 .if (!0) 6807 SPILL_TMP1(rINST) # save copy, need "B" later 6808 sarl $4,rINST 6809 .endif 6810 movl rINST,OUT_ARG1(%esp) # arg1<- A or AA (length) 6811 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags) 6812 movl rGLUE,%ecx 6813 testl %eax,%eax # alloc successful? 6814 je common_exceptionThrown # no, handle exception 6815 movl %eax,offGlue_retval(%ecx) # retval.l<- new array 6816 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC 6817 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents 6818 6819/* at this point: 6820 * eax is pointer to tgt 6821 * rINST is length 6822 * ecx is FEDC or CCCC 6823 * TMP_SPILL1 is BA 6824 * We now need to copy values from registers into the array 6825 */ 6826 6827 .if 0 6828 # set up src pointer 6829 SPILL_TMP2(%esi) 6830 SPILL_TMP3(%edi) 6831 leal (rFP,%ecx,4),%esi # set up src ptr 6832 movl %eax,%edi # set up dst ptr 6833 movl rINST,%ecx # load count register 6834 rep 6835 movsd 6836 UNSPILL_TMP2(%esi) 6837 UNSPILL_TMP3(%edi) 6838 movl rGLUE,%ecx 6839 movl offGlue_retval+4(%ecx),%eax # eax<- type 6840 FETCH_INST_OPCODE 3 %edx 6841 .else 6842 testl rINST,rINST 6843 je 4f 6844 UNSPILL_TMP1(%edx) # restore "BA" 6845 andl $0x0f,%edx # edx<- 0000000A 6846 sall $16,%edx # edx<- 000A0000 6847 orl %ecx,%edx # edx<- 000AFEDC 68483: 6849 movl $0xf,%ecx 6850 andl %edx,%ecx # ecx<- next reg to load 6851 GET_VREG_R %ecx %ecx 6852 shrl $4,%edx 6853 leal 4(%eax),%eax 6854 movl %ecx,-4(%eax) 6855 sub $1,rINST 6856 jne 3b 68574: 6858 movl rGLUE,%ecx 6859 movl offGlue_retval+4(%ecx),%eax # eax<- type 6860 FETCH_INST_OPCODE 3 %edx 6861 .endif 6862 6863 cmpb $'I',%al # Int array? 6864 je 5f # skip card mark if so 6865 movl offGlue_retval(%ecx),%eax # eax<- object head 6866 movl offGlue_cardTable(%ecx),%ecx # card table base 6867 shrl $GC_CARD_SHIFT,%eax # convert to card num 6868 movb %cl,(%ecx,%eax) # mark card based on object head 68695: 6870 ADVANCE_PC 3 6871 GOTO_NEXT_R %edx 6872 6873 6874 /* 6875 * Throw an exception indicating that we have not implemented this 6876 * mode of filled-new-array. 6877 */ 6878.LOP_FILLED_NEW_ARRAY_notimpl: 6879 movl $.LstrInternalErrorA,%eax 6880 movl %eax,OUT_ARG0(%esp) 6881 movl $.LstrFilledNewArrayNotImplA,%eax 6882 movl %eax,OUT_ARG1(%esp) 6883 call dvmThrowException 6884 jmp common_exceptionThrown 6885 6886/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 6887 6888.LOP_FILLED_NEW_ARRAY_RANGE_more: 6889 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 6890 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 6891 call dvmResolveClass # eax<- call(clazz,ref,flag) 6892 testl %eax,%eax # null? 6893 je common_exceptionThrown # yes, handle it 6894 6895 # note: fall through to .LOP_FILLED_NEW_ARRAY_RANGE_continue 6896 6897 /* 6898 * On entry: 6899 * eax holds array class [r0] 6900 * rINST holds AA or BB [r10] 6901 * ecx is scratch 6902 */ 6903.LOP_FILLED_NEW_ARRAY_RANGE_continue: 6904 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor 6905 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags 6906 movzbl 1(%ecx),%ecx # ecx<- descriptor[1] 6907 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass 6908 movl rGLUE,%eax 6909 cmpb $'I',%cl # supported? 6910 je 1f 6911 cmpb $'L',%cl 6912 je 1f 6913 cmpb $'[',%cl 6914 jne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl # no, not handled yet 69151: 6916 movl %ecx,offGlue_retval+4(%eax) # save type 6917 .if (!1) 6918 SPILL_TMP1(rINST) # save copy, need "B" later 6919 sarl $4,rINST 6920 .endif 6921 movl rINST,OUT_ARG1(%esp) # arg1<- A or AA (length) 6922 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags) 6923 movl rGLUE,%ecx 6924 testl %eax,%eax # alloc successful? 6925 je common_exceptionThrown # no, handle exception 6926 movl %eax,offGlue_retval(%ecx) # retval.l<- new array 6927 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC 6928 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents 6929 6930/* at this point: 6931 * eax is pointer to tgt 6932 * rINST is length 6933 * ecx is FEDC or CCCC 6934 * TMP_SPILL1 is BA 6935 * We now need to copy values from registers into the array 6936 */ 6937 6938 .if 1 6939 # set up src pointer 6940 SPILL_TMP2(%esi) 6941 SPILL_TMP3(%edi) 6942 leal (rFP,%ecx,4),%esi # set up src ptr 6943 movl %eax,%edi # set up dst ptr 6944 movl rINST,%ecx # load count register 6945 rep 6946 movsd 6947 UNSPILL_TMP2(%esi) 6948 UNSPILL_TMP3(%edi) 6949 movl rGLUE,%ecx 6950 movl offGlue_retval+4(%ecx),%eax # eax<- type 6951 FETCH_INST_OPCODE 3 %edx 6952 .else 6953 testl rINST,rINST 6954 je 4f 6955 UNSPILL_TMP1(%edx) # restore "BA" 6956 andl $0x0f,%edx # edx<- 0000000A 6957 sall $16,%edx # edx<- 000A0000 6958 orl %ecx,%edx # edx<- 000AFEDC 69593: 6960 movl $0xf,%ecx 6961 andl %edx,%ecx # ecx<- next reg to load 6962 GET_VREG_R %ecx %ecx 6963 shrl $4,%edx 6964 leal 4(%eax),%eax 6965 movl %ecx,-4(%eax) 6966 sub $1,rINST 6967 jne 3b 69684: 6969 movl rGLUE,%ecx 6970 movl offGlue_retval+4(%ecx),%eax # eax<- type 6971 FETCH_INST_OPCODE 3 %edx 6972 .endif 6973 6974 cmpb $'I',%al # Int array? 6975 je 5f # skip card mark if so 6976 movl offGlue_retval(%ecx),%eax # eax<- object head 6977 movl offGlue_cardTable(%ecx),%ecx # card table base 6978 shrl $GC_CARD_SHIFT,%eax # convert to card num 6979 movb %cl,(%ecx,%eax) # mark card based on object head 69805: 6981 ADVANCE_PC 3 6982 GOTO_NEXT_R %edx 6983 6984 6985 /* 6986 * Throw an exception indicating that we have not implemented this 6987 * mode of filled-new-array. 6988 */ 6989.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 6990 movl $.LstrInternalErrorA,%eax 6991 movl %eax,OUT_ARG0(%esp) 6992 movl $.LstrFilledNewArrayNotImplA,%eax 6993 movl %eax,OUT_ARG1(%esp) 6994 call dvmThrowException 6995 jmp common_exceptionThrown 6996 6997/* continuation for OP_CMPL_FLOAT */ 6998 6999.LOP_CMPL_FLOAT_isNaN: 7000 movl $-1,%ecx 7001 jmp .LOP_CMPL_FLOAT_finish 7002 7003/* continuation for OP_CMPG_FLOAT */ 7004 7005.LOP_CMPG_FLOAT_isNaN: 7006 movl $1,%ecx 7007 jmp .LOP_CMPG_FLOAT_finish 7008 7009/* continuation for OP_CMPL_DOUBLE */ 7010 7011.LOP_CMPL_DOUBLE_isNaN: 7012 movl $-1,%ecx 7013 jmp .LOP_CMPL_DOUBLE_finish 7014 7015/* continuation for OP_CMPG_DOUBLE */ 7016 7017.LOP_CMPG_DOUBLE_isNaN: 7018 movl $1,%ecx 7019 jmp .LOP_CMPG_DOUBLE_finish 7020 7021/* continuation for OP_CMP_LONG */ 7022 7023.LOP_CMP_LONG_bigger: 7024 movl $1,%ecx 7025 jmp .LOP_CMP_LONG_finish 7026.LOP_CMP_LONG_smaller: 7027 movl $-1,%ecx 7028.LOP_CMP_LONG_finish: 7029 SET_VREG %ecx rINST 7030 FETCH_INST_OPCODE 2 %edx 7031 ADVANCE_PC 2 7032 GOTO_NEXT_R %edx 7033 7034/* continuation for OP_AGET_WIDE */ 7035 7036.LOP_AGET_WIDE_finish: 7037 leal offArrayObject_contents(%eax,%ecx,8),%eax 7038 movl (%eax),%ecx 7039 movl 4(%eax),%eax 7040 SET_VREG_WORD %ecx rINST 0 7041 SET_VREG_WORD %eax rINST 1 7042 FETCH_INST_OPCODE 2 %edx 7043 ADVANCE_PC 2 7044 GOTO_NEXT_R %edx 7045 7046/* continuation for OP_APUT_WIDE */ 7047 7048.LOP_APUT_WIDE_finish: 7049 leal offArrayObject_contents(%eax,%ecx,8),%eax 7050 GET_VREG_WORD %ecx rINST 0 7051 GET_VREG_WORD rINST rINST 1 7052 movl rINST,4(%eax) 7053 FETCH_INST_OPCODE 2 %edx 7054 movl %ecx,(%eax) 7055 ADVANCE_PC 2 7056 GOTO_NEXT_R %edx 7057 7058/* continuation for OP_APUT_OBJECT */ 7059 7060 /* On entry: 7061 * eax<- array object 7062 * ecx<- index 7063 * rINST<- vAA 7064 */ 7065.LOP_APUT_OBJECT_continue: 7066 leal offArrayObject_contents(%eax,%ecx,4),%ecx 7067 testl rINST,rINST # storing null reference? 7068 je .LOP_APUT_OBJECT_skip_check 7069 SPILL_TMP1(%ecx) # save target address 7070 SPILL_TMP2(%eax) # save object head 7071 movl offObject_clazz(%eax),%eax # eax<- arrayObj->clazz 7072 movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz 7073 movl %eax,OUT_ARG1(%esp) 7074 movl %ecx,OUT_ARG0(%esp) 7075 movl %ecx,sReg0 # store the two classes for later 7076 movl %eax,sReg1 7077 call dvmCanPutArrayElement # test object type vs. array type 7078 UNSPILL_TMP1(%ecx) # recover target address 7079 testl %eax,%eax 7080 movl rGLUE,%eax 7081 jne .LOP_APUT_OBJECT_types_okay 7082 7083 # The types don't match. We need to throw an ArrayStoreException. 7084 EXPORT_PC 7085 movl sReg0,%eax # restore the two classes... 7086 movl %eax,OUT_ARG0(%esp) 7087 movl sReg1,%ecx 7088 movl %ecx,OUT_ARG1(%esp) 7089 call dvmThrowArrayStoreException # ...and throw 7090 jmp common_exceptionThrown 7091 7092.LOP_APUT_OBJECT_types_okay: 7093 movl offGlue_cardTable(%eax),%eax # get card table base 7094 movl rINST,(%ecx) # store into array 7095 UNSPILL_TMP2(%ecx) # recover object head 7096 FETCH_INST_OPCODE 2 %edx 7097 shrl $GC_CARD_SHIFT,%ecx # object head to card number 7098 movb %al,(%eax,%ecx) # mark card using object head 7099 ADVANCE_PC 2 7100 GOTO_NEXT_R %edx 7101 7102.LOP_APUT_OBJECT_skip_check: 7103 movl rINST,(%ecx) 7104 FETCH_INST_OPCODE 2 %edx 7105 ADVANCE_PC 2 7106 GOTO_NEXT_R %edx 7107 7108/* continuation for OP_IGET */ 7109 7110 7111.LOP_IGET_resolve: 7112 EXPORT_PC 7113 movl offGlue_method(%edx),%edx # edx<- current method 7114 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7115 SPILL_TMP1(%ecx) # save obj pointer across call 7116 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7117 call dvmResolveInstField # ... to dvmResolveInstField 7118 UNSPILL_TMP1(%ecx) 7119 testl %eax,%eax # returns InstrField ptr 7120 jne .LOP_IGET_finish 7121 jmp common_exceptionThrown 7122 7123.LOP_IGET_finish: 7124 /* 7125 * Currently: 7126 * eax holds resolved field 7127 * ecx holds object 7128 * rINST holds A 7129 */ 7130 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7131 testl %ecx,%ecx # object null? 7132 je common_errNullObject # object was null 7133 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7134 movl rINST,%eax # eax<- A 7135 FETCH_INST_OPCODE 2 %edx 7136 SET_VREG %ecx %eax 7137 ADVANCE_PC 2 7138 GOTO_NEXT_R %edx 7139 7140/* continuation for OP_IGET_WIDE */ 7141 7142 7143.LOP_IGET_WIDE_resolve: 7144 EXPORT_PC 7145 movl offGlue_method(%edx),%edx # edx<- current method 7146 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7147 SPILL_TMP1(%ecx) # save objpointer across call 7148 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7149 call dvmResolveInstField # ... to dvmResolveInstField 7150 UNSPILL_TMP1(%ecx) 7151 testl %eax,%eax # returns InstrField ptr 7152 jne .LOP_IGET_WIDE_finish 7153 jmp common_exceptionThrown 7154 7155.LOP_IGET_WIDE_finish: 7156 /* 7157 * Currently: 7158 * eax holds resolved field 7159 * ecx holds object 7160 * rINST holds A 7161 */ 7162 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7163 testl %ecx,%ecx # object null? 7164 je common_errNullObject # object was null 7165 leal (%ecx,%eax,1),%eax # eax<- address of field 7166 movl (%eax),%ecx # ecx<- lsw 7167 movl 4(%eax),%eax # eax<- msw 7168 FETCH_INST_OPCODE 2 %edx 7169 SET_VREG_WORD %ecx rINST 0 7170 SET_VREG_WORD %eax rINST 1 7171 ADVANCE_PC 2 7172 GOTO_NEXT_R %edx 7173 7174/* continuation for OP_IGET_OBJECT */ 7175 7176 7177.LOP_IGET_OBJECT_resolve: 7178 EXPORT_PC 7179 movl offGlue_method(%edx),%edx # edx<- current method 7180 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7181 SPILL_TMP1(%ecx) # save obj pointer across call 7182 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7183 call dvmResolveInstField # ... to dvmResolveInstField 7184 UNSPILL_TMP1(%ecx) 7185 testl %eax,%eax # returns InstrField ptr 7186 jne .LOP_IGET_OBJECT_finish 7187 jmp common_exceptionThrown 7188 7189.LOP_IGET_OBJECT_finish: 7190 /* 7191 * Currently: 7192 * eax holds resolved field 7193 * ecx holds object 7194 * rINST holds A 7195 */ 7196 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7197 testl %ecx,%ecx # object null? 7198 je common_errNullObject # object was null 7199 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7200 movl rINST,%eax # eax<- A 7201 FETCH_INST_OPCODE 2 %edx 7202 SET_VREG %ecx %eax 7203 ADVANCE_PC 2 7204 GOTO_NEXT_R %edx 7205 7206/* continuation for OP_IGET_BOOLEAN */ 7207 7208 7209.LOP_IGET_BOOLEAN_resolve: 7210 EXPORT_PC 7211 movl offGlue_method(%edx),%edx # edx<- current method 7212 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7213 SPILL_TMP1(%ecx) # save obj pointer across call 7214 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7215 call dvmResolveInstField # ... to dvmResolveInstField 7216 UNSPILL_TMP1(%ecx) 7217 testl %eax,%eax # returns InstrField ptr 7218 jne .LOP_IGET_BOOLEAN_finish 7219 jmp common_exceptionThrown 7220 7221.LOP_IGET_BOOLEAN_finish: 7222 /* 7223 * Currently: 7224 * eax holds resolved field 7225 * ecx holds object 7226 * rINST holds A 7227 */ 7228 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7229 testl %ecx,%ecx # object null? 7230 je common_errNullObject # object was null 7231 movzbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7232 movl rINST,%eax # eax<- A 7233 FETCH_INST_OPCODE 2 %edx 7234 SET_VREG %ecx %eax 7235 ADVANCE_PC 2 7236 GOTO_NEXT_R %edx 7237 7238/* continuation for OP_IGET_BYTE */ 7239 7240 7241.LOP_IGET_BYTE_resolve: 7242 EXPORT_PC 7243 movl offGlue_method(%edx),%edx # edx<- current method 7244 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7245 SPILL_TMP1(%ecx) # save obj pointer across call 7246 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7247 call dvmResolveInstField # ... to dvmResolveInstField 7248 UNSPILL_TMP1(%ecx) 7249 testl %eax,%eax # returns InstrField ptr 7250 jne .LOP_IGET_BYTE_finish 7251 jmp common_exceptionThrown 7252 7253.LOP_IGET_BYTE_finish: 7254 /* 7255 * Currently: 7256 * eax holds resolved field 7257 * ecx holds object 7258 * rINST holds A 7259 */ 7260 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7261 testl %ecx,%ecx # object null? 7262 je common_errNullObject # object was null 7263 movsbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7264 movl rINST,%eax # eax<- A 7265 FETCH_INST_OPCODE 2 %edx 7266 SET_VREG %ecx %eax 7267 ADVANCE_PC 2 7268 GOTO_NEXT_R %edx 7269 7270/* continuation for OP_IGET_CHAR */ 7271 7272 7273.LOP_IGET_CHAR_resolve: 7274 EXPORT_PC 7275 movl offGlue_method(%edx),%edx # edx<- current method 7276 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7277 SPILL_TMP1(%ecx) # save obj pointer across call 7278 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7279 call dvmResolveInstField # ... to dvmResolveInstField 7280 UNSPILL_TMP1(%ecx) 7281 testl %eax,%eax # returns InstrField ptr 7282 jne .LOP_IGET_CHAR_finish 7283 jmp common_exceptionThrown 7284 7285.LOP_IGET_CHAR_finish: 7286 /* 7287 * Currently: 7288 * eax holds resolved field 7289 * ecx holds object 7290 * rINST holds A 7291 */ 7292 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7293 testl %ecx,%ecx # object null? 7294 je common_errNullObject # object was null 7295 movzwl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7296 movl rINST,%eax # eax<- A 7297 FETCH_INST_OPCODE 2 %edx 7298 SET_VREG %ecx %eax 7299 ADVANCE_PC 2 7300 GOTO_NEXT_R %edx 7301 7302/* continuation for OP_IGET_SHORT */ 7303 7304 7305.LOP_IGET_SHORT_resolve: 7306 EXPORT_PC 7307 movl offGlue_method(%edx),%edx # edx<- current method 7308 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7309 SPILL_TMP1(%ecx) # save obj pointer across call 7310 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7311 call dvmResolveInstField # ... to dvmResolveInstField 7312 UNSPILL_TMP1(%ecx) 7313 testl %eax,%eax # returns InstrField ptr 7314 jne .LOP_IGET_SHORT_finish 7315 jmp common_exceptionThrown 7316 7317.LOP_IGET_SHORT_finish: 7318 /* 7319 * Currently: 7320 * eax holds resolved field 7321 * ecx holds object 7322 * rINST holds A 7323 */ 7324 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7325 testl %ecx,%ecx # object null? 7326 je common_errNullObject # object was null 7327 movswl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7328 movl rINST,%eax # eax<- A 7329 FETCH_INST_OPCODE 2 %edx 7330 SET_VREG %ecx %eax 7331 ADVANCE_PC 2 7332 GOTO_NEXT_R %edx 7333 7334/* continuation for OP_IPUT */ 7335 7336 7337.LOP_IPUT_resolve: 7338 EXPORT_PC 7339 movl offGlue_method(%edx),%edx # edx<- current method 7340 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7341 SPILL_TMP1(%ecx) # save obj pointer across call 7342 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7343 call dvmResolveInstField # ... to dvmResolveInstField 7344 UNSPILL_TMP1(%ecx) 7345 testl %eax,%eax # returns InstrField ptr 7346 jne .LOP_IPUT_finish 7347 jmp common_exceptionThrown 7348 7349.LOP_IPUT_finish: 7350 /* 7351 * Currently: 7352 * eax holds resolved field 7353 * ecx holds object 7354 * rINST holds A 7355 */ 7356 GET_VREG_R rINST rINST # rINST<- v[A] 7357 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7358 testl %ecx,%ecx # object null? 7359 je common_errNullObject # object was null 7360 FETCH_INST_OPCODE 2 %edx 7361 movl rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7362 ADVANCE_PC 2 7363 GOTO_NEXT_R %edx 7364 7365/* continuation for OP_IPUT_WIDE */ 7366 7367 7368.LOP_IPUT_WIDE_resolve: 7369 EXPORT_PC 7370 movl offGlue_method(%edx),%edx # edx<- current method 7371 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7372 SPILL_TMP1(%ecx) # save obj pointer across call 7373 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7374 call dvmResolveInstField # ... to dvmResolveInstField 7375 UNSPILL_TMP1(%ecx) 7376 testl %eax,%eax # ... which returns InstrField ptr 7377 jne .LOP_IPUT_WIDE_finish 7378 jmp common_exceptionThrown 7379 7380.LOP_IPUT_WIDE_finish: 7381 /* 7382 * Currently: 7383 * eax holds resolved field 7384 * ecx holds object 7385 * %edx is scratch, but needs to be unspilled 7386 * rINST holds A 7387 */ 7388 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7389 testl %ecx,%ecx # object null? 7390 je common_errNullObject # object was null 7391 leal (%ecx,%eax,1),%eax # eax<- address of field 7392 GET_VREG_WORD %ecx rINST 0 # ecx<- lsw 7393 GET_VREG_WORD rINST rINST 1 # rINST<- msw 7394 FETCH_INST_OPCODE 2 %edx 7395 movl rINST,4(%eax) 7396 movl %ecx,(%eax) 7397 ADVANCE_PC 2 7398 GOTO_NEXT_R %edx 7399 7400/* continuation for OP_IPUT_OBJECT */ 7401 7402 7403.LOP_IPUT_OBJECT_resolve: 7404 EXPORT_PC 7405 movl offGlue_method(%edx),%edx # edx<- current method 7406 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7407 SPILL_TMP1(%ecx) # save obj pointer across call 7408 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7409 call dvmResolveInstField # ... to dvmResolveInstField 7410 UNSPILL_TMP1(%ecx) 7411 testl %eax,%eax # returns InstrField ptr 7412 jne .LOP_IPUT_OBJECT_finish 7413 jmp common_exceptionThrown 7414 7415.LOP_IPUT_OBJECT_finish: 7416 /* 7417 * Currently: 7418 * eax holds resolved field 7419 * ecx holds object 7420 * %edx is scratch, but needs to be unspilled 7421 * rINST holds A 7422 */ 7423 GET_VREG_R rINST rINST # rINST<- v[A] 7424 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7425 testl %ecx,%ecx # object null? 7426 je common_errNullObject # object was null 7427 movl rINST,(%ecx,%eax) # obj.field <- v[A](8/16/32 bits) 7428 movl rGLUE,%eax 7429 testl rINST,rINST # stored a NULL? 7430 movl offGlue_cardTable(%eax),%eax # get card table base 7431 FETCH_INST_OPCODE 2 %edx 7432 je 1f # skip card mark if null store 7433 shrl $GC_CARD_SHIFT,%ecx # object head to card number 7434 movb %al,(%eax,%ecx) # mark card using object head 74351: 7436 ADVANCE_PC 2 7437 GOTO_NEXT_R %edx 7438 7439/* continuation for OP_IPUT_BOOLEAN */ 7440 7441 7442.LOP_IPUT_BOOLEAN_resolve: 7443 EXPORT_PC 7444 movl offGlue_method(%edx),%edx # edx<- current method 7445 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7446 SPILL_TMP1(%ecx) # save obj pointer across call 7447 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7448 call dvmResolveInstField # ... to dvmResolveInstField 7449 UNSPILL_TMP1(%ecx) 7450 testl %eax,%eax # returns InstrField ptr 7451 jne .LOP_IPUT_BOOLEAN_finish 7452 jmp common_exceptionThrown 7453 7454.LOP_IPUT_BOOLEAN_finish: 7455 /* 7456 * Currently: 7457 * eax holds resolved field 7458 * ecx holds object 7459 * rINST holds A 7460 */ 7461 GET_VREG_R rINST rINST # rINST<- v[A] 7462 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7463 testl %ecx,%ecx # object null? 7464 je common_errNullObject # object was null 7465 FETCH_INST_OPCODE 2 %edx 7466 movb rINSTbl,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7467 ADVANCE_PC 2 7468 GOTO_NEXT_R %edx 7469 7470/* continuation for OP_IPUT_BYTE */ 7471 7472 7473.LOP_IPUT_BYTE_resolve: 7474 EXPORT_PC 7475 movl offGlue_method(%edx),%edx # edx<- current method 7476 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7477 SPILL_TMP1(%ecx) # save obj pointer across call 7478 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7479 call dvmResolveInstField # ... to dvmResolveInstField 7480 UNSPILL_TMP1(%ecx) 7481 testl %eax,%eax # returns InstrField ptr 7482 jne .LOP_IPUT_BYTE_finish 7483 jmp common_exceptionThrown 7484 7485.LOP_IPUT_BYTE_finish: 7486 /* 7487 * Currently: 7488 * eax holds resolved field 7489 * ecx holds object 7490 * rINST holds A 7491 */ 7492 GET_VREG_R rINST rINST # rINST<- v[A] 7493 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7494 testl %ecx,%ecx # object null? 7495 je common_errNullObject # object was null 7496 FETCH_INST_OPCODE 2 %edx 7497 movb rINSTbl,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7498 ADVANCE_PC 2 7499 GOTO_NEXT_R %edx 7500 7501/* continuation for OP_IPUT_CHAR */ 7502 7503 7504.LOP_IPUT_CHAR_resolve: 7505 EXPORT_PC 7506 movl offGlue_method(%edx),%edx # edx<- current method 7507 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7508 SPILL_TMP1(%ecx) # save obj pointer across call 7509 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7510 call dvmResolveInstField # ... to dvmResolveInstField 7511 UNSPILL_TMP1(%ecx) 7512 testl %eax,%eax # returns InstrField ptr 7513 jne .LOP_IPUT_CHAR_finish 7514 jmp common_exceptionThrown 7515 7516.LOP_IPUT_CHAR_finish: 7517 /* 7518 * Currently: 7519 * eax holds resolved field 7520 * ecx holds object 7521 * rINST holds A 7522 */ 7523 GET_VREG_R rINST rINST # rINST<- v[A] 7524 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7525 testl %ecx,%ecx # object null? 7526 je common_errNullObject # object was null 7527 FETCH_INST_OPCODE 2 %edx 7528 movw rINSTw,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7529 ADVANCE_PC 2 7530 GOTO_NEXT_R %edx 7531 7532/* continuation for OP_IPUT_SHORT */ 7533 7534 7535.LOP_IPUT_SHORT_resolve: 7536 EXPORT_PC 7537 movl offGlue_method(%edx),%edx # edx<- current method 7538 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7539 SPILL_TMP1(%ecx) # save obj pointer across call 7540 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7541 call dvmResolveInstField # ... to dvmResolveInstField 7542 UNSPILL_TMP1(%ecx) 7543 testl %eax,%eax # returns InstrField ptr 7544 jne .LOP_IPUT_SHORT_finish 7545 jmp common_exceptionThrown 7546 7547.LOP_IPUT_SHORT_finish: 7548 /* 7549 * Currently: 7550 * eax holds resolved field 7551 * ecx holds object 7552 * rINST holds A 7553 */ 7554 GET_VREG_R rINST rINST # rINST<- v[A] 7555 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7556 testl %ecx,%ecx # object null? 7557 je common_errNullObject # object was null 7558 FETCH_INST_OPCODE 2 %edx 7559 movw rINSTw,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7560 ADVANCE_PC 2 7561 GOTO_NEXT_R %edx 7562 7563/* continuation for OP_SGET */ 7564 7565 /* 7566 * Go resolve the field 7567 */ 7568.LOP_SGET_resolve: 7569 movl rGLUE,%ecx 7570 movzwl 2(rPC),%eax # eax<- field ref BBBB 7571 movl offGlue_method(%ecx),%ecx # ecx<- current method 7572 EXPORT_PC # could throw, need to export 7573 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7574 movl %eax,OUT_ARG1(%esp) 7575 movl %ecx,OUT_ARG0(%esp) 7576 call dvmResolveStaticField # eax<- resolved StaticField ptr 7577 testl %eax,%eax 7578 jne .LOP_SGET_finish # success, continue 7579 jmp common_exceptionThrown # no, handle exception 7580 7581/* continuation for OP_SGET_WIDE */ 7582 7583 /* 7584 * Go resolve the field 7585 */ 7586.LOP_SGET_WIDE_resolve: 7587 movl rGLUE,%ecx 7588 movzwl 2(rPC),%eax # eax<- field ref BBBB 7589 movl offGlue_method(%ecx),%ecx # ecx<- current method 7590 EXPORT_PC # could throw, need to export 7591 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7592 movl %eax,OUT_ARG1(%esp) 7593 movl %ecx,OUT_ARG0(%esp) 7594 call dvmResolveStaticField # eax<- resolved StaticField ptr 7595 testl %eax,%eax 7596 jne .LOP_SGET_WIDE_finish # success, continue 7597 jmp common_exceptionThrown # no, handle exception 7598 7599/* continuation for OP_SGET_OBJECT */ 7600 7601 /* 7602 * Go resolve the field 7603 */ 7604.LOP_SGET_OBJECT_resolve: 7605 movl rGLUE,%ecx 7606 movzwl 2(rPC),%eax # eax<- field ref BBBB 7607 movl offGlue_method(%ecx),%ecx # ecx<- current method 7608 EXPORT_PC # could throw, need to export 7609 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7610 movl %eax,OUT_ARG1(%esp) 7611 movl %ecx,OUT_ARG0(%esp) 7612 call dvmResolveStaticField # eax<- resolved StaticField ptr 7613 testl %eax,%eax 7614 jne .LOP_SGET_OBJECT_finish # success, continue 7615 jmp common_exceptionThrown # no, handle exception 7616 7617/* continuation for OP_SGET_BOOLEAN */ 7618 7619 /* 7620 * Go resolve the field 7621 */ 7622.LOP_SGET_BOOLEAN_resolve: 7623 movl rGLUE,%ecx 7624 movzwl 2(rPC),%eax # eax<- field ref BBBB 7625 movl offGlue_method(%ecx),%ecx # ecx<- current method 7626 EXPORT_PC # could throw, need to export 7627 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7628 movl %eax,OUT_ARG1(%esp) 7629 movl %ecx,OUT_ARG0(%esp) 7630 call dvmResolveStaticField # eax<- resolved StaticField ptr 7631 testl %eax,%eax 7632 jne .LOP_SGET_BOOLEAN_finish # success, continue 7633 jmp common_exceptionThrown # no, handle exception 7634 7635/* continuation for OP_SGET_BYTE */ 7636 7637 /* 7638 * Go resolve the field 7639 */ 7640.LOP_SGET_BYTE_resolve: 7641 movl rGLUE,%ecx 7642 movzwl 2(rPC),%eax # eax<- field ref BBBB 7643 movl offGlue_method(%ecx),%ecx # ecx<- current method 7644 EXPORT_PC # could throw, need to export 7645 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7646 movl %eax,OUT_ARG1(%esp) 7647 movl %ecx,OUT_ARG0(%esp) 7648 call dvmResolveStaticField # eax<- resolved StaticField ptr 7649 testl %eax,%eax 7650 jne .LOP_SGET_BYTE_finish # success, continue 7651 jmp common_exceptionThrown # no, handle exception 7652 7653/* continuation for OP_SGET_CHAR */ 7654 7655 /* 7656 * Go resolve the field 7657 */ 7658.LOP_SGET_CHAR_resolve: 7659 movl rGLUE,%ecx 7660 movzwl 2(rPC),%eax # eax<- field ref BBBB 7661 movl offGlue_method(%ecx),%ecx # ecx<- current method 7662 EXPORT_PC # could throw, need to export 7663 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7664 movl %eax,OUT_ARG1(%esp) 7665 movl %ecx,OUT_ARG0(%esp) 7666 call dvmResolveStaticField # eax<- resolved StaticField ptr 7667 testl %eax,%eax 7668 jne .LOP_SGET_CHAR_finish # success, continue 7669 jmp common_exceptionThrown # no, handle exception 7670 7671/* continuation for OP_SGET_SHORT */ 7672 7673 /* 7674 * Go resolve the field 7675 */ 7676.LOP_SGET_SHORT_resolve: 7677 movl rGLUE,%ecx 7678 movzwl 2(rPC),%eax # eax<- field ref BBBB 7679 movl offGlue_method(%ecx),%ecx # ecx<- current method 7680 EXPORT_PC # could throw, need to export 7681 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7682 movl %eax,OUT_ARG1(%esp) 7683 movl %ecx,OUT_ARG0(%esp) 7684 call dvmResolveStaticField # eax<- resolved StaticField ptr 7685 testl %eax,%eax 7686 jne .LOP_SGET_SHORT_finish # success, continue 7687 jmp common_exceptionThrown # no, handle exception 7688 7689/* continuation for OP_SPUT */ 7690 7691 /* 7692 * Go resolve the field 7693 */ 7694.LOP_SPUT_resolve: 7695 movl rGLUE,%ecx 7696 movzwl 2(rPC),%eax # eax<- field ref BBBB 7697 movl offGlue_method(%ecx),%ecx # ecx<- current method 7698 EXPORT_PC # could throw, need to export 7699 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7700 movl %eax,OUT_ARG1(%esp) 7701 movl %ecx,OUT_ARG0(%esp) 7702 call dvmResolveStaticField # eax<- resolved StaticField ptr 7703 testl %eax,%eax 7704 jne .LOP_SPUT_finish # success, continue 7705 jmp common_exceptionThrown # no, handle exception 7706 7707/* continuation for OP_SPUT_WIDE */ 7708 7709 /* 7710 * Go resolve the field 7711 */ 7712.LOP_SPUT_WIDE_resolve: 7713 movl rGLUE,%ecx 7714 movzwl 2(rPC),%eax # eax<- field ref BBBB 7715 movl offGlue_method(%ecx),%ecx # ecx<- current method 7716 EXPORT_PC # could throw, need to export 7717 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7718 movl %eax,OUT_ARG1(%esp) 7719 movl %ecx,OUT_ARG0(%esp) 7720 call dvmResolveStaticField # eax<- resolved StaticField ptr 7721 testl %eax,%eax 7722 jne .LOP_SPUT_WIDE_finish # success, continue 7723 jmp common_exceptionThrown # no, handle exception 7724 7725/* continuation for OP_SPUT_OBJECT */ 7726 7727 7728.LOP_SPUT_OBJECT_continue: 7729 movl %ecx,offStaticField_value(%eax) # do the store 7730 testl %ecx,%ecx # stored null object ptr? 7731 FETCH_INST_OPCODE 2 %edx 7732 je 1f # skip card mark if null 7733 movl rGLUE,%ecx 7734 movl offField_clazz(%eax),%eax # eax<- method->clazz 7735 movl offGlue_cardTable(%ecx),%ecx # get card table base 7736 shrl $GC_CARD_SHIFT,%eax # head to card number 7737 movb %cl,(%ecx,%eax) # mark card 77381: 7739 ADVANCE_PC 2 7740 GOTO_NEXT_R %edx 7741 7742.LOP_SPUT_OBJECT_resolve: 7743 movl rGLUE,%ecx 7744 movzwl 2(rPC),%eax # eax<- field ref BBBB 7745 movl offGlue_method(%ecx),%ecx # ecx<- current method 7746 EXPORT_PC # could throw, need to export 7747 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7748 movl %eax,OUT_ARG1(%esp) 7749 movl %ecx,OUT_ARG0(%esp) 7750 call dvmResolveStaticField # eax<- resolved StaticField ptr 7751 testl %eax,%eax 7752 jne .LOP_SPUT_OBJECT_finish # success, continue 7753 jmp common_exceptionThrown # no, handle exception 7754 7755/* continuation for OP_SPUT_BOOLEAN */ 7756 7757 /* 7758 * Go resolve the field 7759 */ 7760.LOP_SPUT_BOOLEAN_resolve: 7761 movl rGLUE,%ecx 7762 movzwl 2(rPC),%eax # eax<- field ref BBBB 7763 movl offGlue_method(%ecx),%ecx # ecx<- current method 7764 EXPORT_PC # could throw, need to export 7765 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7766 movl %eax,OUT_ARG1(%esp) 7767 movl %ecx,OUT_ARG0(%esp) 7768 call dvmResolveStaticField # eax<- resolved StaticField ptr 7769 testl %eax,%eax 7770 jne .LOP_SPUT_BOOLEAN_finish # success, continue 7771 jmp common_exceptionThrown # no, handle exception 7772 7773/* continuation for OP_SPUT_BYTE */ 7774 7775 /* 7776 * Go resolve the field 7777 */ 7778.LOP_SPUT_BYTE_resolve: 7779 movl rGLUE,%ecx 7780 movzwl 2(rPC),%eax # eax<- field ref BBBB 7781 movl offGlue_method(%ecx),%ecx # ecx<- current method 7782 EXPORT_PC # could throw, need to export 7783 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7784 movl %eax,OUT_ARG1(%esp) 7785 movl %ecx,OUT_ARG0(%esp) 7786 call dvmResolveStaticField # eax<- resolved StaticField ptr 7787 testl %eax,%eax 7788 jne .LOP_SPUT_BYTE_finish # success, continue 7789 jmp common_exceptionThrown # no, handle exception 7790 7791/* continuation for OP_SPUT_CHAR */ 7792 7793 /* 7794 * Go resolve the field 7795 */ 7796.LOP_SPUT_CHAR_resolve: 7797 movl rGLUE,%ecx 7798 movzwl 2(rPC),%eax # eax<- field ref BBBB 7799 movl offGlue_method(%ecx),%ecx # ecx<- current method 7800 EXPORT_PC # could throw, need to export 7801 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7802 movl %eax,OUT_ARG1(%esp) 7803 movl %ecx,OUT_ARG0(%esp) 7804 call dvmResolveStaticField # eax<- resolved StaticField ptr 7805 testl %eax,%eax 7806 jne .LOP_SPUT_CHAR_finish # success, continue 7807 jmp common_exceptionThrown # no, handle exception 7808 7809/* continuation for OP_SPUT_SHORT */ 7810 7811 /* 7812 * Go resolve the field 7813 */ 7814.LOP_SPUT_SHORT_resolve: 7815 movl rGLUE,%ecx 7816 movzwl 2(rPC),%eax # eax<- field ref BBBB 7817 movl offGlue_method(%ecx),%ecx # ecx<- current method 7818 EXPORT_PC # could throw, need to export 7819 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7820 movl %eax,OUT_ARG1(%esp) 7821 movl %ecx,OUT_ARG0(%esp) 7822 call dvmResolveStaticField # eax<- resolved StaticField ptr 7823 testl %eax,%eax 7824 jne .LOP_SPUT_SHORT_finish # success, continue 7825 jmp common_exceptionThrown # no, handle exception 7826 7827/* continuation for OP_INVOKE_VIRTUAL */ 7828 7829 7830.LOP_INVOKE_VIRTUAL_more: 7831 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 7832 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 7833 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 7834 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7835 testl %eax,%eax # got null? 7836 jne .LOP_INVOKE_VIRTUAL_continue # no, continue 7837 jmp common_exceptionThrown # yes, handle exception 7838 7839 /* At this point: 7840 * eax = resolved base method 7841 * ecx = scratch 7842 */ 7843.LOP_INVOKE_VIRTUAL_continue: 7844 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 7845 .if (!0) 7846 andl $0xf,%ecx # ecx<- D (or stays CCCC) 7847 .endif 7848 GET_VREG_R %ecx %ecx # ecx<- "this" 7849 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 7850 testl %ecx,%ecx # null this? 7851 je common_errNullObject # go if so 7852 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz 7853 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable 7854 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex] 7855 jmp common_invokeMethodNoRange 7856 7857/* continuation for OP_INVOKE_SUPER */ 7858 7859 /* 7860 * At this point: 7861 * ecx = resolved base method [r0] 7862 * eax = method->clazz [r9] 7863 */ 7864.LOP_INVOKE_SUPER_continue: 7865 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super 7866 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex 7867 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount) 7868 jae .LOP_INVOKE_SUPER_nsm # method not present in superclass 7869 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable 7870 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex] 7871 jmp common_invokeMethodNoRange 7872 7873 7874 /* At this point: 7875 * ecx = null (needs to be resolved base method) 7876 * eax = method->clazz 7877 */ 7878.LOP_INVOKE_SUPER_resolve: 7879 SPILL_TMP1(%eax) # method->clazz 7880 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz 7881 movzwl 2(rPC),%ecx # ecx<- BBBB 7882 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type 7883 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 7884 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7885 testl %eax,%eax # got null? 7886 movl %eax,%ecx # ecx<- resolved base method 7887 UNSPILL_TMP1(%eax) # restore method->clazz 7888 jne .LOP_INVOKE_SUPER_continue # good to go - continue 7889 jmp common_exceptionThrown # handle exception 7890 7891 /* 7892 * Throw a NoSuchMethodError with the method name as the message. 7893 * ecx = resolved base method 7894 */ 7895.LOP_INVOKE_SUPER_nsm: 7896 movl offMethod_name(%ecx),%eax 7897 mov %eax,OUT_ARG1(%esp) 7898 jmp common_errNoSuchMethod 7899 7900/* continuation for OP_INVOKE_DIRECT */ 7901 7902 /* 7903 * On entry: 7904 * TMP_SPILL <- "this" register 7905 * Things a bit ugly on this path, but it's the less 7906 * frequent one. We'll have to do some reloading. 7907 */ 7908.LOP_INVOKE_DIRECT_resolve: 7909 SPILL_TMP1(%ecx) 7910 movl rGLUE,%ecx 7911 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 7912 movzwl 2(rPC),%eax # reference (BBBB or CCCC) 7913 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7914 movl $METHOD_DIRECT,OUT_ARG2(%esp) 7915 movl %eax,OUT_ARG1(%esp) 7916 movl %ecx,OUT_ARG0(%esp) 7917 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7918 UNSPILL_TMP1(%ecx) 7919 testl %eax,%eax 7920 jne .LOP_INVOKE_DIRECT_finish 7921 jmp common_exceptionThrown 7922 7923/* continuation for OP_INVOKE_STATIC */ 7924 7925.LOP_INVOKE_STATIC_continue: 7926 movl $METHOD_STATIC,%eax 7927 movl %eax,OUT_ARG2(%esp) # arg2<- flags 7928 call dvmResolveMethod # call(clazz,ref,flags) 7929 testl %eax,%eax # got null? 7930 jne common_invokeMethodNoRange 7931 jmp common_exceptionThrown 7932 7933/* continuation for OP_INVOKE_INTERFACE */ 7934 7935.LOP_INVOKE_INTERFACE_continue: 7936 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex) 7937 testl %eax,%eax 7938 je common_exceptionThrown 7939 jmp common_invokeMethodNoRange 7940 7941/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 7942 7943 7944.LOP_INVOKE_VIRTUAL_RANGE_more: 7945 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 7946 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 7947 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 7948 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7949 testl %eax,%eax # got null? 7950 jne .LOP_INVOKE_VIRTUAL_RANGE_continue # no, continue 7951 jmp common_exceptionThrown # yes, handle exception 7952 7953 /* At this point: 7954 * eax = resolved base method 7955 * ecx = scratch 7956 */ 7957.LOP_INVOKE_VIRTUAL_RANGE_continue: 7958 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 7959 .if (!1) 7960 andl $0xf,%ecx # ecx<- D (or stays CCCC) 7961 .endif 7962 GET_VREG_R %ecx %ecx # ecx<- "this" 7963 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 7964 testl %ecx,%ecx # null this? 7965 je common_errNullObject # go if so 7966 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz 7967 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable 7968 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex] 7969 jmp common_invokeMethodRange 7970 7971/* continuation for OP_INVOKE_SUPER_RANGE */ 7972 7973 /* 7974 * At this point: 7975 * ecx = resolved base method [r0] 7976 * eax = method->clazz [r9] 7977 */ 7978.LOP_INVOKE_SUPER_RANGE_continue: 7979 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super 7980 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex 7981 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount) 7982 jae .LOP_INVOKE_SUPER_RANGE_nsm # method not present in superclass 7983 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable 7984 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex] 7985 jmp common_invokeMethodRange 7986 7987 7988 /* At this point: 7989 * ecx = null (needs to be resolved base method) 7990 * eax = method->clazz 7991 */ 7992.LOP_INVOKE_SUPER_RANGE_resolve: 7993 SPILL_TMP1(%eax) # method->clazz 7994 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz 7995 movzwl 2(rPC),%ecx # ecx<- BBBB 7996 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type 7997 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 7998 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7999 testl %eax,%eax # got null? 8000 movl %eax,%ecx # ecx<- resolved base method 8001 UNSPILL_TMP1(%eax) # restore method->clazz 8002 jne .LOP_INVOKE_SUPER_RANGE_continue # good to go - continue 8003 jmp common_exceptionThrown # handle exception 8004 8005 /* 8006 * Throw a NoSuchMethodError with the method name as the message. 8007 * ecx = resolved base method 8008 */ 8009.LOP_INVOKE_SUPER_RANGE_nsm: 8010 movl offMethod_name(%ecx),%eax 8011 mov %eax,OUT_ARG1(%esp) 8012 jmp common_errNoSuchMethod 8013 8014/* continuation for OP_INVOKE_DIRECT_RANGE */ 8015 8016 /* 8017 * On entry: 8018 * TMP_SPILL <- "this" register 8019 * Things a bit ugly on this path, but it's the less 8020 * frequent one. We'll have to do some reloading. 8021 */ 8022.LOP_INVOKE_DIRECT_RANGE_resolve: 8023 SPILL_TMP1(%ecx) 8024 movl rGLUE,%ecx 8025 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 8026 movzwl 2(rPC),%eax # reference (BBBB or CCCC) 8027 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8028 movl $METHOD_DIRECT,OUT_ARG2(%esp) 8029 movl %eax,OUT_ARG1(%esp) 8030 movl %ecx,OUT_ARG0(%esp) 8031 call dvmResolveMethod # eax<- call(clazz, ref, flags) 8032 UNSPILL_TMP1(%ecx) 8033 testl %eax,%eax 8034 jne .LOP_INVOKE_DIRECT_RANGE_finish 8035 jmp common_exceptionThrown 8036 8037/* continuation for OP_INVOKE_STATIC_RANGE */ 8038 8039.LOP_INVOKE_STATIC_RANGE_continue: 8040 movl $METHOD_STATIC,%eax 8041 movl %eax,OUT_ARG2(%esp) # arg2<- flags 8042 call dvmResolveMethod # call(clazz,ref,flags) 8043 testl %eax,%eax # got null? 8044 jne common_invokeMethodRange 8045 jmp common_exceptionThrown 8046 8047/* continuation for OP_INVOKE_INTERFACE_RANGE */ 8048 8049.LOP_INVOKE_INTERFACE_RANGE_continue: 8050 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex) 8051 testl %eax,%eax 8052 je common_exceptionThrown 8053 jmp common_invokeMethodRange 8054 8055/* continuation for OP_FLOAT_TO_INT */ 8056 8057 8058.LOP_FLOAT_TO_INT_continue: 8059 .if 0 8060 movl $0x80000000,%eax 8061 xorl 4(rFP,%ecx,4),%eax 8062 orl (rFP,%ecx,4),%eax 8063 .else 8064 cmpl $0x80000000,(rFP,%ecx,4) 8065 .endif 8066 je .LOP_FLOAT_TO_INT_special_case # fix up result 8067 8068.LOP_FLOAT_TO_INT_finish: 8069 ADVANCE_PC 1 8070 GOTO_NEXT_R %edx 8071 8072.LOP_FLOAT_TO_INT_special_case: 8073 fnstsw %ax 8074 sahf 8075 jp .LOP_FLOAT_TO_INT_isNaN 8076 adcl $-1,(rFP,%ecx,4) 8077 .if 0 8078 adcl $-1,4(rFP,%ecx,4) 8079 .endif 8080 jmp .LOP_FLOAT_TO_INT_finish 8081.LOP_FLOAT_TO_INT_isNaN: 8082 movl $0,(rFP,%ecx,4) 8083 .if 0 8084 movl $0,4(rFP,%ecx,4) 8085 .endif 8086 jmp .LOP_FLOAT_TO_INT_finish 8087 8088/* continuation for OP_FLOAT_TO_LONG */ 8089 8090 8091.LOP_FLOAT_TO_LONG_continue: 8092 .if 1 8093 movl $0x80000000,%eax 8094 xorl 4(rFP,%ecx,4),%eax 8095 orl (rFP,%ecx,4),%eax 8096 .else 8097 cmpl $0x80000000,(rFP,%ecx,4) 8098 .endif 8099 je .LOP_FLOAT_TO_LONG_special_case # fix up result 8100 8101.LOP_FLOAT_TO_LONG_finish: 8102 ADVANCE_PC 1 8103 GOTO_NEXT_R %edx 8104 8105.LOP_FLOAT_TO_LONG_special_case: 8106 fnstsw %ax 8107 sahf 8108 jp .LOP_FLOAT_TO_LONG_isNaN 8109 adcl $-1,(rFP,%ecx,4) 8110 .if 1 8111 adcl $-1,4(rFP,%ecx,4) 8112 .endif 8113 jmp .LOP_FLOAT_TO_LONG_finish 8114.LOP_FLOAT_TO_LONG_isNaN: 8115 movl $0,(rFP,%ecx,4) 8116 .if 1 8117 movl $0,4(rFP,%ecx,4) 8118 .endif 8119 jmp .LOP_FLOAT_TO_LONG_finish 8120 8121/* continuation for OP_DOUBLE_TO_INT */ 8122 8123 8124.LOP_DOUBLE_TO_INT_continue: 8125 .if 0 8126 movl $0x80000000,%eax 8127 xorl 4(rFP,%ecx,4),%eax 8128 orl (rFP,%ecx,4),%eax 8129 .else 8130 cmpl $0x80000000,(rFP,%ecx,4) 8131 .endif 8132 je .LOP_DOUBLE_TO_INT_special_case # fix up result 8133 8134.LOP_DOUBLE_TO_INT_finish: 8135 ADVANCE_PC 1 8136 GOTO_NEXT_R %edx 8137 8138.LOP_DOUBLE_TO_INT_special_case: 8139 fnstsw %ax 8140 sahf 8141 jp .LOP_DOUBLE_TO_INT_isNaN 8142 adcl $-1,(rFP,%ecx,4) 8143 .if 0 8144 adcl $-1,4(rFP,%ecx,4) 8145 .endif 8146 jmp .LOP_DOUBLE_TO_INT_finish 8147.LOP_DOUBLE_TO_INT_isNaN: 8148 movl $0,(rFP,%ecx,4) 8149 .if 0 8150 movl $0,4(rFP,%ecx,4) 8151 .endif 8152 jmp .LOP_DOUBLE_TO_INT_finish 8153 8154/* continuation for OP_DOUBLE_TO_LONG */ 8155 8156 8157.LOP_DOUBLE_TO_LONG_continue: 8158 .if 1 8159 movl $0x80000000,%eax 8160 xorl 4(rFP,%ecx,4),%eax 8161 orl (rFP,%ecx,4),%eax 8162 .else 8163 cmpl $0x80000000,(rFP,%ecx,4) 8164 .endif 8165 je .LOP_DOUBLE_TO_LONG_special_case # fix up result 8166 8167.LOP_DOUBLE_TO_LONG_finish: 8168 ADVANCE_PC 1 8169 GOTO_NEXT_R %edx 8170 8171.LOP_DOUBLE_TO_LONG_special_case: 8172 fnstsw %ax 8173 sahf 8174 jp .LOP_DOUBLE_TO_LONG_isNaN 8175 adcl $-1,(rFP,%ecx,4) 8176 .if 1 8177 adcl $-1,4(rFP,%ecx,4) 8178 .endif 8179 jmp .LOP_DOUBLE_TO_LONG_finish 8180.LOP_DOUBLE_TO_LONG_isNaN: 8181 movl $0,(rFP,%ecx,4) 8182 .if 1 8183 movl $0,4(rFP,%ecx,4) 8184 .endif 8185 jmp .LOP_DOUBLE_TO_LONG_finish 8186 8187/* continuation for OP_DIV_INT */ 8188.LOP_DIV_INT_continue_div: 8189 cltd 8190 idivl %ecx 8191.LOP_DIV_INT_finish_div: 8192 SET_VREG %eax rINST 8193 FETCH_INST_OPCODE 2 %edx 8194 ADVANCE_PC 2 8195 GOTO_NEXT_R %edx 8196 8197/* continuation for OP_REM_INT */ 8198.LOP_REM_INT_continue_div: 8199 cltd 8200 idivl %ecx 8201.LOP_REM_INT_finish_div: 8202 SET_VREG %edx rINST 8203 FETCH_INST_OPCODE 2 %edx 8204 ADVANCE_PC 2 8205 GOTO_NEXT_R %edx 8206 8207/* continuation for OP_MUL_LONG */ 8208 8209.LOP_MUL_LONG_continue: 8210 leal (%ecx,%edx),%edx # full result now in %edx:%eax 8211 UNSPILL_TMP2(%esi) # Restore Dalvik PC 8212 FETCH_INST_OPCODE 2 %ecx # Fetch next instruction 8213 movl %edx,4(rFP,rINST,4) # v[B+1]<- %edx 8214 movl %eax,(rFP,rINST,4) # v[B]<- %eax 8215 ADVANCE_PC 2 8216 GOTO_NEXT_R %ecx 8217 8218/* continuation for OP_DIV_LONG */ 8219 8220.LOP_DIV_LONG_continue: 8221 call __divdi3 8222.LOP_DIV_LONG_finish: 8223 SET_VREG_WORD %edx rINST 1 8224 SET_VREG_WORD %eax rINST 0 8225 FETCH_INST_OPCODE 2 %edx 8226 ADVANCE_PC 2 8227 GOTO_NEXT_R %edx 8228 8229.LOP_DIV_LONG_check_zero: 8230 testl %edx,%edx 8231 jne .LOP_DIV_LONG_notSpecial 8232 jmp common_errDivideByZero 8233.LOP_DIV_LONG_check_neg1: 8234 testl %edx,%eax 8235 jne .LOP_DIV_LONG_notSpecial 8236 GET_VREG_WORD %edx %ecx 0 8237 GET_VREG_WORD %ecx %ecx 1 8238 testl %edx,%edx 8239 jne .LOP_DIV_LONG_notSpecial1 8240 cmpl $0x80000000,%ecx 8241 jne .LOP_DIV_LONG_notSpecial1 8242 /* minint / -1, return minint on div, 0 on rem */ 8243 xorl %eax,%eax 8244 movl $0x80000000,%edx 8245 jmp .LOP_DIV_LONG_finish 8246 8247/* continuation for OP_REM_LONG */ 8248 8249.LOP_REM_LONG_continue: 8250 call __moddi3 8251.LOP_REM_LONG_finish: 8252 SET_VREG_WORD %edx rINST 1 8253 SET_VREG_WORD %eax rINST 0 8254 FETCH_INST_OPCODE 2 %edx 8255 ADVANCE_PC 2 8256 GOTO_NEXT_R %edx 8257 8258.LOP_REM_LONG_check_zero: 8259 testl %edx,%edx 8260 jne .LOP_REM_LONG_notSpecial 8261 jmp common_errDivideByZero 8262.LOP_REM_LONG_check_neg1: 8263 testl %edx,%eax 8264 jne .LOP_REM_LONG_notSpecial 8265 GET_VREG_WORD %edx %ecx 0 8266 GET_VREG_WORD %ecx %ecx 1 8267 testl %edx,%edx 8268 jne .LOP_REM_LONG_notSpecial1 8269 cmpl $0x80000000,%ecx 8270 jne .LOP_REM_LONG_notSpecial1 8271 /* minint / -1, return minint on div, 0 on rem */ 8272 xorl %eax,%eax 8273 movl $0,%edx 8274 jmp .LOP_REM_LONG_finish 8275 8276/* continuation for OP_SHL_LONG */ 8277 8278.LOP_SHL_LONG_finish: 8279 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- %eax 8280 ADVANCE_PC 2 8281 GOTO_NEXT_R %edx 8282 8283/* continuation for OP_SHR_LONG */ 8284 8285 8286.LOP_SHR_LONG_finish: 8287 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax 8288 ADVANCE_PC 2 8289 GOTO_NEXT_R %edx 8290 8291/* continuation for OP_USHR_LONG */ 8292 8293 8294.LOP_USHR_LONG_finish: 8295 SET_VREG_WORD %eax rINST 0 # v[BB+0]<- eax 8296 ADVANCE_PC 2 8297 GOTO_NEXT_R %edx 8298 8299/* continuation for OP_DIV_INT_2ADDR */ 8300.LOP_DIV_INT_2ADDR_continue_div2addr: 8301 cltd 8302 idivl %ecx 8303.LOP_DIV_INT_2ADDR_finish_div2addr: 8304 SET_VREG %eax rINST 8305 FETCH_INST_OPCODE 1 %edx 8306 ADVANCE_PC 1 8307 GOTO_NEXT_R %edx 8308 8309/* continuation for OP_REM_INT_2ADDR */ 8310.LOP_REM_INT_2ADDR_continue_div2addr: 8311 cltd 8312 idivl %ecx 8313.LOP_REM_INT_2ADDR_finish_div2addr: 8314 SET_VREG %edx rINST 8315 FETCH_INST_OPCODE 1 %edx 8316 ADVANCE_PC 1 8317 GOTO_NEXT_R %edx 8318 8319/* continuation for OP_MUL_LONG_2ADDR */ 8320 8321.LOP_MUL_LONG_2ADDR_continue: 8322 leal (%ecx,%edx),%edx # full result now in %edx:%eax 8323 movl %edx,4(%esi) # v[A+1]<- %edx 8324 movl %eax,(%esi) # v[A]<- %eax 8325 UNSPILL_TMP2(%esi) 8326 FETCH_INST_OPCODE 1 %ecx 8327 UNSPILL(rFP) 8328 ADVANCE_PC 1 8329 GOTO_NEXT_R %ecx 8330 8331/* continuation for OP_DIV_LONG_2ADDR */ 8332 8333.LOP_DIV_LONG_2ADDR_continue: 8334 movl %eax,OUT_ARG3(%esp) 8335 movl %edx,OUT_ARG0(%esp) 8336 movl %ecx,OUT_ARG1(%esp) 8337 call __divdi3 8338.LOP_DIV_LONG_2ADDR_finish: 8339 SET_VREG_WORD %edx rINST 1 8340 SET_VREG_WORD %eax rINST 0 8341 FETCH_INST_OPCODE 1 %edx 8342 ADVANCE_PC 1 8343 GOTO_NEXT_R %edx 8344 8345.LOP_DIV_LONG_2ADDR_check_zero: 8346 testl %edx,%edx 8347 jne .LOP_DIV_LONG_2ADDR_notSpecial 8348 jmp common_errDivideByZero 8349.LOP_DIV_LONG_2ADDR_check_neg1: 8350 testl %edx,%eax 8351 jne .LOP_DIV_LONG_2ADDR_notSpecial 8352 GET_VREG_WORD %edx rINST 0 8353 GET_VREG_WORD %ecx rINST 1 8354 testl %edx,%edx 8355 jne .LOP_DIV_LONG_2ADDR_notSpecial1 8356 cmpl $0x80000000,%ecx 8357 jne .LOP_DIV_LONG_2ADDR_notSpecial1 8358 /* minint / -1, return minint on div, 0 on rem */ 8359 xorl %eax,%eax 8360 movl $0x80000000,%edx 8361 jmp .LOP_DIV_LONG_2ADDR_finish 8362 8363/* continuation for OP_REM_LONG_2ADDR */ 8364 8365.LOP_REM_LONG_2ADDR_continue: 8366 movl %eax,OUT_ARG3(%esp) 8367 movl %edx,OUT_ARG0(%esp) 8368 movl %ecx,OUT_ARG1(%esp) 8369 call __moddi3 8370.LOP_REM_LONG_2ADDR_finish: 8371 SET_VREG_WORD %edx rINST 1 8372 SET_VREG_WORD %eax rINST 0 8373 FETCH_INST_OPCODE 1 %edx 8374 ADVANCE_PC 1 8375 GOTO_NEXT_R %edx 8376 8377.LOP_REM_LONG_2ADDR_check_zero: 8378 testl %edx,%edx 8379 jne .LOP_REM_LONG_2ADDR_notSpecial 8380 jmp common_errDivideByZero 8381.LOP_REM_LONG_2ADDR_check_neg1: 8382 testl %edx,%eax 8383 jne .LOP_REM_LONG_2ADDR_notSpecial 8384 GET_VREG_WORD %edx rINST 0 8385 GET_VREG_WORD %ecx rINST 1 8386 testl %edx,%edx 8387 jne .LOP_REM_LONG_2ADDR_notSpecial1 8388 cmpl $0x80000000,%ecx 8389 jne .LOP_REM_LONG_2ADDR_notSpecial1 8390 /* minint / -1, return minint on div, 0 on rem */ 8391 xorl %eax,%eax 8392 movl $0,%edx 8393 jmp .LOP_REM_LONG_2ADDR_finish 8394 8395/* continuation for OP_SHL_LONG_2ADDR */ 8396 8397 8398.LOP_SHL_LONG_2ADDR_finish: 8399 FETCH_INST_OPCODE 1 %edx 8400 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax 8401 ADVANCE_PC 1 8402 GOTO_NEXT_R %edx 8403 8404/* continuation for OP_SHR_LONG_2ADDR */ 8405 8406 8407.LOP_SHR_LONG_2ADDR_finish: 8408 FETCH_INST_OPCODE 1 %edx 8409 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax 8410 ADVANCE_PC 1 8411 GOTO_NEXT_R %edx 8412 8413/* continuation for OP_USHR_LONG_2ADDR */ 8414 8415 8416.LOP_USHR_LONG_2ADDR_finish: 8417 FETCH_INST_OPCODE 1 %edx 8418 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax 8419 ADVANCE_PC 1 8420 GOTO_NEXT_R %edx 8421 8422/* continuation for OP_DIV_INT_LIT16 */ 8423.LOP_DIV_INT_LIT16_continue_div: 8424 cltd 8425 idivl %ecx 8426.LOP_DIV_INT_LIT16_finish_div: 8427 SET_VREG %eax rINST 8428 FETCH_INST_OPCODE 2 %edx 8429 ADVANCE_PC 2 8430 GOTO_NEXT_R %edx 8431 8432/* continuation for OP_REM_INT_LIT16 */ 8433.LOP_REM_INT_LIT16_continue_div: 8434 cltd 8435 idivl %ecx 8436.LOP_REM_INT_LIT16_finish_div: 8437 SET_VREG %edx rINST 8438 FETCH_INST_OPCODE 2 %edx 8439 ADVANCE_PC 2 8440 GOTO_NEXT_R %edx 8441 8442/* continuation for OP_DIV_INT_LIT8 */ 8443.LOP_DIV_INT_LIT8_continue_div: 8444 cltd 8445 idivl %ecx 8446.LOP_DIV_INT_LIT8_finish_div: 8447 SET_VREG %eax rINST 8448 FETCH_INST_OPCODE 2 %edx 8449 ADVANCE_PC 2 8450 GOTO_NEXT_R %edx 8451 8452/* continuation for OP_REM_INT_LIT8 */ 8453.LOP_REM_INT_LIT8_continue_div: 8454 cltd 8455 idivl %ecx 8456.LOP_REM_INT_LIT8_finish_div: 8457 SET_VREG %edx rINST 8458 FETCH_INST_OPCODE 2 %edx 8459 ADVANCE_PC 2 8460 GOTO_NEXT_R %edx 8461 8462/* continuation for OP_IGET_VOLATILE */ 8463 8464 8465.LOP_IGET_VOLATILE_resolve: 8466 EXPORT_PC 8467 movl offGlue_method(%edx),%edx # edx<- current method 8468 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 8469 SPILL_TMP1(%ecx) # save obj pointer across call 8470 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 8471 call dvmResolveInstField # ... to dvmResolveInstField 8472 UNSPILL_TMP1(%ecx) 8473 testl %eax,%eax # returns InstrField ptr 8474 jne .LOP_IGET_VOLATILE_finish 8475 jmp common_exceptionThrown 8476 8477.LOP_IGET_VOLATILE_finish: 8478 /* 8479 * Currently: 8480 * eax holds resolved field 8481 * ecx holds object 8482 * rINST holds A 8483 */ 8484 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8485 testl %ecx,%ecx # object null? 8486 je common_errNullObject # object was null 8487 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 8488 movl rINST,%eax # eax<- A 8489 FETCH_INST_OPCODE 2 %edx 8490 SET_VREG %ecx %eax 8491 ADVANCE_PC 2 8492 GOTO_NEXT_R %edx 8493 8494/* continuation for OP_IPUT_VOLATILE */ 8495 8496 8497.LOP_IPUT_VOLATILE_resolve: 8498 EXPORT_PC 8499 movl offGlue_method(%edx),%edx # edx<- current method 8500 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 8501 SPILL_TMP1(%ecx) # save obj pointer across call 8502 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 8503 call dvmResolveInstField # ... to dvmResolveInstField 8504 UNSPILL_TMP1(%ecx) 8505 testl %eax,%eax # returns InstrField ptr 8506 jne .LOP_IPUT_VOLATILE_finish 8507 jmp common_exceptionThrown 8508 8509.LOP_IPUT_VOLATILE_finish: 8510 /* 8511 * Currently: 8512 * eax holds resolved field 8513 * ecx holds object 8514 * rINST holds A 8515 */ 8516 GET_VREG_R rINST rINST # rINST<- v[A] 8517 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8518 testl %ecx,%ecx # object null? 8519 je common_errNullObject # object was null 8520 FETCH_INST_OPCODE 2 %edx 8521 movl rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 8522 ADVANCE_PC 2 8523 GOTO_NEXT_R %edx 8524 8525/* continuation for OP_SGET_VOLATILE */ 8526 8527 /* 8528 * Go resolve the field 8529 */ 8530.LOP_SGET_VOLATILE_resolve: 8531 movl rGLUE,%ecx 8532 movzwl 2(rPC),%eax # eax<- field ref BBBB 8533 movl offGlue_method(%ecx),%ecx # ecx<- current method 8534 EXPORT_PC # could throw, need to export 8535 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8536 movl %eax,OUT_ARG1(%esp) 8537 movl %ecx,OUT_ARG0(%esp) 8538 call dvmResolveStaticField # eax<- resolved StaticField ptr 8539 testl %eax,%eax 8540 jne .LOP_SGET_VOLATILE_finish # success, continue 8541 jmp common_exceptionThrown # no, handle exception 8542 8543/* continuation for OP_SPUT_VOLATILE */ 8544 8545 /* 8546 * Go resolve the field 8547 */ 8548.LOP_SPUT_VOLATILE_resolve: 8549 movl rGLUE,%ecx 8550 movzwl 2(rPC),%eax # eax<- field ref BBBB 8551 movl offGlue_method(%ecx),%ecx # ecx<- current method 8552 EXPORT_PC # could throw, need to export 8553 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8554 movl %eax,OUT_ARG1(%esp) 8555 movl %ecx,OUT_ARG0(%esp) 8556 call dvmResolveStaticField # eax<- resolved StaticField ptr 8557 testl %eax,%eax 8558 jne .LOP_SPUT_VOLATILE_finish # success, continue 8559 jmp common_exceptionThrown # no, handle exception 8560 8561/* continuation for OP_IGET_OBJECT_VOLATILE */ 8562 8563 8564.LOP_IGET_OBJECT_VOLATILE_resolve: 8565 EXPORT_PC 8566 movl offGlue_method(%edx),%edx # edx<- current method 8567 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 8568 SPILL_TMP1(%ecx) # save obj pointer across call 8569 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 8570 call dvmResolveInstField # ... to dvmResolveInstField 8571 UNSPILL_TMP1(%ecx) 8572 testl %eax,%eax # returns InstrField ptr 8573 jne .LOP_IGET_OBJECT_VOLATILE_finish 8574 jmp common_exceptionThrown 8575 8576.LOP_IGET_OBJECT_VOLATILE_finish: 8577 /* 8578 * Currently: 8579 * eax holds resolved field 8580 * ecx holds object 8581 * rINST holds A 8582 */ 8583 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8584 testl %ecx,%ecx # object null? 8585 je common_errNullObject # object was null 8586 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 8587 movl rINST,%eax # eax<- A 8588 FETCH_INST_OPCODE 2 %edx 8589 SET_VREG %ecx %eax 8590 ADVANCE_PC 2 8591 GOTO_NEXT_R %edx 8592 8593/* continuation for OP_EXECUTE_INLINE */ 8594 8595.LOP_EXECUTE_INLINE_continue: 8596 /* 8597 * Extract args, call function. 8598 * ecx = #of args (0-4) 8599 * eax = call index 8600 * @esp = return addr 8601 * esp is -4 from normal 8602 * 8603 * Go ahead and load all 4 args, even if not used. 8604 */ 8605 movzwl 4(rPC),%edx 8606 8607 movl $0xf,%ecx 8608 andl %edx,%ecx 8609 GET_VREG_R %ecx %ecx 8610 sarl $4,%edx 8611 movl %ecx,4+OUT_ARG0(%esp) 8612 8613 movl $0xf,%ecx 8614 andl %edx,%ecx 8615 GET_VREG_R %ecx %ecx 8616 sarl $4,%edx 8617 movl %ecx,4+OUT_ARG1(%esp) 8618 8619 movl $0xf,%ecx 8620 andl %edx,%ecx 8621 GET_VREG_R %ecx %ecx 8622 sarl $4,%edx 8623 movl %ecx,4+OUT_ARG2(%esp) 8624 8625 movl $0xf,%ecx 8626 andl %edx,%ecx 8627 GET_VREG_R %ecx %ecx 8628 sarl $4,%edx 8629 movl %ecx,4+OUT_ARG3(%esp) 8630 8631 sall $4,%eax # index *= sizeof(table entry) 8632 jmp *gDvmInlineOpsTable(%eax) 8633 # will return to caller of .LOP_EXECUTE_INLINE_continue 8634 8635/* continuation for OP_IPUT_OBJECT_QUICK */ 8636 8637.LOP_IPUT_OBJECT_QUICK_finish: 8638 testl rINST,rINST # did we store null? 8639 FETCH_INST_OPCODE 2 %edx 8640 movl offGlue_cardTable(%eax),%eax # get card table base 8641 je 1f # skip card mark if null store 8642 shrl $GC_CARD_SHIFT,%ecx # object head to card number 8643 movb %al,(%eax,%ecx) # mark card based on object head 86441: 8645 ADVANCE_PC 2 8646 GOTO_NEXT_R %edx 8647 8648/* continuation for OP_IPUT_OBJECT_VOLATILE */ 8649 8650 8651.LOP_IPUT_OBJECT_VOLATILE_resolve: 8652 EXPORT_PC 8653 movl offGlue_method(%edx),%edx # edx<- current method 8654 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 8655 SPILL_TMP1(%ecx) # save obj pointer across call 8656 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 8657 call dvmResolveInstField # ... to dvmResolveInstField 8658 UNSPILL_TMP1(%ecx) 8659 testl %eax,%eax # returns InstrField ptr 8660 jne .LOP_IPUT_OBJECT_VOLATILE_finish 8661 jmp common_exceptionThrown 8662 8663.LOP_IPUT_OBJECT_VOLATILE_finish: 8664 /* 8665 * Currently: 8666 * eax holds resolved field 8667 * ecx holds object 8668 * %edx is scratch, but needs to be unspilled 8669 * rINST holds A 8670 */ 8671 GET_VREG_R rINST rINST # rINST<- v[A] 8672 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8673 testl %ecx,%ecx # object null? 8674 je common_errNullObject # object was null 8675 movl rINST,(%ecx,%eax) # obj.field <- v[A](8/16/32 bits) 8676 movl rGLUE,%eax 8677 testl rINST,rINST # stored a NULL? 8678 movl offGlue_cardTable(%eax),%eax # get card table base 8679 FETCH_INST_OPCODE 2 %edx 8680 je 1f # skip card mark if null store 8681 shrl $GC_CARD_SHIFT,%ecx # object head to card number 8682 movb %al,(%eax,%ecx) # mark card using object head 86831: 8684 ADVANCE_PC 2 8685 GOTO_NEXT_R %edx 8686 8687/* continuation for OP_SGET_OBJECT_VOLATILE */ 8688 8689 /* 8690 * Go resolve the field 8691 */ 8692.LOP_SGET_OBJECT_VOLATILE_resolve: 8693 movl rGLUE,%ecx 8694 movzwl 2(rPC),%eax # eax<- field ref BBBB 8695 movl offGlue_method(%ecx),%ecx # ecx<- current method 8696 EXPORT_PC # could throw, need to export 8697 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8698 movl %eax,OUT_ARG1(%esp) 8699 movl %ecx,OUT_ARG0(%esp) 8700 call dvmResolveStaticField # eax<- resolved StaticField ptr 8701 testl %eax,%eax 8702 jne .LOP_SGET_OBJECT_VOLATILE_finish # success, continue 8703 jmp common_exceptionThrown # no, handle exception 8704 8705/* continuation for OP_SPUT_OBJECT_VOLATILE */ 8706 8707 8708.LOP_SPUT_OBJECT_VOLATILE_continue: 8709 movl %ecx,offStaticField_value(%eax) # do the store 8710 testl %ecx,%ecx # stored null object ptr? 8711 FETCH_INST_OPCODE 2 %edx 8712 je 1f # skip card mark if null 8713 movl rGLUE,%ecx 8714 movl offField_clazz(%eax),%eax # eax<- method->clazz 8715 movl offGlue_cardTable(%ecx),%ecx # get card table base 8716 shrl $GC_CARD_SHIFT,%eax # head to card number 8717 movb %cl,(%ecx,%eax) # mark card 87181: 8719 ADVANCE_PC 2 8720 GOTO_NEXT_R %edx 8721 8722.LOP_SPUT_OBJECT_VOLATILE_resolve: 8723 movl rGLUE,%ecx 8724 movzwl 2(rPC),%eax # eax<- field ref BBBB 8725 movl offGlue_method(%ecx),%ecx # ecx<- current method 8726 EXPORT_PC # could throw, need to export 8727 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8728 movl %eax,OUT_ARG1(%esp) 8729 movl %ecx,OUT_ARG0(%esp) 8730 call dvmResolveStaticField # eax<- resolved StaticField ptr 8731 testl %eax,%eax 8732 jne .LOP_SPUT_OBJECT_VOLATILE_finish # success, continue 8733 jmp common_exceptionThrown # no, handle exception 8734 8735 .size dvmAsmSisterStart, .-dvmAsmSisterStart 8736 .global dvmAsmSisterEnd 8737dvmAsmSisterEnd: 8738 8739/* File: x86/entry.S */ 8740/* 8741 * Copyright (C) 2008 The Android Open Source Project 8742 * 8743 * Licensed under the Apache License, Version 2.0 (the "License"); 8744 * you may not use this file except in compliance with the License. 8745 * You may obtain a copy of the License at 8746 * 8747 * http://www.apache.org/licenses/LICENSE-2.0 8748 * 8749 * Unless required by applicable law or agreed to in writing, software 8750 * distributed under the License is distributed on an "AS IS" BASIS, 8751 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8752 * See the License for the specific language governing permissions and 8753 * limitations under the License. 8754 */ 8755 8756 8757 .text 8758 .global dvmMterpStdRun 8759 .type dvmMterpStdRun, %function 8760/* 8761 * bool dvmMterpStdRun(MterpGlue* glue) 8762 * 8763 * Interpreter entry point. Returns changeInterp. 8764 * 8765 */ 8766dvmMterpStdRun: 8767 movl 4(%esp), %ecx # get incoming rGLUE 8768 push %ebp # save caller base pointer 8769 push %ecx # save rGLUE at (%ebp) 8770 movl %esp, %ebp # set our %ebp 8771/* 8772 * At this point we've allocated two slots on the stack 8773 * via push and stack is 8-byte aligned. Allocate space 8774 * for 8 spill slots, 3 local slots, 5 arg slots + 2 slots for 8775 * padding to bring us to 16-byte alignment 8776 */ 8777 subl $(FRAME_SIZE-8), %esp 8778 8779/* Spill callee save regs */ 8780 movl %edi,EDI_SPILL(%ebp) 8781 movl %esi,ESI_SPILL(%ebp) 8782 movl %ebx,EBX_SPILL(%ebp) 8783 8784/* Set up "named" registers */ 8785 movl offGlue_pc(%ecx),rPC 8786 movl offGlue_fp(%ecx),rFP 8787 8788/* Remember %esp for future "longjmp" */ 8789 movl %esp,offGlue_bailPtr(%ecx) 8790 8791/* How to start? */ 8792 movb offGlue_entryPoint(%ecx),%al 8793 8794/* Normal start? */ 8795 cmpb $kInterpEntryInstr,%al 8796 jne .Lnot_instr 8797 8798 /* Normal case: start executing the instruction at rPC */ 8799 FETCH_INST 8800 GOTO_NEXT 8801 8802.Lnot_instr: 8803 /* Reset to normal case */ 8804 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx) 8805 cmpb $kInterpEntryReturn,%al 8806 je common_returnFromMethod 8807 cmpb $kInterpEntryThrow,%al 8808 je common_exceptionThrown 8809 movzx %al,%eax 8810 movl %eax,OUT_ARG1(%esp) 8811 movl $.LstrBadEntryPoint,OUT_ARG0(%esp) 8812 call printf 8813 call dvmAbort 8814 /* Not reached */ 8815 8816 8817 .global dvmMterpStdBail 8818 .type dvmMterpStdBail, %function 8819/* 8820 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp) 8821 * 8822 * Restore the stack pointer and PC from the save point established on entry. 8823 * This is essentially the same as a longjmp, but should be cheaper. The 8824 * last instruction causes us to return to whoever called dvmMterpStdRun. 8825 * 8826 * We're not going to build a standard frame here, so the arg accesses will 8827 * look a little strange. 8828 * 8829 * On entry: 8830 * esp+4 (arg0) MterpGlue* glue 8831 * esp+8 (arg1) bool changeInterp 8832 */ 8833dvmMterpStdBail: 8834 movl 4(%esp),%ecx # grab glue 8835 movl 8(%esp),%eax # changeInterp to return reg 8836 movl offGlue_bailPtr(%ecx),%esp # Restore "setjmp" esp 8837 movl %esp,%ebp 8838 addl $(FRAME_SIZE-8), %ebp # Restore %ebp at point of setjmp 8839 movl EDI_SPILL(%ebp),%edi 8840 movl ESI_SPILL(%ebp),%esi 8841 movl EBX_SPILL(%ebp),%ebx 8842 movl PREV_FP(%ebp),%ebp # restore caller's ebp 8843 addl $FRAME_SIZE,%esp # strip frame 8844 ret # return to dvmMterpStdRun's caller 8845 8846 8847/* 8848 * Strings 8849 */ 8850 .section .rodata 8851.LstrBadEntryPoint: 8852 .asciz "Bad entry point %d\n" 8853 8854 8855/* 8856 * FIXME: Should have the config/rebuild mechanism generate this 8857 * for targets that need it. 8858 */ 8859 8860/* Jump table */ 8861dvmAsmInstructionJmpTable = .LdvmAsmInstructionJmpTable 8862.LdvmAsmInstructionJmpTable: 8863.long .L_OP_NOP 8864.long .L_OP_MOVE 8865.long .L_OP_MOVE_FROM16 8866.long .L_OP_MOVE_16 8867.long .L_OP_MOVE_WIDE 8868.long .L_OP_MOVE_WIDE_FROM16 8869.long .L_OP_MOVE_WIDE_16 8870.long .L_OP_MOVE_OBJECT 8871.long .L_OP_MOVE_OBJECT_FROM16 8872.long .L_OP_MOVE_OBJECT_16 8873.long .L_OP_MOVE_RESULT 8874.long .L_OP_MOVE_RESULT_WIDE 8875.long .L_OP_MOVE_RESULT_OBJECT 8876.long .L_OP_MOVE_EXCEPTION 8877.long .L_OP_RETURN_VOID 8878.long .L_OP_RETURN 8879.long .L_OP_RETURN_WIDE 8880.long .L_OP_RETURN_OBJECT 8881.long .L_OP_CONST_4 8882.long .L_OP_CONST_16 8883.long .L_OP_CONST 8884.long .L_OP_CONST_HIGH16 8885.long .L_OP_CONST_WIDE_16 8886.long .L_OP_CONST_WIDE_32 8887.long .L_OP_CONST_WIDE 8888.long .L_OP_CONST_WIDE_HIGH16 8889.long .L_OP_CONST_STRING 8890.long .L_OP_CONST_STRING_JUMBO 8891.long .L_OP_CONST_CLASS 8892.long .L_OP_MONITOR_ENTER 8893.long .L_OP_MONITOR_EXIT 8894.long .L_OP_CHECK_CAST 8895.long .L_OP_INSTANCE_OF 8896.long .L_OP_ARRAY_LENGTH 8897.long .L_OP_NEW_INSTANCE 8898.long .L_OP_NEW_ARRAY 8899.long .L_OP_FILLED_NEW_ARRAY 8900.long .L_OP_FILLED_NEW_ARRAY_RANGE 8901.long .L_OP_FILL_ARRAY_DATA 8902.long .L_OP_THROW 8903.long .L_OP_GOTO 8904.long .L_OP_GOTO_16 8905.long .L_OP_GOTO_32 8906.long .L_OP_PACKED_SWITCH 8907.long .L_OP_SPARSE_SWITCH 8908.long .L_OP_CMPL_FLOAT 8909.long .L_OP_CMPG_FLOAT 8910.long .L_OP_CMPL_DOUBLE 8911.long .L_OP_CMPG_DOUBLE 8912.long .L_OP_CMP_LONG 8913.long .L_OP_IF_EQ 8914.long .L_OP_IF_NE 8915.long .L_OP_IF_LT 8916.long .L_OP_IF_GE 8917.long .L_OP_IF_GT 8918.long .L_OP_IF_LE 8919.long .L_OP_IF_EQZ 8920.long .L_OP_IF_NEZ 8921.long .L_OP_IF_LTZ 8922.long .L_OP_IF_GEZ 8923.long .L_OP_IF_GTZ 8924.long .L_OP_IF_LEZ 8925.long .L_OP_UNUSED_3E 8926.long .L_OP_UNUSED_3F 8927.long .L_OP_UNUSED_40 8928.long .L_OP_UNUSED_41 8929.long .L_OP_UNUSED_42 8930.long .L_OP_UNUSED_43 8931.long .L_OP_AGET 8932.long .L_OP_AGET_WIDE 8933.long .L_OP_AGET_OBJECT 8934.long .L_OP_AGET_BOOLEAN 8935.long .L_OP_AGET_BYTE 8936.long .L_OP_AGET_CHAR 8937.long .L_OP_AGET_SHORT 8938.long .L_OP_APUT 8939.long .L_OP_APUT_WIDE 8940.long .L_OP_APUT_OBJECT 8941.long .L_OP_APUT_BOOLEAN 8942.long .L_OP_APUT_BYTE 8943.long .L_OP_APUT_CHAR 8944.long .L_OP_APUT_SHORT 8945.long .L_OP_IGET 8946.long .L_OP_IGET_WIDE 8947.long .L_OP_IGET_OBJECT 8948.long .L_OP_IGET_BOOLEAN 8949.long .L_OP_IGET_BYTE 8950.long .L_OP_IGET_CHAR 8951.long .L_OP_IGET_SHORT 8952.long .L_OP_IPUT 8953.long .L_OP_IPUT_WIDE 8954.long .L_OP_IPUT_OBJECT 8955.long .L_OP_IPUT_BOOLEAN 8956.long .L_OP_IPUT_BYTE 8957.long .L_OP_IPUT_CHAR 8958.long .L_OP_IPUT_SHORT 8959.long .L_OP_SGET 8960.long .L_OP_SGET_WIDE 8961.long .L_OP_SGET_OBJECT 8962.long .L_OP_SGET_BOOLEAN 8963.long .L_OP_SGET_BYTE 8964.long .L_OP_SGET_CHAR 8965.long .L_OP_SGET_SHORT 8966.long .L_OP_SPUT 8967.long .L_OP_SPUT_WIDE 8968.long .L_OP_SPUT_OBJECT 8969.long .L_OP_SPUT_BOOLEAN 8970.long .L_OP_SPUT_BYTE 8971.long .L_OP_SPUT_CHAR 8972.long .L_OP_SPUT_SHORT 8973.long .L_OP_INVOKE_VIRTUAL 8974.long .L_OP_INVOKE_SUPER 8975.long .L_OP_INVOKE_DIRECT 8976.long .L_OP_INVOKE_STATIC 8977.long .L_OP_INVOKE_INTERFACE 8978.long .L_OP_UNUSED_73 8979.long .L_OP_INVOKE_VIRTUAL_RANGE 8980.long .L_OP_INVOKE_SUPER_RANGE 8981.long .L_OP_INVOKE_DIRECT_RANGE 8982.long .L_OP_INVOKE_STATIC_RANGE 8983.long .L_OP_INVOKE_INTERFACE_RANGE 8984.long .L_OP_UNUSED_79 8985.long .L_OP_UNUSED_7A 8986.long .L_OP_NEG_INT 8987.long .L_OP_NOT_INT 8988.long .L_OP_NEG_LONG 8989.long .L_OP_NOT_LONG 8990.long .L_OP_NEG_FLOAT 8991.long .L_OP_NEG_DOUBLE 8992.long .L_OP_INT_TO_LONG 8993.long .L_OP_INT_TO_FLOAT 8994.long .L_OP_INT_TO_DOUBLE 8995.long .L_OP_LONG_TO_INT 8996.long .L_OP_LONG_TO_FLOAT 8997.long .L_OP_LONG_TO_DOUBLE 8998.long .L_OP_FLOAT_TO_INT 8999.long .L_OP_FLOAT_TO_LONG 9000.long .L_OP_FLOAT_TO_DOUBLE 9001.long .L_OP_DOUBLE_TO_INT 9002.long .L_OP_DOUBLE_TO_LONG 9003.long .L_OP_DOUBLE_TO_FLOAT 9004.long .L_OP_INT_TO_BYTE 9005.long .L_OP_INT_TO_CHAR 9006.long .L_OP_INT_TO_SHORT 9007.long .L_OP_ADD_INT 9008.long .L_OP_SUB_INT 9009.long .L_OP_MUL_INT 9010.long .L_OP_DIV_INT 9011.long .L_OP_REM_INT 9012.long .L_OP_AND_INT 9013.long .L_OP_OR_INT 9014.long .L_OP_XOR_INT 9015.long .L_OP_SHL_INT 9016.long .L_OP_SHR_INT 9017.long .L_OP_USHR_INT 9018.long .L_OP_ADD_LONG 9019.long .L_OP_SUB_LONG 9020.long .L_OP_MUL_LONG 9021.long .L_OP_DIV_LONG 9022.long .L_OP_REM_LONG 9023.long .L_OP_AND_LONG 9024.long .L_OP_OR_LONG 9025.long .L_OP_XOR_LONG 9026.long .L_OP_SHL_LONG 9027.long .L_OP_SHR_LONG 9028.long .L_OP_USHR_LONG 9029.long .L_OP_ADD_FLOAT 9030.long .L_OP_SUB_FLOAT 9031.long .L_OP_MUL_FLOAT 9032.long .L_OP_DIV_FLOAT 9033.long .L_OP_REM_FLOAT 9034.long .L_OP_ADD_DOUBLE 9035.long .L_OP_SUB_DOUBLE 9036.long .L_OP_MUL_DOUBLE 9037.long .L_OP_DIV_DOUBLE 9038.long .L_OP_REM_DOUBLE 9039.long .L_OP_ADD_INT_2ADDR 9040.long .L_OP_SUB_INT_2ADDR 9041.long .L_OP_MUL_INT_2ADDR 9042.long .L_OP_DIV_INT_2ADDR 9043.long .L_OP_REM_INT_2ADDR 9044.long .L_OP_AND_INT_2ADDR 9045.long .L_OP_OR_INT_2ADDR 9046.long .L_OP_XOR_INT_2ADDR 9047.long .L_OP_SHL_INT_2ADDR 9048.long .L_OP_SHR_INT_2ADDR 9049.long .L_OP_USHR_INT_2ADDR 9050.long .L_OP_ADD_LONG_2ADDR 9051.long .L_OP_SUB_LONG_2ADDR 9052.long .L_OP_MUL_LONG_2ADDR 9053.long .L_OP_DIV_LONG_2ADDR 9054.long .L_OP_REM_LONG_2ADDR 9055.long .L_OP_AND_LONG_2ADDR 9056.long .L_OP_OR_LONG_2ADDR 9057.long .L_OP_XOR_LONG_2ADDR 9058.long .L_OP_SHL_LONG_2ADDR 9059.long .L_OP_SHR_LONG_2ADDR 9060.long .L_OP_USHR_LONG_2ADDR 9061.long .L_OP_ADD_FLOAT_2ADDR 9062.long .L_OP_SUB_FLOAT_2ADDR 9063.long .L_OP_MUL_FLOAT_2ADDR 9064.long .L_OP_DIV_FLOAT_2ADDR 9065.long .L_OP_REM_FLOAT_2ADDR 9066.long .L_OP_ADD_DOUBLE_2ADDR 9067.long .L_OP_SUB_DOUBLE_2ADDR 9068.long .L_OP_MUL_DOUBLE_2ADDR 9069.long .L_OP_DIV_DOUBLE_2ADDR 9070.long .L_OP_REM_DOUBLE_2ADDR 9071.long .L_OP_ADD_INT_LIT16 9072.long .L_OP_RSUB_INT 9073.long .L_OP_MUL_INT_LIT16 9074.long .L_OP_DIV_INT_LIT16 9075.long .L_OP_REM_INT_LIT16 9076.long .L_OP_AND_INT_LIT16 9077.long .L_OP_OR_INT_LIT16 9078.long .L_OP_XOR_INT_LIT16 9079.long .L_OP_ADD_INT_LIT8 9080.long .L_OP_RSUB_INT_LIT8 9081.long .L_OP_MUL_INT_LIT8 9082.long .L_OP_DIV_INT_LIT8 9083.long .L_OP_REM_INT_LIT8 9084.long .L_OP_AND_INT_LIT8 9085.long .L_OP_OR_INT_LIT8 9086.long .L_OP_XOR_INT_LIT8 9087.long .L_OP_SHL_INT_LIT8 9088.long .L_OP_SHR_INT_LIT8 9089.long .L_OP_USHR_INT_LIT8 9090.long .L_OP_IGET_VOLATILE 9091.long .L_OP_IPUT_VOLATILE 9092.long .L_OP_SGET_VOLATILE 9093.long .L_OP_SPUT_VOLATILE 9094.long .L_OP_IGET_OBJECT_VOLATILE 9095.long .L_OP_IGET_WIDE_VOLATILE 9096.long .L_OP_IPUT_WIDE_VOLATILE 9097.long .L_OP_SGET_WIDE_VOLATILE 9098.long .L_OP_SPUT_WIDE_VOLATILE 9099.long .L_OP_BREAKPOINT 9100.long .L_OP_THROW_VERIFICATION_ERROR 9101.long .L_OP_EXECUTE_INLINE 9102.long .L_OP_EXECUTE_INLINE_RANGE 9103.long .L_OP_INVOKE_DIRECT_EMPTY 9104.long .L_OP_RETURN_VOID_BARRIER 9105.long .L_OP_IGET_QUICK 9106.long .L_OP_IGET_WIDE_QUICK 9107.long .L_OP_IGET_OBJECT_QUICK 9108.long .L_OP_IPUT_QUICK 9109.long .L_OP_IPUT_WIDE_QUICK 9110.long .L_OP_IPUT_OBJECT_QUICK 9111.long .L_OP_INVOKE_VIRTUAL_QUICK 9112.long .L_OP_INVOKE_VIRTUAL_QUICK_RANGE 9113.long .L_OP_INVOKE_SUPER_QUICK 9114.long .L_OP_INVOKE_SUPER_QUICK_RANGE 9115.long .L_OP_IPUT_OBJECT_VOLATILE 9116.long .L_OP_SGET_OBJECT_VOLATILE 9117.long .L_OP_SPUT_OBJECT_VOLATILE 9118.long .L_OP_DISPATCH_FF 9119 9120 9121/* File: x86/footer.S */ 9122/* 9123 * Copyright (C) 2008 The Android Open Source Project 9124 * 9125 * Licensed under the Apache License, Version 2.0 (the "License"); 9126 * you may not use this file except in compliance with the License. 9127 * You may obtain a copy of the License at 9128 * 9129 * http://www.apache.org/licenses/LICENSE-2.0 9130 * 9131 * Unless required by applicable law or agreed to in writing, software 9132 * distributed under the License is distributed on an "AS IS" BASIS, 9133 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9134 * See the License for the specific language governing permissions and 9135 * limitations under the License. 9136 */ 9137/* 9138 * Common subroutines and data. 9139 */ 9140 9141#if defined(WITH_JIT) 9142/* 9143 * JIT-related re-entries into the interpreter. In general, if the 9144 * exit from a translation can at some point be chained, the entry 9145 * here requires that control arrived via a call, and that the "rp" 9146 * on TOS is actually a pointer to a 32-bit cell containing the Dalvik PC 9147 * of the next insn to handle. If no chaining will happen, the entry 9148 * should be reached via a direct jump and rPC set beforehand. 9149 */ 9150 9151 .global dvmJitToInterpPunt 9152/* 9153 * The compiler will generate a jump to this entry point when it is 9154 * having difficulty translating a Dalvik instruction. We must skip 9155 * the code cache lookup & prevent chaining to avoid bouncing between 9156 * the interpreter and code cache. rPC must be set on entry. 9157 */ 9158dvmJitToInterpPunt: 9159#if defined(WITH_JIT_TUNING) 9160 movl rPC, OUT_ARG0(%esp) 9161 call dvmBumpPunt 9162#endif 9163 FETCH_INST_R %edx 9164 GOTO_NEXT_R %edx 9165 9166 .global dvmJitToInterpSingleStep 9167/* 9168 * Return to the interpreter to handle a single instruction. 9169 * Should be reached via a call. 9170 * On entry: 9171 * 0(%esp) <= native return address within trace 9172 * rPC <= Dalvik PC of this instruction 9173 * OUT_ARG0+4(%esp) <= Dalvik PC of next instruction 9174 */ 9175dvmJitToInterpSingleStep: 9176 pop %eax 9177 movl rGLUE, %ecx 9178 movl OUT_ARG0(%esp), %edx 9179 movl %eax,offGlue_jitResumeNPC(%ecx) 9180 movl %edx,offGlue_jitResumeDPC(%ecx) 9181 movl $kInterpEntryInstr,offGlue_entryPoint(%ecx) 9182 movl $1,rINST # changeInterp <= true 9183 jmp common_gotoBail 9184 9185 .global dvmJitToInterpNoChainNoProfile 9186/* 9187 * Return from the translation cache to the interpreter to do method 9188 * invocation. Check if the translation exists for the callee, but don't 9189 * chain to it. rPC must be set on entry. 9190 */ 9191dvmJitToInterpNoChainNoProfile: 9192#if defined(WITH_JIT_TUNING) 9193 call dvmBumpNoChain 9194#endif 9195 movl rPC,OUT_ARG0(%esp) 9196 call dvmJitGetCodeAddr # is there a translation? 9197 movl rGLUE,%ecx 9198 movl offGlue_self(%ecx), %ecx # ecx <- glue->self 9199 movl %eax,offThread_inJitCodeCache(%ecx) # set inJitCodeCache flag 9200 cmpl $0, %eax 9201 jz 1f 9202 call *%eax # exec translation if we've got one 9203 # won't return 92041: 9205 FETCH_INST_R %edx 9206 GOTO_NEXT_R %edx 9207 9208/* 9209 * Return from the translation cache and immediately request a 9210 * translation fro the exit target, but don't attempt to chain. 9211 * rPC set on entry. 9212 */ 9213 .global dvmJitToInterpTraceSelectNoChain 9214dvmJitToInterpTraceSelectNoChain: 9215#if defined(WITH_JIT_TUNING) 9216 call dvmBumpNoChain 9217#endif 9218 movl rPC,OUT_ARG0(%esp) 9219 call dvmJitGetCodeAddr # is there a translation? 9220 movl rGLUE,%ecx 9221 movl offGlue_self(%ecx),%ecx 9222 cmpl $0,%eax 9223 movl %eax,offThread_inJitCodeCache(%ecx) # set inJitCodeCache flag 9224 jz 1f 9225 call *%eax # jump to tranlation 9226 # won't return 9227 9228/* No Translation - request one */ 92291: 9230 GET_JIT_PROF_TABLE %ecx %eax 9231 cmpl $0, %eax # JIT enabled? 9232 jnz 2f # Request one if so 9233 FETCH_INST_R %edx # Continue interpreting if not 9234 GOTO_NEXT_R %edx 92352: 9236 movl $kJitTSelectRequestHot,rINST # ask for trace select 9237 jmp common_selectTrace 9238 9239/* 9240 * Return from the translation cache and immediately request a 9241 * translation for the exit target. Reached via a call, and 9242 * (TOS)->rPC. 9243 */ 9244 .global dvmJitToInterpTraceSelect 9245dvmJitToInterpTraceSelect: 9246 pop rINST # save chain cell address in callee save reg 9247 movl (rINST),rPC 9248 movl rPC,OUT_ARG0(%esp) 9249 call dvmJitGetCodeAddr # is there a translation? 9250 cmpl $0,%eax 9251 jz 1b # no - ask for one 9252 movl %eax,OUT_ARG0(%esp) 9253# FIXME - need to adjust rINST to beginning of sequence 9254 movl rINST,OUT_ARG1(%esp) 9255 call dvmJitChain # Attempt dvmJitChain(codeAddr,chainAddr) 9256 cmpl $0,%eax # Success? 9257 jz toInterpreter # didn't chain - interpret 9258 call *%eax 9259 # won't return 9260 9261/* 9262 * Placeholder entries for x86 JIT 9263 */ 9264 .global dvmJitToInterpBackwardBranch 9265dvmJitToInterpBackwardBranch: 9266 .global dvmJitToInterpNormal 9267dvmJitToInterpNormal: 9268 .global dvmJitToInterpNoChain 9269dvmJitToInterpNoChain: 9270toInterpreter: 9271 jmp common_abort 9272#endif 9273 9274/* 9275 * Common code when a backwards branch is taken 9276 * 9277 * On entry: 9278 * ebx (a.k.a. rINST) -> PC adjustment in 16-bit words 9279 */ 9280common_backwardBranch: 9281 movl rGLUE,%ecx 9282 call common_periodicChecks # rPC and ecx/rGLUE preserved 9283#if defined(WITH_JIT) 9284 GET_JIT_PROF_TABLE %ecx %edx 9285 ADVANCE_PC_INDEXED rINST 9286 cmpl $0,%edx 9287 FETCH_INST 9288 jz 1f # Profiling off - continue 9289 .global updateProfile 9290updateProfile: 9291common_updateProfile: 9292 # quick & dirty hash 9293 movl rPC, %eax 9294 shrl $12, %eax 9295 xorl rPC, %eax 9296 andl $((1<<JIT_PROF_SIZE_LOG_2)-1),%eax 9297 decb (%edx,%eax) 9298 jz 2f 92991: 9300 GOTO_NEXT 93012: 9302/* 9303 * Here, we switch to the debug interpreter to request 9304 * trace selection. First, though, check to see if there 9305 * is already a native translation in place (and, if so, 9306 * jump to it now. 9307 */ 9308 GET_JIT_THRESHOLD %ecx rINST 9309 EXPORT_PC 9310 movb rINSTbl,(%edx,%eax) # reset counter 9311 movl offGlue_self(%ecx),rINST 9312 movl rPC,OUT_ARG0(%esp) 9313 call dvmJitGetCodeAddr # already have one? 9314 movl %eax,offThread_inJitCodeCache(rINST) # set the inJitCodeCache flag 9315 cmpl $0,%eax 9316 jz 1f 9317 call *%eax # FIXME: decide call vs/ jmp!. No return either way 93181: 9319 movl $kJitTSelectRequest,%eax 9320 # On entry, eax<- jitState, rPC valid 9321common_selectTrace: 9322 movl rGLUE,%ecx 9323 movl %eax,offGlue_jitState(%ecx) 9324 movl $kInterpEntryInstr,offGlue_entryPoint(%ecx) 9325 movl $1,rINST 9326 jmp common_gotoBail 9327#else 9328 ADVANCE_PC_INDEXED rINST 9329 FETCH_INST 9330 GOTO_NEXT 9331#endif 9332 9333 9334 9335/* 9336 * Common code for method invocation with range. 9337 * 9338 * On entry: 9339 * eax = Method* methodToCall 9340 * rINSTw trashed, must reload 9341 */ 9342 9343common_invokeMethodRange: 9344.LinvokeNewRange: 9345 9346 /* 9347 * prepare to copy args to "outs" area of current frame 9348 */ 9349 9350 movzbl 1(rPC),rINST # rINST<- AA 9351 movzwl 4(rPC), %ecx # %ecx<- CCCC 9352 SAVEAREA_FROM_FP %edx # %edx<- &StackSaveArea 9353 test rINST, rINST 9354 movl rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA 9355 jz .LinvokeArgsDone # no args; jump to args done 9356 9357 9358 /* 9359 * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea) 9360 * (very few methods have > 10 args; could unroll for common cases) 9361 */ 9362 9363 movl %ebx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- save %ebx 9364 lea (rFP, %ecx, 4), %ecx # %ecx<- &vCCCC 9365 shll $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 9366 subl LOCAL0_OFFSET(%ebp), %edx # %edx<- update &outs 9367 shrl $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 93681: 9369 movl (%ecx), %ebx # %ebx<- vCCCC 9370 lea 4(%ecx), %ecx # %ecx<- &vCCCC++ 9371 subl $1, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- LOCAL0_OFFSET-- 9372 movl %ebx, (%edx) # *outs<- vCCCC 9373 lea 4(%edx), %edx # outs++ 9374 jne 1b # loop if count (LOCAL0_OFFSET(%ebp)) not zero 9375 movl LOCAL1_OFFSET(%ebp), %ebx # %ebx<- restore %ebx 9376 jmp .LinvokeArgsDone # continue 9377 9378 /* 9379 * %eax is "Method* methodToCall", the method we're trying to call 9380 * prepare to copy args to "outs" area of current frame 9381 */ 9382 9383common_invokeMethodNoRange: 9384.LinvokeNewNoRange: 9385 movzbl 1(rPC),rINST # rINST<- BA 9386 movl rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA 9387 shrl $4, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- B 9388 je .LinvokeArgsDone # no args; jump to args done 9389 movzwl 4(rPC), %ecx # %ecx<- GFED 9390 SAVEAREA_FROM_FP %edx # %edx<- &StackSaveArea 9391 9392 /* 9393 * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs 9394 */ 9395 9396.LinvokeNonRange: 9397 cmp $2, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 2 9398 movl %ecx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- GFED 9399 jl 1f # handle 1 arg 9400 je 2f # handle 2 args 9401 cmp $4, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 4 9402 jl 3f # handle 3 args 9403 je 4f # handle 4 args 94045: 9405 andl $15, rINST # rINSTw<- A 9406 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9407 movl (rFP, rINST, 4), %ecx # %ecx<- vA 9408 movl %ecx, (%edx) # *outs<- vA 9409 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 94104: 9411 shr $12, %ecx # %ecx<- G 9412 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9413 movl (rFP, %ecx, 4), %ecx # %ecx<- vG 9414 movl %ecx, (%edx) # *outs<- vG 9415 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 94163: 9417 and $0x0f00, %ecx # %ecx<- 0F00 9418 shr $8, %ecx # %ecx<- F 9419 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9420 movl (rFP, %ecx, 4), %ecx # %ecx<- vF 9421 movl %ecx, (%edx) # *outs<- vF 9422 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 94232: 9424 and $0x00f0, %ecx # %ecx<- 00E0 9425 shr $4, %ecx # %ecx<- E 9426 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9427 movl (rFP, %ecx, 4), %ecx # %ecx<- vE 9428 movl %ecx, (%edx) # *outs<- vE 9429 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 94301: 9431 and $0x000f, %ecx # %ecx<- 000D 9432 movl (rFP, %ecx, 4), %ecx # %ecx<- vD 9433 movl %ecx, -4(%edx) # *--outs<- vD 94340: 9435 9436 /* 9437 * %eax is "Method* methodToCall", the method we're trying to call 9438 * find space for the new stack frame, check for overflow 9439 */ 9440 9441.LinvokeArgsDone: 9442 movzwl offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize 9443 movzwl offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize 9444 movl %eax, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- methodToCall 9445 shl $2, %edx # %edx<- update offset 9446 SAVEAREA_FROM_FP %eax # %eax<- &StackSaveArea 9447 subl %edx, %eax # %eax<- newFP; (old savearea - regsSize) 9448 movl rGLUE,%edx # %edx<- pMterpGlue 9449 movl %eax, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- &outs 9450 subl $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP) 9451 movl offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd 9452 movl %edx, LOCAL2_OFFSET(%ebp) # LOCAL2_OFFSET<- glue->interpStackEnd 9453 shl $2, %ecx # %ecx<- update offset for outsSize 9454 movl %eax, %edx # %edx<- newSaveArea 9455 sub %ecx, %eax # %eax<- bottom; (newSaveArea - outsSize) 9456 cmp LOCAL2_OFFSET(%ebp), %eax # compare interpStackEnd and bottom 9457 movl LOCAL0_OFFSET(%ebp), %eax # %eax<- restore methodToCall 9458 jl .LstackOverflow # handle frame overflow 9459 9460 /* 9461 * set up newSaveArea 9462 */ 9463 9464#ifdef EASY_GDB 9465 SAVEAREA_FROM_FP %ecx # %ecx<- &StackSaveArea 9466 movl %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs 9467#endif 9468 movl rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP 9469 movl rPC, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC 9470 testl $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call 9471 movl %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call 9472 jne .LinvokeNative # handle native call 9473 9474 /* 9475 * Update "glue" values for the new method 9476 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp 9477 */ 9478 9479 movl offMethod_clazz(%eax), %edx # %edx<- method->clazz 9480 movl rGLUE,%ecx # %ecx<- pMterpGlue 9481 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex 9482 movl %eax, offGlue_method(%ecx) # glue->method<- methodToCall 9483 movl %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex 9484 movl offMethod_insns(%eax), rPC # rPC<- methodToCall->insns 9485 movl offGlue_self(%ecx), %eax # %eax<- glue->self 9486 movl LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP 9487 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP 9488 FETCH_INST 9489 GOTO_NEXT # jump to methodToCall->insns 9490 9491 /* 9492 * Prep for the native call 9493 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea 9494 */ 9495 9496.LinvokeNative: 9497 movl rGLUE,%ecx # %ecx<- pMterpGlue 9498 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 9499 movl offGlue_self(%ecx), %ecx # %ecx<- glue->self 9500 movl offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->... 9501 movl %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top 9502 movl %edx, OUT_ARG4(%esp) # save newSaveArea 9503 movl LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP 9504 movl %edx, offThread_curFrame(%ecx) # glue->self->curFrame<- newFP 9505 movl %ecx, OUT_ARG3(%esp) # save glue->self 9506 movl %ecx, OUT_ARG2(%esp) # push parameter glue->self 9507 movl rGLUE,%ecx # %ecx<- pMterpGlue 9508 movl OUT_ARG1(%esp), %eax # %eax<- methodToCall 9509 lea offGlue_retval(%ecx), %ecx # %ecx<- &retval 9510 movl %ecx, OUT_ARG0(%esp) # push parameter pMterpGlue 9511 push %edx # push parameter newFP 9512 9513 call *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc 9514 lea 4(%esp), %esp 9515 movl OUT_ARG4(%esp), %ecx # %ecx<- newSaveArea 9516 movl OUT_ARG3(%esp), %eax # %eax<- glue->self 9517 movl offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top 9518 cmp $0, offThread_exception(%eax) # check for exception 9519 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP 9520 movl %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top 9521 jne common_exceptionThrown # handle exception 9522 FETCH_INST_OPCODE 3 %edx 9523 ADVANCE_PC 3 9524 GOTO_NEXT_R %edx # jump to next instruction 9525 9526.LstackOverflow: # eax=methodToCall 9527 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 9528 movl rGLUE,%eax # %eax<- pMterpGlue 9529 movl offGlue_self(%eax), %eax # %eax<- glue->self 9530 movl %eax, OUT_ARG0(%esp) # push parameter self 9531 call dvmHandleStackOverflow # call: (Thread* self, Method* meth) 9532 jmp common_exceptionThrown # handle exception 9533 9534 9535/* 9536 * Do we need the thread to be suspended or have debugger/profiling activity? 9537 * 9538 * On entry: 9539 * ebx -> PC adjustment in 16-bit words (must be preserved) 9540 * ecx -> GLUE pointer 9541 * reentry type, e.g. kInterpEntryInstr stored in rGLUE->entryPoint 9542 * 9543 * Note: A call will normally kill %eax and %ecx. To 9544 * streamline the normal case, this routine will preserve 9545 * %ecx in addition to the normal caller save regs. The save/restore 9546 * is a bit ugly, but will happen in the relatively uncommon path. 9547 * TODO: Basic-block style Jit will need a hook here as well. Fold it into 9548 * the suspendCount check so we can get both in 1 shot. 9549 */ 9550common_periodicChecks: 9551 movl offGlue_pSelfSuspendCount(%ecx),%eax # eax <- &suspendCount 9552 cmpl $0,(%eax) 9553 jne 1f 9554 95556: 9556 movl offGlue_pDebuggerActive(%ecx),%eax # eax <- &DebuggerActive 9557 movl offGlue_pActiveProfilers(%ecx),%ecx # ecx <- &ActiveProfilers 9558 testl %eax,%eax # debugger enabled? 9559 je 2f 9560 movzbl (%eax),%eax # get active count 95612: 9562 orl (%ecx),%eax # eax <- debuggerActive | activeProfilers 9563 movl rGLUE,%ecx # restore rGLUE 9564 jne 3f # one or both active - switch interp 9565 95665: 9567 ret 9568 9569 /* Check for suspend */ 95701: 9571 /* At this point, the return pointer to the caller of 9572 * common_periodicChecks is on the top of stack. We need to preserve 9573 * GLUE(ecx). 9574 * The outgoing profile is: 9575 * bool dvmCheckSuspendPending(Thread* self) 9576 * Because we reached here via a call, go ahead and build a new frame. 9577 */ 9578 EXPORT_PC # need for precise GC 9579 movl offGlue_self(%ecx),%eax # eax<- glue->self 9580 push %ebp 9581 movl %esp,%ebp 9582 subl $24,%esp 9583 movl %eax,OUT_ARG0(%esp) 9584 call dvmCheckSuspendPending 9585 addl $24,%esp 9586 pop %ebp 9587 movl rGLUE,%ecx 9588 9589 /* 9590 * Need to check to see if debugger or profiler flags got set 9591 * while we were suspended. 9592 */ 9593 jmp 6b 9594 9595 /* Switch interpreters */ 9596 /* Note: %ebx contains the 16-bit word offset to be applied to rPC to 9597 * "complete" the interpretation of backwards branches. In effect, we 9598 * are completing the interpretation of the branch instruction here, 9599 * and the new interpreter will resume interpretation at the branch 9600 * target. However, a switch request recognized during the handling 9601 * of a return from method instruction results in an immediate abort, 9602 * and the new interpreter will resume by re-interpreting the return 9603 * instruction. 9604 */ 96053: 9606 leal (rPC,%ebx,2),rPC # adjust pc to show target 9607 movl rGLUE,%ecx # bail expect GLUE already loaded 9608 movl $1,rINST # set changeInterp to true 9609 jmp common_gotoBail 9610 9611 9612/* 9613 * Common code for handling a return instruction 9614 */ 9615common_returnFromMethod: 9616 movl rGLUE,%ecx 9617 /* Set entry mode in case we bail */ 9618 movb $kInterpEntryReturn,offGlue_entryPoint(%ecx) 9619 xorl rINST,rINST # zero offset in case we switch interps 9620 call common_periodicChecks # Note: expects %ecx to be preserved 9621 9622 SAVEAREA_FROM_FP %eax # eax<- saveArea (old) 9623 movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame 9624 movl (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST 9625 cmpl $0,rINST # break? 9626 je common_gotoBail # break frame, bail out completely 9627 9628 movl offStackSaveArea_savedPc(%eax),rPC # pc<- saveArea->savedPC 9629 movl offGlue_self(%ecx),%eax # eax<- self 9630 movl rINST,offGlue_method(%ecx) # glue->method = newSave->meethod 9631 movl rFP,offThread_curFrame(%eax) # self->curFrame = fp 9632 movl offMethod_clazz(rINST),%eax # eax<- method->clazz 9633 FETCH_INST_OPCODE 3 %edx 9634 movl offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex 9635 ADVANCE_PC 3 9636 movl %eax,offGlue_methodClassDex(%ecx) 9637 /* not bailing - restore entry mode to default */ 9638 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx) 9639 GOTO_NEXT_R %edx 9640 9641/* 9642 * Prepare to strip the current frame and "longjump" back to caller of 9643 * dvmMterpStdRun. 9644 * 9645 * on entry: 9646 * rINST holds changeInterp 9647 * ecx holds glue pointer 9648 * 9649 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp) 9650 */ 9651common_gotoBail: 9652 movl rPC,offGlue_pc(%ecx) # export state to glue 9653 movl rFP,offGlue_fp(%ecx) 9654 movl %ecx,OUT_ARG0(%esp) # glue in arg0 9655 movl rINST,OUT_ARG1(%esp) # changeInterp in arg1 9656 call dvmMterpStdBail # bail out.... 9657 9658 9659/* 9660 * After returning from a "glued" function, pull out the updated values 9661 * and start executing at the next instruction. 9662 */ 9663 common_resumeAfterGlueCall: 9664 LOAD_PC_FP_FROM_GLUE 9665 FETCH_INST 9666 GOTO_NEXT 9667 9668/* 9669 * Integer divide or mod by zero 9670 */ 9671common_errDivideByZero: 9672 EXPORT_PC 9673 movl $.LstrArithmeticException,%eax 9674 movl %eax,OUT_ARG0(%esp) 9675 movl $.LstrDivideByZero,%eax 9676 movl %eax,OUT_ARG1(%esp) 9677 call dvmThrowException 9678 jmp common_exceptionThrown 9679 9680/* 9681 * Attempt to allocate an array with a negative size. 9682 */ 9683common_errNegativeArraySize: 9684 EXPORT_PC 9685 movl $.LstrNegativeArraySizeException,%eax 9686 movl %eax,OUT_ARG0(%esp) 9687 xorl %eax,%eax 9688 movl %eax,OUT_ARG1(%esp) 9689 call dvmThrowException 9690 jmp common_exceptionThrown 9691 9692/* 9693 * Attempt to allocate an array with a negative size. 9694 */ 9695common_errNoSuchMethod: 9696 9697 EXPORT_PC 9698 movl $.LstrNoSuchMethodError,%eax 9699 movl %eax,OUT_ARG0(%esp) 9700 xorl %eax,%eax 9701 movl %eax,OUT_ARG1(%esp) 9702 call dvmThrowException 9703 jmp common_exceptionThrown 9704 9705/* 9706 * Hit a null object when we weren't expecting one. Export the PC, throw a 9707 * NullPointerException and goto the exception processing code. 9708 */ 9709common_errNullObject: 9710 EXPORT_PC 9711 movl $.LstrNullPointerException,%eax 9712 movl %eax,OUT_ARG0(%esp) 9713 xorl %eax,%eax 9714 movl %eax,OUT_ARG1(%esp) 9715 call dvmThrowException 9716 jmp common_exceptionThrown 9717 9718/* 9719 * Array index exceeds max. 9720 * On entry: 9721 * eax <- array object 9722 * ecx <- index 9723 */ 9724common_errArrayIndex: 9725 EXPORT_PC 9726 movl offArrayObject_length(%eax), %eax 9727 movl %ecx,OUT_ARG0(%esp) 9728 movl %eax,OUT_ARG1(%esp) 9729 call dvmThrowAIOOBE # dvmThrowAIOO(index, length) 9730 jmp common_exceptionThrown 9731 9732/* 9733 * Somebody has thrown an exception. Handle it. 9734 * 9735 * If the exception processing code returns to us (instead of falling 9736 * out of the interpreter), continue with whatever the next instruction 9737 * now happens to be. 9738 * 9739 * This does not return. 9740 */ 9741common_exceptionThrown: 9742 movl rGLUE,%ecx 9743 movl rPC,offGlue_pc(%ecx) 9744 movl rFP,offGlue_fp(%ecx) 9745 movl %ecx,OUT_ARG0(%esp) 9746 call dvmMterp_exceptionThrown 9747 jmp common_resumeAfterGlueCall 9748 9749common_abort: 9750 movl $0xdeadf00d,%eax 9751 call *%eax 9752 9753 9754/* 9755 * Strings 9756 */ 9757 9758 .section .rodata 9759.LstrNullPointerException: 9760 .asciz "Ljava/lang/NullPointerException;" 9761.LstrArithmeticException: 9762 .asciz "Ljava/lang/ArithmeticException;" 9763.LstrDivideByZero: 9764 .asciz "divide by zero" 9765.LstrNegativeArraySizeException: 9766 .asciz "Ljava/lang/NegativeArraySizeException;" 9767.LstrInstantiationError: 9768 .asciz "Ljava/lang/InstantiationError;" 9769.LstrNoSuchMethodError: 9770 .asciz "Ljava/lang/NoSuchMethodError;" 9771.LstrInternalErrorA: 9772 .asciz "Ljava/lang/InternalError;" 9773.LstrFilledNewArrayNotImplA: 9774 .asciz "filled-new-array only implemented for 'int'" 9775 9776