InterpAsm-x86.S revision 3e1bbffab14075a340ad0165c6ada6a43875a01f
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,OUT_ARG1(%esp) 6560 movl %ecx,OUT_ARG0(%esp) 6561 call dvmInstanceofNonTrivial # eax<- boolean result 6562 testl %eax,%eax # failed? 6563 jne .LOP_CHECK_CAST_okay # no, success 6564 6565 # A cast has failed. We need to throw a ClassCastException with the 6566 # class of the object that failed to be cast. 6567 EXPORT_PC 6568 movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz 6569 movl $.LstrClassCastException,%eax 6570 movl offClassObject_descriptor(%ecx),%ecx 6571 movl %eax,OUT_ARG0(%esp) # arg0<- message 6572 movl %ecx,OUT_ARG1(%esp) # arg1<- obj->clazz->descriptor 6573 call dvmThrowExceptionWithClassMessage 6574 jmp common_exceptionThrown 6575 6576 /* 6577 * Resolution required. This is the least-likely path, and we're 6578 * going to have to recreate some data. 6579 * 6580 * rINST holds object 6581 */ 6582.LOP_CHECK_CAST_resolve: 6583 movl rGLUE,%ecx 6584 EXPORT_PC 6585 movzwl 2(rPC),%eax # eax<- BBBB 6586 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6587 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 6588 movl offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz 6589 movl $0,OUT_ARG2(%esp) # arg2<- false 6590 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz 6591 call dvmResolveClass # eax<- resolved ClassObject ptr 6592 testl %eax,%eax # got null? 6593 je common_exceptionThrown # yes, handle exception 6594 movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz 6595 jmp .LOP_CHECK_CAST_resolved # pick up where we left off 6596 6597/* continuation for OP_INSTANCE_OF */ 6598 6599 /* 6600 * Trivial test failed, need to perform full check. This is common. 6601 * eax holds obj->clazz 6602 * ecx holds class resolved from BBBB 6603 * rINST has BA 6604 */ 6605.LOP_INSTANCE_OF_fullcheck: 6606 movl %eax,OUT_ARG0(%esp) 6607 movl %ecx,OUT_ARG1(%esp) 6608 call dvmInstanceofNonTrivial # eax<- boolean result 6609 # fall through to OP_INSTANCE_OF_store 6610 6611 /* 6612 * eax holds boolean result 6613 * rINST holds BA 6614 */ 6615.LOP_INSTANCE_OF_store: 6616 FETCH_INST_OPCODE 2 %edx 6617 andb $0xf,rINSTbl # <- A 6618 ADVANCE_PC 2 6619 SET_VREG %eax rINST # vA<- eax 6620 GOTO_NEXT_R %edx 6621 6622 /* 6623 * Trivial test succeeded, save and bail. 6624 * r9 holds A 6625 */ 6626.LOP_INSTANCE_OF_trivial: 6627 FETCH_INST_OPCODE 2 %edx 6628 andb $0xf,rINSTbl # <- A 6629 ADVANCE_PC 2 6630 movl $1,%eax 6631 SET_VREG %eax rINST # vA<- true 6632 GOTO_NEXT_R %edx 6633 6634 /* 6635 * Resolution required. This is the least-likely path. 6636 * 6637 * edx holds BBBB 6638 * rINST holds BA 6639 */ 6640.LOP_INSTANCE_OF_resolve: 6641 movl %edx,OUT_ARG1(%esp) # arg1<- BBBB 6642 movl rGLUE,%ecx 6643 movl offGlue_method(%ecx),%ecx 6644 movl $1,OUT_ARG2(%esp) # arg2<- true 6645 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6646 EXPORT_PC 6647 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz 6648 call dvmResolveClass # eax<- resolved ClassObject ptr 6649 testl %eax,%eax # success? 6650 je common_exceptionThrown # no, handle exception 6651/* Now, we need to sync up with fast path. We need eax to 6652 * hold the obj->clazz, and ecx to hold the resolved class 6653 */ 6654 movl %eax,%ecx # ecx<- resolved class 6655 movl rINST,%eax # eax<- BA 6656 sarl $4,%eax # eax<- B 6657 GET_VREG_R %eax %eax # eax<- vB (obj) 6658 movl offObject_clazz(%eax),%eax # eax<- obj->clazz 6659 jmp .LOP_INSTANCE_OF_resolved 6660 6661/* continuation for OP_NEW_INSTANCE */ 6662 6663.LOP_NEW_INSTANCE_initialized: # on entry, ecx<- class 6664 /* TODO: remove test for interface/abstract, now done in verifier */ 6665 testl $(ACC_INTERFACE|ACC_ABSTRACT),offClassObject_accessFlags(%ecx) 6666 movl $ALLOC_DONT_TRACK,OUT_ARG1(%esp) 6667 jne .LOP_NEW_INSTANCE_abstract 6668.LOP_NEW_INSTANCE_finish: # ecx=class 6669 movl %ecx,OUT_ARG0(%esp) 6670 call dvmAllocObject # eax<- new object 6671 FETCH_INST_OPCODE 2 %edx 6672 testl %eax,%eax # success? 6673 je common_exceptionThrown # no, bail out 6674 SET_VREG %eax rINST 6675 ADVANCE_PC 2 6676 GOTO_NEXT_R %edx 6677 6678 /* 6679 * Class initialization required. 6680 * 6681 * ecx holds class object 6682 */ 6683.LOP_NEW_INSTANCE_needinit: 6684 SPILL_TMP1(%ecx) # save object 6685 movl %ecx,OUT_ARG0(%esp) 6686 call dvmInitClass # initialize class 6687 UNSPILL_TMP1(%ecx) # restore object 6688 testl %eax,%eax # success? 6689 jne .LOP_NEW_INSTANCE_initialized # success, continue 6690 jmp common_exceptionThrown # go deal with init exception 6691 6692 /* 6693 * Resolution required. This is the least-likely path. 6694 * 6695 */ 6696.LOP_NEW_INSTANCE_resolve: 6697 movl rGLUE,%ecx 6698 movzwl 2(rPC),%eax 6699 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6700 movl %eax,OUT_ARG1(%esp) 6701 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6702 movl $0,OUT_ARG2(%esp) 6703 movl %ecx,OUT_ARG0(%esp) 6704 call dvmResolveClass # call(clazz,off,flags) 6705 movl %eax,%ecx # ecx<- resolved ClassObject ptr 6706 testl %ecx,%ecx # success? 6707 jne .LOP_NEW_INSTANCE_resolved # good to go 6708 jmp common_exceptionThrown # no, handle exception 6709 6710 /* 6711 * TODO: remove this 6712 * We can't instantiate an abstract class or interface, so throw an 6713 * InstantiationError with the class descriptor as the message. 6714 * 6715 * ecx holds class object 6716 */ 6717.LOP_NEW_INSTANCE_abstract: 6718 movl offClassObject_descriptor(%ecx),%eax 6719 movl $.LstrInstantiationError,OUT_ARG0(%esp) 6720 movl %eax,OUT_ARG1(%esp) 6721 call dvmThrowExceptionWithClassMessage 6722 jmp common_exceptionThrown 6723 6724/* continuation for OP_NEW_ARRAY */ 6725 6726 /* 6727 * Resolve class. (This is an uncommon case.) 6728 * ecx holds class (null here) 6729 * eax holds array length (vB) 6730 */ 6731.LOP_NEW_ARRAY_resolve: 6732 movl rGLUE,%ecx 6733 SPILL_TMP1(%eax) # save array length 6734 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6735 movzwl 2(rPC),%eax # eax<- CCCC 6736 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6737 movl %eax,OUT_ARG1(%esp) 6738 movl $0,OUT_ARG2(%esp) 6739 movl %ecx,OUT_ARG0(%esp) 6740 call dvmResolveClass # eax<- call(clazz,ref,flag) 6741 movl %eax,%ecx 6742 UNSPILL_TMP1(%eax) 6743 testl %ecx,%ecx # successful resolution? 6744 je common_exceptionThrown # no, bail. 6745# fall through to OP_NEW_ARRAY_finish 6746 6747 /* 6748 * Finish allocation 6749 * 6750 * ecx holds class 6751 * eax holds array length (vB) 6752 */ 6753.LOP_NEW_ARRAY_finish: 6754 movl %ecx,OUT_ARG0(%esp) 6755 movl %eax,OUT_ARG1(%esp) 6756 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) 6757 call dvmAllocArrayByClass # eax<- call(clazz,length,flags) 6758 FETCH_INST_OPCODE 2 %edx 6759 testl %eax,%eax # failed? 6760 je common_exceptionThrown # yup - go handle 6761 SET_VREG %eax rINST 6762 ADVANCE_PC 2 6763 GOTO_NEXT_R %edx 6764 6765/* continuation for OP_FILLED_NEW_ARRAY */ 6766 6767.LOP_FILLED_NEW_ARRAY_more: 6768 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 6769 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 6770 call dvmResolveClass # eax<- call(clazz,ref,flag) 6771 testl %eax,%eax # null? 6772 je common_exceptionThrown # yes, handle it 6773 6774 # note: fall through to .LOP_FILLED_NEW_ARRAY_continue 6775 6776 /* 6777 * On entry: 6778 * eax holds array class [r0] 6779 * rINST holds AA or BB [r10] 6780 * ecx is scratch 6781 */ 6782.LOP_FILLED_NEW_ARRAY_continue: 6783 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor 6784 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags 6785 movzbl 1(%ecx),%ecx # ecx<- descriptor[1] 6786 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass 6787 movl rGLUE,%eax 6788 cmpb $'I',%cl # supported? 6789 je 1f 6790 cmpb $'L',%cl 6791 je 1f 6792 cmpb $'[',%cl 6793 jne .LOP_FILLED_NEW_ARRAY_notimpl # no, not handled yet 67941: 6795 movl %ecx,offGlue_retval+4(%eax) # save type 6796 .if (!0) 6797 SPILL_TMP1(rINST) # save copy, need "B" later 6798 sarl $4,rINST 6799 .endif 6800 movl rINST,OUT_ARG1(%esp) # arg1<- A or AA (length) 6801 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags) 6802 movl rGLUE,%ecx 6803 testl %eax,%eax # alloc successful? 6804 je common_exceptionThrown # no, handle exception 6805 movl %eax,offGlue_retval(%ecx) # retval.l<- new array 6806 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC 6807 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents 6808 6809/* at this point: 6810 * eax is pointer to tgt 6811 * rINST is length 6812 * ecx is FEDC or CCCC 6813 * TMP_SPILL is BA 6814 * We now need to copy values from registers into the array 6815 */ 6816 6817 .if 0 6818 # set up src pointer 6819 SPILL_TMP2(%esi) 6820 SPILL_TMP3(%edi) 6821 movl %eax,%edi # set up dst ptr 6822 leal (rFP,%ecx,4),%esi # set up src ptr 6823 movl rINST,%ecx # load count register 6824 rep 6825 movsd 6826 UNSPILL_TMP2(%esi) 6827 UNSPILL_TMP3(%edi) 6828 movl rGLUE,%ecx 6829 movl offGlue_retval+4(%ecx),%eax # eax<- type 6830 FETCH_INST_OPCODE 3 %edx 6831 .else 6832 testl rINST,rINST 6833 je 4f 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_SPILL 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 movl %eax,%edi # set up dst ptr 6932 leal (rFP,%ecx,4),%esi # set up src 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 andl $0x0f,%edx # edx<- 0000000A 6945 sall $16,%edx # edx<- 000A0000 6946 orl %ecx,%edx # edx<- 000AFEDC 69473: 6948 movl $0xf,%ecx 6949 andl %edx,%ecx # ecx<- next reg to load 6950 GET_VREG_R %ecx %ecx 6951 shrl $4,%edx 6952 leal 4(%eax),%eax 6953 movl %ecx,-4(%eax) 6954 sub $1,rINST 6955 jne 3b 69564: 6957 movl rGLUE,%ecx 6958 movl offGlue_retval+4(%ecx),%eax # eax<- type 6959 FETCH_INST_OPCODE 3 %edx 6960 .endif 6961 6962 cmpb $'I',%al # Int array? 6963 je 5f # skip card mark if so 6964 movl offGlue_retval(%ecx),%eax # eax<- object head 6965 movl offGlue_cardTable(%ecx),%ecx # card table base 6966 shrl $GC_CARD_SHIFT,%eax # convert to card num 6967 movb %cl,(%ecx,%eax) # mark card based on object head 69685: 6969 ADVANCE_PC 3 6970 GOTO_NEXT_R %edx 6971 6972 6973 /* 6974 * Throw an exception indicating that we have not implemented this 6975 * mode of filled-new-array. 6976 */ 6977.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 6978 movl $.LstrInternalErrorA,%eax 6979 movl %eax,OUT_ARG0(%esp) 6980 movl $.LstrFilledNewArrayNotImplA,%eax 6981 movl %eax,OUT_ARG1(%esp) 6982 call dvmThrowException 6983 jmp common_exceptionThrown 6984 6985/* continuation for OP_CMPL_FLOAT */ 6986 6987.LOP_CMPL_FLOAT_isNaN: 6988 movl $-1,%ecx 6989 jmp .LOP_CMPL_FLOAT_finish 6990 6991/* continuation for OP_CMPG_FLOAT */ 6992 6993.LOP_CMPG_FLOAT_isNaN: 6994 movl $1,%ecx 6995 jmp .LOP_CMPG_FLOAT_finish 6996 6997/* continuation for OP_CMPL_DOUBLE */ 6998 6999.LOP_CMPL_DOUBLE_isNaN: 7000 movl $-1,%ecx 7001 jmp .LOP_CMPL_DOUBLE_finish 7002 7003/* continuation for OP_CMPG_DOUBLE */ 7004 7005.LOP_CMPG_DOUBLE_isNaN: 7006 movl $1,%ecx 7007 jmp .LOP_CMPG_DOUBLE_finish 7008 7009/* continuation for OP_CMP_LONG */ 7010 7011.LOP_CMP_LONG_bigger: 7012 movl $1,%ecx 7013 jmp .LOP_CMP_LONG_finish 7014.LOP_CMP_LONG_smaller: 7015 movl $-1,%ecx 7016.LOP_CMP_LONG_finish: 7017 SET_VREG %ecx rINST 7018 FETCH_INST_OPCODE 2 %edx 7019 ADVANCE_PC 2 7020 GOTO_NEXT_R %edx 7021 7022/* continuation for OP_AGET_WIDE */ 7023 7024.LOP_AGET_WIDE_finish: 7025 leal offArrayObject_contents(%eax,%ecx,8),%eax 7026 movl (%eax),%ecx 7027 movl 4(%eax),%eax 7028 SET_VREG_WORD %ecx rINST 0 7029 SET_VREG_WORD %eax rINST 1 7030 FETCH_INST_OPCODE 2 %edx 7031 ADVANCE_PC 2 7032 GOTO_NEXT_R %edx 7033 7034/* continuation for OP_APUT_WIDE */ 7035 7036.LOP_APUT_WIDE_finish: 7037 leal offArrayObject_contents(%eax,%ecx,8),%eax 7038 GET_VREG_WORD %ecx rINST 0 7039 GET_VREG_WORD rINST rINST 1 7040 movl rINST,4(%eax) 7041 FETCH_INST_OPCODE 2 %edx 7042 movl %ecx,(%eax) 7043 ADVANCE_PC 2 7044 GOTO_NEXT_R %edx 7045 7046/* continuation for OP_APUT_OBJECT */ 7047 7048 /* On entry: 7049 * eax<- array object 7050 * ecx<- index 7051 * rINST<- vAA 7052 */ 7053.LOP_APUT_OBJECT_continue: 7054 leal offArrayObject_contents(%eax,%ecx,4),%ecx 7055 testl rINST,rINST # storing null reference? 7056 je .LOP_APUT_OBJECT_skip_check 7057 SPILL_TMP1(%ecx) # save target address 7058 SPILL_TMP2(%eax) # save object head 7059 movl offObject_clazz(%eax),%eax # eax<- arrayObj->clazz 7060 movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz 7061 movl %eax,OUT_ARG1(%esp) 7062 movl %ecx,OUT_ARG0(%esp) 7063 call dvmCanPutArrayElement # test object type vs. array type 7064 UNSPILL_TMP1(%ecx) # recover target address 7065 testl %eax,%eax 7066 movl rGLUE,%eax 7067 je common_errArrayStore 7068 movl offGlue_cardTable(%eax),%eax # get card table base 7069 movl rINST,(%ecx) # store into array 7070 UNSPILL_TMP2(%ecx) # recover object head 7071 FETCH_INST_OPCODE 2 %edx 7072 shrl $GC_CARD_SHIFT,%ecx # object head to card number 7073 movb %al,(%eax,%ecx) # mark card using object head 7074 ADVANCE_PC 2 7075 GOTO_NEXT_R %edx 7076 7077.LOP_APUT_OBJECT_skip_check: 7078 movl rINST,(%ecx) 7079 FETCH_INST_OPCODE 2 %edx 7080 ADVANCE_PC 2 7081 GOTO_NEXT_R %edx 7082 7083/* continuation for OP_IGET */ 7084 7085 7086.LOP_IGET_resolve: 7087 EXPORT_PC 7088 movl offGlue_method(%edx),%edx # edx<- current method 7089 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7090 SPILL_TMP1(%ecx) # save obj pointer across call 7091 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7092 call dvmResolveInstField # ... to dvmResolveInstField 7093 UNSPILL_TMP1(%ecx) 7094 testl %eax,%eax # returns InstrField ptr 7095 jne .LOP_IGET_finish 7096 jmp common_exceptionThrown 7097 7098.LOP_IGET_finish: 7099 /* 7100 * Currently: 7101 * eax holds resolved field 7102 * ecx holds object 7103 * rINST holds A 7104 */ 7105 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7106 testl %ecx,%ecx # object null? 7107 je common_errNullObject # object was null 7108 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7109 movl rINST,%eax # eax<- A 7110 FETCH_INST_OPCODE 2 %edx 7111 SET_VREG %ecx %eax 7112 ADVANCE_PC 2 7113 GOTO_NEXT_R %edx 7114 7115/* continuation for OP_IGET_WIDE */ 7116 7117 7118.LOP_IGET_WIDE_resolve: 7119 EXPORT_PC 7120 movl offGlue_method(%edx),%edx # edx<- current method 7121 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7122 SPILL_TMP1(%ecx) # save objpointer across call 7123 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7124 call dvmResolveInstField # ... to dvmResolveInstField 7125 UNSPILL_TMP1(%ecx) 7126 testl %eax,%eax # returns InstrField ptr 7127 jne .LOP_IGET_WIDE_finish 7128 jmp common_exceptionThrown 7129 7130.LOP_IGET_WIDE_finish: 7131 /* 7132 * Currently: 7133 * eax holds resolved field 7134 * ecx holds object 7135 * rINST holds A 7136 */ 7137 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7138 testl %ecx,%ecx # object null? 7139 je common_errNullObject # object was null 7140 leal (%ecx,%eax,1),%eax # eax<- address of field 7141 movl (%eax),%ecx # ecx<- lsw 7142 movl 4(%eax),%eax # eax<- msw 7143 FETCH_INST_OPCODE 2 %edx 7144 SET_VREG_WORD %ecx rINST 0 7145 SET_VREG_WORD %eax rINST 1 7146 ADVANCE_PC 2 7147 GOTO_NEXT_R %edx 7148 7149/* continuation for OP_IGET_OBJECT */ 7150 7151 7152.LOP_IGET_OBJECT_resolve: 7153 EXPORT_PC 7154 movl offGlue_method(%edx),%edx # edx<- current method 7155 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7156 SPILL_TMP1(%ecx) # save obj pointer across call 7157 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7158 call dvmResolveInstField # ... to dvmResolveInstField 7159 UNSPILL_TMP1(%ecx) 7160 testl %eax,%eax # returns InstrField ptr 7161 jne .LOP_IGET_OBJECT_finish 7162 jmp common_exceptionThrown 7163 7164.LOP_IGET_OBJECT_finish: 7165 /* 7166 * Currently: 7167 * eax holds resolved field 7168 * ecx holds object 7169 * rINST holds A 7170 */ 7171 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7172 testl %ecx,%ecx # object null? 7173 je common_errNullObject # object was null 7174 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7175 movl rINST,%eax # eax<- A 7176 FETCH_INST_OPCODE 2 %edx 7177 SET_VREG %ecx %eax 7178 ADVANCE_PC 2 7179 GOTO_NEXT_R %edx 7180 7181/* continuation for OP_IGET_BOOLEAN */ 7182 7183 7184.LOP_IGET_BOOLEAN_resolve: 7185 EXPORT_PC 7186 movl offGlue_method(%edx),%edx # edx<- current method 7187 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7188 SPILL_TMP1(%ecx) # save obj pointer across call 7189 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7190 call dvmResolveInstField # ... to dvmResolveInstField 7191 UNSPILL_TMP1(%ecx) 7192 testl %eax,%eax # returns InstrField ptr 7193 jne .LOP_IGET_BOOLEAN_finish 7194 jmp common_exceptionThrown 7195 7196.LOP_IGET_BOOLEAN_finish: 7197 /* 7198 * Currently: 7199 * eax holds resolved field 7200 * ecx holds object 7201 * rINST holds A 7202 */ 7203 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7204 testl %ecx,%ecx # object null? 7205 je common_errNullObject # object was null 7206 movzbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7207 movl rINST,%eax # eax<- A 7208 FETCH_INST_OPCODE 2 %edx 7209 SET_VREG %ecx %eax 7210 ADVANCE_PC 2 7211 GOTO_NEXT_R %edx 7212 7213/* continuation for OP_IGET_BYTE */ 7214 7215 7216.LOP_IGET_BYTE_resolve: 7217 EXPORT_PC 7218 movl offGlue_method(%edx),%edx # edx<- current method 7219 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7220 SPILL_TMP1(%ecx) # save obj pointer across call 7221 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7222 call dvmResolveInstField # ... to dvmResolveInstField 7223 UNSPILL_TMP1(%ecx) 7224 testl %eax,%eax # returns InstrField ptr 7225 jne .LOP_IGET_BYTE_finish 7226 jmp common_exceptionThrown 7227 7228.LOP_IGET_BYTE_finish: 7229 /* 7230 * Currently: 7231 * eax holds resolved field 7232 * ecx holds object 7233 * rINST holds A 7234 */ 7235 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7236 testl %ecx,%ecx # object null? 7237 je common_errNullObject # object was null 7238 movsbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7239 movl rINST,%eax # eax<- A 7240 FETCH_INST_OPCODE 2 %edx 7241 SET_VREG %ecx %eax 7242 ADVANCE_PC 2 7243 GOTO_NEXT_R %edx 7244 7245/* continuation for OP_IGET_CHAR */ 7246 7247 7248.LOP_IGET_CHAR_resolve: 7249 EXPORT_PC 7250 movl offGlue_method(%edx),%edx # edx<- current method 7251 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7252 SPILL_TMP1(%ecx) # save obj pointer across call 7253 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7254 call dvmResolveInstField # ... to dvmResolveInstField 7255 UNSPILL_TMP1(%ecx) 7256 testl %eax,%eax # returns InstrField ptr 7257 jne .LOP_IGET_CHAR_finish 7258 jmp common_exceptionThrown 7259 7260.LOP_IGET_CHAR_finish: 7261 /* 7262 * Currently: 7263 * eax holds resolved field 7264 * ecx holds object 7265 * rINST holds A 7266 */ 7267 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7268 testl %ecx,%ecx # object null? 7269 je common_errNullObject # object was null 7270 movzwl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7271 movl rINST,%eax # eax<- A 7272 FETCH_INST_OPCODE 2 %edx 7273 SET_VREG %ecx %eax 7274 ADVANCE_PC 2 7275 GOTO_NEXT_R %edx 7276 7277/* continuation for OP_IGET_SHORT */ 7278 7279 7280.LOP_IGET_SHORT_resolve: 7281 EXPORT_PC 7282 movl offGlue_method(%edx),%edx # edx<- current method 7283 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7284 SPILL_TMP1(%ecx) # save obj pointer across call 7285 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7286 call dvmResolveInstField # ... to dvmResolveInstField 7287 UNSPILL_TMP1(%ecx) 7288 testl %eax,%eax # returns InstrField ptr 7289 jne .LOP_IGET_SHORT_finish 7290 jmp common_exceptionThrown 7291 7292.LOP_IGET_SHORT_finish: 7293 /* 7294 * Currently: 7295 * eax holds resolved field 7296 * ecx holds object 7297 * rINST holds A 7298 */ 7299 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7300 testl %ecx,%ecx # object null? 7301 je common_errNullObject # object was null 7302 movswl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7303 movl rINST,%eax # eax<- A 7304 FETCH_INST_OPCODE 2 %edx 7305 SET_VREG %ecx %eax 7306 ADVANCE_PC 2 7307 GOTO_NEXT_R %edx 7308 7309/* continuation for OP_IPUT */ 7310 7311 7312.LOP_IPUT_resolve: 7313 EXPORT_PC 7314 movl offGlue_method(%edx),%edx # edx<- current method 7315 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7316 SPILL_TMP1(%ecx) # save obj pointer across call 7317 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7318 call dvmResolveInstField # ... to dvmResolveInstField 7319 UNSPILL_TMP1(%ecx) 7320 testl %eax,%eax # returns InstrField ptr 7321 jne .LOP_IPUT_finish 7322 jmp common_exceptionThrown 7323 7324.LOP_IPUT_finish: 7325 /* 7326 * Currently: 7327 * eax holds resolved field 7328 * ecx holds object 7329 * rINST holds A 7330 */ 7331 GET_VREG_R rINST rINST # rINST<- v[A] 7332 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7333 testl %ecx,%ecx # object null? 7334 je common_errNullObject # object was null 7335 FETCH_INST_OPCODE 2 %edx 7336 movl rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7337 ADVANCE_PC 2 7338 GOTO_NEXT_R %edx 7339 7340/* continuation for OP_IPUT_WIDE */ 7341 7342 7343.LOP_IPUT_WIDE_resolve: 7344 EXPORT_PC 7345 movl offGlue_method(%edx),%edx # edx<- current method 7346 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7347 SPILL_TMP1(%ecx) # save obj pointer across call 7348 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7349 call dvmResolveInstField # ... to dvmResolveInstField 7350 UNSPILL_TMP1(%ecx) 7351 testl %eax,%eax # ... which returns InstrField ptr 7352 jne .LOP_IPUT_WIDE_finish 7353 jmp common_exceptionThrown 7354 7355.LOP_IPUT_WIDE_finish: 7356 /* 7357 * Currently: 7358 * eax holds resolved field 7359 * ecx holds object 7360 * %edx is scratch, but needs to be unspilled 7361 * rINST holds A 7362 */ 7363 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7364 testl %ecx,%ecx # object null? 7365 je common_errNullObject # object was null 7366 leal (%ecx,%eax,1),%eax # eax<- address of field 7367 GET_VREG_WORD %ecx rINST 0 # ecx<- lsw 7368 GET_VREG_WORD rINST rINST 1 # rINST<- msw 7369 FETCH_INST_OPCODE 2 %edx 7370 movl rINST,4(%eax) 7371 movl %ecx,(%eax) 7372 ADVANCE_PC 2 7373 GOTO_NEXT_R %edx 7374 7375/* continuation for OP_IPUT_OBJECT */ 7376 7377 7378.LOP_IPUT_OBJECT_resolve: 7379 EXPORT_PC 7380 movl offGlue_method(%edx),%edx # edx<- current method 7381 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7382 SPILL_TMP1(%ecx) # save obj pointer across call 7383 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7384 call dvmResolveInstField # ... to dvmResolveInstField 7385 UNSPILL_TMP1(%ecx) 7386 testl %eax,%eax # returns InstrField ptr 7387 jne .LOP_IPUT_OBJECT_finish 7388 jmp common_exceptionThrown 7389 7390.LOP_IPUT_OBJECT_finish: 7391 /* 7392 * Currently: 7393 * eax holds resolved field 7394 * ecx holds object 7395 * %edx is scratch, but needs to be unspilled 7396 * rINST holds A 7397 */ 7398 GET_VREG_R rINST rINST # rINST<- v[A] 7399 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7400 testl %ecx,%ecx # object null? 7401 je common_errNullObject # object was null 7402 movl rINST,(%ecx,%eax) # obj.field <- v[A](8/16/32 bits) 7403 movl rGLUE,%eax 7404 testl rINST,rINST # stored a NULL? 7405 movl offGlue_cardTable(%eax),%eax # get card table base 7406 FETCH_INST_OPCODE 2 %edx 7407 je 1f # skip card mark if null store 7408 shrl $GC_CARD_SHIFT,%ecx # object head to card number 7409 movb %al,(%eax,%ecx) # mark card using object head 74101: 7411 ADVANCE_PC 2 7412 GOTO_NEXT_R %edx 7413 7414/* continuation for OP_IPUT_BOOLEAN */ 7415 7416 7417.LOP_IPUT_BOOLEAN_resolve: 7418 EXPORT_PC 7419 movl offGlue_method(%edx),%edx # edx<- current method 7420 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7421 SPILL_TMP1(%ecx) # save obj pointer across call 7422 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7423 call dvmResolveInstField # ... to dvmResolveInstField 7424 UNSPILL_TMP1(%ecx) 7425 testl %eax,%eax # returns InstrField ptr 7426 jne .LOP_IPUT_BOOLEAN_finish 7427 jmp common_exceptionThrown 7428 7429.LOP_IPUT_BOOLEAN_finish: 7430 /* 7431 * Currently: 7432 * eax holds resolved field 7433 * ecx holds object 7434 * rINST holds A 7435 */ 7436 GET_VREG_R rINST rINST # rINST<- v[A] 7437 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7438 testl %ecx,%ecx # object null? 7439 je common_errNullObject # object was null 7440 FETCH_INST_OPCODE 2 %edx 7441 movb rINSTbl,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7442 ADVANCE_PC 2 7443 GOTO_NEXT_R %edx 7444 7445/* continuation for OP_IPUT_BYTE */ 7446 7447 7448.LOP_IPUT_BYTE_resolve: 7449 EXPORT_PC 7450 movl offGlue_method(%edx),%edx # edx<- current method 7451 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7452 SPILL_TMP1(%ecx) # save obj pointer across call 7453 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7454 call dvmResolveInstField # ... to dvmResolveInstField 7455 UNSPILL_TMP1(%ecx) 7456 testl %eax,%eax # returns InstrField ptr 7457 jne .LOP_IPUT_BYTE_finish 7458 jmp common_exceptionThrown 7459 7460.LOP_IPUT_BYTE_finish: 7461 /* 7462 * Currently: 7463 * eax holds resolved field 7464 * ecx holds object 7465 * rINST holds A 7466 */ 7467 GET_VREG_R rINST rINST # rINST<- v[A] 7468 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7469 testl %ecx,%ecx # object null? 7470 je common_errNullObject # object was null 7471 FETCH_INST_OPCODE 2 %edx 7472 movb rINSTbl,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7473 ADVANCE_PC 2 7474 GOTO_NEXT_R %edx 7475 7476/* continuation for OP_IPUT_CHAR */ 7477 7478 7479.LOP_IPUT_CHAR_resolve: 7480 EXPORT_PC 7481 movl offGlue_method(%edx),%edx # edx<- current method 7482 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7483 SPILL_TMP1(%ecx) # save obj pointer across call 7484 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7485 call dvmResolveInstField # ... to dvmResolveInstField 7486 UNSPILL_TMP1(%ecx) 7487 testl %eax,%eax # returns InstrField ptr 7488 jne .LOP_IPUT_CHAR_finish 7489 jmp common_exceptionThrown 7490 7491.LOP_IPUT_CHAR_finish: 7492 /* 7493 * Currently: 7494 * eax holds resolved field 7495 * ecx holds object 7496 * rINST holds A 7497 */ 7498 GET_VREG_R rINST rINST # rINST<- v[A] 7499 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7500 testl %ecx,%ecx # object null? 7501 je common_errNullObject # object was null 7502 FETCH_INST_OPCODE 2 %edx 7503 movw rINSTw,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7504 ADVANCE_PC 2 7505 GOTO_NEXT_R %edx 7506 7507/* continuation for OP_IPUT_SHORT */ 7508 7509 7510.LOP_IPUT_SHORT_resolve: 7511 EXPORT_PC 7512 movl offGlue_method(%edx),%edx # edx<- current method 7513 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7514 SPILL_TMP1(%ecx) # save obj pointer across call 7515 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7516 call dvmResolveInstField # ... to dvmResolveInstField 7517 UNSPILL_TMP1(%ecx) 7518 testl %eax,%eax # returns InstrField ptr 7519 jne .LOP_IPUT_SHORT_finish 7520 jmp common_exceptionThrown 7521 7522.LOP_IPUT_SHORT_finish: 7523 /* 7524 * Currently: 7525 * eax holds resolved field 7526 * ecx holds object 7527 * rINST holds A 7528 */ 7529 GET_VREG_R rINST rINST # rINST<- v[A] 7530 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7531 testl %ecx,%ecx # object null? 7532 je common_errNullObject # object was null 7533 FETCH_INST_OPCODE 2 %edx 7534 movw rINSTw,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7535 ADVANCE_PC 2 7536 GOTO_NEXT_R %edx 7537 7538/* continuation for OP_SGET */ 7539 7540 /* 7541 * Go resolve the field 7542 */ 7543.LOP_SGET_resolve: 7544 movl rGLUE,%ecx 7545 movzwl 2(rPC),%eax # eax<- field ref BBBB 7546 movl offGlue_method(%ecx),%ecx # ecx<- current method 7547 EXPORT_PC # could throw, need to export 7548 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7549 movl %eax,OUT_ARG1(%esp) 7550 movl %ecx,OUT_ARG0(%esp) 7551 call dvmResolveStaticField # eax<- resolved StaticField ptr 7552 testl %eax,%eax 7553 jne .LOP_SGET_finish # success, continue 7554 jmp common_exceptionThrown # no, handle exception 7555 7556/* continuation for OP_SGET_WIDE */ 7557 7558 /* 7559 * Go resolve the field 7560 */ 7561.LOP_SGET_WIDE_resolve: 7562 movl rGLUE,%ecx 7563 movzwl 2(rPC),%eax # eax<- field ref BBBB 7564 movl offGlue_method(%ecx),%ecx # ecx<- current method 7565 EXPORT_PC # could throw, need to export 7566 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7567 movl %eax,OUT_ARG1(%esp) 7568 movl %ecx,OUT_ARG0(%esp) 7569 call dvmResolveStaticField # eax<- resolved StaticField ptr 7570 testl %eax,%eax 7571 jne .LOP_SGET_WIDE_finish # success, continue 7572 jmp common_exceptionThrown # no, handle exception 7573 7574/* continuation for OP_SGET_OBJECT */ 7575 7576 /* 7577 * Go resolve the field 7578 */ 7579.LOP_SGET_OBJECT_resolve: 7580 movl rGLUE,%ecx 7581 movzwl 2(rPC),%eax # eax<- field ref BBBB 7582 movl offGlue_method(%ecx),%ecx # ecx<- current method 7583 EXPORT_PC # could throw, need to export 7584 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7585 movl %eax,OUT_ARG1(%esp) 7586 movl %ecx,OUT_ARG0(%esp) 7587 call dvmResolveStaticField # eax<- resolved StaticField ptr 7588 testl %eax,%eax 7589 jne .LOP_SGET_OBJECT_finish # success, continue 7590 jmp common_exceptionThrown # no, handle exception 7591 7592/* continuation for OP_SGET_BOOLEAN */ 7593 7594 /* 7595 * Go resolve the field 7596 */ 7597.LOP_SGET_BOOLEAN_resolve: 7598 movl rGLUE,%ecx 7599 movzwl 2(rPC),%eax # eax<- field ref BBBB 7600 movl offGlue_method(%ecx),%ecx # ecx<- current method 7601 EXPORT_PC # could throw, need to export 7602 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7603 movl %eax,OUT_ARG1(%esp) 7604 movl %ecx,OUT_ARG0(%esp) 7605 call dvmResolveStaticField # eax<- resolved StaticField ptr 7606 testl %eax,%eax 7607 jne .LOP_SGET_BOOLEAN_finish # success, continue 7608 jmp common_exceptionThrown # no, handle exception 7609 7610/* continuation for OP_SGET_BYTE */ 7611 7612 /* 7613 * Go resolve the field 7614 */ 7615.LOP_SGET_BYTE_resolve: 7616 movl rGLUE,%ecx 7617 movzwl 2(rPC),%eax # eax<- field ref BBBB 7618 movl offGlue_method(%ecx),%ecx # ecx<- current method 7619 EXPORT_PC # could throw, need to export 7620 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7621 movl %eax,OUT_ARG1(%esp) 7622 movl %ecx,OUT_ARG0(%esp) 7623 call dvmResolveStaticField # eax<- resolved StaticField ptr 7624 testl %eax,%eax 7625 jne .LOP_SGET_BYTE_finish # success, continue 7626 jmp common_exceptionThrown # no, handle exception 7627 7628/* continuation for OP_SGET_CHAR */ 7629 7630 /* 7631 * Go resolve the field 7632 */ 7633.LOP_SGET_CHAR_resolve: 7634 movl rGLUE,%ecx 7635 movzwl 2(rPC),%eax # eax<- field ref BBBB 7636 movl offGlue_method(%ecx),%ecx # ecx<- current method 7637 EXPORT_PC # could throw, need to export 7638 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7639 movl %eax,OUT_ARG1(%esp) 7640 movl %ecx,OUT_ARG0(%esp) 7641 call dvmResolveStaticField # eax<- resolved StaticField ptr 7642 testl %eax,%eax 7643 jne .LOP_SGET_CHAR_finish # success, continue 7644 jmp common_exceptionThrown # no, handle exception 7645 7646/* continuation for OP_SGET_SHORT */ 7647 7648 /* 7649 * Go resolve the field 7650 */ 7651.LOP_SGET_SHORT_resolve: 7652 movl rGLUE,%ecx 7653 movzwl 2(rPC),%eax # eax<- field ref BBBB 7654 movl offGlue_method(%ecx),%ecx # ecx<- current method 7655 EXPORT_PC # could throw, need to export 7656 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7657 movl %eax,OUT_ARG1(%esp) 7658 movl %ecx,OUT_ARG0(%esp) 7659 call dvmResolveStaticField # eax<- resolved StaticField ptr 7660 testl %eax,%eax 7661 jne .LOP_SGET_SHORT_finish # success, continue 7662 jmp common_exceptionThrown # no, handle exception 7663 7664/* continuation for OP_SPUT */ 7665 7666 /* 7667 * Go resolve the field 7668 */ 7669.LOP_SPUT_resolve: 7670 movl rGLUE,%ecx 7671 movzwl 2(rPC),%eax # eax<- field ref BBBB 7672 movl offGlue_method(%ecx),%ecx # ecx<- current method 7673 EXPORT_PC # could throw, need to export 7674 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7675 movl %eax,OUT_ARG1(%esp) 7676 movl %ecx,OUT_ARG0(%esp) 7677 call dvmResolveStaticField # eax<- resolved StaticField ptr 7678 testl %eax,%eax 7679 jne .LOP_SPUT_finish # success, continue 7680 jmp common_exceptionThrown # no, handle exception 7681 7682/* continuation for OP_SPUT_WIDE */ 7683 7684 /* 7685 * Go resolve the field 7686 */ 7687.LOP_SPUT_WIDE_resolve: 7688 movl rGLUE,%ecx 7689 movzwl 2(rPC),%eax # eax<- field ref BBBB 7690 movl offGlue_method(%ecx),%ecx # ecx<- current method 7691 EXPORT_PC # could throw, need to export 7692 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7693 movl %eax,OUT_ARG1(%esp) 7694 movl %ecx,OUT_ARG0(%esp) 7695 call dvmResolveStaticField # eax<- resolved StaticField ptr 7696 testl %eax,%eax 7697 jne .LOP_SPUT_WIDE_finish # success, continue 7698 jmp common_exceptionThrown # no, handle exception 7699 7700/* continuation for OP_SPUT_OBJECT */ 7701 7702 7703.LOP_SPUT_OBJECT_continue: 7704 movl %ecx,offStaticField_value(%eax) # do the store 7705 testl %ecx,%ecx # stored null object ptr? 7706 FETCH_INST_OPCODE 2 %edx 7707 je 1f # skip card mark if null 7708 movl rGLUE,%ecx 7709 movl offField_clazz(%eax),%eax # eax<- method->clazz 7710 movl offGlue_cardTable(%ecx),%ecx # get card table base 7711 shrl $GC_CARD_SHIFT,%eax # head to card number 7712 movb %cl,(%ecx,%eax) # mark card 77131: 7714 ADVANCE_PC 2 7715 GOTO_NEXT_R %edx 7716 7717.LOP_SPUT_OBJECT_resolve: 7718 movl rGLUE,%ecx 7719 movzwl 2(rPC),%eax # eax<- field ref BBBB 7720 movl offGlue_method(%ecx),%ecx # ecx<- current method 7721 EXPORT_PC # could throw, need to export 7722 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7723 movl %eax,OUT_ARG1(%esp) 7724 movl %ecx,OUT_ARG0(%esp) 7725 call dvmResolveStaticField # eax<- resolved StaticField ptr 7726 testl %eax,%eax 7727 jne .LOP_SPUT_OBJECT_finish # success, continue 7728 jmp common_exceptionThrown # no, handle exception 7729 7730/* continuation for OP_SPUT_BOOLEAN */ 7731 7732 /* 7733 * Go resolve the field 7734 */ 7735.LOP_SPUT_BOOLEAN_resolve: 7736 movl rGLUE,%ecx 7737 movzwl 2(rPC),%eax # eax<- field ref BBBB 7738 movl offGlue_method(%ecx),%ecx # ecx<- current method 7739 EXPORT_PC # could throw, need to export 7740 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7741 movl %eax,OUT_ARG1(%esp) 7742 movl %ecx,OUT_ARG0(%esp) 7743 call dvmResolveStaticField # eax<- resolved StaticField ptr 7744 testl %eax,%eax 7745 jne .LOP_SPUT_BOOLEAN_finish # success, continue 7746 jmp common_exceptionThrown # no, handle exception 7747 7748/* continuation for OP_SPUT_BYTE */ 7749 7750 /* 7751 * Go resolve the field 7752 */ 7753.LOP_SPUT_BYTE_resolve: 7754 movl rGLUE,%ecx 7755 movzwl 2(rPC),%eax # eax<- field ref BBBB 7756 movl offGlue_method(%ecx),%ecx # ecx<- current method 7757 EXPORT_PC # could throw, need to export 7758 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7759 movl %eax,OUT_ARG1(%esp) 7760 movl %ecx,OUT_ARG0(%esp) 7761 call dvmResolveStaticField # eax<- resolved StaticField ptr 7762 testl %eax,%eax 7763 jne .LOP_SPUT_BYTE_finish # success, continue 7764 jmp common_exceptionThrown # no, handle exception 7765 7766/* continuation for OP_SPUT_CHAR */ 7767 7768 /* 7769 * Go resolve the field 7770 */ 7771.LOP_SPUT_CHAR_resolve: 7772 movl rGLUE,%ecx 7773 movzwl 2(rPC),%eax # eax<- field ref BBBB 7774 movl offGlue_method(%ecx),%ecx # ecx<- current method 7775 EXPORT_PC # could throw, need to export 7776 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7777 movl %eax,OUT_ARG1(%esp) 7778 movl %ecx,OUT_ARG0(%esp) 7779 call dvmResolveStaticField # eax<- resolved StaticField ptr 7780 testl %eax,%eax 7781 jne .LOP_SPUT_CHAR_finish # success, continue 7782 jmp common_exceptionThrown # no, handle exception 7783 7784/* continuation for OP_SPUT_SHORT */ 7785 7786 /* 7787 * Go resolve the field 7788 */ 7789.LOP_SPUT_SHORT_resolve: 7790 movl rGLUE,%ecx 7791 movzwl 2(rPC),%eax # eax<- field ref BBBB 7792 movl offGlue_method(%ecx),%ecx # ecx<- current method 7793 EXPORT_PC # could throw, need to export 7794 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7795 movl %eax,OUT_ARG1(%esp) 7796 movl %ecx,OUT_ARG0(%esp) 7797 call dvmResolveStaticField # eax<- resolved StaticField ptr 7798 testl %eax,%eax 7799 jne .LOP_SPUT_SHORT_finish # success, continue 7800 jmp common_exceptionThrown # no, handle exception 7801 7802/* continuation for OP_INVOKE_VIRTUAL */ 7803 7804 7805.LOP_INVOKE_VIRTUAL_more: 7806 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 7807 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 7808 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 7809 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7810 testl %eax,%eax # got null? 7811 jne .LOP_INVOKE_VIRTUAL_continue # no, continue 7812 jmp common_exceptionThrown # yes, handle exception 7813 7814 /* At this point: 7815 * eax = resolved base method 7816 * ecx = scratch 7817 */ 7818.LOP_INVOKE_VIRTUAL_continue: 7819 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 7820 .if (!0) 7821 andl $0xf,%ecx # ecx<- D (or stays CCCC) 7822 .endif 7823 GET_VREG_R %ecx %ecx # ecx<- "this" 7824 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 7825 testl %ecx,%ecx # null this? 7826 je common_errNullObject # go if so 7827 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz 7828 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable 7829 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex] 7830 jmp common_invokeMethodNoRange 7831 7832/* continuation for OP_INVOKE_SUPER */ 7833 7834 /* 7835 * At this point: 7836 * ecx = resolved base method [r0] 7837 * eax = method->clazz [r9] 7838 */ 7839.LOP_INVOKE_SUPER_continue: 7840 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super 7841 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex 7842 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount) 7843 jae .LOP_INVOKE_SUPER_nsm # method not present in superclass 7844 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable 7845 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex] 7846 jmp common_invokeMethodNoRange 7847 7848 7849 /* At this point: 7850 * ecx = null (needs to be resolved base method) 7851 * eax = method->clazz 7852 */ 7853.LOP_INVOKE_SUPER_resolve: 7854 SPILL_TMP1(%eax) # method->clazz 7855 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz 7856 movzwl 2(rPC),%ecx # ecx<- BBBB 7857 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type 7858 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 7859 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7860 testl %eax,%eax # got null? 7861 movl %eax,%ecx # ecx<- resolved base method 7862 UNSPILL_TMP1(%eax) # restore method->clazz 7863 jne .LOP_INVOKE_SUPER_continue # good to go - continue 7864 jmp common_exceptionThrown # handle exception 7865 7866 /* 7867 * Throw a NoSuchMethodError with the method name as the message. 7868 * ecx = resolved base method 7869 */ 7870.LOP_INVOKE_SUPER_nsm: 7871 movl offMethod_name(%ecx),%eax 7872 mov %eax,OUT_ARG1(%esp) 7873 jmp common_errNoSuchMethod 7874 7875/* continuation for OP_INVOKE_DIRECT */ 7876 7877 /* 7878 * On entry: 7879 * TMP_SPILL <- "this" register 7880 * Things a bit ugly on this path, but it's the less 7881 * frequent one. We'll have to do some reloading. 7882 */ 7883.LOP_INVOKE_DIRECT_resolve: 7884 SPILL_TMP1(%ecx) 7885 movl rGLUE,%ecx 7886 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 7887 movzwl 2(rPC),%eax # reference (BBBB or CCCC) 7888 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7889 movl $METHOD_DIRECT,OUT_ARG2(%esp) 7890 movl %eax,OUT_ARG1(%esp) 7891 movl %ecx,OUT_ARG0(%esp) 7892 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7893 UNSPILL_TMP1(%ecx) 7894 testl %eax,%eax 7895 jne .LOP_INVOKE_DIRECT_finish 7896 jmp common_exceptionThrown 7897 7898/* continuation for OP_INVOKE_STATIC */ 7899 7900.LOP_INVOKE_STATIC_continue: 7901 movl $METHOD_STATIC,%eax 7902 movl %eax,OUT_ARG2(%esp) # arg2<- flags 7903 call dvmResolveMethod # call(clazz,ref,flags) 7904 testl %eax,%eax # got null? 7905 jne common_invokeMethodNoRange 7906 jmp common_exceptionThrown 7907 7908/* continuation for OP_INVOKE_INTERFACE */ 7909 7910.LOP_INVOKE_INTERFACE_continue: 7911 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex) 7912 testl %eax,%eax 7913 je common_exceptionThrown 7914 jmp common_invokeMethodNoRange 7915 7916/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 7917 7918 7919.LOP_INVOKE_VIRTUAL_RANGE_more: 7920 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 7921 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 7922 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 7923 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7924 testl %eax,%eax # got null? 7925 jne .LOP_INVOKE_VIRTUAL_RANGE_continue # no, continue 7926 jmp common_exceptionThrown # yes, handle exception 7927 7928 /* At this point: 7929 * eax = resolved base method 7930 * ecx = scratch 7931 */ 7932.LOP_INVOKE_VIRTUAL_RANGE_continue: 7933 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 7934 .if (!1) 7935 andl $0xf,%ecx # ecx<- D (or stays CCCC) 7936 .endif 7937 GET_VREG_R %ecx %ecx # ecx<- "this" 7938 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 7939 testl %ecx,%ecx # null this? 7940 je common_errNullObject # go if so 7941 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz 7942 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable 7943 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex] 7944 jmp common_invokeMethodRange 7945 7946/* continuation for OP_INVOKE_SUPER_RANGE */ 7947 7948 /* 7949 * At this point: 7950 * ecx = resolved base method [r0] 7951 * eax = method->clazz [r9] 7952 */ 7953.LOP_INVOKE_SUPER_RANGE_continue: 7954 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super 7955 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex 7956 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount) 7957 jae .LOP_INVOKE_SUPER_RANGE_nsm # method not present in superclass 7958 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable 7959 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex] 7960 jmp common_invokeMethodRange 7961 7962 7963 /* At this point: 7964 * ecx = null (needs to be resolved base method) 7965 * eax = method->clazz 7966 */ 7967.LOP_INVOKE_SUPER_RANGE_resolve: 7968 SPILL_TMP1(%eax) # method->clazz 7969 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz 7970 movzwl 2(rPC),%ecx # ecx<- BBBB 7971 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type 7972 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 7973 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7974 testl %eax,%eax # got null? 7975 movl %eax,%ecx # ecx<- resolved base method 7976 UNSPILL_TMP1(%eax) # restore method->clazz 7977 jne .LOP_INVOKE_SUPER_RANGE_continue # good to go - continue 7978 jmp common_exceptionThrown # handle exception 7979 7980 /* 7981 * Throw a NoSuchMethodError with the method name as the message. 7982 * ecx = resolved base method 7983 */ 7984.LOP_INVOKE_SUPER_RANGE_nsm: 7985 movl offMethod_name(%ecx),%eax 7986 mov %eax,OUT_ARG1(%esp) 7987 jmp common_errNoSuchMethod 7988 7989/* continuation for OP_INVOKE_DIRECT_RANGE */ 7990 7991 /* 7992 * On entry: 7993 * TMP_SPILL <- "this" register 7994 * Things a bit ugly on this path, but it's the less 7995 * frequent one. We'll have to do some reloading. 7996 */ 7997.LOP_INVOKE_DIRECT_RANGE_resolve: 7998 SPILL_TMP1(%ecx) 7999 movl rGLUE,%ecx 8000 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 8001 movzwl 2(rPC),%eax # reference (BBBB or CCCC) 8002 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8003 movl $METHOD_DIRECT,OUT_ARG2(%esp) 8004 movl %eax,OUT_ARG1(%esp) 8005 movl %ecx,OUT_ARG0(%esp) 8006 call dvmResolveMethod # eax<- call(clazz, ref, flags) 8007 UNSPILL_TMP1(%ecx) 8008 testl %eax,%eax 8009 jne .LOP_INVOKE_DIRECT_RANGE_finish 8010 jmp common_exceptionThrown 8011 8012/* continuation for OP_INVOKE_STATIC_RANGE */ 8013 8014.LOP_INVOKE_STATIC_RANGE_continue: 8015 movl $METHOD_STATIC,%eax 8016 movl %eax,OUT_ARG2(%esp) # arg2<- flags 8017 call dvmResolveMethod # call(clazz,ref,flags) 8018 testl %eax,%eax # got null? 8019 jne common_invokeMethodRange 8020 jmp common_exceptionThrown 8021 8022/* continuation for OP_INVOKE_INTERFACE_RANGE */ 8023 8024.LOP_INVOKE_INTERFACE_RANGE_continue: 8025 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex) 8026 testl %eax,%eax 8027 je common_exceptionThrown 8028 jmp common_invokeMethodRange 8029 8030/* continuation for OP_FLOAT_TO_INT */ 8031 8032 8033.LOP_FLOAT_TO_INT_continue: 8034 .if 0 8035 movl $0x80000000,%eax 8036 xorl 4(rFP,%ecx,4),%eax 8037 orl (rFP,%ecx,4),%eax 8038 .else 8039 cmpl $0x80000000,(rFP,%ecx,4) 8040 .endif 8041 je .LOP_FLOAT_TO_INT_special_case # fix up result 8042 8043.LOP_FLOAT_TO_INT_finish: 8044 ADVANCE_PC 1 8045 GOTO_NEXT_R %edx 8046 8047.LOP_FLOAT_TO_INT_special_case: 8048 fnstsw %ax 8049 sahf 8050 jp .LOP_FLOAT_TO_INT_isNaN 8051 adcl $-1,(rFP,%ecx,4) 8052 .if 0 8053 adcl $-1,4(rFP,%ecx,4) 8054 .endif 8055 jmp .LOP_FLOAT_TO_INT_finish 8056.LOP_FLOAT_TO_INT_isNaN: 8057 movl $0,(rFP,%ecx,4) 8058 .if 0 8059 movl $0,4(rFP,%ecx,4) 8060 .endif 8061 jmp .LOP_FLOAT_TO_INT_finish 8062 8063/* continuation for OP_FLOAT_TO_LONG */ 8064 8065 8066.LOP_FLOAT_TO_LONG_continue: 8067 .if 1 8068 movl $0x80000000,%eax 8069 xorl 4(rFP,%ecx,4),%eax 8070 orl (rFP,%ecx,4),%eax 8071 .else 8072 cmpl $0x80000000,(rFP,%ecx,4) 8073 .endif 8074 je .LOP_FLOAT_TO_LONG_special_case # fix up result 8075 8076.LOP_FLOAT_TO_LONG_finish: 8077 ADVANCE_PC 1 8078 GOTO_NEXT_R %edx 8079 8080.LOP_FLOAT_TO_LONG_special_case: 8081 fnstsw %ax 8082 sahf 8083 jp .LOP_FLOAT_TO_LONG_isNaN 8084 adcl $-1,(rFP,%ecx,4) 8085 .if 1 8086 adcl $-1,4(rFP,%ecx,4) 8087 .endif 8088 jmp .LOP_FLOAT_TO_LONG_finish 8089.LOP_FLOAT_TO_LONG_isNaN: 8090 movl $0,(rFP,%ecx,4) 8091 .if 1 8092 movl $0,4(rFP,%ecx,4) 8093 .endif 8094 jmp .LOP_FLOAT_TO_LONG_finish 8095 8096/* continuation for OP_DOUBLE_TO_INT */ 8097 8098 8099.LOP_DOUBLE_TO_INT_continue: 8100 .if 0 8101 movl $0x80000000,%eax 8102 xorl 4(rFP,%ecx,4),%eax 8103 orl (rFP,%ecx,4),%eax 8104 .else 8105 cmpl $0x80000000,(rFP,%ecx,4) 8106 .endif 8107 je .LOP_DOUBLE_TO_INT_special_case # fix up result 8108 8109.LOP_DOUBLE_TO_INT_finish: 8110 ADVANCE_PC 1 8111 GOTO_NEXT_R %edx 8112 8113.LOP_DOUBLE_TO_INT_special_case: 8114 fnstsw %ax 8115 sahf 8116 jp .LOP_DOUBLE_TO_INT_isNaN 8117 adcl $-1,(rFP,%ecx,4) 8118 .if 0 8119 adcl $-1,4(rFP,%ecx,4) 8120 .endif 8121 jmp .LOP_DOUBLE_TO_INT_finish 8122.LOP_DOUBLE_TO_INT_isNaN: 8123 movl $0,(rFP,%ecx,4) 8124 .if 0 8125 movl $0,4(rFP,%ecx,4) 8126 .endif 8127 jmp .LOP_DOUBLE_TO_INT_finish 8128 8129/* continuation for OP_DOUBLE_TO_LONG */ 8130 8131 8132.LOP_DOUBLE_TO_LONG_continue: 8133 .if 1 8134 movl $0x80000000,%eax 8135 xorl 4(rFP,%ecx,4),%eax 8136 orl (rFP,%ecx,4),%eax 8137 .else 8138 cmpl $0x80000000,(rFP,%ecx,4) 8139 .endif 8140 je .LOP_DOUBLE_TO_LONG_special_case # fix up result 8141 8142.LOP_DOUBLE_TO_LONG_finish: 8143 ADVANCE_PC 1 8144 GOTO_NEXT_R %edx 8145 8146.LOP_DOUBLE_TO_LONG_special_case: 8147 fnstsw %ax 8148 sahf 8149 jp .LOP_DOUBLE_TO_LONG_isNaN 8150 adcl $-1,(rFP,%ecx,4) 8151 .if 1 8152 adcl $-1,4(rFP,%ecx,4) 8153 .endif 8154 jmp .LOP_DOUBLE_TO_LONG_finish 8155.LOP_DOUBLE_TO_LONG_isNaN: 8156 movl $0,(rFP,%ecx,4) 8157 .if 1 8158 movl $0,4(rFP,%ecx,4) 8159 .endif 8160 jmp .LOP_DOUBLE_TO_LONG_finish 8161 8162/* continuation for OP_DIV_INT */ 8163.LOP_DIV_INT_continue_div: 8164 cltd 8165 idivl %ecx 8166.LOP_DIV_INT_finish_div: 8167 SET_VREG %eax rINST 8168 FETCH_INST_OPCODE 2 %edx 8169 ADVANCE_PC 2 8170 GOTO_NEXT_R %edx 8171 8172/* continuation for OP_REM_INT */ 8173.LOP_REM_INT_continue_div: 8174 cltd 8175 idivl %ecx 8176.LOP_REM_INT_finish_div: 8177 SET_VREG %edx rINST 8178 FETCH_INST_OPCODE 2 %edx 8179 ADVANCE_PC 2 8180 GOTO_NEXT_R %edx 8181 8182/* continuation for OP_MUL_LONG */ 8183 8184.LOP_MUL_LONG_continue: 8185 leal (%ecx,%edx),%edx # full result now in %edx:%eax 8186 UNSPILL_TMP2(%esi) # Restore Dalvik PC 8187 FETCH_INST_OPCODE 2 %ecx # Fetch next instruction 8188 movl %edx,4(rFP,rINST,4) # v[B+1]<- %edx 8189 movl %eax,(rFP,rINST,4) # v[B]<- %eax 8190 ADVANCE_PC 2 8191 GOTO_NEXT_R %ecx 8192 8193/* continuation for OP_DIV_LONG */ 8194 8195.LOP_DIV_LONG_continue: 8196 call __divdi3 8197.LOP_DIV_LONG_finish: 8198 SET_VREG_WORD %edx rINST 1 8199 SET_VREG_WORD %eax rINST 0 8200 FETCH_INST_OPCODE 2 %edx 8201 ADVANCE_PC 2 8202 GOTO_NEXT_R %edx 8203 8204.LOP_DIV_LONG_check_zero: 8205 testl %edx,%edx 8206 jne .LOP_DIV_LONG_notSpecial 8207 jmp common_errDivideByZero 8208.LOP_DIV_LONG_check_neg1: 8209 testl %edx,%eax 8210 jne .LOP_DIV_LONG_notSpecial 8211 GET_VREG_WORD %edx %ecx 0 8212 GET_VREG_WORD %ecx %ecx 1 8213 testl %edx,%edx 8214 jne .LOP_DIV_LONG_notSpecial1 8215 cmpl $0x80000000,%ecx 8216 jne .LOP_DIV_LONG_notSpecial1 8217 /* minint / -1, return minint on div, 0 on rem */ 8218 xorl %eax,%eax 8219 movl $0x80000000,%edx 8220 jmp .LOP_DIV_LONG_finish 8221 8222/* continuation for OP_REM_LONG */ 8223 8224.LOP_REM_LONG_continue: 8225 call __moddi3 8226.LOP_REM_LONG_finish: 8227 SET_VREG_WORD %edx rINST 1 8228 SET_VREG_WORD %eax rINST 0 8229 FETCH_INST_OPCODE 2 %edx 8230 ADVANCE_PC 2 8231 GOTO_NEXT_R %edx 8232 8233.LOP_REM_LONG_check_zero: 8234 testl %edx,%edx 8235 jne .LOP_REM_LONG_notSpecial 8236 jmp common_errDivideByZero 8237.LOP_REM_LONG_check_neg1: 8238 testl %edx,%eax 8239 jne .LOP_REM_LONG_notSpecial 8240 GET_VREG_WORD %edx %ecx 0 8241 GET_VREG_WORD %ecx %ecx 1 8242 testl %edx,%edx 8243 jne .LOP_REM_LONG_notSpecial1 8244 cmpl $0x80000000,%ecx 8245 jne .LOP_REM_LONG_notSpecial1 8246 /* minint / -1, return minint on div, 0 on rem */ 8247 xorl %eax,%eax 8248 movl $0,%edx 8249 jmp .LOP_REM_LONG_finish 8250 8251/* continuation for OP_SHL_LONG */ 8252 8253.LOP_SHL_LONG_finish: 8254 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- %eax 8255 ADVANCE_PC 2 8256 GOTO_NEXT_R %edx 8257 8258/* continuation for OP_SHR_LONG */ 8259 8260 8261.LOP_SHR_LONG_finish: 8262 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax 8263 ADVANCE_PC 2 8264 GOTO_NEXT_R %edx 8265 8266/* continuation for OP_USHR_LONG */ 8267 8268 8269.LOP_USHR_LONG_finish: 8270 SET_VREG_WORD %eax rINST 0 # v[BB+0]<- eax 8271 ADVANCE_PC 2 8272 GOTO_NEXT_R %edx 8273 8274/* continuation for OP_DIV_INT_2ADDR */ 8275.LOP_DIV_INT_2ADDR_continue_div2addr: 8276 cltd 8277 idivl %ecx 8278.LOP_DIV_INT_2ADDR_finish_div2addr: 8279 SET_VREG %eax rINST 8280 FETCH_INST_OPCODE 1 %edx 8281 ADVANCE_PC 1 8282 GOTO_NEXT_R %edx 8283 8284/* continuation for OP_REM_INT_2ADDR */ 8285.LOP_REM_INT_2ADDR_continue_div2addr: 8286 cltd 8287 idivl %ecx 8288.LOP_REM_INT_2ADDR_finish_div2addr: 8289 SET_VREG %edx rINST 8290 FETCH_INST_OPCODE 1 %edx 8291 ADVANCE_PC 1 8292 GOTO_NEXT_R %edx 8293 8294/* continuation for OP_MUL_LONG_2ADDR */ 8295 8296.LOP_MUL_LONG_2ADDR_continue: 8297 leal (%ecx,%edx),%edx # full result now in %edx:%eax 8298 movl %edx,4(%esi) # v[A+1]<- %edx 8299 movl %eax,(%esi) # v[A]<- %eax 8300 UNSPILL_TMP2(%esi) 8301 FETCH_INST_OPCODE 1 %ecx 8302 UNSPILL(rFP) 8303 ADVANCE_PC 1 8304 GOTO_NEXT_R %ecx 8305 8306/* continuation for OP_DIV_LONG_2ADDR */ 8307 8308.LOP_DIV_LONG_2ADDR_continue: 8309 movl %eax,OUT_ARG3(%esp) 8310 movl %edx,OUT_ARG0(%esp) 8311 movl %ecx,OUT_ARG1(%esp) 8312 call __divdi3 8313.LOP_DIV_LONG_2ADDR_finish: 8314 SET_VREG_WORD %edx rINST 1 8315 SET_VREG_WORD %eax rINST 0 8316 FETCH_INST_OPCODE 1 %edx 8317 ADVANCE_PC 1 8318 GOTO_NEXT_R %edx 8319 8320.LOP_DIV_LONG_2ADDR_check_zero: 8321 testl %edx,%edx 8322 jne .LOP_DIV_LONG_2ADDR_notSpecial 8323 jmp common_errDivideByZero 8324.LOP_DIV_LONG_2ADDR_check_neg1: 8325 testl %edx,%eax 8326 jne .LOP_DIV_LONG_2ADDR_notSpecial 8327 GET_VREG_WORD %edx rINST 0 8328 GET_VREG_WORD %ecx rINST 1 8329 testl %edx,%edx 8330 jne .LOP_DIV_LONG_2ADDR_notSpecial1 8331 cmpl $0x80000000,%ecx 8332 jne .LOP_DIV_LONG_2ADDR_notSpecial1 8333 /* minint / -1, return minint on div, 0 on rem */ 8334 xorl %eax,%eax 8335 movl $0x80000000,%edx 8336 jmp .LOP_DIV_LONG_2ADDR_finish 8337 8338/* continuation for OP_REM_LONG_2ADDR */ 8339 8340.LOP_REM_LONG_2ADDR_continue: 8341 movl %eax,OUT_ARG3(%esp) 8342 movl %edx,OUT_ARG0(%esp) 8343 movl %ecx,OUT_ARG1(%esp) 8344 call __moddi3 8345.LOP_REM_LONG_2ADDR_finish: 8346 SET_VREG_WORD %edx rINST 1 8347 SET_VREG_WORD %eax rINST 0 8348 FETCH_INST_OPCODE 1 %edx 8349 ADVANCE_PC 1 8350 GOTO_NEXT_R %edx 8351 8352.LOP_REM_LONG_2ADDR_check_zero: 8353 testl %edx,%edx 8354 jne .LOP_REM_LONG_2ADDR_notSpecial 8355 jmp common_errDivideByZero 8356.LOP_REM_LONG_2ADDR_check_neg1: 8357 testl %edx,%eax 8358 jne .LOP_REM_LONG_2ADDR_notSpecial 8359 GET_VREG_WORD %edx rINST 0 8360 GET_VREG_WORD %ecx rINST 1 8361 testl %edx,%edx 8362 jne .LOP_REM_LONG_2ADDR_notSpecial1 8363 cmpl $0x80000000,%ecx 8364 jne .LOP_REM_LONG_2ADDR_notSpecial1 8365 /* minint / -1, return minint on div, 0 on rem */ 8366 xorl %eax,%eax 8367 movl $0,%edx 8368 jmp .LOP_REM_LONG_2ADDR_finish 8369 8370/* continuation for OP_SHL_LONG_2ADDR */ 8371 8372 8373.LOP_SHL_LONG_2ADDR_finish: 8374 FETCH_INST_OPCODE 1 %edx 8375 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax 8376 ADVANCE_PC 1 8377 GOTO_NEXT_R %edx 8378 8379/* continuation for OP_SHR_LONG_2ADDR */ 8380 8381 8382.LOP_SHR_LONG_2ADDR_finish: 8383 FETCH_INST_OPCODE 1 %edx 8384 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax 8385 ADVANCE_PC 1 8386 GOTO_NEXT_R %edx 8387 8388/* continuation for OP_USHR_LONG_2ADDR */ 8389 8390 8391.LOP_USHR_LONG_2ADDR_finish: 8392 FETCH_INST_OPCODE 1 %edx 8393 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax 8394 ADVANCE_PC 1 8395 GOTO_NEXT_R %edx 8396 8397/* continuation for OP_DIV_INT_LIT16 */ 8398.LOP_DIV_INT_LIT16_continue_div: 8399 cltd 8400 idivl %ecx 8401.LOP_DIV_INT_LIT16_finish_div: 8402 SET_VREG %eax rINST 8403 FETCH_INST_OPCODE 2 %edx 8404 ADVANCE_PC 2 8405 GOTO_NEXT_R %edx 8406 8407/* continuation for OP_REM_INT_LIT16 */ 8408.LOP_REM_INT_LIT16_continue_div: 8409 cltd 8410 idivl %ecx 8411.LOP_REM_INT_LIT16_finish_div: 8412 SET_VREG %edx rINST 8413 FETCH_INST_OPCODE 2 %edx 8414 ADVANCE_PC 2 8415 GOTO_NEXT_R %edx 8416 8417/* continuation for OP_DIV_INT_LIT8 */ 8418.LOP_DIV_INT_LIT8_continue_div: 8419 cltd 8420 idivl %ecx 8421.LOP_DIV_INT_LIT8_finish_div: 8422 SET_VREG %eax rINST 8423 FETCH_INST_OPCODE 2 %edx 8424 ADVANCE_PC 2 8425 GOTO_NEXT_R %edx 8426 8427/* continuation for OP_REM_INT_LIT8 */ 8428.LOP_REM_INT_LIT8_continue_div: 8429 cltd 8430 idivl %ecx 8431.LOP_REM_INT_LIT8_finish_div: 8432 SET_VREG %edx rINST 8433 FETCH_INST_OPCODE 2 %edx 8434 ADVANCE_PC 2 8435 GOTO_NEXT_R %edx 8436 8437/* continuation for OP_IGET_VOLATILE */ 8438 8439 8440.LOP_IGET_VOLATILE_resolve: 8441 EXPORT_PC 8442 movl offGlue_method(%edx),%edx # edx<- current method 8443 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 8444 SPILL_TMP1(%ecx) # save obj pointer across call 8445 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 8446 call dvmResolveInstField # ... to dvmResolveInstField 8447 UNSPILL_TMP1(%ecx) 8448 testl %eax,%eax # returns InstrField ptr 8449 jne .LOP_IGET_VOLATILE_finish 8450 jmp common_exceptionThrown 8451 8452.LOP_IGET_VOLATILE_finish: 8453 /* 8454 * Currently: 8455 * eax holds resolved field 8456 * ecx holds object 8457 * rINST holds A 8458 */ 8459 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8460 testl %ecx,%ecx # object null? 8461 je common_errNullObject # object was null 8462 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 8463 movl rINST,%eax # eax<- A 8464 FETCH_INST_OPCODE 2 %edx 8465 SET_VREG %ecx %eax 8466 ADVANCE_PC 2 8467 GOTO_NEXT_R %edx 8468 8469/* continuation for OP_IPUT_VOLATILE */ 8470 8471 8472.LOP_IPUT_VOLATILE_resolve: 8473 EXPORT_PC 8474 movl offGlue_method(%edx),%edx # edx<- current method 8475 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 8476 SPILL_TMP1(%ecx) # save obj pointer across call 8477 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 8478 call dvmResolveInstField # ... to dvmResolveInstField 8479 UNSPILL_TMP1(%ecx) 8480 testl %eax,%eax # returns InstrField ptr 8481 jne .LOP_IPUT_VOLATILE_finish 8482 jmp common_exceptionThrown 8483 8484.LOP_IPUT_VOLATILE_finish: 8485 /* 8486 * Currently: 8487 * eax holds resolved field 8488 * ecx holds object 8489 * rINST holds A 8490 */ 8491 GET_VREG_R rINST rINST # rINST<- v[A] 8492 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8493 testl %ecx,%ecx # object null? 8494 je common_errNullObject # object was null 8495 FETCH_INST_OPCODE 2 %edx 8496 movl rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 8497 ADVANCE_PC 2 8498 GOTO_NEXT_R %edx 8499 8500/* continuation for OP_SGET_VOLATILE */ 8501 8502 /* 8503 * Go resolve the field 8504 */ 8505.LOP_SGET_VOLATILE_resolve: 8506 movl rGLUE,%ecx 8507 movzwl 2(rPC),%eax # eax<- field ref BBBB 8508 movl offGlue_method(%ecx),%ecx # ecx<- current method 8509 EXPORT_PC # could throw, need to export 8510 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8511 movl %eax,OUT_ARG1(%esp) 8512 movl %ecx,OUT_ARG0(%esp) 8513 call dvmResolveStaticField # eax<- resolved StaticField ptr 8514 testl %eax,%eax 8515 jne .LOP_SGET_VOLATILE_finish # success, continue 8516 jmp common_exceptionThrown # no, handle exception 8517 8518/* continuation for OP_SPUT_VOLATILE */ 8519 8520 /* 8521 * Go resolve the field 8522 */ 8523.LOP_SPUT_VOLATILE_resolve: 8524 movl rGLUE,%ecx 8525 movzwl 2(rPC),%eax # eax<- field ref BBBB 8526 movl offGlue_method(%ecx),%ecx # ecx<- current method 8527 EXPORT_PC # could throw, need to export 8528 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8529 movl %eax,OUT_ARG1(%esp) 8530 movl %ecx,OUT_ARG0(%esp) 8531 call dvmResolveStaticField # eax<- resolved StaticField ptr 8532 testl %eax,%eax 8533 jne .LOP_SPUT_VOLATILE_finish # success, continue 8534 jmp common_exceptionThrown # no, handle exception 8535 8536/* continuation for OP_IGET_OBJECT_VOLATILE */ 8537 8538 8539.LOP_IGET_OBJECT_VOLATILE_resolve: 8540 EXPORT_PC 8541 movl offGlue_method(%edx),%edx # edx<- current method 8542 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 8543 SPILL_TMP1(%ecx) # save obj pointer across call 8544 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 8545 call dvmResolveInstField # ... to dvmResolveInstField 8546 UNSPILL_TMP1(%ecx) 8547 testl %eax,%eax # returns InstrField ptr 8548 jne .LOP_IGET_OBJECT_VOLATILE_finish 8549 jmp common_exceptionThrown 8550 8551.LOP_IGET_OBJECT_VOLATILE_finish: 8552 /* 8553 * Currently: 8554 * eax holds resolved field 8555 * ecx holds object 8556 * rINST holds A 8557 */ 8558 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8559 testl %ecx,%ecx # object null? 8560 je common_errNullObject # object was null 8561 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 8562 movl rINST,%eax # eax<- A 8563 FETCH_INST_OPCODE 2 %edx 8564 SET_VREG %ecx %eax 8565 ADVANCE_PC 2 8566 GOTO_NEXT_R %edx 8567 8568/* continuation for OP_EXECUTE_INLINE */ 8569 8570.LOP_EXECUTE_INLINE_continue: 8571 /* 8572 * Extract args, call function. 8573 * ecx = #of args (0-4) 8574 * eax = call index 8575 * @esp = return addr 8576 * esp is -4 from normal 8577 * 8578 * Go ahead and load all 4 args, even if not used. 8579 */ 8580 movzwl 4(rPC),%edx 8581 8582 movl $0xf,%ecx 8583 andl %edx,%ecx 8584 GET_VREG_R %ecx %ecx 8585 sarl $4,%edx 8586 movl %ecx,4+OUT_ARG0(%esp) 8587 8588 movl $0xf,%ecx 8589 andl %edx,%ecx 8590 GET_VREG_R %ecx %ecx 8591 sarl $4,%edx 8592 movl %ecx,4+OUT_ARG1(%esp) 8593 8594 movl $0xf,%ecx 8595 andl %edx,%ecx 8596 GET_VREG_R %ecx %ecx 8597 sarl $4,%edx 8598 movl %ecx,4+OUT_ARG2(%esp) 8599 8600 movl $0xf,%ecx 8601 andl %edx,%ecx 8602 GET_VREG_R %ecx %ecx 8603 sarl $4,%edx 8604 movl %ecx,4+OUT_ARG3(%esp) 8605 8606 sall $4,%eax # index *= sizeof(table entry) 8607 jmp *gDvmInlineOpsTable(%eax) 8608 # will return to caller of .LOP_EXECUTE_INLINE_continue 8609 8610/* continuation for OP_IPUT_OBJECT_QUICK */ 8611 8612.LOP_IPUT_OBJECT_QUICK_finish: 8613 testl rINST,rINST # did we store null? 8614 FETCH_INST_OPCODE 2 %edx 8615 movl offGlue_cardTable(%eax),%eax # get card table base 8616 je 1f # skip card mark if null store 8617 shrl $GC_CARD_SHIFT,%ecx # object head to card number 8618 movb %al,(%eax,%ecx) # mark card based on object head 86191: 8620 ADVANCE_PC 2 8621 GOTO_NEXT_R %edx 8622 8623/* continuation for OP_IPUT_OBJECT_VOLATILE */ 8624 8625 8626.LOP_IPUT_OBJECT_VOLATILE_resolve: 8627 EXPORT_PC 8628 movl offGlue_method(%edx),%edx # edx<- current method 8629 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 8630 SPILL_TMP1(%ecx) # save obj pointer across call 8631 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 8632 call dvmResolveInstField # ... to dvmResolveInstField 8633 UNSPILL_TMP1(%ecx) 8634 testl %eax,%eax # returns InstrField ptr 8635 jne .LOP_IPUT_OBJECT_VOLATILE_finish 8636 jmp common_exceptionThrown 8637 8638.LOP_IPUT_OBJECT_VOLATILE_finish: 8639 /* 8640 * Currently: 8641 * eax holds resolved field 8642 * ecx holds object 8643 * %edx is scratch, but needs to be unspilled 8644 * rINST holds A 8645 */ 8646 GET_VREG_R rINST rINST # rINST<- v[A] 8647 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8648 testl %ecx,%ecx # object null? 8649 je common_errNullObject # object was null 8650 movl rINST,(%ecx,%eax) # obj.field <- v[A](8/16/32 bits) 8651 movl rGLUE,%eax 8652 testl rINST,rINST # stored a NULL? 8653 movl offGlue_cardTable(%eax),%eax # get card table base 8654 FETCH_INST_OPCODE 2 %edx 8655 je 1f # skip card mark if null store 8656 shrl $GC_CARD_SHIFT,%ecx # object head to card number 8657 movb %al,(%eax,%ecx) # mark card using object head 86581: 8659 ADVANCE_PC 2 8660 GOTO_NEXT_R %edx 8661 8662/* continuation for OP_SGET_OBJECT_VOLATILE */ 8663 8664 /* 8665 * Go resolve the field 8666 */ 8667.LOP_SGET_OBJECT_VOLATILE_resolve: 8668 movl rGLUE,%ecx 8669 movzwl 2(rPC),%eax # eax<- field ref BBBB 8670 movl offGlue_method(%ecx),%ecx # ecx<- current method 8671 EXPORT_PC # could throw, need to export 8672 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8673 movl %eax,OUT_ARG1(%esp) 8674 movl %ecx,OUT_ARG0(%esp) 8675 call dvmResolveStaticField # eax<- resolved StaticField ptr 8676 testl %eax,%eax 8677 jne .LOP_SGET_OBJECT_VOLATILE_finish # success, continue 8678 jmp common_exceptionThrown # no, handle exception 8679 8680/* continuation for OP_SPUT_OBJECT_VOLATILE */ 8681 8682 8683.LOP_SPUT_OBJECT_VOLATILE_continue: 8684 movl %ecx,offStaticField_value(%eax) # do the store 8685 testl %ecx,%ecx # stored null object ptr? 8686 FETCH_INST_OPCODE 2 %edx 8687 je 1f # skip card mark if null 8688 movl rGLUE,%ecx 8689 movl offField_clazz(%eax),%eax # eax<- method->clazz 8690 movl offGlue_cardTable(%ecx),%ecx # get card table base 8691 shrl $GC_CARD_SHIFT,%eax # head to card number 8692 movb %cl,(%ecx,%eax) # mark card 86931: 8694 ADVANCE_PC 2 8695 GOTO_NEXT_R %edx 8696 8697.LOP_SPUT_OBJECT_VOLATILE_resolve: 8698 movl rGLUE,%ecx 8699 movzwl 2(rPC),%eax # eax<- field ref BBBB 8700 movl offGlue_method(%ecx),%ecx # ecx<- current method 8701 EXPORT_PC # could throw, need to export 8702 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8703 movl %eax,OUT_ARG1(%esp) 8704 movl %ecx,OUT_ARG0(%esp) 8705 call dvmResolveStaticField # eax<- resolved StaticField ptr 8706 testl %eax,%eax 8707 jne .LOP_SPUT_OBJECT_VOLATILE_finish # success, continue 8708 jmp common_exceptionThrown # no, handle exception 8709 8710 .size dvmAsmSisterStart, .-dvmAsmSisterStart 8711 .global dvmAsmSisterEnd 8712dvmAsmSisterEnd: 8713 8714/* File: x86/entry.S */ 8715/* 8716 * Copyright (C) 2008 The Android Open Source Project 8717 * 8718 * Licensed under the Apache License, Version 2.0 (the "License"); 8719 * you may not use this file except in compliance with the License. 8720 * You may obtain a copy of the License at 8721 * 8722 * http://www.apache.org/licenses/LICENSE-2.0 8723 * 8724 * Unless required by applicable law or agreed to in writing, software 8725 * distributed under the License is distributed on an "AS IS" BASIS, 8726 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8727 * See the License for the specific language governing permissions and 8728 * limitations under the License. 8729 */ 8730 8731 8732 .text 8733 .global dvmMterpStdRun 8734 .type dvmMterpStdRun, %function 8735/* 8736 * bool dvmMterpStdRun(MterpGlue* glue) 8737 * 8738 * Interpreter entry point. Returns changeInterp. 8739 * 8740 */ 8741dvmMterpStdRun: 8742 movl 4(%esp), %ecx # get incoming rGLUE 8743 push %ebp # save caller base pointer 8744 push %ecx # save rGLUE at (%ebp) 8745 movl %esp, %ebp # set our %ebp 8746/* 8747 * At this point we've allocated two slots on the stack 8748 * via push and stack is 8-byte aligned. Allocate space 8749 * for 8 spill slots, 3 local slots, 5 arg slots + 2 slots for 8750 * padding to bring us to 16-byte alignment 8751 */ 8752 subl $(FRAME_SIZE-8), %esp 8753 8754/* Spill callee save regs */ 8755 movl %edi,EDI_SPILL(%ebp) 8756 movl %esi,ESI_SPILL(%ebp) 8757 movl %ebx,EBX_SPILL(%ebp) 8758 8759/* Set up "named" registers */ 8760 movl offGlue_pc(%ecx),rPC 8761 movl offGlue_fp(%ecx),rFP 8762 8763/* Remember %esp for future "longjmp" */ 8764 movl %esp,offGlue_bailPtr(%ecx) 8765 8766/* How to start? */ 8767 movb offGlue_entryPoint(%ecx),%al 8768 8769/* Normal start? */ 8770 cmpb $kInterpEntryInstr,%al 8771 jne .Lnot_instr 8772 8773 /* Normal case: start executing the instruction at rPC */ 8774 FETCH_INST 8775 GOTO_NEXT 8776 8777.Lnot_instr: 8778 /* Reset to normal case */ 8779 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx) 8780 cmpb $kInterpEntryReturn,%al 8781 je common_returnFromMethod 8782 cmpb $kInterpEntryThrow,%al 8783 je common_exceptionThrown 8784 movzx %al,%eax 8785 movl %eax,OUT_ARG1(%esp) 8786 movl $.LstrBadEntryPoint,OUT_ARG0(%esp) 8787 call printf 8788 call dvmAbort 8789 /* Not reached */ 8790 8791 8792 .global dvmMterpStdBail 8793 .type dvmMterpStdBail, %function 8794/* 8795 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp) 8796 * 8797 * Restore the stack pointer and PC from the save point established on entry. 8798 * This is essentially the same as a longjmp, but should be cheaper. The 8799 * last instruction causes us to return to whoever called dvmMterpStdRun. 8800 * 8801 * We're not going to build a standard frame here, so the arg accesses will 8802 * look a little strange. 8803 * 8804 * On entry: 8805 * esp+4 (arg0) MterpGlue* glue 8806 * esp+8 (arg1) bool changeInterp 8807 */ 8808dvmMterpStdBail: 8809 movl 4(%esp),%ecx # grab glue 8810 movl 8(%esp),%eax # changeInterp to return reg 8811 movl offGlue_bailPtr(%ecx),%esp # Restore "setjmp" esp 8812 movl %esp,%ebp 8813 addl $(FRAME_SIZE-8), %ebp # Restore %ebp at point of setjmp 8814 movl EDI_SPILL(%ebp),%edi 8815 movl ESI_SPILL(%ebp),%esi 8816 movl EBX_SPILL(%ebp),%ebx 8817 movl PREV_FP(%ebp),%ebp # restore caller's ebp 8818 addl $FRAME_SIZE,%esp # strip frame 8819 ret # return to dvmMterpStdRun's caller 8820 8821 8822/* 8823 * Strings 8824 */ 8825 .section .rodata 8826.LstrBadEntryPoint: 8827 .asciz "Bad entry point %d\n" 8828 8829 8830/* 8831 * FIXME: Should have the config/rebuild mechanism generate this 8832 * for targets that need it. 8833 */ 8834 8835/* Jump table */ 8836dvmAsmInstructionJmpTable = .LdvmAsmInstructionJmpTable 8837.LdvmAsmInstructionJmpTable: 8838.long .L_OP_NOP 8839.long .L_OP_MOVE 8840.long .L_OP_MOVE_FROM16 8841.long .L_OP_MOVE_16 8842.long .L_OP_MOVE_WIDE 8843.long .L_OP_MOVE_WIDE_FROM16 8844.long .L_OP_MOVE_WIDE_16 8845.long .L_OP_MOVE_OBJECT 8846.long .L_OP_MOVE_OBJECT_FROM16 8847.long .L_OP_MOVE_OBJECT_16 8848.long .L_OP_MOVE_RESULT 8849.long .L_OP_MOVE_RESULT_WIDE 8850.long .L_OP_MOVE_RESULT_OBJECT 8851.long .L_OP_MOVE_EXCEPTION 8852.long .L_OP_RETURN_VOID 8853.long .L_OP_RETURN 8854.long .L_OP_RETURN_WIDE 8855.long .L_OP_RETURN_OBJECT 8856.long .L_OP_CONST_4 8857.long .L_OP_CONST_16 8858.long .L_OP_CONST 8859.long .L_OP_CONST_HIGH16 8860.long .L_OP_CONST_WIDE_16 8861.long .L_OP_CONST_WIDE_32 8862.long .L_OP_CONST_WIDE 8863.long .L_OP_CONST_WIDE_HIGH16 8864.long .L_OP_CONST_STRING 8865.long .L_OP_CONST_STRING_JUMBO 8866.long .L_OP_CONST_CLASS 8867.long .L_OP_MONITOR_ENTER 8868.long .L_OP_MONITOR_EXIT 8869.long .L_OP_CHECK_CAST 8870.long .L_OP_INSTANCE_OF 8871.long .L_OP_ARRAY_LENGTH 8872.long .L_OP_NEW_INSTANCE 8873.long .L_OP_NEW_ARRAY 8874.long .L_OP_FILLED_NEW_ARRAY 8875.long .L_OP_FILLED_NEW_ARRAY_RANGE 8876.long .L_OP_FILL_ARRAY_DATA 8877.long .L_OP_THROW 8878.long .L_OP_GOTO 8879.long .L_OP_GOTO_16 8880.long .L_OP_GOTO_32 8881.long .L_OP_PACKED_SWITCH 8882.long .L_OP_SPARSE_SWITCH 8883.long .L_OP_CMPL_FLOAT 8884.long .L_OP_CMPG_FLOAT 8885.long .L_OP_CMPL_DOUBLE 8886.long .L_OP_CMPG_DOUBLE 8887.long .L_OP_CMP_LONG 8888.long .L_OP_IF_EQ 8889.long .L_OP_IF_NE 8890.long .L_OP_IF_LT 8891.long .L_OP_IF_GE 8892.long .L_OP_IF_GT 8893.long .L_OP_IF_LE 8894.long .L_OP_IF_EQZ 8895.long .L_OP_IF_NEZ 8896.long .L_OP_IF_LTZ 8897.long .L_OP_IF_GEZ 8898.long .L_OP_IF_GTZ 8899.long .L_OP_IF_LEZ 8900.long .L_OP_UNUSED_3E 8901.long .L_OP_UNUSED_3F 8902.long .L_OP_UNUSED_40 8903.long .L_OP_UNUSED_41 8904.long .L_OP_UNUSED_42 8905.long .L_OP_UNUSED_43 8906.long .L_OP_AGET 8907.long .L_OP_AGET_WIDE 8908.long .L_OP_AGET_OBJECT 8909.long .L_OP_AGET_BOOLEAN 8910.long .L_OP_AGET_BYTE 8911.long .L_OP_AGET_CHAR 8912.long .L_OP_AGET_SHORT 8913.long .L_OP_APUT 8914.long .L_OP_APUT_WIDE 8915.long .L_OP_APUT_OBJECT 8916.long .L_OP_APUT_BOOLEAN 8917.long .L_OP_APUT_BYTE 8918.long .L_OP_APUT_CHAR 8919.long .L_OP_APUT_SHORT 8920.long .L_OP_IGET 8921.long .L_OP_IGET_WIDE 8922.long .L_OP_IGET_OBJECT 8923.long .L_OP_IGET_BOOLEAN 8924.long .L_OP_IGET_BYTE 8925.long .L_OP_IGET_CHAR 8926.long .L_OP_IGET_SHORT 8927.long .L_OP_IPUT 8928.long .L_OP_IPUT_WIDE 8929.long .L_OP_IPUT_OBJECT 8930.long .L_OP_IPUT_BOOLEAN 8931.long .L_OP_IPUT_BYTE 8932.long .L_OP_IPUT_CHAR 8933.long .L_OP_IPUT_SHORT 8934.long .L_OP_SGET 8935.long .L_OP_SGET_WIDE 8936.long .L_OP_SGET_OBJECT 8937.long .L_OP_SGET_BOOLEAN 8938.long .L_OP_SGET_BYTE 8939.long .L_OP_SGET_CHAR 8940.long .L_OP_SGET_SHORT 8941.long .L_OP_SPUT 8942.long .L_OP_SPUT_WIDE 8943.long .L_OP_SPUT_OBJECT 8944.long .L_OP_SPUT_BOOLEAN 8945.long .L_OP_SPUT_BYTE 8946.long .L_OP_SPUT_CHAR 8947.long .L_OP_SPUT_SHORT 8948.long .L_OP_INVOKE_VIRTUAL 8949.long .L_OP_INVOKE_SUPER 8950.long .L_OP_INVOKE_DIRECT 8951.long .L_OP_INVOKE_STATIC 8952.long .L_OP_INVOKE_INTERFACE 8953.long .L_OP_UNUSED_73 8954.long .L_OP_INVOKE_VIRTUAL_RANGE 8955.long .L_OP_INVOKE_SUPER_RANGE 8956.long .L_OP_INVOKE_DIRECT_RANGE 8957.long .L_OP_INVOKE_STATIC_RANGE 8958.long .L_OP_INVOKE_INTERFACE_RANGE 8959.long .L_OP_UNUSED_79 8960.long .L_OP_UNUSED_7A 8961.long .L_OP_NEG_INT 8962.long .L_OP_NOT_INT 8963.long .L_OP_NEG_LONG 8964.long .L_OP_NOT_LONG 8965.long .L_OP_NEG_FLOAT 8966.long .L_OP_NEG_DOUBLE 8967.long .L_OP_INT_TO_LONG 8968.long .L_OP_INT_TO_FLOAT 8969.long .L_OP_INT_TO_DOUBLE 8970.long .L_OP_LONG_TO_INT 8971.long .L_OP_LONG_TO_FLOAT 8972.long .L_OP_LONG_TO_DOUBLE 8973.long .L_OP_FLOAT_TO_INT 8974.long .L_OP_FLOAT_TO_LONG 8975.long .L_OP_FLOAT_TO_DOUBLE 8976.long .L_OP_DOUBLE_TO_INT 8977.long .L_OP_DOUBLE_TO_LONG 8978.long .L_OP_DOUBLE_TO_FLOAT 8979.long .L_OP_INT_TO_BYTE 8980.long .L_OP_INT_TO_CHAR 8981.long .L_OP_INT_TO_SHORT 8982.long .L_OP_ADD_INT 8983.long .L_OP_SUB_INT 8984.long .L_OP_MUL_INT 8985.long .L_OP_DIV_INT 8986.long .L_OP_REM_INT 8987.long .L_OP_AND_INT 8988.long .L_OP_OR_INT 8989.long .L_OP_XOR_INT 8990.long .L_OP_SHL_INT 8991.long .L_OP_SHR_INT 8992.long .L_OP_USHR_INT 8993.long .L_OP_ADD_LONG 8994.long .L_OP_SUB_LONG 8995.long .L_OP_MUL_LONG 8996.long .L_OP_DIV_LONG 8997.long .L_OP_REM_LONG 8998.long .L_OP_AND_LONG 8999.long .L_OP_OR_LONG 9000.long .L_OP_XOR_LONG 9001.long .L_OP_SHL_LONG 9002.long .L_OP_SHR_LONG 9003.long .L_OP_USHR_LONG 9004.long .L_OP_ADD_FLOAT 9005.long .L_OP_SUB_FLOAT 9006.long .L_OP_MUL_FLOAT 9007.long .L_OP_DIV_FLOAT 9008.long .L_OP_REM_FLOAT 9009.long .L_OP_ADD_DOUBLE 9010.long .L_OP_SUB_DOUBLE 9011.long .L_OP_MUL_DOUBLE 9012.long .L_OP_DIV_DOUBLE 9013.long .L_OP_REM_DOUBLE 9014.long .L_OP_ADD_INT_2ADDR 9015.long .L_OP_SUB_INT_2ADDR 9016.long .L_OP_MUL_INT_2ADDR 9017.long .L_OP_DIV_INT_2ADDR 9018.long .L_OP_REM_INT_2ADDR 9019.long .L_OP_AND_INT_2ADDR 9020.long .L_OP_OR_INT_2ADDR 9021.long .L_OP_XOR_INT_2ADDR 9022.long .L_OP_SHL_INT_2ADDR 9023.long .L_OP_SHR_INT_2ADDR 9024.long .L_OP_USHR_INT_2ADDR 9025.long .L_OP_ADD_LONG_2ADDR 9026.long .L_OP_SUB_LONG_2ADDR 9027.long .L_OP_MUL_LONG_2ADDR 9028.long .L_OP_DIV_LONG_2ADDR 9029.long .L_OP_REM_LONG_2ADDR 9030.long .L_OP_AND_LONG_2ADDR 9031.long .L_OP_OR_LONG_2ADDR 9032.long .L_OP_XOR_LONG_2ADDR 9033.long .L_OP_SHL_LONG_2ADDR 9034.long .L_OP_SHR_LONG_2ADDR 9035.long .L_OP_USHR_LONG_2ADDR 9036.long .L_OP_ADD_FLOAT_2ADDR 9037.long .L_OP_SUB_FLOAT_2ADDR 9038.long .L_OP_MUL_FLOAT_2ADDR 9039.long .L_OP_DIV_FLOAT_2ADDR 9040.long .L_OP_REM_FLOAT_2ADDR 9041.long .L_OP_ADD_DOUBLE_2ADDR 9042.long .L_OP_SUB_DOUBLE_2ADDR 9043.long .L_OP_MUL_DOUBLE_2ADDR 9044.long .L_OP_DIV_DOUBLE_2ADDR 9045.long .L_OP_REM_DOUBLE_2ADDR 9046.long .L_OP_ADD_INT_LIT16 9047.long .L_OP_RSUB_INT 9048.long .L_OP_MUL_INT_LIT16 9049.long .L_OP_DIV_INT_LIT16 9050.long .L_OP_REM_INT_LIT16 9051.long .L_OP_AND_INT_LIT16 9052.long .L_OP_OR_INT_LIT16 9053.long .L_OP_XOR_INT_LIT16 9054.long .L_OP_ADD_INT_LIT8 9055.long .L_OP_RSUB_INT_LIT8 9056.long .L_OP_MUL_INT_LIT8 9057.long .L_OP_DIV_INT_LIT8 9058.long .L_OP_REM_INT_LIT8 9059.long .L_OP_AND_INT_LIT8 9060.long .L_OP_OR_INT_LIT8 9061.long .L_OP_XOR_INT_LIT8 9062.long .L_OP_SHL_INT_LIT8 9063.long .L_OP_SHR_INT_LIT8 9064.long .L_OP_USHR_INT_LIT8 9065.long .L_OP_IGET_VOLATILE 9066.long .L_OP_IPUT_VOLATILE 9067.long .L_OP_SGET_VOLATILE 9068.long .L_OP_SPUT_VOLATILE 9069.long .L_OP_IGET_OBJECT_VOLATILE 9070.long .L_OP_IGET_WIDE_VOLATILE 9071.long .L_OP_IPUT_WIDE_VOLATILE 9072.long .L_OP_SGET_WIDE_VOLATILE 9073.long .L_OP_SPUT_WIDE_VOLATILE 9074.long .L_OP_BREAKPOINT 9075.long .L_OP_THROW_VERIFICATION_ERROR 9076.long .L_OP_EXECUTE_INLINE 9077.long .L_OP_EXECUTE_INLINE_RANGE 9078.long .L_OP_INVOKE_DIRECT_EMPTY 9079.long .L_OP_RETURN_VOID_BARRIER 9080.long .L_OP_IGET_QUICK 9081.long .L_OP_IGET_WIDE_QUICK 9082.long .L_OP_IGET_OBJECT_QUICK 9083.long .L_OP_IPUT_QUICK 9084.long .L_OP_IPUT_WIDE_QUICK 9085.long .L_OP_IPUT_OBJECT_QUICK 9086.long .L_OP_INVOKE_VIRTUAL_QUICK 9087.long .L_OP_INVOKE_VIRTUAL_QUICK_RANGE 9088.long .L_OP_INVOKE_SUPER_QUICK 9089.long .L_OP_INVOKE_SUPER_QUICK_RANGE 9090.long .L_OP_IPUT_OBJECT_VOLATILE 9091.long .L_OP_SGET_OBJECT_VOLATILE 9092.long .L_OP_SPUT_OBJECT_VOLATILE 9093.long .L_OP_UNUSED_FF 9094 9095 9096/* File: x86/footer.S */ 9097/* 9098 * Copyright (C) 2008 The Android Open Source Project 9099 * 9100 * Licensed under the Apache License, Version 2.0 (the "License"); 9101 * you may not use this file except in compliance with the License. 9102 * You may obtain a copy of the License at 9103 * 9104 * http://www.apache.org/licenses/LICENSE-2.0 9105 * 9106 * Unless required by applicable law or agreed to in writing, software 9107 * distributed under the License is distributed on an "AS IS" BASIS, 9108 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9109 * See the License for the specific language governing permissions and 9110 * limitations under the License. 9111 */ 9112/* 9113 * Common subroutines and data. 9114 */ 9115 9116#if defined(WITH_JIT) 9117/* 9118 * Placeholder entries for x86 JIT 9119 */ 9120 .global dvmJitToInterpPunt 9121dvmJitToInterpPunt: 9122 .global dvmJitToInterpSingleStep 9123dvmJitToInterpSingleStep: 9124 .global dvmJitToInterpNoChainNoProfile 9125dvmJitToInterpNoChainNoProfile: 9126 .global dvmJitToInterpTraceSelectNoChain 9127dvmJitToInterpTraceSelectNoChain: 9128 .global dvmJitToInterpTraceSelect 9129dvmJitToInterpTraceSelect: 9130 .global dvmJitToInterpBackwardBranch 9131dvmJitToInterpBackwardBranch: 9132 .global dvmJitToInterpNormal 9133dvmJitToInterpNormal: 9134 .global dvmJitToInterpNoChain 9135dvmJitToInterpNoChain: 9136 jmp common_abort 9137#endif 9138 9139/* 9140 * Common code when a backwards branch is taken 9141 * 9142 * On entry: 9143 * ebx (a.k.a. rINST) -> PC adjustment in 16-bit words 9144 */ 9145common_backwardBranch: 9146 movl rGLUE,%ecx 9147 call common_periodicChecks # Note: expects rPC to be preserved 9148 ADVANCE_PC_INDEXED rINST 9149 FETCH_INST 9150 GOTO_NEXT 9151 9152 9153 9154/* 9155 * Common code for method invocation with range. 9156 * 9157 * On entry: 9158 * eax = Method* methodToCall 9159 * rINSTw trashed, must reload 9160 */ 9161 9162common_invokeMethodRange: 9163.LinvokeNewRange: 9164 9165 /* 9166 * prepare to copy args to "outs" area of current frame 9167 */ 9168 9169 movzbl 1(rPC),rINST # rINST<- AA 9170 movzwl 4(rPC), %ecx # %ecx<- CCCC 9171 SAVEAREA_FROM_FP %edx # %edx<- &StackSaveArea 9172 test rINST, rINST 9173 movl rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA 9174 jz .LinvokeArgsDone # no args; jump to args done 9175 9176 9177 /* 9178 * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea) 9179 * (very few methods have > 10 args; could unroll for common cases) 9180 */ 9181 9182 movl %ebx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- save %ebx 9183 lea (rFP, %ecx, 4), %ecx # %ecx<- &vCCCC 9184 shll $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 9185 subl LOCAL0_OFFSET(%ebp), %edx # %edx<- update &outs 9186 shrl $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 91871: 9188 movl (%ecx), %ebx # %ebx<- vCCCC 9189 lea 4(%ecx), %ecx # %ecx<- &vCCCC++ 9190 subl $1, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- LOCAL0_OFFSET-- 9191 movl %ebx, (%edx) # *outs<- vCCCC 9192 lea 4(%edx), %edx # outs++ 9193 jne 1b # loop if count (LOCAL0_OFFSET(%ebp)) not zero 9194 movl LOCAL1_OFFSET(%ebp), %ebx # %ebx<- restore %ebx 9195 jmp .LinvokeArgsDone # continue 9196 9197 /* 9198 * %eax is "Method* methodToCall", the method we're trying to call 9199 * prepare to copy args to "outs" area of current frame 9200 */ 9201 9202common_invokeMethodNoRange: 9203.LinvokeNewNoRange: 9204 movzbl 1(rPC),rINST # rINST<- BA 9205 movl rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA 9206 shrl $4, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- B 9207 je .LinvokeArgsDone # no args; jump to args done 9208 movzwl 4(rPC), %ecx # %ecx<- GFED 9209 SAVEAREA_FROM_FP %edx # %edx<- &StackSaveArea 9210 9211 /* 9212 * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs 9213 */ 9214 9215.LinvokeNonRange: 9216 cmp $2, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 2 9217 movl %ecx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- GFED 9218 jl 1f # handle 1 arg 9219 je 2f # handle 2 args 9220 cmp $4, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 4 9221 jl 3f # handle 3 args 9222 je 4f # handle 4 args 92235: 9224 andl $15, rINST # rINSTw<- A 9225 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9226 movl (rFP, rINST, 4), %ecx # %ecx<- vA 9227 movl %ecx, (%edx) # *outs<- vA 9228 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 92294: 9230 shr $12, %ecx # %ecx<- G 9231 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9232 movl (rFP, %ecx, 4), %ecx # %ecx<- vG 9233 movl %ecx, (%edx) # *outs<- vG 9234 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 92353: 9236 and $0x0f00, %ecx # %ecx<- 0F00 9237 shr $8, %ecx # %ecx<- F 9238 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9239 movl (rFP, %ecx, 4), %ecx # %ecx<- vF 9240 movl %ecx, (%edx) # *outs<- vF 9241 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 92422: 9243 and $0x00f0, %ecx # %ecx<- 00E0 9244 shr $4, %ecx # %ecx<- E 9245 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9246 movl (rFP, %ecx, 4), %ecx # %ecx<- vE 9247 movl %ecx, (%edx) # *outs<- vE 9248 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 92491: 9250 and $0x000f, %ecx # %ecx<- 000D 9251 movl (rFP, %ecx, 4), %ecx # %ecx<- vD 9252 movl %ecx, -4(%edx) # *--outs<- vD 92530: 9254 9255 /* 9256 * %eax is "Method* methodToCall", the method we're trying to call 9257 * find space for the new stack frame, check for overflow 9258 */ 9259 9260.LinvokeArgsDone: 9261 movzwl offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize 9262 movzwl offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize 9263 movl %eax, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- methodToCall 9264 shl $2, %edx # %edx<- update offset 9265 SAVEAREA_FROM_FP %eax # %eax<- &StackSaveArea 9266 subl %edx, %eax # %eax<- newFP; (old savearea - regsSize) 9267 movl rGLUE,%edx # %edx<- pMterpGlue 9268 movl %eax, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- &outs 9269 subl $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP) 9270 movl offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd 9271 movl %edx, LOCAL2_OFFSET(%ebp) # LOCAL2_OFFSET<- glue->interpStackEnd 9272 shl $2, %ecx # %ecx<- update offset for outsSize 9273 movl %eax, %edx # %edx<- newSaveArea 9274 sub %ecx, %eax # %eax<- bottom; (newSaveArea - outsSize) 9275 cmp LOCAL2_OFFSET(%ebp), %eax # compare interpStackEnd and bottom 9276 movl LOCAL0_OFFSET(%ebp), %eax # %eax<- restore methodToCall 9277 jl .LstackOverflow # handle frame overflow 9278 9279 /* 9280 * set up newSaveArea 9281 */ 9282 9283#ifdef EASY_GDB 9284 SAVEAREA_FROM_FP %ecx # %ecx<- &StackSaveArea 9285 movl %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs 9286#endif 9287 movl rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP 9288 movl rPC, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC 9289 testl $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call 9290 movl %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call 9291 jne .LinvokeNative # handle native call 9292 9293 /* 9294 * Update "glue" values for the new method 9295 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp 9296 */ 9297 9298 movl offMethod_clazz(%eax), %edx # %edx<- method->clazz 9299 movl rGLUE,%ecx # %ecx<- pMterpGlue 9300 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex 9301 movl %eax, offGlue_method(%ecx) # glue->method<- methodToCall 9302 movl %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex 9303 movl offMethod_insns(%eax), rPC # rPC<- methodToCall->insns 9304 movl offGlue_self(%ecx), %eax # %eax<- glue->self 9305 movl LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP 9306 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP 9307 FETCH_INST 9308 GOTO_NEXT # jump to methodToCall->insns 9309 9310 /* 9311 * Prep for the native call 9312 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea 9313 */ 9314 9315.LinvokeNative: 9316 movl rGLUE,%ecx # %ecx<- pMterpGlue 9317 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 9318 movl offGlue_self(%ecx), %ecx # %ecx<- glue->self 9319 movl offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->... 9320 movl %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top 9321 movl %edx, OUT_ARG4(%esp) # save newSaveArea 9322 movl LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP 9323 movl %edx, offThread_curFrame(%ecx) # glue->self->curFrame<- newFP 9324 movl %ecx, OUT_ARG3(%esp) # save glue->self 9325 movl %ecx, OUT_ARG2(%esp) # push parameter glue->self 9326 movl rGLUE,%ecx # %ecx<- pMterpGlue 9327 movl OUT_ARG1(%esp), %eax # %eax<- methodToCall 9328 lea offGlue_retval(%ecx), %ecx # %ecx<- &retval 9329 movl %ecx, OUT_ARG0(%esp) # push parameter pMterpGlue 9330 push %edx # push parameter newFP 9331 9332 call *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc 9333 lea 4(%esp), %esp 9334 movl OUT_ARG4(%esp), %ecx # %ecx<- newSaveArea 9335 movl OUT_ARG3(%esp), %eax # %eax<- glue->self 9336 movl offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top 9337 cmp $0, offThread_exception(%eax) # check for exception 9338 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP 9339 movl %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top 9340 jne common_exceptionThrown # handle exception 9341 FETCH_INST_OPCODE 3 %edx 9342 ADVANCE_PC 3 9343 GOTO_NEXT_R %edx # jump to next instruction 9344 9345.LstackOverflow: # eax=methodToCall 9346 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 9347 movl rGLUE,%eax # %eax<- pMterpGlue 9348 movl offGlue_self(%eax), %eax # %eax<- glue->self 9349 movl %eax, OUT_ARG0(%esp) # push parameter self 9350 call dvmHandleStackOverflow # call: (Thread* self, Method* meth) 9351 jmp common_exceptionThrown # handle exception 9352 9353 9354/* 9355 * Do we need the thread to be suspended or have debugger/profiling activity? 9356 * 9357 * On entry: 9358 * ebx -> PC adjustment in 16-bit words (must be preserved) 9359 * ecx -> GLUE pointer 9360 * reentry type, e.g. kInterpEntryInstr stored in rGLUE->entryPoint 9361 * 9362 * Note: A call will normally kill %eax and %ecx. To 9363 * streamline the normal case, this routine will preserve 9364 * %ecx in addition to the normal caller save regs. The save/restore 9365 * is a bit ugly, but will happen in the relatively uncommon path. 9366 * TODO: Basic-block style Jit will need a hook here as well. Fold it into 9367 * the suspendCount check so we can get both in 1 shot. 9368 */ 9369common_periodicChecks: 9370 movl offGlue_pSelfSuspendCount(%ecx),%eax # eax <- &suspendCount 9371 cmpl $0,(%eax) 9372 jne 1f 9373 93746: 9375 movl offGlue_pDebuggerActive(%ecx),%eax # eax <- &DebuggerActive 9376 movl offGlue_pActiveProfilers(%ecx),%ecx # ecx <- &ActiveProfilers 9377 testl %eax,%eax # debugger enabled? 9378 je 2f 9379 movzbl (%eax),%eax # get active count 93802: 9381 orl (%ecx),%eax # eax <- debuggerActive | activeProfilers 9382 movl rGLUE,%ecx # restore rGLUE 9383 jne 3f # one or both active - switch interp 9384 93855: 9386 ret 9387 9388 /* Check for suspend */ 93891: 9390 /* At this point, the return pointer to the caller of 9391 * common_periodicChecks is on the top of stack. We need to preserve 9392 * GLUE(ecx). 9393 * The outgoing profile is: 9394 * bool dvmCheckSuspendPending(Thread* self) 9395 * Because we reached here via a call, go ahead and build a new frame. 9396 */ 9397 EXPORT_PC # need for precise GC 9398 movl offGlue_self(%ecx),%eax # eax<- glue->self 9399 push %ebp 9400 movl %esp,%ebp 9401 subl $24,%esp 9402 movl %eax,OUT_ARG0(%esp) 9403 call dvmCheckSuspendPending 9404 addl $24,%esp 9405 pop %ebp 9406 movl rGLUE,%ecx 9407 9408 /* 9409 * Need to check to see if debugger or profiler flags got set 9410 * while we were suspended. 9411 */ 9412 jmp 6b 9413 9414 /* Switch interpreters */ 9415 /* Note: %ebx contains the 16-bit word offset to be applied to rPC to 9416 * "complete" the interpretation of backwards branches. In effect, we 9417 * are completing the interpretation of the branch instruction here, 9418 * and the new interpreter will resume interpretation at the branch 9419 * target. However, a switch request recognized during the handling 9420 * of a return from method instruction results in an immediate abort, 9421 * and the new interpreter will resume by re-interpreting the return 9422 * instruction. 9423 */ 94243: 9425 leal (rPC,%ebx,2),rPC # adjust pc to show target 9426 movl rGLUE,%ecx # bail expect GLUE already loaded 9427 movl $1,rINST # set changeInterp to true 9428 jmp common_gotoBail 9429 9430 9431/* 9432 * Common code for handling a return instruction 9433 */ 9434common_returnFromMethod: 9435 movl rGLUE,%ecx 9436 /* Set entry mode in case we bail */ 9437 movb $kInterpEntryReturn,offGlue_entryPoint(%ecx) 9438 xorl rINST,rINST # zero offset in case we switch interps 9439 call common_periodicChecks # Note: expects %ecx to be preserved 9440 9441 SAVEAREA_FROM_FP %eax # eax<- saveArea (old) 9442 movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame 9443 movl (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST 9444 cmpl $0,rINST # break? 9445 je common_gotoBail # break frame, bail out completely 9446 9447 movl offStackSaveArea_savedPc(%eax),rPC # pc<- saveArea->savedPC 9448 movl offGlue_self(%ecx),%eax # eax<- self 9449 movl rINST,offGlue_method(%ecx) # glue->method = newSave->meethod 9450 movl rFP,offThread_curFrame(%eax) # self->curFrame = fp 9451 movl offMethod_clazz(rINST),%eax # eax<- method->clazz 9452 FETCH_INST_OPCODE 3 %edx 9453 movl offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex 9454 ADVANCE_PC 3 9455 movl %eax,offGlue_methodClassDex(%ecx) 9456 /* not bailing - restore entry mode to default */ 9457 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx) 9458 GOTO_NEXT_R %edx 9459 9460/* 9461 * Prepare to strip the current frame and "longjump" back to caller of 9462 * dvmMterpStdRun. 9463 * 9464 * on entry: 9465 * rINST holds changeInterp 9466 * ecx holds glue pointer 9467 * 9468 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp) 9469 */ 9470common_gotoBail: 9471 movl rPC,offGlue_pc(%ecx) # export state to glue 9472 movl rFP,offGlue_fp(%ecx) 9473 movl %ecx,OUT_ARG0(%esp) # glue in arg0 9474 movl rINST,OUT_ARG1(%esp) # changeInterp in arg1 9475 call dvmMterpStdBail # bail out.... 9476 9477 9478/* 9479 * After returning from a "glued" function, pull out the updated values 9480 * and start executing at the next instruction. 9481 */ 9482 common_resumeAfterGlueCall: 9483 LOAD_PC_FP_FROM_GLUE 9484 FETCH_INST 9485 GOTO_NEXT 9486 9487/* 9488 * Integer divide or mod by zero 9489 */ 9490common_errDivideByZero: 9491 EXPORT_PC 9492 movl $.LstrArithmeticException,%eax 9493 movl %eax,OUT_ARG0(%esp) 9494 movl $.LstrDivideByZero,%eax 9495 movl %eax,OUT_ARG1(%esp) 9496 call dvmThrowException 9497 jmp common_exceptionThrown 9498 9499/* 9500 * Attempt to allocate an array with a negative size. 9501 */ 9502common_errNegativeArraySize: 9503 EXPORT_PC 9504 movl $.LstrNegativeArraySizeException,%eax 9505 movl %eax,OUT_ARG0(%esp) 9506 xorl %eax,%eax 9507 movl %eax,OUT_ARG1(%esp) 9508 call dvmThrowException 9509 jmp common_exceptionThrown 9510 9511/* 9512 * Attempt to allocate an array with a negative size. 9513 */ 9514common_errNoSuchMethod: 9515 9516 EXPORT_PC 9517 movl $.LstrNoSuchMethodError,%eax 9518 movl %eax,OUT_ARG0(%esp) 9519 xorl %eax,%eax 9520 movl %eax,OUT_ARG1(%esp) 9521 call dvmThrowException 9522 jmp common_exceptionThrown 9523 9524/* 9525 * Hit a null object when we weren't expecting one. Export the PC, throw a 9526 * NullPointerException and goto the exception processing code. 9527 */ 9528common_errNullObject: 9529 EXPORT_PC 9530 movl $.LstrNullPointerException,%eax 9531 movl %eax,OUT_ARG0(%esp) 9532 xorl %eax,%eax 9533 movl %eax,OUT_ARG1(%esp) 9534 call dvmThrowException 9535 jmp common_exceptionThrown 9536 9537/* 9538 * Array index exceeds max. 9539 * On entry: 9540 * eax <- array object 9541 * ecx <- index 9542 */ 9543common_errArrayIndex: 9544 EXPORT_PC 9545 movl offArrayObject_length(%eax), %eax 9546 movl %ecx,OUT_ARG0(%esp) 9547 movl %eax,OUT_ARG1(%esp) 9548 call dvmThrowAIOOBE # dvmThrowAIOO(index, length) 9549 jmp common_exceptionThrown 9550/* 9551 * Invalid array value. 9552 */ 9553common_errArrayStore: 9554 EXPORT_PC 9555 movl $.LstrArrayStoreException,%eax 9556 movl %eax,OUT_ARG0(%esp) 9557 xorl %eax,%eax 9558 movl %eax,OUT_ARG1(%esp) 9559 call dvmThrowException 9560 jmp common_exceptionThrown 9561 9562/* 9563 * Somebody has thrown an exception. Handle it. 9564 * 9565 * If the exception processing code returns to us (instead of falling 9566 * out of the interpreter), continue with whatever the next instruction 9567 * now happens to be. 9568 * 9569 * This does not return. 9570 */ 9571common_exceptionThrown: 9572 movl rGLUE,%ecx 9573 movl rPC,offGlue_pc(%ecx) 9574 movl rFP,offGlue_fp(%ecx) 9575 movl %ecx,OUT_ARG0(%esp) 9576 call dvmMterp_exceptionThrown 9577 jmp common_resumeAfterGlueCall 9578 9579common_abort: 9580 movl $0xdeadf00d,%eax 9581 call *%eax 9582 9583 9584/* 9585 * Strings 9586 */ 9587 9588 .section .rodata 9589.LstrNullPointerException: 9590 .asciz "Ljava/lang/NullPointerException;" 9591.LstrArithmeticException: 9592 .asciz "Ljava/lang/ArithmeticException;" 9593.LstrDivideByZero: 9594 .asciz "divide by zero" 9595.LstrArrayStoreException: 9596 .asciz "Ljava/lang/ArrayStoreException;" 9597.LstrNegativeArraySizeException: 9598 .asciz "Ljava/lang/NegativeArraySizeException;" 9599.LstrInstantiationError: 9600 .asciz "Ljava/lang/InstantiationError;" 9601.LstrClassCastException: 9602 .asciz "Ljava/lang/ClassCastException;" 9603.LstrNoSuchMethodError: 9604 .asciz "Ljava/lang/NoSuchMethodError;" 9605.LstrInternalErrorA: 9606 .asciz "Ljava/lang/InternalError;" 9607.LstrFilledNewArrayNotImplA: 9608 .asciz "filled-new-array only implemented for 'int'" 9609 9610