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