InterpAsm-x86.S revision 3b8a9072510222067b7c48fe2d59d1e58436be24
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 1943 movl offArrayObject_contents(%eax,%ecx,4),%eax 1944.LOP_AGET_finish: 1945 FETCH_INST_OPCODE 2 %edx 1946 SET_VREG %eax rINST 1947 ADVANCE_PC 2 1948 GOTO_NEXT_R %edx 1949 1950/* ------------------------------ */ 1951 .balign 64 1952.L_OP_AGET_WIDE: /* 0x45 */ 1953/* File: x86/OP_AGET_WIDE.S */ 1954 /* 1955 * Array get, 64 bits. vAA <- vBB[vCC]. 1956 * 1957 */ 1958 /* op vAA, vBB, vCC */ 1959 movzbl 2(rPC),%eax # eax<- BB 1960 movzbl 3(rPC),%ecx # ecx<- CC 1961 GET_VREG_R %eax %eax # eax<- vBB (array object) 1962 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 1963 testl %eax,%eax # null array object? 1964 je common_errNullObject # bail if so 1965 cmpl offArrayObject_length(%eax),%ecx 1966 jb .LOP_AGET_WIDE_finish # index < length, OK 1967 jmp common_errArrayIndex # index >= length, bail 1968 1969/* ------------------------------ */ 1970 .balign 64 1971.L_OP_AGET_OBJECT: /* 0x46 */ 1972/* File: x86/OP_AGET_OBJECT.S */ 1973/* File: x86/OP_AGET.S */ 1974 /* 1975 * Array get, 32 bits or less. vAA <- vBB[vCC]. 1976 * 1977 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 1978 */ 1979 /* op vAA, vBB, vCC */ 1980 movzbl 2(rPC),%eax # eax<- BB 1981 movzbl 3(rPC),%ecx # ecx<- CC 1982 GET_VREG_R %eax %eax # eax<- vBB (array object) 1983 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 1984 testl %eax,%eax # null array object? 1985 je common_errNullObject # bail if so 1986 cmpl offArrayObject_length(%eax),%ecx 1987 jae common_errArrayIndex # index >= length, bail 1988 movl offArrayObject_contents(%eax,%ecx,4),%eax 1989.LOP_AGET_OBJECT_finish: 1990 FETCH_INST_OPCODE 2 %edx 1991 SET_VREG %eax rINST 1992 ADVANCE_PC 2 1993 GOTO_NEXT_R %edx 1994 1995 1996/* ------------------------------ */ 1997 .balign 64 1998.L_OP_AGET_BOOLEAN: /* 0x47 */ 1999/* File: x86/OP_AGET_BOOLEAN.S */ 2000/* File: x86/OP_AGET.S */ 2001 /* 2002 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2003 * 2004 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2005 */ 2006 /* op vAA, vBB, vCC */ 2007 movzbl 2(rPC),%eax # eax<- BB 2008 movzbl 3(rPC),%ecx # ecx<- CC 2009 GET_VREG_R %eax %eax # eax<- vBB (array object) 2010 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2011 testl %eax,%eax # null array object? 2012 je common_errNullObject # bail if so 2013 cmpl offArrayObject_length(%eax),%ecx 2014 jae common_errArrayIndex # index >= length, bail 2015 movzbl offArrayObject_contents(%eax,%ecx,1),%eax 2016.LOP_AGET_BOOLEAN_finish: 2017 FETCH_INST_OPCODE 2 %edx 2018 SET_VREG %eax rINST 2019 ADVANCE_PC 2 2020 GOTO_NEXT_R %edx 2021 2022 2023/* ------------------------------ */ 2024 .balign 64 2025.L_OP_AGET_BYTE: /* 0x48 */ 2026/* File: x86/OP_AGET_BYTE.S */ 2027/* File: x86/OP_AGET.S */ 2028 /* 2029 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2030 * 2031 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2032 */ 2033 /* op vAA, vBB, vCC */ 2034 movzbl 2(rPC),%eax # eax<- BB 2035 movzbl 3(rPC),%ecx # ecx<- CC 2036 GET_VREG_R %eax %eax # eax<- vBB (array object) 2037 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2038 testl %eax,%eax # null array object? 2039 je common_errNullObject # bail if so 2040 cmpl offArrayObject_length(%eax),%ecx 2041 jae common_errArrayIndex # index >= length, bail 2042 movsbl offArrayObject_contents(%eax,%ecx,1),%eax 2043.LOP_AGET_BYTE_finish: 2044 FETCH_INST_OPCODE 2 %edx 2045 SET_VREG %eax rINST 2046 ADVANCE_PC 2 2047 GOTO_NEXT_R %edx 2048 2049 2050/* ------------------------------ */ 2051 .balign 64 2052.L_OP_AGET_CHAR: /* 0x49 */ 2053/* File: x86/OP_AGET_CHAR.S */ 2054/* File: x86/OP_AGET.S */ 2055 /* 2056 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2057 * 2058 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2059 */ 2060 /* op vAA, vBB, vCC */ 2061 movzbl 2(rPC),%eax # eax<- BB 2062 movzbl 3(rPC),%ecx # ecx<- CC 2063 GET_VREG_R %eax %eax # eax<- vBB (array object) 2064 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2065 testl %eax,%eax # null array object? 2066 je common_errNullObject # bail if so 2067 cmpl offArrayObject_length(%eax),%ecx 2068 jae common_errArrayIndex # index >= length, bail 2069 movzwl offArrayObject_contents(%eax,%ecx,2),%eax 2070.LOP_AGET_CHAR_finish: 2071 FETCH_INST_OPCODE 2 %edx 2072 SET_VREG %eax rINST 2073 ADVANCE_PC 2 2074 GOTO_NEXT_R %edx 2075 2076 2077/* ------------------------------ */ 2078 .balign 64 2079.L_OP_AGET_SHORT: /* 0x4a */ 2080/* File: x86/OP_AGET_SHORT.S */ 2081/* File: x86/OP_AGET.S */ 2082 /* 2083 * Array get, 32 bits or less. vAA <- vBB[vCC]. 2084 * 2085 * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short 2086 */ 2087 /* op vAA, vBB, vCC */ 2088 movzbl 2(rPC),%eax # eax<- BB 2089 movzbl 3(rPC),%ecx # ecx<- CC 2090 GET_VREG_R %eax %eax # eax<- vBB (array object) 2091 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2092 testl %eax,%eax # null array object? 2093 je common_errNullObject # bail if so 2094 cmpl offArrayObject_length(%eax),%ecx 2095 jae common_errArrayIndex # index >= length, bail 2096 movswl offArrayObject_contents(%eax,%ecx,2),%eax 2097.LOP_AGET_SHORT_finish: 2098 FETCH_INST_OPCODE 2 %edx 2099 SET_VREG %eax rINST 2100 ADVANCE_PC 2 2101 GOTO_NEXT_R %edx 2102 2103 2104/* ------------------------------ */ 2105 .balign 64 2106.L_OP_APUT: /* 0x4b */ 2107/* File: x86/OP_APUT.S */ 2108 /* 2109 * Array put, 32 bits or less. vBB[vCC] <- vAA 2110 * 2111 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short 2112 */ 2113 /* op vAA, vBB, vCC */ 2114 movzbl 2(rPC),%eax # eax<- BB 2115 movzbl 3(rPC),%ecx # ecx<- CC 2116 GET_VREG_R %eax %eax # eax<- vBB (array object) 2117 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2118 testl %eax,%eax # null array object? 2119 je common_errNullObject # bail if so 2120 cmpl offArrayObject_length(%eax),%ecx 2121 jae common_errArrayIndex # index >= length, bail 2122 leal offArrayObject_contents(%eax,%ecx,4),%eax 2123.LOP_APUT_finish: 2124 GET_VREG_R %ecx rINST 2125 FETCH_INST_OPCODE 2 %edx 2126 movl %ecx,(%eax) 2127 ADVANCE_PC 2 2128 GOTO_NEXT_R %edx 2129 2130/* ------------------------------ */ 2131 .balign 64 2132.L_OP_APUT_WIDE: /* 0x4c */ 2133/* File: x86/OP_APUT_WIDE.S */ 2134 /* 2135 * Array put, 64 bits. vBB[vCC]<-vAA. 2136 * 2137 */ 2138 /* op vAA, vBB, vCC */ 2139 movzbl 2(rPC),%eax # eax<- BB 2140 movzbl 3(rPC),%ecx # ecx<- CC 2141 GET_VREG_R %eax %eax # eax<- vBB (array object) 2142 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2143 testl %eax,%eax # null array object? 2144 je common_errNullObject # bail if so 2145 cmpl offArrayObject_length(%eax),%ecx 2146 jb .LOP_APUT_WIDE_finish # index < length, OK 2147 jmp common_errArrayIndex # index >= length, bail 2148 2149/* ------------------------------ */ 2150 .balign 64 2151.L_OP_APUT_OBJECT: /* 0x4d */ 2152/* File: x86/OP_APUT_OBJECT.S */ 2153 /* 2154 * Array put, 32 bits or less. vBB[vCC] <- vAA 2155 * 2156 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short 2157 */ 2158 /* op vAA, vBB, vCC */ 2159 movzbl 2(rPC),%eax # eax<- BB 2160 movzbl 3(rPC),%ecx # ecx<- CC 2161 GET_VREG_R %eax %eax # eax<- vBB (array object) 2162 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2163 GET_VREG_R rINST rINST # rINST<- vAA 2164 testl %eax,%eax # null array object? 2165 je common_errNullObject # bail if so 2166 cmpl offArrayObject_length(%eax),%ecx 2167 jb .LOP_APUT_OBJECT_continue 2168 jmp common_errArrayIndex # index >= length, bail 2169 2170/* ------------------------------ */ 2171 .balign 64 2172.L_OP_APUT_BOOLEAN: /* 0x4e */ 2173/* File: x86/OP_APUT_BOOLEAN.S */ 2174/* File: x86/OP_APUT.S */ 2175 /* 2176 * Array put, 32 bits or less. vBB[vCC] <- vAA 2177 * 2178 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short 2179 */ 2180 /* op vAA, vBB, vCC */ 2181 movzbl 2(rPC),%eax # eax<- BB 2182 movzbl 3(rPC),%ecx # ecx<- CC 2183 GET_VREG_R %eax %eax # eax<- vBB (array object) 2184 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2185 testl %eax,%eax # null array object? 2186 je common_errNullObject # bail if so 2187 cmpl offArrayObject_length(%eax),%ecx 2188 jae common_errArrayIndex # index >= length, bail 2189 leal offArrayObject_contents(%eax,%ecx,1),%eax 2190.LOP_APUT_BOOLEAN_finish: 2191 GET_VREG_R %ecx rINST 2192 FETCH_INST_OPCODE 2 %edx 2193 movb %cl,(%eax) 2194 ADVANCE_PC 2 2195 GOTO_NEXT_R %edx 2196 2197 2198/* ------------------------------ */ 2199 .balign 64 2200.L_OP_APUT_BYTE: /* 0x4f */ 2201/* File: x86/OP_APUT_BYTE.S */ 2202/* File: x86/OP_APUT.S */ 2203 /* 2204 * Array put, 32 bits or less. vBB[vCC] <- vAA 2205 * 2206 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short 2207 */ 2208 /* op vAA, vBB, vCC */ 2209 movzbl 2(rPC),%eax # eax<- BB 2210 movzbl 3(rPC),%ecx # ecx<- CC 2211 GET_VREG_R %eax %eax # eax<- vBB (array object) 2212 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2213 testl %eax,%eax # null array object? 2214 je common_errNullObject # bail if so 2215 cmpl offArrayObject_length(%eax),%ecx 2216 jae common_errArrayIndex # index >= length, bail 2217 leal offArrayObject_contents(%eax,%ecx,1),%eax 2218.LOP_APUT_BYTE_finish: 2219 GET_VREG_R %ecx rINST 2220 FETCH_INST_OPCODE 2 %edx 2221 movb %cl,(%eax) 2222 ADVANCE_PC 2 2223 GOTO_NEXT_R %edx 2224 2225 2226/* ------------------------------ */ 2227 .balign 64 2228.L_OP_APUT_CHAR: /* 0x50 */ 2229/* File: x86/OP_APUT_CHAR.S */ 2230/* File: x86/OP_APUT.S */ 2231 /* 2232 * Array put, 32 bits or less. vBB[vCC] <- vAA 2233 * 2234 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short 2235 */ 2236 /* op vAA, vBB, vCC */ 2237 movzbl 2(rPC),%eax # eax<- BB 2238 movzbl 3(rPC),%ecx # ecx<- CC 2239 GET_VREG_R %eax %eax # eax<- vBB (array object) 2240 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2241 testl %eax,%eax # null array object? 2242 je common_errNullObject # bail if so 2243 cmpl offArrayObject_length(%eax),%ecx 2244 jae common_errArrayIndex # index >= length, bail 2245 leal offArrayObject_contents(%eax,%ecx,2),%eax 2246.LOP_APUT_CHAR_finish: 2247 GET_VREG_R %ecx rINST 2248 FETCH_INST_OPCODE 2 %edx 2249 movw %cx,(%eax) 2250 ADVANCE_PC 2 2251 GOTO_NEXT_R %edx 2252 2253 2254/* ------------------------------ */ 2255 .balign 64 2256.L_OP_APUT_SHORT: /* 0x51 */ 2257/* File: x86/OP_APUT_SHORT.S */ 2258/* File: x86/OP_APUT.S */ 2259 /* 2260 * Array put, 32 bits or less. vBB[vCC] <- vAA 2261 * 2262 * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short 2263 */ 2264 /* op vAA, vBB, vCC */ 2265 movzbl 2(rPC),%eax # eax<- BB 2266 movzbl 3(rPC),%ecx # ecx<- CC 2267 GET_VREG_R %eax %eax # eax<- vBB (array object) 2268 GET_VREG_R %ecx %ecx # ecs<- vCC (requested index) 2269 testl %eax,%eax # null array object? 2270 je common_errNullObject # bail if so 2271 cmpl offArrayObject_length(%eax),%ecx 2272 jae common_errArrayIndex # index >= length, bail 2273 leal offArrayObject_contents(%eax,%ecx,2),%eax 2274.LOP_APUT_SHORT_finish: 2275 GET_VREG_R %ecx rINST 2276 FETCH_INST_OPCODE 2 %edx 2277 movw %cx,(%eax) 2278 ADVANCE_PC 2 2279 GOTO_NEXT_R %edx 2280 2281 2282/* ------------------------------ */ 2283 .balign 64 2284.L_OP_IGET: /* 0x52 */ 2285/* File: x86/OP_IGET.S */ 2286 /* 2287 * General 32-bit instance field get. 2288 * 2289 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2290 */ 2291 /* op vA, vB, field@CCCC */ 2292 movl rGLUE,%ecx 2293 movzwl 2(rPC),%edx # edx<- 0000CCCC 2294 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2295 movzbl rINSTbl,%ecx # ecx<- BA 2296 sarl $4,%ecx # ecx<- B 2297 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2298 andb $0xf,rINSTbl # rINST<- A 2299 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2300 movl (%eax,%edx,4),%eax # resolved entry 2301 testl %eax,%eax # is resolved entry null? 2302 jne .LOP_IGET_finish # no, already resolved 2303 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 2304 movl rGLUE,%edx 2305 jmp .LOP_IGET_resolve 2306 2307/* ------------------------------ */ 2308 .balign 64 2309.L_OP_IGET_WIDE: /* 0x53 */ 2310/* File: x86/OP_IGET_WIDE.S */ 2311 /* 2312 * 64-bit instance field get. 2313 * 2314 */ 2315 /* op vA, vB, field@CCCC */ 2316 movl rGLUE,%ecx 2317 movzwl 2(rPC),%edx # edx<- 0000CCCC 2318 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2319 movzbl rINSTbl,%ecx # ecx<- BA 2320 sarl $4,%ecx # ecx<- B 2321 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2322 andb $0xf,rINSTbl # rINST<- A 2323 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2324 movl (%eax,%edx,4),%eax # resolved entry 2325 testl %eax,%eax # is resolved entry null? 2326 jne .LOP_IGET_WIDE_finish # no, already resolved 2327 movl %edx,OUT_ARG1(%esp) # for dvmResolveInstField 2328 movl rGLUE,%edx 2329 jmp .LOP_IGET_WIDE_resolve 2330 2331/* ------------------------------ */ 2332 .balign 64 2333.L_OP_IGET_OBJECT: /* 0x54 */ 2334/* File: x86/OP_IGET_OBJECT.S */ 2335/* File: x86/OP_IGET.S */ 2336 /* 2337 * General 32-bit instance field get. 2338 * 2339 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2340 */ 2341 /* op vA, vB, field@CCCC */ 2342 movl rGLUE,%ecx 2343 movzwl 2(rPC),%edx # edx<- 0000CCCC 2344 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2345 movzbl rINSTbl,%ecx # ecx<- BA 2346 sarl $4,%ecx # ecx<- B 2347 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2348 andb $0xf,rINSTbl # rINST<- A 2349 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2350 movl (%eax,%edx,4),%eax # resolved entry 2351 testl %eax,%eax # is resolved entry null? 2352 jne .LOP_IGET_OBJECT_finish # no, already resolved 2353 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 2354 movl rGLUE,%edx 2355 jmp .LOP_IGET_OBJECT_resolve 2356 2357 2358/* ------------------------------ */ 2359 .balign 64 2360.L_OP_IGET_BOOLEAN: /* 0x55 */ 2361/* File: x86/OP_IGET_BOOLEAN.S */ 2362/* File: x86/OP_IGET.S */ 2363 /* 2364 * General 32-bit instance field get. 2365 * 2366 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2367 */ 2368 /* op vA, vB, field@CCCC */ 2369 movl rGLUE,%ecx 2370 movzwl 2(rPC),%edx # edx<- 0000CCCC 2371 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2372 movzbl rINSTbl,%ecx # ecx<- BA 2373 sarl $4,%ecx # ecx<- B 2374 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2375 andb $0xf,rINSTbl # rINST<- A 2376 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2377 movl (%eax,%edx,4),%eax # resolved entry 2378 testl %eax,%eax # is resolved entry null? 2379 jne .LOP_IGET_BOOLEAN_finish # no, already resolved 2380 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 2381 movl rGLUE,%edx 2382 jmp .LOP_IGET_BOOLEAN_resolve 2383 2384 2385/* ------------------------------ */ 2386 .balign 64 2387.L_OP_IGET_BYTE: /* 0x56 */ 2388/* File: x86/OP_IGET_BYTE.S */ 2389/* File: x86/OP_IGET.S */ 2390 /* 2391 * General 32-bit instance field get. 2392 * 2393 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2394 */ 2395 /* op vA, vB, field@CCCC */ 2396 movl rGLUE,%ecx 2397 movzwl 2(rPC),%edx # edx<- 0000CCCC 2398 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2399 movzbl rINSTbl,%ecx # ecx<- BA 2400 sarl $4,%ecx # ecx<- B 2401 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2402 andb $0xf,rINSTbl # rINST<- A 2403 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2404 movl (%eax,%edx,4),%eax # resolved entry 2405 testl %eax,%eax # is resolved entry null? 2406 jne .LOP_IGET_BYTE_finish # no, already resolved 2407 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 2408 movl rGLUE,%edx 2409 jmp .LOP_IGET_BYTE_resolve 2410 2411 2412/* ------------------------------ */ 2413 .balign 64 2414.L_OP_IGET_CHAR: /* 0x57 */ 2415/* File: x86/OP_IGET_CHAR.S */ 2416/* File: x86/OP_IGET.S */ 2417 /* 2418 * General 32-bit instance field get. 2419 * 2420 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2421 */ 2422 /* op vA, vB, field@CCCC */ 2423 movl rGLUE,%ecx 2424 movzwl 2(rPC),%edx # edx<- 0000CCCC 2425 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2426 movzbl rINSTbl,%ecx # ecx<- BA 2427 sarl $4,%ecx # ecx<- B 2428 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2429 andb $0xf,rINSTbl # rINST<- A 2430 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2431 movl (%eax,%edx,4),%eax # resolved entry 2432 testl %eax,%eax # is resolved entry null? 2433 jne .LOP_IGET_CHAR_finish # no, already resolved 2434 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 2435 movl rGLUE,%edx 2436 jmp .LOP_IGET_CHAR_resolve 2437 2438 2439/* ------------------------------ */ 2440 .balign 64 2441.L_OP_IGET_SHORT: /* 0x58 */ 2442/* File: x86/OP_IGET_SHORT.S */ 2443/* File: x86/OP_IGET.S */ 2444 /* 2445 * General 32-bit instance field get. 2446 * 2447 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 2448 */ 2449 /* op vA, vB, field@CCCC */ 2450 movl rGLUE,%ecx 2451 movzwl 2(rPC),%edx # edx<- 0000CCCC 2452 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2453 movzbl rINSTbl,%ecx # ecx<- BA 2454 sarl $4,%ecx # ecx<- B 2455 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2456 andb $0xf,rINSTbl # rINST<- A 2457 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2458 movl (%eax,%edx,4),%eax # resolved entry 2459 testl %eax,%eax # is resolved entry null? 2460 jne .LOP_IGET_SHORT_finish # no, already resolved 2461 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 2462 movl rGLUE,%edx 2463 jmp .LOP_IGET_SHORT_resolve 2464 2465 2466/* ------------------------------ */ 2467 .balign 64 2468.L_OP_IPUT: /* 0x59 */ 2469/* File: x86/OP_IPUT.S */ 2470 2471 /* 2472 * General 32-bit instance field put. 2473 * 2474 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2475 */ 2476 /* op vA, vB, field@CCCC */ 2477 movl rGLUE,%ecx 2478 movzwl 2(rPC),%edx # %edx<- 0000CCCC 2479 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2480 movzbl rINSTbl,%ecx # ecx<- BA 2481 sarl $4,%ecx # ecx<- B 2482 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2483 andb $0xf,rINSTbl # rINST<- A 2484 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2485 movl (%eax,%edx,4),%eax # resolved entry 2486 testl %eax,%eax # is resolved entry null? 2487 jne .LOP_IPUT_finish # no, already resolved 2488 movl %edx,OUT_ARG1(%esp) 2489 movl rGLUE,%edx 2490 jmp .LOP_IPUT_resolve 2491 2492/* ------------------------------ */ 2493 .balign 64 2494.L_OP_IPUT_WIDE: /* 0x5a */ 2495/* File: x86/OP_IPUT_WIDE.S */ 2496 /* 2497 * 64-bit instance field put. 2498 * 2499 */ 2500 /* op vA, vB, field@CCCC */ 2501 movl rGLUE,%ecx 2502 movzwl 2(rPC),%edx # edx<- 0000CCCC 2503 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2504 movzbl rINSTbl,%ecx # ecx<- BA 2505 sarl $4,%ecx # ecx<- B 2506 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2507 andb $0xf,rINSTbl # rINST<- A 2508 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2509 movl (%eax,%edx,4),%eax # resolved entry 2510 testl %eax,%eax # is resolved entry null? 2511 jne .LOP_IPUT_WIDE_finish # no, already resolved 2512 movl %edx,OUT_ARG1(%esp) 2513 movl rGLUE,%edx 2514 jmp .LOP_IPUT_WIDE_resolve 2515 2516/* ------------------------------ */ 2517 .balign 64 2518.L_OP_IPUT_OBJECT: /* 0x5b */ 2519/* File: x86/OP_IPUT_OBJECT.S */ 2520 /* 2521 * Object field put. 2522 * 2523 * for: iput-object 2524 */ 2525 /* op vA, vB, field@CCCC */ 2526 movl rGLUE,%ecx 2527 movzwl 2(rPC),%edx # edx<- 0000CCCC 2528 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2529 movzbl rINSTbl,%ecx # ecx<- BA 2530 sarl $4,%ecx # ecx<- B 2531 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2532 andb $0xf,rINSTbl # rINST<- A 2533 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2534 movl (%eax,%edx,4),%eax # resolved entry 2535 testl %eax,%eax # is resolved entry null? 2536 jne .LOP_IPUT_OBJECT_finish # no, already resolved 2537 movl %edx,OUT_ARG1(%esp) 2538 movl rGLUE,%edx 2539 jmp .LOP_IPUT_OBJECT_resolve 2540 2541/* ------------------------------ */ 2542 .balign 64 2543.L_OP_IPUT_BOOLEAN: /* 0x5c */ 2544/* File: x86/OP_IPUT_BOOLEAN.S */ 2545/* File: x86/OP_IPUT.S */ 2546 2547 /* 2548 * General 32-bit instance field put. 2549 * 2550 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short 2551 */ 2552 /* op vA, vB, field@CCCC */ 2553 movl rGLUE,%ecx 2554 movzwl 2(rPC),%edx # %edx<- 0000CCCC 2555 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 2556 movzbl rINSTbl,%ecx # ecx<- BA 2557 sarl $4,%ecx # ecx<- B 2558 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 2559 andb $0xf,rINSTbl # rINST<- A 2560 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 2561 movl (%eax,%edx,4),%eax # resolved entry 2562 testl %eax,%eax # is resolved entry null? 2563 jne .LOP_IPUT_BOOLEAN_finish # no, already resolved 2564 movl %edx,OUT_ARG1(%esp) 2565 movl rGLUE,%edx 2566 jmp .LOP_IPUT_BOOLEAN_resolve 2567 2568 2569/* ------------------------------ */ 2570 .balign 64 2571.L_OP_IPUT_BYTE: /* 0x5d */ 2572/* File: x86/OP_IPUT_BYTE.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_BYTE_finish # no, already resolved 2592 movl %edx,OUT_ARG1(%esp) 2593 movl rGLUE,%edx 2594 jmp .LOP_IPUT_BYTE_resolve 2595 2596 2597/* ------------------------------ */ 2598 .balign 64 2599.L_OP_IPUT_CHAR: /* 0x5e */ 2600/* File: x86/OP_IPUT_CHAR.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_CHAR_finish # no, already resolved 2620 movl %edx,OUT_ARG1(%esp) 2621 movl rGLUE,%edx 2622 jmp .LOP_IPUT_CHAR_resolve 2623 2624 2625/* ------------------------------ */ 2626 .balign 64 2627.L_OP_IPUT_SHORT: /* 0x5f */ 2628/* File: x86/OP_IPUT_SHORT.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_SHORT_finish # no, already resolved 2648 movl %edx,OUT_ARG1(%esp) 2649 movl rGLUE,%edx 2650 jmp .LOP_IPUT_SHORT_resolve 2651 2652 2653/* ------------------------------ */ 2654 .balign 64 2655.L_OP_SGET: /* 0x60 */ 2656/* File: x86/OP_SGET.S */ 2657 /* 2658 * General 32-bit SGET handler. 2659 * 2660 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2661 */ 2662 /* op vAA, field@BBBB */ 2663 movl rGLUE,%ecx 2664 movzwl 2(rPC),%eax # eax<- field ref BBBB 2665 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2666 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2667 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2668 testl %eax,%eax # resolved entry null? 2669 je .LOP_SGET_resolve # if not, make it so 2670.LOP_SGET_finish: # field ptr in eax 2671 movl offStaticField_value(%eax),%eax 2672 FETCH_INST_OPCODE 2 %edx 2673 ADVANCE_PC 2 2674 SET_VREG %eax rINST 2675 GOTO_NEXT_R %edx 2676 2677/* ------------------------------ */ 2678 .balign 64 2679.L_OP_SGET_WIDE: /* 0x61 */ 2680/* File: x86/OP_SGET_WIDE.S */ 2681 /* 2682 * 64-bit SGET handler. 2683 * 2684 */ 2685 /* sget-wide vAA, field@BBBB */ 2686 movl rGLUE,%ecx 2687 movzwl 2(rPC),%eax # eax<- field ref BBBB 2688 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2689 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2690 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2691 testl %eax,%eax # resolved entry null? 2692 je .LOP_SGET_WIDE_resolve # if not, make it so 2693.LOP_SGET_WIDE_finish: # field ptr in eax 2694 movl offStaticField_value(%eax),%ecx # ecx<- lsw 2695 movl 4+offStaticField_value(%eax),%eax # eax<- msw 2696 FETCH_INST_OPCODE 2 %edx 2697 ADVANCE_PC 2 2698 SET_VREG_WORD %ecx rINST 0 2699 SET_VREG_WORD %eax rINST 1 2700 GOTO_NEXT_R %edx 2701 2702/* ------------------------------ */ 2703 .balign 64 2704.L_OP_SGET_OBJECT: /* 0x62 */ 2705/* File: x86/OP_SGET_OBJECT.S */ 2706/* File: x86/OP_SGET.S */ 2707 /* 2708 * General 32-bit SGET handler. 2709 * 2710 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2711 */ 2712 /* op vAA, field@BBBB */ 2713 movl rGLUE,%ecx 2714 movzwl 2(rPC),%eax # eax<- field ref BBBB 2715 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2716 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2717 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2718 testl %eax,%eax # resolved entry null? 2719 je .LOP_SGET_OBJECT_resolve # if not, make it so 2720.LOP_SGET_OBJECT_finish: # field ptr in eax 2721 movl offStaticField_value(%eax),%eax 2722 FETCH_INST_OPCODE 2 %edx 2723 ADVANCE_PC 2 2724 SET_VREG %eax rINST 2725 GOTO_NEXT_R %edx 2726 2727 2728/* ------------------------------ */ 2729 .balign 64 2730.L_OP_SGET_BOOLEAN: /* 0x63 */ 2731/* File: x86/OP_SGET_BOOLEAN.S */ 2732/* File: x86/OP_SGET.S */ 2733 /* 2734 * General 32-bit SGET handler. 2735 * 2736 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2737 */ 2738 /* op vAA, field@BBBB */ 2739 movl rGLUE,%ecx 2740 movzwl 2(rPC),%eax # eax<- field ref BBBB 2741 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2742 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2743 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2744 testl %eax,%eax # resolved entry null? 2745 je .LOP_SGET_BOOLEAN_resolve # if not, make it so 2746.LOP_SGET_BOOLEAN_finish: # field ptr in eax 2747 movl offStaticField_value(%eax),%eax 2748 FETCH_INST_OPCODE 2 %edx 2749 ADVANCE_PC 2 2750 SET_VREG %eax rINST 2751 GOTO_NEXT_R %edx 2752 2753 2754/* ------------------------------ */ 2755 .balign 64 2756.L_OP_SGET_BYTE: /* 0x64 */ 2757/* File: x86/OP_SGET_BYTE.S */ 2758/* File: x86/OP_SGET.S */ 2759 /* 2760 * General 32-bit SGET handler. 2761 * 2762 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2763 */ 2764 /* op vAA, field@BBBB */ 2765 movl rGLUE,%ecx 2766 movzwl 2(rPC),%eax # eax<- field ref BBBB 2767 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2768 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2769 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2770 testl %eax,%eax # resolved entry null? 2771 je .LOP_SGET_BYTE_resolve # if not, make it so 2772.LOP_SGET_BYTE_finish: # field ptr in eax 2773 movl offStaticField_value(%eax),%eax 2774 FETCH_INST_OPCODE 2 %edx 2775 ADVANCE_PC 2 2776 SET_VREG %eax rINST 2777 GOTO_NEXT_R %edx 2778 2779 2780/* ------------------------------ */ 2781 .balign 64 2782.L_OP_SGET_CHAR: /* 0x65 */ 2783/* File: x86/OP_SGET_CHAR.S */ 2784/* File: x86/OP_SGET.S */ 2785 /* 2786 * General 32-bit SGET handler. 2787 * 2788 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2789 */ 2790 /* op vAA, field@BBBB */ 2791 movl rGLUE,%ecx 2792 movzwl 2(rPC),%eax # eax<- field ref BBBB 2793 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2794 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2795 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2796 testl %eax,%eax # resolved entry null? 2797 je .LOP_SGET_CHAR_resolve # if not, make it so 2798.LOP_SGET_CHAR_finish: # field ptr in eax 2799 movl offStaticField_value(%eax),%eax 2800 FETCH_INST_OPCODE 2 %edx 2801 ADVANCE_PC 2 2802 SET_VREG %eax rINST 2803 GOTO_NEXT_R %edx 2804 2805 2806/* ------------------------------ */ 2807 .balign 64 2808.L_OP_SGET_SHORT: /* 0x66 */ 2809/* File: x86/OP_SGET_SHORT.S */ 2810/* File: x86/OP_SGET.S */ 2811 /* 2812 * General 32-bit SGET handler. 2813 * 2814 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 2815 */ 2816 /* op vAA, field@BBBB */ 2817 movl rGLUE,%ecx 2818 movzwl 2(rPC),%eax # eax<- field ref BBBB 2819 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2820 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2821 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2822 testl %eax,%eax # resolved entry null? 2823 je .LOP_SGET_SHORT_resolve # if not, make it so 2824.LOP_SGET_SHORT_finish: # field ptr in eax 2825 movl offStaticField_value(%eax),%eax 2826 FETCH_INST_OPCODE 2 %edx 2827 ADVANCE_PC 2 2828 SET_VREG %eax rINST 2829 GOTO_NEXT_R %edx 2830 2831 2832/* ------------------------------ */ 2833 .balign 64 2834.L_OP_SPUT: /* 0x67 */ 2835/* File: x86/OP_SPUT.S */ 2836 /* 2837 * General 32-bit SPUT handler. 2838 * 2839 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2840 */ 2841 /* op vAA, field@BBBB */ 2842 movl rGLUE,%ecx 2843 movzwl 2(rPC),%eax # eax<- field ref BBBB 2844 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2845 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2846 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2847 testl %eax,%eax # resolved entry null? 2848 je .LOP_SPUT_resolve # if not, make it so 2849.LOP_SPUT_finish: # field ptr in eax 2850 GET_VREG_R %ecx rINST 2851 FETCH_INST_OPCODE 2 %edx 2852 ADVANCE_PC 2 2853 movl %ecx,offStaticField_value(%eax) 2854 GOTO_NEXT_R %edx 2855 2856/* ------------------------------ */ 2857 .balign 64 2858.L_OP_SPUT_WIDE: /* 0x68 */ 2859/* File: x86/OP_SPUT_WIDE.S */ 2860 /* 2861 * General 32-bit SPUT handler. 2862 * 2863 * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short 2864 */ 2865 /* op vAA, field@BBBB */ 2866 movl rGLUE,%ecx 2867 movzwl 2(rPC),%eax # eax<- field ref BBBB 2868 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2869 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2870 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2871 testl %eax,%eax # resolved entry null? 2872 je .LOP_SPUT_WIDE_resolve # if not, make it so 2873.LOP_SPUT_WIDE_finish: # field ptr in eax 2874 GET_VREG_WORD %ecx rINST 0 # rINST<- lsw 2875 GET_VREG_WORD rINST rINST 1 # ecx<- msw 2876 FETCH_INST_OPCODE 2 %edx 2877 ADVANCE_PC 2 2878 movl %ecx,offStaticField_value(%eax) 2879 movl rINST,4+offStaticField_value(%eax) 2880 GOTO_NEXT_R %edx 2881 2882/* ------------------------------ */ 2883 .balign 64 2884.L_OP_SPUT_OBJECT: /* 0x69 */ 2885/* File: x86/OP_SPUT_OBJECT.S */ 2886 /* 2887 * SPUT object handler. 2888 */ 2889 /* op vAA, field@BBBB */ 2890 movl rGLUE,%ecx 2891 movzwl 2(rPC),%eax # eax<- field ref BBBB 2892 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2893 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2894 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField 2895 testl %eax,%eax # resolved entry null? 2896 je .LOP_SPUT_OBJECT_resolve # if not, make it so 2897.LOP_SPUT_OBJECT_finish: # field ptr in eax 2898 movzbl rINSTbl,%ecx # ecx<- AA 2899 GET_VREG_R %ecx %ecx 2900 jmp .LOP_SPUT_OBJECT_continue 2901 2902/* ------------------------------ */ 2903 .balign 64 2904.L_OP_SPUT_BOOLEAN: /* 0x6a */ 2905/* File: x86/OP_SPUT_BOOLEAN.S */ 2906/* File: x86/OP_SPUT.S */ 2907 /* 2908 * General 32-bit SPUT handler. 2909 * 2910 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2911 */ 2912 /* op vAA, field@BBBB */ 2913 movl rGLUE,%ecx 2914 movzwl 2(rPC),%eax # eax<- field ref BBBB 2915 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2916 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2917 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2918 testl %eax,%eax # resolved entry null? 2919 je .LOP_SPUT_BOOLEAN_resolve # if not, make it so 2920.LOP_SPUT_BOOLEAN_finish: # field ptr in eax 2921 GET_VREG_R %ecx rINST 2922 FETCH_INST_OPCODE 2 %edx 2923 ADVANCE_PC 2 2924 movl %ecx,offStaticField_value(%eax) 2925 GOTO_NEXT_R %edx 2926 2927 2928/* ------------------------------ */ 2929 .balign 64 2930.L_OP_SPUT_BYTE: /* 0x6b */ 2931/* File: x86/OP_SPUT_BYTE.S */ 2932/* File: x86/OP_SPUT.S */ 2933 /* 2934 * General 32-bit SPUT handler. 2935 * 2936 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2937 */ 2938 /* op vAA, field@BBBB */ 2939 movl rGLUE,%ecx 2940 movzwl 2(rPC),%eax # eax<- field ref BBBB 2941 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2942 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2943 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2944 testl %eax,%eax # resolved entry null? 2945 je .LOP_SPUT_BYTE_resolve # if not, make it so 2946.LOP_SPUT_BYTE_finish: # field ptr in eax 2947 GET_VREG_R %ecx rINST 2948 FETCH_INST_OPCODE 2 %edx 2949 ADVANCE_PC 2 2950 movl %ecx,offStaticField_value(%eax) 2951 GOTO_NEXT_R %edx 2952 2953 2954/* ------------------------------ */ 2955 .balign 64 2956.L_OP_SPUT_CHAR: /* 0x6c */ 2957/* File: x86/OP_SPUT_CHAR.S */ 2958/* File: x86/OP_SPUT.S */ 2959 /* 2960 * General 32-bit SPUT handler. 2961 * 2962 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2963 */ 2964 /* op vAA, field@BBBB */ 2965 movl rGLUE,%ecx 2966 movzwl 2(rPC),%eax # eax<- field ref BBBB 2967 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2968 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2969 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2970 testl %eax,%eax # resolved entry null? 2971 je .LOP_SPUT_CHAR_resolve # if not, make it so 2972.LOP_SPUT_CHAR_finish: # field ptr in eax 2973 GET_VREG_R %ecx rINST 2974 FETCH_INST_OPCODE 2 %edx 2975 ADVANCE_PC 2 2976 movl %ecx,offStaticField_value(%eax) 2977 GOTO_NEXT_R %edx 2978 2979 2980/* ------------------------------ */ 2981 .balign 64 2982.L_OP_SPUT_SHORT: /* 0x6d */ 2983/* File: x86/OP_SPUT_SHORT.S */ 2984/* File: x86/OP_SPUT.S */ 2985 /* 2986 * General 32-bit SPUT handler. 2987 * 2988 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 2989 */ 2990 /* op vAA, field@BBBB */ 2991 movl rGLUE,%ecx 2992 movzwl 2(rPC),%eax # eax<- field ref BBBB 2993 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 2994 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 2995 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 2996 testl %eax,%eax # resolved entry null? 2997 je .LOP_SPUT_SHORT_resolve # if not, make it so 2998.LOP_SPUT_SHORT_finish: # field ptr in eax 2999 GET_VREG_R %ecx rINST 3000 FETCH_INST_OPCODE 2 %edx 3001 ADVANCE_PC 2 3002 movl %ecx,offStaticField_value(%eax) 3003 GOTO_NEXT_R %edx 3004 3005 3006/* ------------------------------ */ 3007 .balign 64 3008.L_OP_INVOKE_VIRTUAL: /* 0x6e */ 3009/* File: x86/OP_INVOKE_VIRTUAL.S */ 3010 3011 /* 3012 * Handle a virtual method call. 3013 * 3014 * for: invoke-virtual, invoke-virtual/range 3015 */ 3016 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3017 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3018 movl rGLUE,%eax 3019 movzwl 2(rPC),%ecx # ecx<- BBBB 3020 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex 3021 EXPORT_PC 3022 movl offDvmDex_pResMethods(%eax),%eax # eax<- pDvmDex->pResMethods 3023 movl (%eax,%ecx,4),%eax # eax<- resolved baseMethod 3024 testl %eax,%eax # already resolved? 3025 jne .LOP_INVOKE_VIRTUAL_continue # yes, continue 3026 movl rGLUE,%eax 3027 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 3028 movl offGlue_method(%eax),%eax # eax<- glue->method 3029 jmp .LOP_INVOKE_VIRTUAL_more 3030 3031/* ------------------------------ */ 3032 .balign 64 3033.L_OP_INVOKE_SUPER: /* 0x6f */ 3034/* File: x86/OP_INVOKE_SUPER.S */ 3035 /* 3036 * Handle a "super" method call. 3037 * 3038 * for: invoke-super, invoke-super/range 3039 */ 3040 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3041 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3042 movl rGLUE,rINST 3043 movzwl 2(rPC),%eax # eax<- BBBB 3044 movl offGlue_methodClassDex(rINST),%ecx # ecx<- pDvmDex 3045 EXPORT_PC 3046 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 3047 movl (%ecx,%eax,4),%ecx # ecx<- resolved baseMethod 3048 movl offGlue_method(rINST),%eax # eax<- method 3049 movzwl 4(rPC),rINST # rINST<- GFED or CCCC 3050 .if (!0) 3051 andl $0xf,rINST # rINST<- D (or stays CCCC) 3052 .endif 3053 GET_VREG_R rINST rINST # rINST<- "this" ptr 3054 testl rINST,rINST # null "this"? 3055 je common_errNullObject # yes, throw 3056 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 3057 testl %ecx,%ecx # already resolved? 3058 jne .LOP_INVOKE_SUPER_continue # yes - go on 3059 jmp .LOP_INVOKE_SUPER_resolve 3060 3061/* ------------------------------ */ 3062 .balign 64 3063.L_OP_INVOKE_DIRECT: /* 0x70 */ 3064/* File: x86/OP_INVOKE_DIRECT.S */ 3065 /* 3066 * Handle a direct method call. 3067 * 3068 * (We could defer the "is 'this' pointer null" test to the common 3069 * method invocation code, and use a flag to indicate that static 3070 * calls don't count. If we do this as part of copying the arguments 3071 * out we could avoiding loading the first arg twice.) 3072 * 3073 * for: invoke-direct, invoke-direct/range 3074 */ 3075 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3076 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3077 movl rGLUE,%ecx 3078 movzwl 2(rPC),%eax # eax<- BBBB 3079 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 3080 EXPORT_PC 3081 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 3082 movzwl 4(rPC),%edx # edx<- GFED or CCCC 3083 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall 3084 .if (!0) 3085 andl $0xf,%edx # edx<- D (or stays CCCC) 3086 .endif 3087 testl %eax,%eax # already resolved? 3088 GET_VREG_R %ecx %edx # ecx<- "this" ptr 3089 je .LOP_INVOKE_DIRECT_resolve # not resolved, do it now 3090.LOP_INVOKE_DIRECT_finish: 3091 testl %ecx,%ecx # null "this"? 3092 jne common_invokeMethodNoRange # no, continue on 3093 jmp common_errNullObject 3094 3095/* ------------------------------ */ 3096 .balign 64 3097.L_OP_INVOKE_STATIC: /* 0x71 */ 3098/* File: x86/OP_INVOKE_STATIC.S */ 3099 /* 3100 * Handle a static method call. 3101 * 3102 * for: invoke-static, invoke-static/range 3103 */ 3104 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3105 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3106 movl rGLUE,%ecx 3107 movzwl 2(rPC),%eax # eax<- BBBB 3108 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 3109 EXPORT_PC 3110 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 3111 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall 3112 testl %eax,%eax 3113 jne common_invokeMethodNoRange 3114 movl rGLUE,%ecx 3115 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 3116 movzwl 2(rPC),%eax 3117 movl offMethod_clazz(%ecx),%ecx# ecx<- method->clazz 3118 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 3119 movl %ecx,OUT_ARG0(%esp) # arg0<- clazz 3120 jmp .LOP_INVOKE_STATIC_continue 3121 3122/* ------------------------------ */ 3123 .balign 64 3124.L_OP_INVOKE_INTERFACE: /* 0x72 */ 3125/* File: x86/OP_INVOKE_INTERFACE.S */ 3126 /* 3127 * Handle an interface method call. 3128 * 3129 * for: invoke-interface, invoke-interface/range 3130 */ 3131 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3132 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3133 movzwl 4(rPC),%eax # eax<- FEDC or CCCC 3134 movl rGLUE,%ecx 3135 .if (!0) 3136 andl $0xf,%eax # eax<- C (or stays CCCC) 3137 .endif 3138 GET_VREG_R %eax %eax # eax<- "this" 3139 EXPORT_PC 3140 testl %eax,%eax # null this? 3141 je common_errNullObject # yes, fail 3142 movl offObject_clazz(%eax),%eax# eax<- thisPtr->clazz 3143 movl %eax,OUT_ARG0(%esp) # arg0<- class 3144 movl offGlue_methodClassDex(%ecx),%eax # eax<- methodClassDex 3145 movl offGlue_method(%ecx),%ecx # ecx<- method 3146 movl %eax,OUT_ARG3(%esp) # arg3<- dex 3147 movzwl 2(rPC),%eax # eax<- BBBB 3148 movl %ecx,OUT_ARG2(%esp) # arg2<- method 3149 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 3150 jmp .LOP_INVOKE_INTERFACE_continue 3151 3152/* ------------------------------ */ 3153 .balign 64 3154.L_OP_UNUSED_73: /* 0x73 */ 3155/* File: x86/OP_UNUSED_73.S */ 3156/* File: x86/unused.S */ 3157 jmp common_abort 3158 3159 3160/* ------------------------------ */ 3161 .balign 64 3162.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */ 3163/* File: x86/OP_INVOKE_VIRTUAL_RANGE.S */ 3164/* File: x86/OP_INVOKE_VIRTUAL.S */ 3165 3166 /* 3167 * Handle a virtual method call. 3168 * 3169 * for: invoke-virtual, invoke-virtual/range 3170 */ 3171 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3172 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3173 movl rGLUE,%eax 3174 movzwl 2(rPC),%ecx # ecx<- BBBB 3175 movl offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex 3176 EXPORT_PC 3177 movl offDvmDex_pResMethods(%eax),%eax # eax<- pDvmDex->pResMethods 3178 movl (%eax,%ecx,4),%eax # eax<- resolved baseMethod 3179 testl %eax,%eax # already resolved? 3180 jne .LOP_INVOKE_VIRTUAL_RANGE_continue # yes, continue 3181 movl rGLUE,%eax 3182 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 3183 movl offGlue_method(%eax),%eax # eax<- glue->method 3184 jmp .LOP_INVOKE_VIRTUAL_RANGE_more 3185 3186 3187/* ------------------------------ */ 3188 .balign 64 3189.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */ 3190/* File: x86/OP_INVOKE_SUPER_RANGE.S */ 3191/* File: x86/OP_INVOKE_SUPER.S */ 3192 /* 3193 * Handle a "super" method call. 3194 * 3195 * for: invoke-super, invoke-super/range 3196 */ 3197 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3198 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3199 movl rGLUE,rINST 3200 movzwl 2(rPC),%eax # eax<- BBBB 3201 movl offGlue_methodClassDex(rINST),%ecx # ecx<- pDvmDex 3202 EXPORT_PC 3203 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 3204 movl (%ecx,%eax,4),%ecx # ecx<- resolved baseMethod 3205 movl offGlue_method(rINST),%eax # eax<- method 3206 movzwl 4(rPC),rINST # rINST<- GFED or CCCC 3207 .if (!1) 3208 andl $0xf,rINST # rINST<- D (or stays CCCC) 3209 .endif 3210 GET_VREG_R rINST rINST # rINST<- "this" ptr 3211 testl rINST,rINST # null "this"? 3212 je common_errNullObject # yes, throw 3213 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 3214 testl %ecx,%ecx # already resolved? 3215 jne .LOP_INVOKE_SUPER_RANGE_continue # yes - go on 3216 jmp .LOP_INVOKE_SUPER_RANGE_resolve 3217 3218 3219/* ------------------------------ */ 3220 .balign 64 3221.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */ 3222/* File: x86/OP_INVOKE_DIRECT_RANGE.S */ 3223/* File: x86/OP_INVOKE_DIRECT.S */ 3224 /* 3225 * Handle a direct method call. 3226 * 3227 * (We could defer the "is 'this' pointer null" test to the common 3228 * method invocation code, and use a flag to indicate that static 3229 * calls don't count. If we do this as part of copying the arguments 3230 * out we could avoiding loading the first arg twice.) 3231 * 3232 * for: invoke-direct, invoke-direct/range 3233 */ 3234 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3235 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3236 movl rGLUE,%ecx 3237 movzwl 2(rPC),%eax # eax<- BBBB 3238 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 3239 EXPORT_PC 3240 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 3241 movzwl 4(rPC),%edx # edx<- GFED or CCCC 3242 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall 3243 .if (!1) 3244 andl $0xf,%edx # edx<- D (or stays CCCC) 3245 .endif 3246 testl %eax,%eax # already resolved? 3247 GET_VREG_R %ecx %edx # ecx<- "this" ptr 3248 je .LOP_INVOKE_DIRECT_RANGE_resolve # not resolved, do it now 3249.LOP_INVOKE_DIRECT_RANGE_finish: 3250 testl %ecx,%ecx # null "this"? 3251 jne common_invokeMethodRange # no, continue on 3252 jmp common_errNullObject 3253 3254 3255/* ------------------------------ */ 3256 .balign 64 3257.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */ 3258/* File: x86/OP_INVOKE_STATIC_RANGE.S */ 3259/* File: x86/OP_INVOKE_STATIC.S */ 3260 /* 3261 * Handle a static method call. 3262 * 3263 * for: invoke-static, invoke-static/range 3264 */ 3265 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3266 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3267 movl rGLUE,%ecx 3268 movzwl 2(rPC),%eax # eax<- BBBB 3269 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex 3270 EXPORT_PC 3271 movl offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods 3272 movl (%ecx,%eax,4),%eax # eax<- resolved methodToCall 3273 testl %eax,%eax 3274 jne common_invokeMethodRange 3275 movl rGLUE,%ecx 3276 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 3277 movzwl 2(rPC),%eax 3278 movl offMethod_clazz(%ecx),%ecx# ecx<- method->clazz 3279 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 3280 movl %ecx,OUT_ARG0(%esp) # arg0<- clazz 3281 jmp .LOP_INVOKE_STATIC_RANGE_continue 3282 3283 3284/* ------------------------------ */ 3285 .balign 64 3286.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */ 3287/* File: x86/OP_INVOKE_INTERFACE_RANGE.S */ 3288/* File: x86/OP_INVOKE_INTERFACE.S */ 3289 /* 3290 * Handle an interface method call. 3291 * 3292 * for: invoke-interface, invoke-interface/range 3293 */ 3294 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 3295 /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 3296 movzwl 4(rPC),%eax # eax<- FEDC or CCCC 3297 movl rGLUE,%ecx 3298 .if (!1) 3299 andl $0xf,%eax # eax<- C (or stays CCCC) 3300 .endif 3301 GET_VREG_R %eax %eax # eax<- "this" 3302 EXPORT_PC 3303 testl %eax,%eax # null this? 3304 je common_errNullObject # yes, fail 3305 movl offObject_clazz(%eax),%eax# eax<- thisPtr->clazz 3306 movl %eax,OUT_ARG0(%esp) # arg0<- class 3307 movl offGlue_methodClassDex(%ecx),%eax # eax<- methodClassDex 3308 movl offGlue_method(%ecx),%ecx # ecx<- method 3309 movl %eax,OUT_ARG3(%esp) # arg3<- dex 3310 movzwl 2(rPC),%eax # eax<- BBBB 3311 movl %ecx,OUT_ARG2(%esp) # arg2<- method 3312 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 3313 jmp .LOP_INVOKE_INTERFACE_RANGE_continue 3314 3315 3316/* ------------------------------ */ 3317 .balign 64 3318.L_OP_UNUSED_79: /* 0x79 */ 3319/* File: x86/OP_UNUSED_79.S */ 3320/* File: x86/unused.S */ 3321 jmp common_abort 3322 3323 3324/* ------------------------------ */ 3325 .balign 64 3326.L_OP_UNUSED_7A: /* 0x7a */ 3327/* File: x86/OP_UNUSED_7A.S */ 3328/* File: x86/unused.S */ 3329 jmp common_abort 3330 3331 3332/* ------------------------------ */ 3333 .balign 64 3334.L_OP_NEG_INT: /* 0x7b */ 3335/* File: x86/OP_NEG_INT.S */ 3336/* File: x86/unop.S */ 3337 /* 3338 * Generic 32-bit unary operation. Provide an "instr" line that 3339 * specifies an instruction that performs "result = op eax". 3340 */ 3341 /* unop vA, vB */ 3342 movzbl rINSTbl,%ecx # ecx<- A+ 3343 sarl $4,rINST # rINST<- B 3344 GET_VREG_R %eax rINST # eax<- vB 3345 andb $0xf,%cl # ecx<- A 3346 FETCH_INST_OPCODE 1 %edx 3347 ADVANCE_PC 1 3348 3349 3350 negl %eax 3351 SET_VREG %eax %ecx 3352 GOTO_NEXT_R %edx 3353 3354 3355/* ------------------------------ */ 3356 .balign 64 3357.L_OP_NOT_INT: /* 0x7c */ 3358/* File: x86/OP_NOT_INT.S */ 3359/* File: x86/unop.S */ 3360 /* 3361 * Generic 32-bit unary operation. Provide an "instr" line that 3362 * specifies an instruction that performs "result = op eax". 3363 */ 3364 /* unop vA, vB */ 3365 movzbl rINSTbl,%ecx # ecx<- A+ 3366 sarl $4,rINST # rINST<- B 3367 GET_VREG_R %eax rINST # eax<- vB 3368 andb $0xf,%cl # ecx<- A 3369 FETCH_INST_OPCODE 1 %edx 3370 ADVANCE_PC 1 3371 3372 3373 notl %eax 3374 SET_VREG %eax %ecx 3375 GOTO_NEXT_R %edx 3376 3377 3378/* ------------------------------ */ 3379 .balign 64 3380.L_OP_NEG_LONG: /* 0x7d */ 3381/* File: x86/OP_NEG_LONG.S */ 3382 /* unop vA, vB */ 3383 movzbl rINSTbl,%ecx # ecx<- BA 3384 sarl $4,%ecx # ecx<- B 3385 andb $0xf,rINSTbl # rINST<- A 3386 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0] 3387 GET_VREG_WORD %ecx %ecx 1 # ecx<- v[B+1] 3388 negl %eax 3389 adcl $0,%ecx 3390 negl %ecx 3391 FETCH_INST_OPCODE 1 %edx 3392 SET_VREG_WORD %eax rINST 0 # v[A+0]<- eax 3393 SET_VREG_WORD %ecx rINST 1 # v[A+1]<- ecx 3394 ADVANCE_PC 1 3395 GOTO_NEXT_R %edx 3396 3397/* ------------------------------ */ 3398 .balign 64 3399.L_OP_NOT_LONG: /* 0x7e */ 3400/* File: x86/OP_NOT_LONG.S */ 3401 /* unop vA, vB */ 3402 movzbl rINSTbl,%ecx # ecx<- BA 3403 sarl $4,%ecx # ecx<- B 3404 andb $0xf,rINSTbl # rINST<- A 3405 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0] 3406 GET_VREG_WORD %ecx %ecx 1 # ecx<- v[B+1] 3407 FETCH_INST_OPCODE 1 %edx 3408 notl %eax 3409 notl %ecx 3410 SET_VREG_WORD %eax rINST 0 # v[A+0]<- eax 3411 SET_VREG_WORD %ecx rINST 1 # v[A+1]<- ecx 3412 ADVANCE_PC 1 3413 GOTO_NEXT_R %edx 3414 3415/* ------------------------------ */ 3416 .balign 64 3417.L_OP_NEG_FLOAT: /* 0x7f */ 3418/* File: x86/OP_NEG_FLOAT.S */ 3419/* File: x86/fpcvt.S */ 3420 /* 3421 * Generic 32-bit FP conversion operation. 3422 */ 3423 /* unop vA, vB */ 3424 movzbl rINSTbl,%ecx # ecx<- A+ 3425 sarl $4,rINST # rINST<- B 3426 flds (rFP,rINST,4) # %st0<- vB 3427 andb $0xf,%cl # ecx<- A 3428 FETCH_INST_OPCODE 1 %edx 3429 ADVANCE_PC 1 3430 fchs 3431 fstps (rFP,%ecx,4) # vA<- %st0 3432 GOTO_NEXT_R %edx 3433 3434 3435/* ------------------------------ */ 3436 .balign 64 3437.L_OP_NEG_DOUBLE: /* 0x80 */ 3438/* File: x86/OP_NEG_DOUBLE.S */ 3439/* File: x86/fpcvt.S */ 3440 /* 3441 * Generic 32-bit FP conversion operation. 3442 */ 3443 /* unop vA, vB */ 3444 movzbl rINSTbl,%ecx # ecx<- A+ 3445 sarl $4,rINST # rINST<- B 3446 fldl (rFP,rINST,4) # %st0<- vB 3447 andb $0xf,%cl # ecx<- A 3448 FETCH_INST_OPCODE 1 %edx 3449 ADVANCE_PC 1 3450 fchs 3451 fstpl (rFP,%ecx,4) # vA<- %st0 3452 GOTO_NEXT_R %edx 3453 3454 3455/* ------------------------------ */ 3456 .balign 64 3457.L_OP_INT_TO_LONG: /* 0x81 */ 3458/* File: x86/OP_INT_TO_LONG.S */ 3459 /* int to long vA, vB */ 3460 movzbl rINSTbl,%eax # eax<- +A 3461 sarl $4,%eax # eax<- B 3462 GET_VREG_R %eax %eax # eax<- vB 3463 andb $0xf,rINSTbl # rINST<- A 3464 cltd # edx:eax<- sssssssBBBBBBBB 3465 SET_VREG_WORD %edx rINST 1 # v[A+1]<- edx/rPC 3466 FETCH_INST_OPCODE 1 %edx 3467 SET_VREG_WORD %eax rINST 0 # v[A+0]<- %eax 3468 ADVANCE_PC 1 3469 GOTO_NEXT_R %edx 3470 3471/* ------------------------------ */ 3472 .balign 64 3473.L_OP_INT_TO_FLOAT: /* 0x82 */ 3474/* File: x86/OP_INT_TO_FLOAT.S */ 3475/* File: x86/fpcvt.S */ 3476 /* 3477 * Generic 32-bit FP conversion operation. 3478 */ 3479 /* unop vA, vB */ 3480 movzbl rINSTbl,%ecx # ecx<- A+ 3481 sarl $4,rINST # rINST<- B 3482 fildl (rFP,rINST,4) # %st0<- vB 3483 andb $0xf,%cl # ecx<- A 3484 FETCH_INST_OPCODE 1 %edx 3485 ADVANCE_PC 1 3486 3487 fstps (rFP,%ecx,4) # vA<- %st0 3488 GOTO_NEXT_R %edx 3489 3490 3491/* ------------------------------ */ 3492 .balign 64 3493.L_OP_INT_TO_DOUBLE: /* 0x83 */ 3494/* File: x86/OP_INT_TO_DOUBLE.S */ 3495/* File: x86/fpcvt.S */ 3496 /* 3497 * Generic 32-bit FP conversion operation. 3498 */ 3499 /* unop vA, vB */ 3500 movzbl rINSTbl,%ecx # ecx<- A+ 3501 sarl $4,rINST # rINST<- B 3502 fildl (rFP,rINST,4) # %st0<- vB 3503 andb $0xf,%cl # ecx<- A 3504 FETCH_INST_OPCODE 1 %edx 3505 ADVANCE_PC 1 3506 3507 fstpl (rFP,%ecx,4) # vA<- %st0 3508 GOTO_NEXT_R %edx 3509 3510 3511/* ------------------------------ */ 3512 .balign 64 3513.L_OP_LONG_TO_INT: /* 0x84 */ 3514/* File: x86/OP_LONG_TO_INT.S */ 3515/* we ignore the high word, making this equivalent to a 32-bit reg move */ 3516/* File: x86/OP_MOVE.S */ 3517 /* for move, move-object, long-to-int */ 3518 /* op vA, vB */ 3519 movzbl rINSTbl,%eax # eax<- BA 3520 andb $0xf,%al # eax<- A 3521 shrl $4,rINST # rINST<- B 3522 GET_VREG_R %ecx rINST 3523 FETCH_INST_OPCODE 1 %edx 3524 ADVANCE_PC 1 3525 SET_VREG %ecx %eax # fp[A]<-fp[B] 3526 GOTO_NEXT_R %edx 3527 3528 3529/* ------------------------------ */ 3530 .balign 64 3531.L_OP_LONG_TO_FLOAT: /* 0x85 */ 3532/* File: x86/OP_LONG_TO_FLOAT.S */ 3533/* File: x86/fpcvt.S */ 3534 /* 3535 * Generic 32-bit FP conversion operation. 3536 */ 3537 /* unop vA, vB */ 3538 movzbl rINSTbl,%ecx # ecx<- A+ 3539 sarl $4,rINST # rINST<- B 3540 fildll (rFP,rINST,4) # %st0<- vB 3541 andb $0xf,%cl # ecx<- A 3542 FETCH_INST_OPCODE 1 %edx 3543 ADVANCE_PC 1 3544 3545 fstps (rFP,%ecx,4) # vA<- %st0 3546 GOTO_NEXT_R %edx 3547 3548 3549/* ------------------------------ */ 3550 .balign 64 3551.L_OP_LONG_TO_DOUBLE: /* 0x86 */ 3552/* File: x86/OP_LONG_TO_DOUBLE.S */ 3553/* File: x86/fpcvt.S */ 3554 /* 3555 * Generic 32-bit FP conversion operation. 3556 */ 3557 /* unop vA, vB */ 3558 movzbl rINSTbl,%ecx # ecx<- A+ 3559 sarl $4,rINST # rINST<- B 3560 fildll (rFP,rINST,4) # %st0<- vB 3561 andb $0xf,%cl # ecx<- A 3562 FETCH_INST_OPCODE 1 %edx 3563 ADVANCE_PC 1 3564 3565 fstpl (rFP,%ecx,4) # vA<- %st0 3566 GOTO_NEXT_R %edx 3567 3568 3569/* ------------------------------ */ 3570 .balign 64 3571.L_OP_FLOAT_TO_INT: /* 0x87 */ 3572/* File: x86/OP_FLOAT_TO_INT.S */ 3573/* File: x86/cvtfp_int.S */ 3574/* On fp to int conversions, Java requires that 3575 * if the result > maxint, it should be clamped to maxint. If it is less 3576 * than minint, it should be clamped to minint. If it is a nan, the result 3577 * should be zero. Further, the rounding mode is to truncate. This model 3578 * differs from what is delivered normally via the x86 fpu, so we have 3579 * to play some games. 3580 */ 3581 /* float/double to int/long vA, vB */ 3582 movzbl rINSTbl,%ecx # ecx<- A+ 3583 sarl $4,rINST # rINST<- B 3584 .if 0 3585 fldl (rFP,rINST,4) # %st0<- vB 3586 .else 3587 flds (rFP,rINST,4) # %st0<- vB 3588 .endif 3589 ftst 3590 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode 3591 movzwl LOCAL0_OFFSET(%ebp),%eax 3592 movb $0xc,%ah 3593 movw %ax,LOCAL0_OFFSET+2(%ebp) 3594 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode 3595 FETCH_INST_OPCODE 1 %edx 3596 andb $0xf,%cl # ecx<- A 3597 .if 0 3598 fistpll (rFP,%ecx,4) # convert and store 3599 .else 3600 fistpl (rFP,%ecx,4) # convert and store 3601 .endif 3602 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode 3603 jmp .LOP_FLOAT_TO_INT_continue 3604 3605 3606/* ------------------------------ */ 3607 .balign 64 3608.L_OP_FLOAT_TO_LONG: /* 0x88 */ 3609/* File: x86/OP_FLOAT_TO_LONG.S */ 3610/* File: x86/cvtfp_int.S */ 3611/* On fp to int conversions, Java requires that 3612 * if the result > maxint, it should be clamped to maxint. If it is less 3613 * than minint, it should be clamped to minint. If it is a nan, the result 3614 * should be zero. Further, the rounding mode is to truncate. This model 3615 * differs from what is delivered normally via the x86 fpu, so we have 3616 * to play some games. 3617 */ 3618 /* float/double to int/long vA, vB */ 3619 movzbl rINSTbl,%ecx # ecx<- A+ 3620 sarl $4,rINST # rINST<- B 3621 .if 0 3622 fldl (rFP,rINST,4) # %st0<- vB 3623 .else 3624 flds (rFP,rINST,4) # %st0<- vB 3625 .endif 3626 ftst 3627 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode 3628 movzwl LOCAL0_OFFSET(%ebp),%eax 3629 movb $0xc,%ah 3630 movw %ax,LOCAL0_OFFSET+2(%ebp) 3631 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode 3632 FETCH_INST_OPCODE 1 %edx 3633 andb $0xf,%cl # ecx<- A 3634 .if 1 3635 fistpll (rFP,%ecx,4) # convert and store 3636 .else 3637 fistpl (rFP,%ecx,4) # convert and store 3638 .endif 3639 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode 3640 jmp .LOP_FLOAT_TO_LONG_continue 3641 3642 3643/* ------------------------------ */ 3644 .balign 64 3645.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */ 3646/* File: x86/OP_FLOAT_TO_DOUBLE.S */ 3647/* File: x86/fpcvt.S */ 3648 /* 3649 * Generic 32-bit FP conversion operation. 3650 */ 3651 /* unop vA, vB */ 3652 movzbl rINSTbl,%ecx # ecx<- A+ 3653 sarl $4,rINST # rINST<- B 3654 flds (rFP,rINST,4) # %st0<- vB 3655 andb $0xf,%cl # ecx<- A 3656 FETCH_INST_OPCODE 1 %edx 3657 ADVANCE_PC 1 3658 3659 fstpl (rFP,%ecx,4) # vA<- %st0 3660 GOTO_NEXT_R %edx 3661 3662 3663/* ------------------------------ */ 3664 .balign 64 3665.L_OP_DOUBLE_TO_INT: /* 0x8a */ 3666/* File: x86/OP_DOUBLE_TO_INT.S */ 3667/* File: x86/cvtfp_int.S */ 3668/* On fp to int conversions, Java requires that 3669 * if the result > maxint, it should be clamped to maxint. If it is less 3670 * than minint, it should be clamped to minint. If it is a nan, the result 3671 * should be zero. Further, the rounding mode is to truncate. This model 3672 * differs from what is delivered normally via the x86 fpu, so we have 3673 * to play some games. 3674 */ 3675 /* float/double to int/long vA, vB */ 3676 movzbl rINSTbl,%ecx # ecx<- A+ 3677 sarl $4,rINST # rINST<- B 3678 .if 1 3679 fldl (rFP,rINST,4) # %st0<- vB 3680 .else 3681 flds (rFP,rINST,4) # %st0<- vB 3682 .endif 3683 ftst 3684 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode 3685 movzwl LOCAL0_OFFSET(%ebp),%eax 3686 movb $0xc,%ah 3687 movw %ax,LOCAL0_OFFSET+2(%ebp) 3688 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode 3689 FETCH_INST_OPCODE 1 %edx 3690 andb $0xf,%cl # ecx<- A 3691 .if 0 3692 fistpll (rFP,%ecx,4) # convert and store 3693 .else 3694 fistpl (rFP,%ecx,4) # convert and store 3695 .endif 3696 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode 3697 jmp .LOP_DOUBLE_TO_INT_continue 3698 3699 3700/* ------------------------------ */ 3701 .balign 64 3702.L_OP_DOUBLE_TO_LONG: /* 0x8b */ 3703/* File: x86/OP_DOUBLE_TO_LONG.S */ 3704/* File: x86/cvtfp_int.S */ 3705/* On fp to int conversions, Java requires that 3706 * if the result > maxint, it should be clamped to maxint. If it is less 3707 * than minint, it should be clamped to minint. If it is a nan, the result 3708 * should be zero. Further, the rounding mode is to truncate. This model 3709 * differs from what is delivered normally via the x86 fpu, so we have 3710 * to play some games. 3711 */ 3712 /* float/double to int/long vA, vB */ 3713 movzbl rINSTbl,%ecx # ecx<- A+ 3714 sarl $4,rINST # rINST<- B 3715 .if 1 3716 fldl (rFP,rINST,4) # %st0<- vB 3717 .else 3718 flds (rFP,rINST,4) # %st0<- vB 3719 .endif 3720 ftst 3721 fnstcw LOCAL0_OFFSET(%ebp) # remember original rounding mode 3722 movzwl LOCAL0_OFFSET(%ebp),%eax 3723 movb $0xc,%ah 3724 movw %ax,LOCAL0_OFFSET+2(%ebp) 3725 fldcw LOCAL0_OFFSET+2(%ebp) # set "to zero" rounding mode 3726 FETCH_INST_OPCODE 1 %edx 3727 andb $0xf,%cl # ecx<- A 3728 .if 1 3729 fistpll (rFP,%ecx,4) # convert and store 3730 .else 3731 fistpl (rFP,%ecx,4) # convert and store 3732 .endif 3733 fldcw LOCAL0_OFFSET(%ebp) # restore previous rounding mode 3734 jmp .LOP_DOUBLE_TO_LONG_continue 3735 3736 3737/* ------------------------------ */ 3738 .balign 64 3739.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */ 3740/* File: x86/OP_DOUBLE_TO_FLOAT.S */ 3741/* File: x86/fpcvt.S */ 3742 /* 3743 * Generic 32-bit FP conversion operation. 3744 */ 3745 /* unop vA, vB */ 3746 movzbl rINSTbl,%ecx # ecx<- A+ 3747 sarl $4,rINST # rINST<- B 3748 fldl (rFP,rINST,4) # %st0<- vB 3749 andb $0xf,%cl # ecx<- A 3750 FETCH_INST_OPCODE 1 %edx 3751 ADVANCE_PC 1 3752 3753 fstps (rFP,%ecx,4) # vA<- %st0 3754 GOTO_NEXT_R %edx 3755 3756 3757/* ------------------------------ */ 3758 .balign 64 3759.L_OP_INT_TO_BYTE: /* 0x8d */ 3760/* File: x86/OP_INT_TO_BYTE.S */ 3761/* File: x86/unop.S */ 3762 /* 3763 * Generic 32-bit unary operation. Provide an "instr" line that 3764 * specifies an instruction that performs "result = op eax". 3765 */ 3766 /* unop vA, vB */ 3767 movzbl rINSTbl,%ecx # ecx<- A+ 3768 sarl $4,rINST # rINST<- B 3769 GET_VREG_R %eax rINST # eax<- vB 3770 andb $0xf,%cl # ecx<- A 3771 FETCH_INST_OPCODE 1 %edx 3772 ADVANCE_PC 1 3773 3774 3775 movsbl %al,%eax 3776 SET_VREG %eax %ecx 3777 GOTO_NEXT_R %edx 3778 3779 3780/* ------------------------------ */ 3781 .balign 64 3782.L_OP_INT_TO_CHAR: /* 0x8e */ 3783/* File: x86/OP_INT_TO_CHAR.S */ 3784/* File: x86/unop.S */ 3785 /* 3786 * Generic 32-bit unary operation. Provide an "instr" line that 3787 * specifies an instruction that performs "result = op eax". 3788 */ 3789 /* unop vA, vB */ 3790 movzbl rINSTbl,%ecx # ecx<- A+ 3791 sarl $4,rINST # rINST<- B 3792 GET_VREG_R %eax rINST # eax<- vB 3793 andb $0xf,%cl # ecx<- A 3794 FETCH_INST_OPCODE 1 %edx 3795 ADVANCE_PC 1 3796 3797 3798 movzwl %ax,%eax 3799 SET_VREG %eax %ecx 3800 GOTO_NEXT_R %edx 3801 3802 3803/* ------------------------------ */ 3804 .balign 64 3805.L_OP_INT_TO_SHORT: /* 0x8f */ 3806/* File: x86/OP_INT_TO_SHORT.S */ 3807/* File: x86/unop.S */ 3808 /* 3809 * Generic 32-bit unary operation. Provide an "instr" line that 3810 * specifies an instruction that performs "result = op eax". 3811 */ 3812 /* unop vA, vB */ 3813 movzbl rINSTbl,%ecx # ecx<- A+ 3814 sarl $4,rINST # rINST<- B 3815 GET_VREG_R %eax rINST # eax<- vB 3816 andb $0xf,%cl # ecx<- A 3817 FETCH_INST_OPCODE 1 %edx 3818 ADVANCE_PC 1 3819 3820 3821 movswl %ax,%eax 3822 SET_VREG %eax %ecx 3823 GOTO_NEXT_R %edx 3824 3825 3826/* ------------------------------ */ 3827 .balign 64 3828.L_OP_ADD_INT: /* 0x90 */ 3829/* File: x86/OP_ADD_INT.S */ 3830/* File: x86/binop.S */ 3831 /* 3832 * Generic 32-bit binary operation. Provide an "instr" line that 3833 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 3834 * This could be an x86 instruction or a function call. (If the result 3835 * comes back in a register other than eax, you can override "result".) 3836 * 3837 * For: add-int, sub-int, and-int, or-int, 3838 * xor-int, shl-int, shr-int, ushr-int 3839 */ 3840 /* binop vAA, vBB, vCC */ 3841 movzbl 2(rPC),%eax # eax<- BB 3842 movzbl 3(rPC),%ecx # ecx<- CC 3843 GET_VREG_R %eax %eax # eax<- vBB 3844 addl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax 3845 FETCH_INST_OPCODE 2 %edx 3846 ADVANCE_PC 2 3847 SET_VREG %eax rINST 3848 GOTO_NEXT_R %edx 3849 3850 3851/* ------------------------------ */ 3852 .balign 64 3853.L_OP_SUB_INT: /* 0x91 */ 3854/* File: x86/OP_SUB_INT.S */ 3855/* File: x86/binop.S */ 3856 /* 3857 * Generic 32-bit binary operation. Provide an "instr" line that 3858 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 3859 * This could be an x86 instruction or a function call. (If the result 3860 * comes back in a register other than eax, you can override "result".) 3861 * 3862 * For: add-int, sub-int, and-int, or-int, 3863 * xor-int, shl-int, shr-int, ushr-int 3864 */ 3865 /* binop vAA, vBB, vCC */ 3866 movzbl 2(rPC),%eax # eax<- BB 3867 movzbl 3(rPC),%ecx # ecx<- CC 3868 GET_VREG_R %eax %eax # eax<- vBB 3869 subl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax 3870 FETCH_INST_OPCODE 2 %edx 3871 ADVANCE_PC 2 3872 SET_VREG %eax rINST 3873 GOTO_NEXT_R %edx 3874 3875 3876/* ------------------------------ */ 3877 .balign 64 3878.L_OP_MUL_INT: /* 0x92 */ 3879/* File: x86/OP_MUL_INT.S */ 3880 /* 3881 * 32-bit binary multiplication. 3882 */ 3883 /* mul vAA, vBB, vCC */ 3884 movzbl 2(rPC),%eax # eax<- BB 3885 movzbl 3(rPC),%ecx # ecx<- CC 3886 GET_VREG_R %eax %eax # eax<- vBB 3887 imull (rFP,%ecx,4),%eax # trashes edx 3888 FETCH_INST_OPCODE 2 %edx 3889 ADVANCE_PC 2 3890 SET_VREG %eax rINST 3891 GOTO_NEXT_R %edx 3892 3893/* ------------------------------ */ 3894 .balign 64 3895.L_OP_DIV_INT: /* 0x93 */ 3896/* File: x86/OP_DIV_INT.S */ 3897/* File: x86/bindiv.S */ 3898 3899 /* 3900 * 32-bit binary div/rem operation. Handles special case of op0=minint and 3901 * op1=-1. 3902 */ 3903 /* binop vAA, vBB, vCC */ 3904 movzbl 2(rPC),%eax # eax<- BB 3905 movzbl 3(rPC),%ecx # ecx<- CC 3906 GET_VREG_R %eax %eax # eax<- vBB 3907 GET_VREG_R %ecx %ecx # eax<- vBB 3908 cmpl $0,%ecx 3909 je common_errDivideByZero 3910 cmpl $-1,%ecx 3911 jne .LOP_DIV_INT_continue_div 3912 cmpl $0x80000000,%eax 3913 jne .LOP_DIV_INT_continue_div 3914 movl $0x80000000,%eax 3915 jmp .LOP_DIV_INT_finish_div 3916 3917 3918 3919/* ------------------------------ */ 3920 .balign 64 3921.L_OP_REM_INT: /* 0x94 */ 3922/* File: x86/OP_REM_INT.S */ 3923/* File: x86/bindiv.S */ 3924 3925 /* 3926 * 32-bit binary div/rem operation. Handles special case of op0=minint and 3927 * op1=-1. 3928 */ 3929 /* binop vAA, vBB, vCC */ 3930 movzbl 2(rPC),%eax # eax<- BB 3931 movzbl 3(rPC),%ecx # ecx<- CC 3932 GET_VREG_R %eax %eax # eax<- vBB 3933 GET_VREG_R %ecx %ecx # eax<- vBB 3934 cmpl $0,%ecx 3935 je common_errDivideByZero 3936 cmpl $-1,%ecx 3937 jne .LOP_REM_INT_continue_div 3938 cmpl $0x80000000,%eax 3939 jne .LOP_REM_INT_continue_div 3940 movl $0,%edx 3941 jmp .LOP_REM_INT_finish_div 3942 3943 3944 3945/* ------------------------------ */ 3946 .balign 64 3947.L_OP_AND_INT: /* 0x95 */ 3948/* File: x86/OP_AND_INT.S */ 3949/* File: x86/binop.S */ 3950 /* 3951 * Generic 32-bit binary operation. Provide an "instr" line that 3952 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 3953 * This could be an x86 instruction or a function call. (If the result 3954 * comes back in a register other than eax, you can override "result".) 3955 * 3956 * For: add-int, sub-int, and-int, or-int, 3957 * xor-int, shl-int, shr-int, ushr-int 3958 */ 3959 /* binop vAA, vBB, vCC */ 3960 movzbl 2(rPC),%eax # eax<- BB 3961 movzbl 3(rPC),%ecx # ecx<- CC 3962 GET_VREG_R %eax %eax # eax<- vBB 3963 andl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax 3964 FETCH_INST_OPCODE 2 %edx 3965 ADVANCE_PC 2 3966 SET_VREG %eax rINST 3967 GOTO_NEXT_R %edx 3968 3969 3970/* ------------------------------ */ 3971 .balign 64 3972.L_OP_OR_INT: /* 0x96 */ 3973/* File: x86/OP_OR_INT.S */ 3974/* File: x86/binop.S */ 3975 /* 3976 * Generic 32-bit binary operation. Provide an "instr" line that 3977 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 3978 * This could be an x86 instruction or a function call. (If the result 3979 * comes back in a register other than eax, you can override "result".) 3980 * 3981 * For: add-int, sub-int, and-int, or-int, 3982 * xor-int, shl-int, shr-int, ushr-int 3983 */ 3984 /* binop vAA, vBB, vCC */ 3985 movzbl 2(rPC),%eax # eax<- BB 3986 movzbl 3(rPC),%ecx # ecx<- CC 3987 GET_VREG_R %eax %eax # eax<- vBB 3988 orl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax 3989 FETCH_INST_OPCODE 2 %edx 3990 ADVANCE_PC 2 3991 SET_VREG %eax rINST 3992 GOTO_NEXT_R %edx 3993 3994 3995/* ------------------------------ */ 3996 .balign 64 3997.L_OP_XOR_INT: /* 0x97 */ 3998/* File: x86/OP_XOR_INT.S */ 3999/* File: x86/binop.S */ 4000 /* 4001 * Generic 32-bit binary operation. Provide an "instr" line that 4002 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)". 4003 * This could be an x86 instruction or a function call. (If the result 4004 * comes back in a register other than eax, you can override "result".) 4005 * 4006 * For: add-int, sub-int, and-int, or-int, 4007 * xor-int, shl-int, shr-int, ushr-int 4008 */ 4009 /* binop vAA, vBB, vCC */ 4010 movzbl 2(rPC),%eax # eax<- BB 4011 movzbl 3(rPC),%ecx # ecx<- CC 4012 GET_VREG_R %eax %eax # eax<- vBB 4013 xorl (rFP,%ecx,4),%eax # ex: addl (rFP,%ecx,4),%eax 4014 FETCH_INST_OPCODE 2 %edx 4015 ADVANCE_PC 2 4016 SET_VREG %eax rINST 4017 GOTO_NEXT_R %edx 4018 4019 4020/* ------------------------------ */ 4021 .balign 64 4022.L_OP_SHL_INT: /* 0x98 */ 4023/* File: x86/OP_SHL_INT.S */ 4024/* File: x86/binop1.S */ 4025 /* 4026 * Generic 32-bit binary operation in which both operands loaded to 4027 * registers (op0 in eax, op1 in ecx). 4028 */ 4029 /* binop vAA, vBB, vCC */ 4030 movzbl 2(rPC),%eax # eax<- BB 4031 movzbl 3(rPC),%ecx # ecx<- CC 4032 GET_VREG_R %eax %eax # eax<- vBB 4033 GET_VREG_R %ecx %ecx # eax<- vBB 4034 sall %cl,%eax # ex: addl %ecx,%eax 4035 FETCH_INST_OPCODE 2 %edx 4036 ADVANCE_PC 2 4037 SET_VREG %eax rINST 4038 GOTO_NEXT_R %edx 4039 4040 4041/* ------------------------------ */ 4042 .balign 64 4043.L_OP_SHR_INT: /* 0x99 */ 4044/* File: x86/OP_SHR_INT.S */ 4045/* File: x86/binop1.S */ 4046 /* 4047 * Generic 32-bit binary operation in which both operands loaded to 4048 * registers (op0 in eax, op1 in ecx). 4049 */ 4050 /* binop vAA, vBB, vCC */ 4051 movzbl 2(rPC),%eax # eax<- BB 4052 movzbl 3(rPC),%ecx # ecx<- CC 4053 GET_VREG_R %eax %eax # eax<- vBB 4054 GET_VREG_R %ecx %ecx # eax<- vBB 4055 sarl %cl,%eax # ex: addl %ecx,%eax 4056 FETCH_INST_OPCODE 2 %edx 4057 ADVANCE_PC 2 4058 SET_VREG %eax rINST 4059 GOTO_NEXT_R %edx 4060 4061 4062/* ------------------------------ */ 4063 .balign 64 4064.L_OP_USHR_INT: /* 0x9a */ 4065/* File: x86/OP_USHR_INT.S */ 4066/* File: x86/binop1.S */ 4067 /* 4068 * Generic 32-bit binary operation in which both operands loaded to 4069 * registers (op0 in eax, op1 in ecx). 4070 */ 4071 /* binop vAA, vBB, vCC */ 4072 movzbl 2(rPC),%eax # eax<- BB 4073 movzbl 3(rPC),%ecx # ecx<- CC 4074 GET_VREG_R %eax %eax # eax<- vBB 4075 GET_VREG_R %ecx %ecx # eax<- vBB 4076 shrl %cl,%eax # ex: addl %ecx,%eax 4077 FETCH_INST_OPCODE 2 %edx 4078 ADVANCE_PC 2 4079 SET_VREG %eax rINST 4080 GOTO_NEXT_R %edx 4081 4082 4083/* ------------------------------ */ 4084 .balign 64 4085.L_OP_ADD_LONG: /* 0x9b */ 4086/* File: x86/OP_ADD_LONG.S */ 4087/* File: x86/binopWide.S */ 4088 /* 4089 * Generic 64-bit binary operation. 4090 */ 4091 /* binop vAA, vBB, vCC */ 4092 4093 movzbl 2(rPC),%eax # eax<- BB 4094 movzbl 3(rPC),%ecx # ecx<- CC 4095 GET_VREG_WORD %edx %eax 0 # edx<- v[BB+0] 4096 GET_VREG_WORD %eax %eax 1 # eax<- v[BB+1] 4097 addl (rFP,%ecx,4),%edx # ex: addl (rFP,%ecx,4),%edx 4098 adcl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax 4099 SET_VREG_WORD %edx rINST 0 # v[AA+0] <- edx 4100 FETCH_INST_OPCODE 2 %edx 4101 SET_VREG_WORD %eax rINST 1 # v[AA+1] <- eax 4102 ADVANCE_PC 2 4103 GOTO_NEXT_R %edx 4104 4105 4106/* ------------------------------ */ 4107 .balign 64 4108.L_OP_SUB_LONG: /* 0x9c */ 4109/* File: x86/OP_SUB_LONG.S */ 4110/* File: x86/binopWide.S */ 4111 /* 4112 * Generic 64-bit binary operation. 4113 */ 4114 /* binop vAA, vBB, vCC */ 4115 4116 movzbl 2(rPC),%eax # eax<- BB 4117 movzbl 3(rPC),%ecx # ecx<- CC 4118 GET_VREG_WORD %edx %eax 0 # edx<- v[BB+0] 4119 GET_VREG_WORD %eax %eax 1 # eax<- v[BB+1] 4120 subl (rFP,%ecx,4),%edx # ex: addl (rFP,%ecx,4),%edx 4121 sbbl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax 4122 SET_VREG_WORD %edx rINST 0 # v[AA+0] <- edx 4123 FETCH_INST_OPCODE 2 %edx 4124 SET_VREG_WORD %eax rINST 1 # v[AA+1] <- eax 4125 ADVANCE_PC 2 4126 GOTO_NEXT_R %edx 4127 4128 4129/* ------------------------------ */ 4130 .balign 64 4131.L_OP_MUL_LONG: /* 0x9d */ 4132/* File: x86/OP_MUL_LONG.S */ 4133 /* 4134 * Signed 64-bit integer multiply. 4135 * 4136 * We could definately use more free registers for 4137 * this code. We spill rINSTw (ebx), 4138 * giving us eax, ebc, ecx and edx as computational 4139 * temps. On top of that, we'll spill edi (rFP) 4140 * for use as the vB pointer and esi (rPC) for use 4141 * as the vC pointer. Yuck. 4142 */ 4143 /* mul-long vAA, vBB, vCC */ 4144 movzbl 2(rPC),%eax # eax<- B 4145 movzbl 3(rPC),%ecx # ecx<- C 4146 SPILL_TMP2(%esi) # save Dalvik PC 4147 SPILL(rFP) 4148 SPILL(rINST) 4149 leal (rFP,%eax,4),%esi # esi<- &v[B] 4150 leal (rFP,%ecx,4),rFP # rFP<- &v[C] 4151 movl 4(%esi),%ecx # ecx<- Bmsw 4152 imull (rFP),%ecx # ecx<- (Bmsw*Clsw) 4153 movl 4(rFP),%eax # eax<- Cmsw 4154 imull (%esi),%eax # eax<- (Cmsw*Blsw) 4155 addl %eax,%ecx # ecx<- (Bmsw*Clsw)+(Cmsw*Blsw) 4156 movl (rFP),%eax # eax<- Clsw 4157 mull (%esi) # eax<- (Clsw*Alsw) 4158 UNSPILL(rINST) 4159 UNSPILL(rFP) 4160 jmp .LOP_MUL_LONG_continue 4161 4162/* ------------------------------ */ 4163 .balign 64 4164.L_OP_DIV_LONG: /* 0x9e */ 4165/* File: x86/OP_DIV_LONG.S */ 4166 /* div vAA, vBB, vCC */ 4167 movzbl 3(rPC),%eax # eax<- CC 4168 movzbl 2(rPC),%ecx # ecx<- BB 4169 GET_VREG_WORD %edx %eax 0 4170 GET_VREG_WORD %eax %eax 1 4171 movl %edx,OUT_ARG2(%esp) 4172 testl %eax,%eax 4173 je .LOP_DIV_LONG_check_zero 4174 cmpl $-1,%eax 4175 je .LOP_DIV_LONG_check_neg1 4176.LOP_DIV_LONG_notSpecial: 4177 GET_VREG_WORD %edx %ecx 0 4178 GET_VREG_WORD %ecx %ecx 1 4179.LOP_DIV_LONG_notSpecial1: 4180 movl %eax,OUT_ARG3(%esp) 4181 movl %edx,OUT_ARG0(%esp) 4182 movl %ecx,OUT_ARG1(%esp) 4183 jmp .LOP_DIV_LONG_continue 4184 4185/* ------------------------------ */ 4186 .balign 64 4187.L_OP_REM_LONG: /* 0x9f */ 4188/* File: x86/OP_REM_LONG.S */ 4189/* File: x86/OP_DIV_LONG.S */ 4190 /* div vAA, vBB, vCC */ 4191 movzbl 3(rPC),%eax # eax<- CC 4192 movzbl 2(rPC),%ecx # ecx<- BB 4193 GET_VREG_WORD %edx %eax 0 4194 GET_VREG_WORD %eax %eax 1 4195 movl %edx,OUT_ARG2(%esp) 4196 testl %eax,%eax 4197 je .LOP_REM_LONG_check_zero 4198 cmpl $-1,%eax 4199 je .LOP_REM_LONG_check_neg1 4200.LOP_REM_LONG_notSpecial: 4201 GET_VREG_WORD %edx %ecx 0 4202 GET_VREG_WORD %ecx %ecx 1 4203.LOP_REM_LONG_notSpecial1: 4204 movl %eax,OUT_ARG3(%esp) 4205 movl %edx,OUT_ARG0(%esp) 4206 movl %ecx,OUT_ARG1(%esp) 4207 jmp .LOP_REM_LONG_continue 4208 4209 4210/* ------------------------------ */ 4211 .balign 64 4212.L_OP_AND_LONG: /* 0xa0 */ 4213/* File: x86/OP_AND_LONG.S */ 4214/* File: x86/binopWide.S */ 4215 /* 4216 * Generic 64-bit binary operation. 4217 */ 4218 /* binop vAA, vBB, vCC */ 4219 4220 movzbl 2(rPC),%eax # eax<- BB 4221 movzbl 3(rPC),%ecx # ecx<- CC 4222 GET_VREG_WORD %edx %eax 0 # edx<- v[BB+0] 4223 GET_VREG_WORD %eax %eax 1 # eax<- v[BB+1] 4224 andl (rFP,%ecx,4),%edx # ex: addl (rFP,%ecx,4),%edx 4225 andl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax 4226 SET_VREG_WORD %edx rINST 0 # v[AA+0] <- edx 4227 FETCH_INST_OPCODE 2 %edx 4228 SET_VREG_WORD %eax rINST 1 # v[AA+1] <- eax 4229 ADVANCE_PC 2 4230 GOTO_NEXT_R %edx 4231 4232 4233/* ------------------------------ */ 4234 .balign 64 4235.L_OP_OR_LONG: /* 0xa1 */ 4236/* File: x86/OP_OR_LONG.S */ 4237/* File: x86/binopWide.S */ 4238 /* 4239 * Generic 64-bit binary operation. 4240 */ 4241 /* binop vAA, vBB, vCC */ 4242 4243 movzbl 2(rPC),%eax # eax<- BB 4244 movzbl 3(rPC),%ecx # ecx<- CC 4245 GET_VREG_WORD %edx %eax 0 # edx<- v[BB+0] 4246 GET_VREG_WORD %eax %eax 1 # eax<- v[BB+1] 4247 orl (rFP,%ecx,4),%edx # ex: addl (rFP,%ecx,4),%edx 4248 orl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax 4249 SET_VREG_WORD %edx rINST 0 # v[AA+0] <- edx 4250 FETCH_INST_OPCODE 2 %edx 4251 SET_VREG_WORD %eax rINST 1 # v[AA+1] <- eax 4252 ADVANCE_PC 2 4253 GOTO_NEXT_R %edx 4254 4255 4256/* ------------------------------ */ 4257 .balign 64 4258.L_OP_XOR_LONG: /* 0xa2 */ 4259/* File: x86/OP_XOR_LONG.S */ 4260/* File: x86/binopWide.S */ 4261 /* 4262 * Generic 64-bit binary operation. 4263 */ 4264 /* binop vAA, vBB, vCC */ 4265 4266 movzbl 2(rPC),%eax # eax<- BB 4267 movzbl 3(rPC),%ecx # ecx<- CC 4268 GET_VREG_WORD %edx %eax 0 # edx<- v[BB+0] 4269 GET_VREG_WORD %eax %eax 1 # eax<- v[BB+1] 4270 xorl (rFP,%ecx,4),%edx # ex: addl (rFP,%ecx,4),%edx 4271 xorl 4(rFP,%ecx,4),%eax # ex: adcl 4(rFP,%ecx,4),%eax 4272 SET_VREG_WORD %edx rINST 0 # v[AA+0] <- edx 4273 FETCH_INST_OPCODE 2 %edx 4274 SET_VREG_WORD %eax rINST 1 # v[AA+1] <- eax 4275 ADVANCE_PC 2 4276 GOTO_NEXT_R %edx 4277 4278 4279/* ------------------------------ */ 4280 .balign 64 4281.L_OP_SHL_LONG: /* 0xa3 */ 4282/* File: x86/OP_SHL_LONG.S */ 4283 /* 4284 * Long integer shift. This is different from the generic 32/64-bit 4285 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4286 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4287 * 6 bits of the shift distance. x86 shifts automatically mask off 4288 * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31 4289 * case specially. 4290 */ 4291 /* shl-long vAA, vBB, vCC */ 4292 /* ecx gets shift count */ 4293 /* Need to spill edx */ 4294 /* rINSTw gets AA */ 4295 movzbl 2(rPC),%eax # eax<- BB 4296 movzbl 3(rPC),%ecx # ecx<- CC 4297 GET_VREG_WORD %edx %eax 1 # ecx<- v[BB+1] 4298 GET_VREG_R %ecx %ecx # ecx<- vCC 4299 GET_VREG_WORD %eax %eax 0 # eax<- v[BB+0] 4300 shldl %eax,%edx 4301 sall %cl,%eax 4302 testb $32,%cl 4303 je 2f 4304 movl %eax,%edx 4305 xorl %eax,%eax 43062: 4307 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- %edx 4308 FETCH_INST_OPCODE 2 %edx 4309 jmp .LOP_SHL_LONG_finish 4310 4311/* ------------------------------ */ 4312 .balign 64 4313.L_OP_SHR_LONG: /* 0xa4 */ 4314/* File: x86/OP_SHR_LONG.S */ 4315 /* 4316 * Long integer shift. This is different from the generic 32/64-bit 4317 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4318 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4319 * 6 bits of the shift distance. x86 shifts automatically mask off 4320 * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31 4321 * case specially. 4322 */ 4323 /* shr-long vAA, vBB, vCC */ 4324 /* ecx gets shift count */ 4325 /* Need to spill edx */ 4326 /* rINSTw gets AA */ 4327 movzbl 2(rPC),%eax # eax<- BB 4328 movzbl 3(rPC),%ecx # ecx<- CC 4329 GET_VREG_WORD %edx %eax 1 # edx<- v[BB+1] 4330 GET_VREG_R %ecx %ecx # ecx<- vCC 4331 GET_VREG_WORD %eax %eax 0 # eax<- v[BB+0] 4332 shrdl %edx,%eax 4333 sarl %cl,%edx 4334 testb $32,%cl 4335 je 2f 4336 movl %edx,%eax 4337 sarl $31,%edx 43382: 4339 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- edx 4340 FETCH_INST_OPCODE 2 %edx 4341 jmp .LOP_SHR_LONG_finish 4342 4343/* ------------------------------ */ 4344 .balign 64 4345.L_OP_USHR_LONG: /* 0xa5 */ 4346/* File: x86/OP_USHR_LONG.S */ 4347 /* 4348 * Long integer shift. This is different from the generic 32/64-bit 4349 * binary operations because vAA/vBB are 64-bit but vCC (the shift 4350 * distance) is 32-bit. Also, Dalvik requires us to mask off the low 4351 * 6 bits of the shift distance. x86 shifts automatically mask off 4352 * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31 4353 * case specially. 4354 */ 4355 /* shr-long vAA, vBB, vCC */ 4356 /* ecx gets shift count */ 4357 /* Need to spill edx */ 4358 /* rINSTw gets AA */ 4359 movzbl 2(rPC),%eax # eax<- BB 4360 movzbl 3(rPC),%ecx # ecx<- CC 4361 GET_VREG_WORD %edx %eax 1 # edx<- v[BB+1] 4362 GET_VREG_R %ecx %ecx # ecx<- vCC 4363 GET_VREG_WORD %eax %eax 0 # eax<- v[BB+0] 4364 shrdl %edx,%eax 4365 shrl %cl,%edx 4366 testb $32,%cl 4367 je 2f 4368 movl %edx,%eax 4369 xorl %edx,%edx 43702: 4371 FETCH_INST_OPCODE 2 %edx 4372 SET_VREG_WORD %edx rINST 1 # v[BB+1]<- edx 4373 jmp .LOP_USHR_LONG_finish 4374 4375/* ------------------------------ */ 4376 .balign 64 4377.L_OP_ADD_FLOAT: /* 0xa6 */ 4378/* File: x86/OP_ADD_FLOAT.S */ 4379/* File: x86/binflop.S */ 4380 /* 4381 * Generic 32-bit binary float operation. 4382 * 4383 * For: add-fp, sub-fp, mul-fp, div-fp 4384 */ 4385 /* binop vAA, vBB, vCC */ 4386 movzbl 2(rPC),%eax # eax<- CC 4387 movzbl 3(rPC),%ecx # ecx<- BB 4388 flds (rFP,%eax,4) # vCC to fp stack 4389 fadds (rFP,%ecx,4) # ex: faddp 4390 FETCH_INST_OPCODE 2 %edx 4391 ADVANCE_PC 2 4392 fstps (rFP,rINST,4) # %st to vAA 4393 GOTO_NEXT_R %edx 4394 4395 4396/* ------------------------------ */ 4397 .balign 64 4398.L_OP_SUB_FLOAT: /* 0xa7 */ 4399/* File: x86/OP_SUB_FLOAT.S */ 4400/* File: x86/binflop.S */ 4401 /* 4402 * Generic 32-bit binary float operation. 4403 * 4404 * For: add-fp, sub-fp, mul-fp, div-fp 4405 */ 4406 /* binop vAA, vBB, vCC */ 4407 movzbl 2(rPC),%eax # eax<- CC 4408 movzbl 3(rPC),%ecx # ecx<- BB 4409 flds (rFP,%eax,4) # vCC to fp stack 4410 fsubs (rFP,%ecx,4) # ex: faddp 4411 FETCH_INST_OPCODE 2 %edx 4412 ADVANCE_PC 2 4413 fstps (rFP,rINST,4) # %st to vAA 4414 GOTO_NEXT_R %edx 4415 4416 4417/* ------------------------------ */ 4418 .balign 64 4419.L_OP_MUL_FLOAT: /* 0xa8 */ 4420/* File: x86/OP_MUL_FLOAT.S */ 4421/* File: x86/binflop.S */ 4422 /* 4423 * Generic 32-bit binary float operation. 4424 * 4425 * For: add-fp, sub-fp, mul-fp, div-fp 4426 */ 4427 /* binop vAA, vBB, vCC */ 4428 movzbl 2(rPC),%eax # eax<- CC 4429 movzbl 3(rPC),%ecx # ecx<- BB 4430 flds (rFP,%eax,4) # vCC to fp stack 4431 fmuls (rFP,%ecx,4) # ex: faddp 4432 FETCH_INST_OPCODE 2 %edx 4433 ADVANCE_PC 2 4434 fstps (rFP,rINST,4) # %st to vAA 4435 GOTO_NEXT_R %edx 4436 4437 4438/* ------------------------------ */ 4439 .balign 64 4440.L_OP_DIV_FLOAT: /* 0xa9 */ 4441/* File: x86/OP_DIV_FLOAT.S */ 4442/* File: x86/binflop.S */ 4443 /* 4444 * Generic 32-bit binary float operation. 4445 * 4446 * For: add-fp, sub-fp, mul-fp, div-fp 4447 */ 4448 /* binop vAA, vBB, vCC */ 4449 movzbl 2(rPC),%eax # eax<- CC 4450 movzbl 3(rPC),%ecx # ecx<- BB 4451 flds (rFP,%eax,4) # vCC to fp stack 4452 fdivs (rFP,%ecx,4) # ex: faddp 4453 FETCH_INST_OPCODE 2 %edx 4454 ADVANCE_PC 2 4455 fstps (rFP,rINST,4) # %st to vAA 4456 GOTO_NEXT_R %edx 4457 4458 4459/* ------------------------------ */ 4460 .balign 64 4461.L_OP_REM_FLOAT: /* 0xaa */ 4462/* File: x86/OP_REM_FLOAT.S */ 4463 /* rem_float vAA, vBB, vCC */ 4464 movzbl 3(rPC),%ecx # ecx<- BB 4465 movzbl 2(rPC),%eax # eax<- CC 4466 flds (rFP,%ecx,4) # vCC to fp stack 4467 flds (rFP,%eax,4) # vCC to fp stack 4468 movzbl rINSTbl,%ecx # ecx<- AA 4469 FETCH_INST_OPCODE 2 %edx 44701: 4471 fprem 4472 fstsw %ax 4473 sahf 4474 jp 1b 4475 fstp %st(1) 4476 ADVANCE_PC 2 4477 fstps (rFP,%ecx,4) # %st to vAA 4478 GOTO_NEXT_R %edx 4479 4480/* ------------------------------ */ 4481 .balign 64 4482.L_OP_ADD_DOUBLE: /* 0xab */ 4483/* File: x86/OP_ADD_DOUBLE.S */ 4484/* File: x86/binflop.S */ 4485 /* 4486 * Generic 32-bit binary float operation. 4487 * 4488 * For: add-fp, sub-fp, mul-fp, div-fp 4489 */ 4490 /* binop vAA, vBB, vCC */ 4491 movzbl 2(rPC),%eax # eax<- CC 4492 movzbl 3(rPC),%ecx # ecx<- BB 4493 fldl (rFP,%eax,4) # vCC to fp stack 4494 faddl (rFP,%ecx,4) # ex: faddp 4495 FETCH_INST_OPCODE 2 %edx 4496 ADVANCE_PC 2 4497 fstpl (rFP,rINST,4) # %st to vAA 4498 GOTO_NEXT_R %edx 4499 4500 4501/* ------------------------------ */ 4502 .balign 64 4503.L_OP_SUB_DOUBLE: /* 0xac */ 4504/* File: x86/OP_SUB_DOUBLE.S */ 4505/* File: x86/binflop.S */ 4506 /* 4507 * Generic 32-bit binary float operation. 4508 * 4509 * For: add-fp, sub-fp, mul-fp, div-fp 4510 */ 4511 /* binop vAA, vBB, vCC */ 4512 movzbl 2(rPC),%eax # eax<- CC 4513 movzbl 3(rPC),%ecx # ecx<- BB 4514 fldl (rFP,%eax,4) # vCC to fp stack 4515 fsubl (rFP,%ecx,4) # ex: faddp 4516 FETCH_INST_OPCODE 2 %edx 4517 ADVANCE_PC 2 4518 fstpl (rFP,rINST,4) # %st to vAA 4519 GOTO_NEXT_R %edx 4520 4521 4522/* ------------------------------ */ 4523 .balign 64 4524.L_OP_MUL_DOUBLE: /* 0xad */ 4525/* File: x86/OP_MUL_DOUBLE.S */ 4526/* File: x86/binflop.S */ 4527 /* 4528 * Generic 32-bit binary float operation. 4529 * 4530 * For: add-fp, sub-fp, mul-fp, div-fp 4531 */ 4532 /* binop vAA, vBB, vCC */ 4533 movzbl 2(rPC),%eax # eax<- CC 4534 movzbl 3(rPC),%ecx # ecx<- BB 4535 fldl (rFP,%eax,4) # vCC to fp stack 4536 fmull (rFP,%ecx,4) # ex: faddp 4537 FETCH_INST_OPCODE 2 %edx 4538 ADVANCE_PC 2 4539 fstpl (rFP,rINST,4) # %st to vAA 4540 GOTO_NEXT_R %edx 4541 4542 4543/* ------------------------------ */ 4544 .balign 64 4545.L_OP_DIV_DOUBLE: /* 0xae */ 4546/* File: x86/OP_DIV_DOUBLE.S */ 4547/* File: x86/binflop.S */ 4548 /* 4549 * Generic 32-bit binary float operation. 4550 * 4551 * For: add-fp, sub-fp, mul-fp, div-fp 4552 */ 4553 /* binop vAA, vBB, vCC */ 4554 movzbl 2(rPC),%eax # eax<- CC 4555 movzbl 3(rPC),%ecx # ecx<- BB 4556 fldl (rFP,%eax,4) # vCC to fp stack 4557 fdivl (rFP,%ecx,4) # ex: faddp 4558 FETCH_INST_OPCODE 2 %edx 4559 ADVANCE_PC 2 4560 fstpl (rFP,rINST,4) # %st to vAA 4561 GOTO_NEXT_R %edx 4562 4563 4564/* ------------------------------ */ 4565 .balign 64 4566.L_OP_REM_DOUBLE: /* 0xaf */ 4567/* File: x86/OP_REM_DOUBLE.S */ 4568 /* rem_float vAA, vBB, vCC */ 4569 movzbl 3(rPC),%ecx # ecx<- BB 4570 movzbl 2(rPC),%eax # eax<- CC 4571 fldl (rFP,%ecx,4) # vCC to fp stack 4572 fldl (rFP,%eax,4) # vCC to fp stack 4573 movzbl rINSTbl,%ecx # ecx<- AA 4574 FETCH_INST_OPCODE 2 %edx 45751: 4576 fprem 4577 fstsw %ax 4578 sahf 4579 jp 1b 4580 fstp %st(1) 4581 ADVANCE_PC 2 4582 fstpl (rFP,%ecx,4) # %st to vAA 4583 GOTO_NEXT_R %edx 4584 4585/* ------------------------------ */ 4586 .balign 64 4587.L_OP_ADD_INT_2ADDR: /* 0xb0 */ 4588/* File: x86/OP_ADD_INT_2ADDR.S */ 4589/* File: x86/binop2addr.S */ 4590 /* 4591 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 4592 * that specifies an instruction that performs "result = r0 op r1". 4593 * This could be an ARM instruction or a function call. (If the result 4594 * comes back in a register other than r0, you can override "result".) 4595 * 4596 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4597 * vCC (r1). Useful for integer division and modulus. 4598 * 4599 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 4600 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 4601 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 4602 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 4603 */ 4604 /* binop/2addr vA, vB */ 4605 movzx rINSTbl,%ecx # ecx<- A+ 4606 sarl $4,rINST # rINST<- B 4607 GET_VREG_R %eax rINST # eax<- vB 4608 FETCH_INST_OPCODE 1 %edx 4609 andb $0xf,%cl # ecx<- A 4610 addl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4) 4611 ADVANCE_PC 1 4612 GOTO_NEXT_R %edx 4613 4614 4615/* ------------------------------ */ 4616 .balign 64 4617.L_OP_SUB_INT_2ADDR: /* 0xb1 */ 4618/* File: x86/OP_SUB_INT_2ADDR.S */ 4619/* File: x86/binop2addr.S */ 4620 /* 4621 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 4622 * that specifies an instruction that performs "result = r0 op r1". 4623 * This could be an ARM instruction or a function call. (If the result 4624 * comes back in a register other than r0, you can override "result".) 4625 * 4626 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4627 * vCC (r1). Useful for integer division and modulus. 4628 * 4629 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 4630 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 4631 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 4632 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 4633 */ 4634 /* binop/2addr vA, vB */ 4635 movzx rINSTbl,%ecx # ecx<- A+ 4636 sarl $4,rINST # rINST<- B 4637 GET_VREG_R %eax rINST # eax<- vB 4638 FETCH_INST_OPCODE 1 %edx 4639 andb $0xf,%cl # ecx<- A 4640 subl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4) 4641 ADVANCE_PC 1 4642 GOTO_NEXT_R %edx 4643 4644 4645/* ------------------------------ */ 4646 .balign 64 4647.L_OP_MUL_INT_2ADDR: /* 0xb2 */ 4648/* File: x86/OP_MUL_INT_2ADDR.S */ 4649 /* mul vA, vB */ 4650 movzx rINSTbl,%ecx # ecx<- A+ 4651 sarl $4,rINST # rINST<- B 4652 GET_VREG_R %eax rINST # eax<- vB 4653 andb $0xf,%cl # ecx<- A 4654 imull (rFP,%ecx,4),%eax 4655 FETCH_INST_OPCODE 1 %edx 4656 SET_VREG %eax %ecx 4657 ADVANCE_PC 1 4658 GOTO_NEXT_R %edx 4659 4660/* ------------------------------ */ 4661 .balign 64 4662.L_OP_DIV_INT_2ADDR: /* 0xb3 */ 4663/* File: x86/OP_DIV_INT_2ADDR.S */ 4664/* File: x86/bindiv2addr.S */ 4665 /* 4666 * 32-bit binary div/rem operation. Handles special case of op0=minint and 4667 * op1=-1. 4668 */ 4669 /* div/rem/2addr vA, vB */ 4670 movzx rINSTbl,%ecx # eax<- BA 4671 sarl $4,%ecx # ecx<- B 4672 GET_VREG_R %ecx %ecx # eax<- vBB 4673 andb $0xf,rINSTbl # rINST<- A 4674 GET_VREG_R %eax rINST # eax<- vBB 4675 cmpl $0,%ecx 4676 je common_errDivideByZero 4677 cmpl $-1,%ecx 4678 jne .LOP_DIV_INT_2ADDR_continue_div2addr 4679 cmpl $0x80000000,%eax 4680 jne .LOP_DIV_INT_2ADDR_continue_div2addr 4681 movl $0x80000000,%eax 4682 jmp .LOP_DIV_INT_2ADDR_finish_div2addr 4683 4684 4685 4686/* ------------------------------ */ 4687 .balign 64 4688.L_OP_REM_INT_2ADDR: /* 0xb4 */ 4689/* File: x86/OP_REM_INT_2ADDR.S */ 4690/* File: x86/bindiv2addr.S */ 4691 /* 4692 * 32-bit binary div/rem operation. Handles special case of op0=minint and 4693 * op1=-1. 4694 */ 4695 /* div/rem/2addr vA, vB */ 4696 movzx rINSTbl,%ecx # eax<- BA 4697 sarl $4,%ecx # ecx<- B 4698 GET_VREG_R %ecx %ecx # eax<- vBB 4699 andb $0xf,rINSTbl # rINST<- A 4700 GET_VREG_R %eax rINST # eax<- vBB 4701 cmpl $0,%ecx 4702 je common_errDivideByZero 4703 cmpl $-1,%ecx 4704 jne .LOP_REM_INT_2ADDR_continue_div2addr 4705 cmpl $0x80000000,%eax 4706 jne .LOP_REM_INT_2ADDR_continue_div2addr 4707 movl $0,%edx 4708 jmp .LOP_REM_INT_2ADDR_finish_div2addr 4709 4710 4711 4712/* ------------------------------ */ 4713 .balign 64 4714.L_OP_AND_INT_2ADDR: /* 0xb5 */ 4715/* File: x86/OP_AND_INT_2ADDR.S */ 4716/* File: x86/binop2addr.S */ 4717 /* 4718 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 4719 * that specifies an instruction that performs "result = r0 op r1". 4720 * This could be an ARM instruction or a function call. (If the result 4721 * comes back in a register other than r0, you can override "result".) 4722 * 4723 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4724 * vCC (r1). Useful for integer division and modulus. 4725 * 4726 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 4727 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 4728 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 4729 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 4730 */ 4731 /* binop/2addr vA, vB */ 4732 movzx rINSTbl,%ecx # ecx<- A+ 4733 sarl $4,rINST # rINST<- B 4734 GET_VREG_R %eax rINST # eax<- vB 4735 FETCH_INST_OPCODE 1 %edx 4736 andb $0xf,%cl # ecx<- A 4737 andl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4) 4738 ADVANCE_PC 1 4739 GOTO_NEXT_R %edx 4740 4741 4742/* ------------------------------ */ 4743 .balign 64 4744.L_OP_OR_INT_2ADDR: /* 0xb6 */ 4745/* File: x86/OP_OR_INT_2ADDR.S */ 4746/* File: x86/binop2addr.S */ 4747 /* 4748 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 4749 * that specifies an instruction that performs "result = r0 op r1". 4750 * This could be an ARM instruction or a function call. (If the result 4751 * comes back in a register other than r0, you can override "result".) 4752 * 4753 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4754 * vCC (r1). Useful for integer division and modulus. 4755 * 4756 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 4757 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 4758 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 4759 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 4760 */ 4761 /* binop/2addr vA, vB */ 4762 movzx rINSTbl,%ecx # ecx<- A+ 4763 sarl $4,rINST # rINST<- B 4764 GET_VREG_R %eax rINST # eax<- vB 4765 FETCH_INST_OPCODE 1 %edx 4766 andb $0xf,%cl # ecx<- A 4767 orl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4) 4768 ADVANCE_PC 1 4769 GOTO_NEXT_R %edx 4770 4771 4772/* ------------------------------ */ 4773 .balign 64 4774.L_OP_XOR_INT_2ADDR: /* 0xb7 */ 4775/* File: x86/OP_XOR_INT_2ADDR.S */ 4776/* File: x86/binop2addr.S */ 4777 /* 4778 * Generic 32-bit "/2addr" binary operation. Provide an "instr" line 4779 * that specifies an instruction that performs "result = r0 op r1". 4780 * This could be an ARM instruction or a function call. (If the result 4781 * comes back in a register other than r0, you can override "result".) 4782 * 4783 * If "chkzero" is set to 1, we perform a divide-by-zero check on 4784 * vCC (r1). Useful for integer division and modulus. 4785 * 4786 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr, 4787 * rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr, 4788 * shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr, 4789 * sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr 4790 */ 4791 /* binop/2addr vA, vB */ 4792 movzx rINSTbl,%ecx # ecx<- A+ 4793 sarl $4,rINST # rINST<- B 4794 GET_VREG_R %eax rINST # eax<- vB 4795 FETCH_INST_OPCODE 1 %edx 4796 andb $0xf,%cl # ecx<- A 4797 xorl %eax,(rFP,%ecx,4) # for ex: addl %eax,(rFP,%ecx,4) 4798 ADVANCE_PC 1 4799 GOTO_NEXT_R %edx 4800 4801 4802/* ------------------------------ */ 4803 .balign 64 4804.L_OP_SHL_INT_2ADDR: /* 0xb8 */ 4805/* File: x86/OP_SHL_INT_2ADDR.S */ 4806/* File: x86/shop2addr.S */ 4807 /* 4808 * Generic 32-bit "shift/2addr" operation. 4809 */ 4810 /* shift/2addr vA, vB */ 4811 movzx rINSTbl,%ecx # eax<- BA 4812 sarl $4,%ecx # ecx<- B 4813 GET_VREG_R %ecx %ecx # eax<- vBB 4814 andb $0xf,rINSTbl # rINST<- A 4815 GET_VREG_R %eax rINST # eax<- vAA 4816 sall %cl,%eax # ex: sarl %cl,%eax 4817 FETCH_INST_OPCODE 1 %edx 4818 SET_VREG %eax rINST 4819 ADVANCE_PC 1 4820 GOTO_NEXT_R %edx 4821 4822 4823/* ------------------------------ */ 4824 .balign 64 4825.L_OP_SHR_INT_2ADDR: /* 0xb9 */ 4826/* File: x86/OP_SHR_INT_2ADDR.S */ 4827/* File: x86/shop2addr.S */ 4828 /* 4829 * Generic 32-bit "shift/2addr" operation. 4830 */ 4831 /* shift/2addr vA, vB */ 4832 movzx rINSTbl,%ecx # eax<- BA 4833 sarl $4,%ecx # ecx<- B 4834 GET_VREG_R %ecx %ecx # eax<- vBB 4835 andb $0xf,rINSTbl # rINST<- A 4836 GET_VREG_R %eax rINST # eax<- vAA 4837 sarl %cl,%eax # ex: sarl %cl,%eax 4838 FETCH_INST_OPCODE 1 %edx 4839 SET_VREG %eax rINST 4840 ADVANCE_PC 1 4841 GOTO_NEXT_R %edx 4842 4843 4844/* ------------------------------ */ 4845 .balign 64 4846.L_OP_USHR_INT_2ADDR: /* 0xba */ 4847/* File: x86/OP_USHR_INT_2ADDR.S */ 4848/* File: x86/shop2addr.S */ 4849 /* 4850 * Generic 32-bit "shift/2addr" operation. 4851 */ 4852 /* shift/2addr vA, vB */ 4853 movzx rINSTbl,%ecx # eax<- BA 4854 sarl $4,%ecx # ecx<- B 4855 GET_VREG_R %ecx %ecx # eax<- vBB 4856 andb $0xf,rINSTbl # rINST<- A 4857 GET_VREG_R %eax rINST # eax<- vAA 4858 shrl %cl,%eax # ex: sarl %cl,%eax 4859 FETCH_INST_OPCODE 1 %edx 4860 SET_VREG %eax rINST 4861 ADVANCE_PC 1 4862 GOTO_NEXT_R %edx 4863 4864 4865/* ------------------------------ */ 4866 .balign 64 4867.L_OP_ADD_LONG_2ADDR: /* 0xbb */ 4868/* File: x86/OP_ADD_LONG_2ADDR.S */ 4869/* File: x86/binopWide2addr.S */ 4870 /* 4871 * Generic 64-bit binary operation. 4872 */ 4873 /* binop/2addr vA, vB */ 4874 movzbl rINSTbl,%ecx # ecx<- BA 4875 sarl $4,%ecx # ecx<- B 4876 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0] 4877 GET_VREG_WORD %ecx %ecx 1 # eax<- v[B+1] 4878 andb $0xF,rINSTbl # rINST<- A 4879 addl %eax,(rFP,rINST,4) # example: addl %eax,(rFP,rINST,4) 4880 adcl %ecx,4(rFP,rINST,4) # example: adcl %ecx,4(rFP,rINST,4) 4881 FETCH_INST_OPCODE 1 %edx 4882 ADVANCE_PC 1 4883 GOTO_NEXT_R %edx 4884 4885 4886/* ------------------------------ */ 4887 .balign 64 4888.L_OP_SUB_LONG_2ADDR: /* 0xbc */ 4889/* File: x86/OP_SUB_LONG_2ADDR.S */ 4890/* File: x86/binopWide2addr.S */ 4891 /* 4892 * Generic 64-bit binary operation. 4893 */ 4894 /* binop/2addr vA, vB */ 4895 movzbl rINSTbl,%ecx # ecx<- BA 4896 sarl $4,%ecx # ecx<- B 4897 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0] 4898 GET_VREG_WORD %ecx %ecx 1 # eax<- v[B+1] 4899 andb $0xF,rINSTbl # rINST<- A 4900 subl %eax,(rFP,rINST,4) # example: addl %eax,(rFP,rINST,4) 4901 sbbl %ecx,4(rFP,rINST,4) # example: adcl %ecx,4(rFP,rINST,4) 4902 FETCH_INST_OPCODE 1 %edx 4903 ADVANCE_PC 1 4904 GOTO_NEXT_R %edx 4905 4906 4907/* ------------------------------ */ 4908 .balign 64 4909.L_OP_MUL_LONG_2ADDR: /* 0xbd */ 4910/* File: x86/OP_MUL_LONG_2ADDR.S */ 4911 /* 4912 * Signed 64-bit integer multiply, 2-addr version 4913 * 4914 * We could definately use more free registers for 4915 * this code. We must spill %edx (edx) because it 4916 * is used by imul. We'll also spill rINST (ebx), 4917 * giving us eax, ebc, ecx and edx as computational 4918 * temps. On top of that, we'll spill %esi (edi) 4919 * for use as the vA pointer and rFP (esi) for use 4920 * as the vB pointer. Yuck. 4921 */ 4922 /* mul-long/2addr vA, vB */ 4923 movzbl rINSTbl,%eax # eax<- BA 4924 andb $0xf,%al # eax<- A 4925 sarl $4,rINST # rINST<- B 4926 SPILL_TMP2(%esi) 4927 SPILL(rFP) 4928 leal (rFP,%eax,4),%esi # %esi<- &v[A] 4929 leal (rFP,rINST,4),rFP # rFP<- &v[B] 4930 movl 4(%esi),%ecx # ecx<- Amsw 4931 imull (rFP),%ecx # ecx<- (Amsw*Blsw) 4932 movl 4(rFP),%eax # eax<- Bmsw 4933 imull (%esi),%eax # eax<- (Bmsw*Alsw) 4934 addl %eax,%ecx # ecx<- (Amsw*Blsw)+(Bmsw*Alsw) 4935 movl (rFP),%eax # eax<- Blsw 4936 mull (%esi) # eax<- (Blsw*Alsw) 4937 jmp .LOP_MUL_LONG_2ADDR_continue 4938 4939/* ------------------------------ */ 4940 .balign 64 4941.L_OP_DIV_LONG_2ADDR: /* 0xbe */ 4942/* File: x86/OP_DIV_LONG_2ADDR.S */ 4943 /* div/2addr vA, vB */ 4944 movzbl rINSTbl,%eax 4945 shrl $4,%eax # eax<- B 4946 andb $0xf,rINSTbl # rINST<- A 4947 GET_VREG_WORD %edx %eax 0 4948 GET_VREG_WORD %eax %eax 1 4949 movl %edx,OUT_ARG2(%esp) 4950 testl %eax,%eax 4951 je .LOP_DIV_LONG_2ADDR_check_zero 4952 cmpl $-1,%eax 4953 je .LOP_DIV_LONG_2ADDR_check_neg1 4954.LOP_DIV_LONG_2ADDR_notSpecial: 4955 GET_VREG_WORD %edx rINST 0 4956 GET_VREG_WORD %ecx rINST 1 4957.LOP_DIV_LONG_2ADDR_notSpecial1: 4958 jmp .LOP_DIV_LONG_2ADDR_continue 4959 4960/* ------------------------------ */ 4961 .balign 64 4962.L_OP_REM_LONG_2ADDR: /* 0xbf */ 4963/* File: x86/OP_REM_LONG_2ADDR.S */ 4964/* File: x86/OP_DIV_LONG_2ADDR.S */ 4965 /* div/2addr vA, vB */ 4966 movzbl rINSTbl,%eax 4967 shrl $4,%eax # eax<- B 4968 andb $0xf,rINSTbl # rINST<- A 4969 GET_VREG_WORD %edx %eax 0 4970 GET_VREG_WORD %eax %eax 1 4971 movl %edx,OUT_ARG2(%esp) 4972 testl %eax,%eax 4973 je .LOP_REM_LONG_2ADDR_check_zero 4974 cmpl $-1,%eax 4975 je .LOP_REM_LONG_2ADDR_check_neg1 4976.LOP_REM_LONG_2ADDR_notSpecial: 4977 GET_VREG_WORD %edx rINST 0 4978 GET_VREG_WORD %ecx rINST 1 4979.LOP_REM_LONG_2ADDR_notSpecial1: 4980 jmp .LOP_REM_LONG_2ADDR_continue 4981 4982 4983/* ------------------------------ */ 4984 .balign 64 4985.L_OP_AND_LONG_2ADDR: /* 0xc0 */ 4986/* File: x86/OP_AND_LONG_2ADDR.S */ 4987/* File: x86/binopWide2addr.S */ 4988 /* 4989 * Generic 64-bit binary operation. 4990 */ 4991 /* binop/2addr vA, vB */ 4992 movzbl rINSTbl,%ecx # ecx<- BA 4993 sarl $4,%ecx # ecx<- B 4994 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0] 4995 GET_VREG_WORD %ecx %ecx 1 # eax<- v[B+1] 4996 andb $0xF,rINSTbl # rINST<- A 4997 andl %eax,(rFP,rINST,4) # example: addl %eax,(rFP,rINST,4) 4998 andl %ecx,4(rFP,rINST,4) # example: adcl %ecx,4(rFP,rINST,4) 4999 FETCH_INST_OPCODE 1 %edx 5000 ADVANCE_PC 1 5001 GOTO_NEXT_R %edx 5002 5003 5004/* ------------------------------ */ 5005 .balign 64 5006.L_OP_OR_LONG_2ADDR: /* 0xc1 */ 5007/* File: x86/OP_OR_LONG_2ADDR.S */ 5008/* File: x86/binopWide2addr.S */ 5009 /* 5010 * Generic 64-bit binary operation. 5011 */ 5012 /* binop/2addr vA, vB */ 5013 movzbl rINSTbl,%ecx # ecx<- BA 5014 sarl $4,%ecx # ecx<- B 5015 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0] 5016 GET_VREG_WORD %ecx %ecx 1 # eax<- v[B+1] 5017 andb $0xF,rINSTbl # rINST<- A 5018 orl %eax,(rFP,rINST,4) # example: addl %eax,(rFP,rINST,4) 5019 orl %ecx,4(rFP,rINST,4) # example: adcl %ecx,4(rFP,rINST,4) 5020 FETCH_INST_OPCODE 1 %edx 5021 ADVANCE_PC 1 5022 GOTO_NEXT_R %edx 5023 5024 5025/* ------------------------------ */ 5026 .balign 64 5027.L_OP_XOR_LONG_2ADDR: /* 0xc2 */ 5028/* File: x86/OP_XOR_LONG_2ADDR.S */ 5029/* File: x86/binopWide2addr.S */ 5030 /* 5031 * Generic 64-bit binary operation. 5032 */ 5033 /* binop/2addr vA, vB */ 5034 movzbl rINSTbl,%ecx # ecx<- BA 5035 sarl $4,%ecx # ecx<- B 5036 GET_VREG_WORD %eax %ecx 0 # eax<- v[B+0] 5037 GET_VREG_WORD %ecx %ecx 1 # eax<- v[B+1] 5038 andb $0xF,rINSTbl # rINST<- A 5039 xorl %eax,(rFP,rINST,4) # example: addl %eax,(rFP,rINST,4) 5040 xorl %ecx,4(rFP,rINST,4) # example: adcl %ecx,4(rFP,rINST,4) 5041 FETCH_INST_OPCODE 1 %edx 5042 ADVANCE_PC 1 5043 GOTO_NEXT_R %edx 5044 5045 5046/* ------------------------------ */ 5047 .balign 64 5048.L_OP_SHL_LONG_2ADDR: /* 0xc3 */ 5049/* File: x86/OP_SHL_LONG_2ADDR.S */ 5050 /* 5051 * Long integer shift, 2addr version. vA is 64-bit value/result, vB is 5052 * 32-bit shift distance. 5053 */ 5054 /* shl-long/2addr vA, vB */ 5055 /* ecx gets shift count */ 5056 /* Need to spill edx */ 5057 /* rINSTw gets AA */ 5058 movzbl rINSTbl,%ecx # ecx<- BA 5059 andb $0xf,rINSTbl # rINST<- A 5060 GET_VREG_WORD %eax rINST 0 # eax<- v[AA+0] 5061 sarl $4,%ecx # ecx<- B 5062 GET_VREG_WORD %edx rINST 1 # edx<- v[AA+1] 5063 GET_VREG_R %ecx %ecx # ecx<- vBB 5064 shldl %eax,%edx 5065 sall %cl,%eax 5066 testb $32,%cl 5067 je 2f 5068 movl %eax,%edx 5069 xorl %eax,%eax 50702: 5071 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- edx 5072 jmp .LOP_SHL_LONG_2ADDR_finish 5073 5074/* ------------------------------ */ 5075 .balign 64 5076.L_OP_SHR_LONG_2ADDR: /* 0xc4 */ 5077/* File: x86/OP_SHR_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 shrdl %edx,%eax 5093 sarl %cl,%edx 5094 testb $32,%cl 5095 je 2f 5096 movl %edx,%eax 5097 sarl $31,%edx 50982: 5099 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- edx 5100 jmp .LOP_SHR_LONG_2ADDR_finish 5101 5102/* ------------------------------ */ 5103 .balign 64 5104.L_OP_USHR_LONG_2ADDR: /* 0xc5 */ 5105/* File: x86/OP_USHR_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 shrl %cl,%edx 5122 testb $32,%cl 5123 je 2f 5124 movl %edx,%eax 5125 xorl %edx,%edx 51262: 5127 SET_VREG_WORD %edx rINST 1 # v[AA+1]<- edx 5128 jmp .LOP_USHR_LONG_2ADDR_finish 5129 5130/* ------------------------------ */ 5131 .balign 64 5132.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */ 5133/* File: x86/OP_ADD_FLOAT_2ADDR.S */ 5134/* File: x86/binflop2addr.S */ 5135 /* 5136 * Generic 32-bit binary float operation. 5137 * 5138 * For: add-fp, sub-fp, mul-fp, div-fp 5139 */ 5140 5141 /* binop/2addr vA, vB */ 5142 movzx rINSTbl,%ecx # ecx<- A+ 5143 andb $0xf,%cl # ecx<- A 5144 flds (rFP,%ecx,4) # vAA to fp stack 5145 sarl $4,rINST # rINST<- B 5146 fadds (rFP,rINST,4) # ex: faddp 5147 FETCH_INST_OPCODE 1 %edx 5148 ADVANCE_PC 1 5149 fstps (rFP,%ecx,4) # %st to vA 5150 GOTO_NEXT_R %edx 5151 5152 5153/* ------------------------------ */ 5154 .balign 64 5155.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */ 5156/* File: x86/OP_SUB_FLOAT_2ADDR.S */ 5157/* File: x86/binflop2addr.S */ 5158 /* 5159 * Generic 32-bit binary float operation. 5160 * 5161 * For: add-fp, sub-fp, mul-fp, div-fp 5162 */ 5163 5164 /* binop/2addr vA, vB */ 5165 movzx rINSTbl,%ecx # ecx<- A+ 5166 andb $0xf,%cl # ecx<- A 5167 flds (rFP,%ecx,4) # vAA to fp stack 5168 sarl $4,rINST # rINST<- B 5169 fsubs (rFP,rINST,4) # ex: faddp 5170 FETCH_INST_OPCODE 1 %edx 5171 ADVANCE_PC 1 5172 fstps (rFP,%ecx,4) # %st to vA 5173 GOTO_NEXT_R %edx 5174 5175 5176/* ------------------------------ */ 5177 .balign 64 5178.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */ 5179/* File: x86/OP_MUL_FLOAT_2ADDR.S */ 5180/* File: x86/binflop2addr.S */ 5181 /* 5182 * Generic 32-bit binary float operation. 5183 * 5184 * For: add-fp, sub-fp, mul-fp, div-fp 5185 */ 5186 5187 /* binop/2addr vA, vB */ 5188 movzx rINSTbl,%ecx # ecx<- A+ 5189 andb $0xf,%cl # ecx<- A 5190 flds (rFP,%ecx,4) # vAA to fp stack 5191 sarl $4,rINST # rINST<- B 5192 fmuls (rFP,rINST,4) # ex: faddp 5193 FETCH_INST_OPCODE 1 %edx 5194 ADVANCE_PC 1 5195 fstps (rFP,%ecx,4) # %st to vA 5196 GOTO_NEXT_R %edx 5197 5198 5199/* ------------------------------ */ 5200 .balign 64 5201.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */ 5202/* File: x86/OP_DIV_FLOAT_2ADDR.S */ 5203/* File: x86/binflop2addr.S */ 5204 /* 5205 * Generic 32-bit binary float operation. 5206 * 5207 * For: add-fp, sub-fp, mul-fp, div-fp 5208 */ 5209 5210 /* binop/2addr vA, vB */ 5211 movzx rINSTbl,%ecx # ecx<- A+ 5212 andb $0xf,%cl # ecx<- A 5213 flds (rFP,%ecx,4) # vAA to fp stack 5214 sarl $4,rINST # rINST<- B 5215 fdivs (rFP,rINST,4) # ex: faddp 5216 FETCH_INST_OPCODE 1 %edx 5217 ADVANCE_PC 1 5218 fstps (rFP,%ecx,4) # %st to vA 5219 GOTO_NEXT_R %edx 5220 5221 5222/* ------------------------------ */ 5223 .balign 64 5224.L_OP_REM_FLOAT_2ADDR: /* 0xca */ 5225/* File: x86/OP_REM_FLOAT_2ADDR.S */ 5226 /* rem_float/2addr vA, vB */ 5227 movzx rINSTbl,%ecx # ecx<- A+ 5228 sarl $4,rINST # rINST<- B 5229 flds (rFP,rINST,4) # vBB to fp stack 5230 andb $0xf,%cl # ecx<- A 5231 flds (rFP,%ecx,4) # vAA to fp stack 5232 FETCH_INST_OPCODE 1 %edx 52331: 5234 fprem 5235 fstsw %ax 5236 sahf 5237 jp 1b 5238 fstp %st(1) 5239 ADVANCE_PC 1 5240 fstps (rFP,%ecx,4) # %st to vA 5241 GOTO_NEXT_R %edx 5242 5243/* ------------------------------ */ 5244 .balign 64 5245.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */ 5246/* File: x86/OP_ADD_DOUBLE_2ADDR.S */ 5247/* File: x86/binflop2addr.S */ 5248 /* 5249 * Generic 32-bit binary float operation. 5250 * 5251 * For: add-fp, sub-fp, mul-fp, div-fp 5252 */ 5253 5254 /* binop/2addr vA, vB */ 5255 movzx rINSTbl,%ecx # ecx<- A+ 5256 andb $0xf,%cl # ecx<- A 5257 fldl (rFP,%ecx,4) # vAA to fp stack 5258 sarl $4,rINST # rINST<- B 5259 faddl (rFP,rINST,4) # ex: faddp 5260 FETCH_INST_OPCODE 1 %edx 5261 ADVANCE_PC 1 5262 fstpl (rFP,%ecx,4) # %st to vA 5263 GOTO_NEXT_R %edx 5264 5265 5266/* ------------------------------ */ 5267 .balign 64 5268.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */ 5269/* File: x86/OP_SUB_DOUBLE_2ADDR.S */ 5270/* File: x86/binflop2addr.S */ 5271 /* 5272 * Generic 32-bit binary float operation. 5273 * 5274 * For: add-fp, sub-fp, mul-fp, div-fp 5275 */ 5276 5277 /* binop/2addr vA, vB */ 5278 movzx rINSTbl,%ecx # ecx<- A+ 5279 andb $0xf,%cl # ecx<- A 5280 fldl (rFP,%ecx,4) # vAA to fp stack 5281 sarl $4,rINST # rINST<- B 5282 fsubl (rFP,rINST,4) # ex: faddp 5283 FETCH_INST_OPCODE 1 %edx 5284 ADVANCE_PC 1 5285 fstpl (rFP,%ecx,4) # %st to vA 5286 GOTO_NEXT_R %edx 5287 5288 5289/* ------------------------------ */ 5290 .balign 64 5291.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */ 5292/* File: x86/OP_MUL_DOUBLE_2ADDR.S */ 5293/* File: x86/binflop2addr.S */ 5294 /* 5295 * Generic 32-bit binary float operation. 5296 * 5297 * For: add-fp, sub-fp, mul-fp, div-fp 5298 */ 5299 5300 /* binop/2addr vA, vB */ 5301 movzx rINSTbl,%ecx # ecx<- A+ 5302 andb $0xf,%cl # ecx<- A 5303 fldl (rFP,%ecx,4) # vAA to fp stack 5304 sarl $4,rINST # rINST<- B 5305 fmull (rFP,rINST,4) # ex: faddp 5306 FETCH_INST_OPCODE 1 %edx 5307 ADVANCE_PC 1 5308 fstpl (rFP,%ecx,4) # %st to vA 5309 GOTO_NEXT_R %edx 5310 5311 5312/* ------------------------------ */ 5313 .balign 64 5314.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */ 5315/* File: x86/OP_DIV_DOUBLE_2ADDR.S */ 5316/* File: x86/binflop2addr.S */ 5317 /* 5318 * Generic 32-bit binary float operation. 5319 * 5320 * For: add-fp, sub-fp, mul-fp, div-fp 5321 */ 5322 5323 /* binop/2addr vA, vB */ 5324 movzx rINSTbl,%ecx # ecx<- A+ 5325 andb $0xf,%cl # ecx<- A 5326 fldl (rFP,%ecx,4) # vAA to fp stack 5327 sarl $4,rINST # rINST<- B 5328 fdivl (rFP,rINST,4) # ex: faddp 5329 FETCH_INST_OPCODE 1 %edx 5330 ADVANCE_PC 1 5331 fstpl (rFP,%ecx,4) # %st to vA 5332 GOTO_NEXT_R %edx 5333 5334 5335/* ------------------------------ */ 5336 .balign 64 5337.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */ 5338/* File: x86/OP_REM_DOUBLE_2ADDR.S */ 5339 /* rem_float/2addr vA, vB */ 5340 movzx rINSTbl,%ecx # ecx<- A+ 5341 sarl $4,rINST # rINST<- B 5342 fldl (rFP,rINST,4) # vBB to fp stack 5343 andb $0xf,%cl # ecx<- A 5344 fldl (rFP,%ecx,4) # vAA to fp stack 5345 FETCH_INST_OPCODE 1 %edx 53461: 5347 fprem 5348 fstsw %ax 5349 sahf 5350 jp 1b 5351 fstp %st(1) 5352 ADVANCE_PC 1 5353 fstpl (rFP,%ecx,4) # %st to vA 5354 GOTO_NEXT_R %edx 5355 5356/* ------------------------------ */ 5357 .balign 64 5358.L_OP_ADD_INT_LIT16: /* 0xd0 */ 5359/* File: x86/OP_ADD_INT_LIT16.S */ 5360/* File: x86/binopLit16.S */ 5361 /* 5362 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 5363 * that specifies an instruction that performs "result = eax op ecx". 5364 * This could be an x86 instruction or a function call. (If the result 5365 * comes back in a register other than eax, you can override "result".) 5366 * 5367 * For: add-int/lit16, rsub-int, 5368 * and-int/lit16, or-int/lit16, xor-int/lit16 5369 */ 5370 /* binop/lit16 vA, vB, #+CCCC */ 5371 movzbl rINSTbl,%eax # eax<- 000000BA 5372 sarl $4,%eax # eax<- B 5373 GET_VREG_R %eax %eax # eax<- vB 5374 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5375 andb $0xf,rINSTbl # rINST<- A 5376 addl %ecx,%eax # for example: addl %ecx, %eax 5377 SET_VREG %eax rINST 5378 FETCH_INST_OPCODE 2 %edx 5379 ADVANCE_PC 2 5380 GOTO_NEXT_R %edx 5381 5382 5383/* ------------------------------ */ 5384 .balign 64 5385.L_OP_RSUB_INT: /* 0xd1 */ 5386/* File: x86/OP_RSUB_INT.S */ 5387/* File: x86/binopLit16.S */ 5388 /* 5389 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 5390 * that specifies an instruction that performs "result = eax op ecx". 5391 * This could be an x86 instruction or a function call. (If the result 5392 * comes back in a register other than eax, you can override "result".) 5393 * 5394 * For: add-int/lit16, rsub-int, 5395 * and-int/lit16, or-int/lit16, xor-int/lit16 5396 */ 5397 /* binop/lit16 vA, vB, #+CCCC */ 5398 movzbl rINSTbl,%eax # eax<- 000000BA 5399 sarl $4,%eax # eax<- B 5400 GET_VREG_R %eax %eax # eax<- vB 5401 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5402 andb $0xf,rINSTbl # rINST<- A 5403 subl %eax,%ecx # for example: addl %ecx, %eax 5404 SET_VREG %ecx rINST 5405 FETCH_INST_OPCODE 2 %edx 5406 ADVANCE_PC 2 5407 GOTO_NEXT_R %edx 5408 5409 5410/* ------------------------------ */ 5411 .balign 64 5412.L_OP_MUL_INT_LIT16: /* 0xd2 */ 5413/* File: x86/OP_MUL_INT_LIT16.S */ 5414 /* mul/lit16 vA, vB, #+CCCC */ 5415 /* Need A in rINST, ssssCCCC in ecx, vB in eax */ 5416 movzbl rINSTbl,%eax # eax<- 000000BA 5417 sarl $4,%eax # eax<- B 5418 GET_VREG_R %eax %eax # eax<- vB 5419 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5420 andb $0xf,rINSTbl # rINST<- A 5421 imull %ecx,%eax # trashes edx 5422 FETCH_INST_OPCODE 2 %edx 5423 ADVANCE_PC 2 5424 SET_VREG %eax rINST 5425 GOTO_NEXT_R %edx 5426 5427/* ------------------------------ */ 5428 .balign 64 5429.L_OP_DIV_INT_LIT16: /* 0xd3 */ 5430/* File: x86/OP_DIV_INT_LIT16.S */ 5431/* File: x86/bindivLit16.S */ 5432 /* 5433 * 32-bit binary div/rem operation. Handles special case of op0=minint and 5434 * op1=-1. 5435 */ 5436 /* div/rem/lit16 vA, vB, #+CCCC */ 5437 /* Need A in rINST, ssssCCCC in ecx, vB in eax */ 5438 movzbl rINSTbl,%eax # eax<- 000000BA 5439 sarl $4,%eax # eax<- B 5440 GET_VREG_R %eax %eax # eax<- vB 5441 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5442 andb $0xf,rINSTbl # rINST<- A 5443 cmpl $0,%ecx 5444 je common_errDivideByZero 5445 cmpl $-1,%ecx 5446 jne .LOP_DIV_INT_LIT16_continue_div 5447 cmpl $0x80000000,%eax 5448 jne .LOP_DIV_INT_LIT16_continue_div 5449 movl $0x80000000,%eax 5450 jmp .LOP_DIV_INT_LIT16_finish_div 5451 5452 5453 5454/* ------------------------------ */ 5455 .balign 64 5456.L_OP_REM_INT_LIT16: /* 0xd4 */ 5457/* File: x86/OP_REM_INT_LIT16.S */ 5458/* File: x86/bindivLit16.S */ 5459 /* 5460 * 32-bit binary div/rem operation. Handles special case of op0=minint and 5461 * op1=-1. 5462 */ 5463 /* div/rem/lit16 vA, vB, #+CCCC */ 5464 /* Need A in rINST, ssssCCCC in ecx, vB in eax */ 5465 movzbl rINSTbl,%eax # eax<- 000000BA 5466 sarl $4,%eax # eax<- B 5467 GET_VREG_R %eax %eax # eax<- vB 5468 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5469 andb $0xf,rINSTbl # rINST<- A 5470 cmpl $0,%ecx 5471 je common_errDivideByZero 5472 cmpl $-1,%ecx 5473 jne .LOP_REM_INT_LIT16_continue_div 5474 cmpl $0x80000000,%eax 5475 jne .LOP_REM_INT_LIT16_continue_div 5476 movl $0,%edx 5477 jmp .LOP_REM_INT_LIT16_finish_div 5478 5479 5480 5481/* ------------------------------ */ 5482 .balign 64 5483.L_OP_AND_INT_LIT16: /* 0xd5 */ 5484/* File: x86/OP_AND_INT_LIT16.S */ 5485/* File: x86/binopLit16.S */ 5486 /* 5487 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 5488 * that specifies an instruction that performs "result = eax op ecx". 5489 * This could be an x86 instruction or a function call. (If the result 5490 * comes back in a register other than eax, you can override "result".) 5491 * 5492 * For: add-int/lit16, rsub-int, 5493 * and-int/lit16, or-int/lit16, xor-int/lit16 5494 */ 5495 /* binop/lit16 vA, vB, #+CCCC */ 5496 movzbl rINSTbl,%eax # eax<- 000000BA 5497 sarl $4,%eax # eax<- B 5498 GET_VREG_R %eax %eax # eax<- vB 5499 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5500 andb $0xf,rINSTbl # rINST<- A 5501 andl %ecx,%eax # for example: addl %ecx, %eax 5502 SET_VREG %eax rINST 5503 FETCH_INST_OPCODE 2 %edx 5504 ADVANCE_PC 2 5505 GOTO_NEXT_R %edx 5506 5507 5508/* ------------------------------ */ 5509 .balign 64 5510.L_OP_OR_INT_LIT16: /* 0xd6 */ 5511/* File: x86/OP_OR_INT_LIT16.S */ 5512/* File: x86/binopLit16.S */ 5513 /* 5514 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 5515 * that specifies an instruction that performs "result = eax op ecx". 5516 * This could be an x86 instruction or a function call. (If the result 5517 * comes back in a register other than eax, you can override "result".) 5518 * 5519 * For: add-int/lit16, rsub-int, 5520 * and-int/lit16, or-int/lit16, xor-int/lit16 5521 */ 5522 /* binop/lit16 vA, vB, #+CCCC */ 5523 movzbl rINSTbl,%eax # eax<- 000000BA 5524 sarl $4,%eax # eax<- B 5525 GET_VREG_R %eax %eax # eax<- vB 5526 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5527 andb $0xf,rINSTbl # rINST<- A 5528 orl %ecx,%eax # for example: addl %ecx, %eax 5529 SET_VREG %eax rINST 5530 FETCH_INST_OPCODE 2 %edx 5531 ADVANCE_PC 2 5532 GOTO_NEXT_R %edx 5533 5534 5535/* ------------------------------ */ 5536 .balign 64 5537.L_OP_XOR_INT_LIT16: /* 0xd7 */ 5538/* File: x86/OP_XOR_INT_LIT16.S */ 5539/* File: x86/binopLit16.S */ 5540 /* 5541 * Generic 32-bit "lit16" binary operation. Provide an "instr" line 5542 * that specifies an instruction that performs "result = eax op ecx". 5543 * This could be an x86 instruction or a function call. (If the result 5544 * comes back in a register other than eax, you can override "result".) 5545 * 5546 * For: add-int/lit16, rsub-int, 5547 * and-int/lit16, or-int/lit16, xor-int/lit16 5548 */ 5549 /* binop/lit16 vA, vB, #+CCCC */ 5550 movzbl rINSTbl,%eax # eax<- 000000BA 5551 sarl $4,%eax # eax<- B 5552 GET_VREG_R %eax %eax # eax<- vB 5553 movswl 2(rPC),%ecx # ecx<- ssssCCCC 5554 andb $0xf,rINSTbl # rINST<- A 5555 xor %ecx,%eax # for example: addl %ecx, %eax 5556 SET_VREG %eax rINST 5557 FETCH_INST_OPCODE 2 %edx 5558 ADVANCE_PC 2 5559 GOTO_NEXT_R %edx 5560 5561 5562/* ------------------------------ */ 5563 .balign 64 5564.L_OP_ADD_INT_LIT8: /* 0xd8 */ 5565/* File: x86/OP_ADD_INT_LIT8.S */ 5566/* File: x86/binopLit8.S */ 5567 /* 5568 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5569 * that specifies an instruction that performs "result = eax op ecx". 5570 * This could be an x86 instruction or a function call. (If the result 5571 * comes back in a register other than r0, you can override "result".) 5572 * 5573 * For: add-int/lit8, rsub-int/lit8 5574 * and-int/lit8, or-int/lit8, xor-int/lit8, 5575 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5576 */ 5577 /* binop/lit8 vAA, vBB, #+CC */ 5578 movzbl 2(rPC),%eax # eax<- BB 5579 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5580 GET_VREG_R %eax %eax # eax<- rBB 5581 addl %ecx,%eax # ex: addl %ecx,%eax 5582 FETCH_INST_OPCODE 2 %edx 5583 SET_VREG %eax rINST 5584 ADVANCE_PC 2 5585 GOTO_NEXT_R %edx 5586 5587 5588/* ------------------------------ */ 5589 .balign 64 5590.L_OP_RSUB_INT_LIT8: /* 0xd9 */ 5591/* File: x86/OP_RSUB_INT_LIT8.S */ 5592/* File: x86/binopLit8.S */ 5593 /* 5594 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5595 * that specifies an instruction that performs "result = eax op ecx". 5596 * This could be an x86 instruction or a function call. (If the result 5597 * comes back in a register other than r0, you can override "result".) 5598 * 5599 * For: add-int/lit8, rsub-int/lit8 5600 * and-int/lit8, or-int/lit8, xor-int/lit8, 5601 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5602 */ 5603 /* binop/lit8 vAA, vBB, #+CC */ 5604 movzbl 2(rPC),%eax # eax<- BB 5605 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5606 GET_VREG_R %eax %eax # eax<- rBB 5607 subl %eax,%ecx # ex: addl %ecx,%eax 5608 FETCH_INST_OPCODE 2 %edx 5609 SET_VREG %ecx rINST 5610 ADVANCE_PC 2 5611 GOTO_NEXT_R %edx 5612 5613 5614/* ------------------------------ */ 5615 .balign 64 5616.L_OP_MUL_INT_LIT8: /* 0xda */ 5617/* File: x86/OP_MUL_INT_LIT8.S */ 5618 /* mul/lit8 vAA, vBB, #+CC */ 5619 movzbl 2(rPC),%eax # eax<- BB 5620 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5621 GET_VREG_R %eax %eax # eax<- rBB 5622 imull %ecx,%eax # trashes edx 5623 FETCH_INST_OPCODE 2 %edx 5624 ADVANCE_PC 2 5625 SET_VREG %eax rINST 5626 GOTO_NEXT_R %edx 5627 5628/* ------------------------------ */ 5629 .balign 64 5630.L_OP_DIV_INT_LIT8: /* 0xdb */ 5631/* File: x86/OP_DIV_INT_LIT8.S */ 5632/* File: x86/bindivLit8.S */ 5633 /* 5634 * 32-bit div/rem "lit8" binary operation. Handles special case of 5635 * op0=minint & op1=-1 5636 */ 5637 /* div/rem/lit8 vAA, vBB, #+CC */ 5638 movzbl 2(rPC),%eax # eax<- BB 5639 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5640 GET_VREG_R %eax %eax # eax<- rBB 5641 cmpl $0,%ecx 5642 je common_errDivideByZero 5643 cmpl $0x80000000,%eax 5644 jne .LOP_DIV_INT_LIT8_continue_div 5645 cmpl $-1,%ecx 5646 jne .LOP_DIV_INT_LIT8_continue_div 5647 movl $0x80000000,%eax 5648 jmp .LOP_DIV_INT_LIT8_finish_div 5649 5650 5651 5652/* ------------------------------ */ 5653 .balign 64 5654.L_OP_REM_INT_LIT8: /* 0xdc */ 5655/* File: x86/OP_REM_INT_LIT8.S */ 5656/* File: x86/bindivLit8.S */ 5657 /* 5658 * 32-bit div/rem "lit8" binary operation. Handles special case of 5659 * op0=minint & op1=-1 5660 */ 5661 /* div/rem/lit8 vAA, vBB, #+CC */ 5662 movzbl 2(rPC),%eax # eax<- BB 5663 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5664 GET_VREG_R %eax %eax # eax<- rBB 5665 cmpl $0,%ecx 5666 je common_errDivideByZero 5667 cmpl $0x80000000,%eax 5668 jne .LOP_REM_INT_LIT8_continue_div 5669 cmpl $-1,%ecx 5670 jne .LOP_REM_INT_LIT8_continue_div 5671 movl $0,%edx 5672 jmp .LOP_REM_INT_LIT8_finish_div 5673 5674 5675 5676/* ------------------------------ */ 5677 .balign 64 5678.L_OP_AND_INT_LIT8: /* 0xdd */ 5679/* File: x86/OP_AND_INT_LIT8.S */ 5680/* File: x86/binopLit8.S */ 5681 /* 5682 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5683 * that specifies an instruction that performs "result = eax op ecx". 5684 * This could be an x86 instruction or a function call. (If the result 5685 * comes back in a register other than r0, you can override "result".) 5686 * 5687 * For: add-int/lit8, rsub-int/lit8 5688 * and-int/lit8, or-int/lit8, xor-int/lit8, 5689 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5690 */ 5691 /* binop/lit8 vAA, vBB, #+CC */ 5692 movzbl 2(rPC),%eax # eax<- BB 5693 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5694 GET_VREG_R %eax %eax # eax<- rBB 5695 andl %ecx,%eax # ex: addl %ecx,%eax 5696 FETCH_INST_OPCODE 2 %edx 5697 SET_VREG %eax rINST 5698 ADVANCE_PC 2 5699 GOTO_NEXT_R %edx 5700 5701 5702/* ------------------------------ */ 5703 .balign 64 5704.L_OP_OR_INT_LIT8: /* 0xde */ 5705/* File: x86/OP_OR_INT_LIT8.S */ 5706/* File: x86/binopLit8.S */ 5707 /* 5708 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5709 * that specifies an instruction that performs "result = eax op ecx". 5710 * This could be an x86 instruction or a function call. (If the result 5711 * comes back in a register other than r0, you can override "result".) 5712 * 5713 * For: add-int/lit8, rsub-int/lit8 5714 * and-int/lit8, or-int/lit8, xor-int/lit8, 5715 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5716 */ 5717 /* binop/lit8 vAA, vBB, #+CC */ 5718 movzbl 2(rPC),%eax # eax<- BB 5719 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5720 GET_VREG_R %eax %eax # eax<- rBB 5721 orl %ecx,%eax # ex: addl %ecx,%eax 5722 FETCH_INST_OPCODE 2 %edx 5723 SET_VREG %eax rINST 5724 ADVANCE_PC 2 5725 GOTO_NEXT_R %edx 5726 5727 5728/* ------------------------------ */ 5729 .balign 64 5730.L_OP_XOR_INT_LIT8: /* 0xdf */ 5731/* File: x86/OP_XOR_INT_LIT8.S */ 5732/* File: x86/binopLit8.S */ 5733 /* 5734 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5735 * that specifies an instruction that performs "result = eax op ecx". 5736 * This could be an x86 instruction or a function call. (If the result 5737 * comes back in a register other than r0, you can override "result".) 5738 * 5739 * For: add-int/lit8, rsub-int/lit8 5740 * and-int/lit8, or-int/lit8, xor-int/lit8, 5741 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5742 */ 5743 /* binop/lit8 vAA, vBB, #+CC */ 5744 movzbl 2(rPC),%eax # eax<- BB 5745 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5746 GET_VREG_R %eax %eax # eax<- rBB 5747 xor %ecx,%eax # ex: addl %ecx,%eax 5748 FETCH_INST_OPCODE 2 %edx 5749 SET_VREG %eax rINST 5750 ADVANCE_PC 2 5751 GOTO_NEXT_R %edx 5752 5753 5754/* ------------------------------ */ 5755 .balign 64 5756.L_OP_SHL_INT_LIT8: /* 0xe0 */ 5757/* File: x86/OP_SHL_INT_LIT8.S */ 5758/* File: x86/binopLit8.S */ 5759 /* 5760 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5761 * that specifies an instruction that performs "result = eax op ecx". 5762 * This could be an x86 instruction or a function call. (If the result 5763 * comes back in a register other than r0, you can override "result".) 5764 * 5765 * For: add-int/lit8, rsub-int/lit8 5766 * and-int/lit8, or-int/lit8, xor-int/lit8, 5767 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5768 */ 5769 /* binop/lit8 vAA, vBB, #+CC */ 5770 movzbl 2(rPC),%eax # eax<- BB 5771 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5772 GET_VREG_R %eax %eax # eax<- rBB 5773 sall %cl,%eax # ex: addl %ecx,%eax 5774 FETCH_INST_OPCODE 2 %edx 5775 SET_VREG %eax rINST 5776 ADVANCE_PC 2 5777 GOTO_NEXT_R %edx 5778 5779 5780/* ------------------------------ */ 5781 .balign 64 5782.L_OP_SHR_INT_LIT8: /* 0xe1 */ 5783/* File: x86/OP_SHR_INT_LIT8.S */ 5784/* File: x86/binopLit8.S */ 5785 /* 5786 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5787 * that specifies an instruction that performs "result = eax op ecx". 5788 * This could be an x86 instruction or a function call. (If the result 5789 * comes back in a register other than r0, you can override "result".) 5790 * 5791 * For: add-int/lit8, rsub-int/lit8 5792 * and-int/lit8, or-int/lit8, xor-int/lit8, 5793 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5794 */ 5795 /* binop/lit8 vAA, vBB, #+CC */ 5796 movzbl 2(rPC),%eax # eax<- BB 5797 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5798 GET_VREG_R %eax %eax # eax<- rBB 5799 sarl %cl,%eax # ex: addl %ecx,%eax 5800 FETCH_INST_OPCODE 2 %edx 5801 SET_VREG %eax rINST 5802 ADVANCE_PC 2 5803 GOTO_NEXT_R %edx 5804 5805 5806/* ------------------------------ */ 5807 .balign 64 5808.L_OP_USHR_INT_LIT8: /* 0xe2 */ 5809/* File: x86/OP_USHR_INT_LIT8.S */ 5810/* File: x86/binopLit8.S */ 5811 /* 5812 * Generic 32-bit "lit8" binary operation. Provide an "instr" line 5813 * that specifies an instruction that performs "result = eax op ecx". 5814 * This could be an x86 instruction or a function call. (If the result 5815 * comes back in a register other than r0, you can override "result".) 5816 * 5817 * For: add-int/lit8, rsub-int/lit8 5818 * and-int/lit8, or-int/lit8, xor-int/lit8, 5819 * shl-int/lit8, shr-int/lit8, ushr-int/lit8 5820 */ 5821 /* binop/lit8 vAA, vBB, #+CC */ 5822 movzbl 2(rPC),%eax # eax<- BB 5823 movsbl 3(rPC),%ecx # ecx<- ssssssCC 5824 GET_VREG_R %eax %eax # eax<- rBB 5825 shrl %cl,%eax # ex: addl %ecx,%eax 5826 FETCH_INST_OPCODE 2 %edx 5827 SET_VREG %eax rINST 5828 ADVANCE_PC 2 5829 GOTO_NEXT_R %edx 5830 5831 5832/* ------------------------------ */ 5833 .balign 64 5834.L_OP_IGET_VOLATILE: /* 0xe3 */ 5835/* File: x86/OP_IGET_VOLATILE.S */ 5836/* File: x86/OP_IGET.S */ 5837 /* 5838 * General 32-bit instance field get. 5839 * 5840 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 5841 */ 5842 /* op vA, vB, field@CCCC */ 5843 movl rGLUE,%ecx 5844 movzwl 2(rPC),%edx # edx<- 0000CCCC 5845 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 5846 movzbl rINSTbl,%ecx # ecx<- BA 5847 sarl $4,%ecx # ecx<- B 5848 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 5849 andb $0xf,rINSTbl # rINST<- A 5850 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 5851 movl (%eax,%edx,4),%eax # resolved entry 5852 testl %eax,%eax # is resolved entry null? 5853 jne .LOP_IGET_VOLATILE_finish # no, already resolved 5854 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 5855 movl rGLUE,%edx 5856 jmp .LOP_IGET_VOLATILE_resolve 5857 5858 5859/* ------------------------------ */ 5860 .balign 64 5861.L_OP_IPUT_VOLATILE: /* 0xe4 */ 5862/* File: x86/OP_IPUT_VOLATILE.S */ 5863/* File: x86/OP_IPUT.S */ 5864 5865 /* 5866 * General 32-bit instance field put. 5867 * 5868 * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-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_IPUT_VOLATILE_finish # no, already resolved 5882 movl %edx,OUT_ARG1(%esp) 5883 movl rGLUE,%edx 5884 jmp .LOP_IPUT_VOLATILE_resolve 5885 5886 5887/* ------------------------------ */ 5888 .balign 64 5889.L_OP_SGET_VOLATILE: /* 0xe5 */ 5890/* File: x86/OP_SGET_VOLATILE.S */ 5891/* File: x86/OP_SGET.S */ 5892 /* 5893 * General 32-bit SGET handler. 5894 * 5895 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 5896 */ 5897 /* op vAA, field@BBBB */ 5898 movl rGLUE,%ecx 5899 movzwl 2(rPC),%eax # eax<- field ref BBBB 5900 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 5901 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 5902 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 5903 testl %eax,%eax # resolved entry null? 5904 je .LOP_SGET_VOLATILE_resolve # if not, make it so 5905.LOP_SGET_VOLATILE_finish: # field ptr in eax 5906 movl offStaticField_value(%eax),%eax 5907 FETCH_INST_OPCODE 2 %edx 5908 ADVANCE_PC 2 5909 SET_VREG %eax rINST 5910 GOTO_NEXT_R %edx 5911 5912 5913/* ------------------------------ */ 5914 .balign 64 5915.L_OP_SPUT_VOLATILE: /* 0xe6 */ 5916/* File: x86/OP_SPUT_VOLATILE.S */ 5917/* File: x86/OP_SPUT.S */ 5918 /* 5919 * General 32-bit SPUT handler. 5920 * 5921 * for: sput, sput-boolean, sput-byte, sput-char, sput-short 5922 */ 5923 /* op vAA, field@BBBB */ 5924 movl rGLUE,%ecx 5925 movzwl 2(rPC),%eax # eax<- field ref BBBB 5926 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 5927 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 5928 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 5929 testl %eax,%eax # resolved entry null? 5930 je .LOP_SPUT_VOLATILE_resolve # if not, make it so 5931.LOP_SPUT_VOLATILE_finish: # field ptr in eax 5932 GET_VREG_R %ecx rINST 5933 FETCH_INST_OPCODE 2 %edx 5934 ADVANCE_PC 2 5935 movl %ecx,offStaticField_value(%eax) 5936 GOTO_NEXT_R %edx 5937 5938 5939/* ------------------------------ */ 5940 .balign 64 5941.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ 5942/* File: x86/OP_IGET_OBJECT_VOLATILE.S */ 5943/* File: x86/OP_IGET.S */ 5944 /* 5945 * General 32-bit instance field get. 5946 * 5947 * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short 5948 */ 5949 /* op vA, vB, field@CCCC */ 5950 movl rGLUE,%ecx 5951 movzwl 2(rPC),%edx # edx<- 0000CCCC 5952 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 5953 movzbl rINSTbl,%ecx # ecx<- BA 5954 sarl $4,%ecx # ecx<- B 5955 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 5956 andb $0xf,rINSTbl # rINST<- A 5957 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 5958 movl (%eax,%edx,4),%eax # resolved entry 5959 testl %eax,%eax # is resolved entry null? 5960 jne .LOP_IGET_OBJECT_VOLATILE_finish # no, already resolved 5961 movl %edx,OUT_ARG1(%esp) # needed by dvmResolveInstField 5962 movl rGLUE,%edx 5963 jmp .LOP_IGET_OBJECT_VOLATILE_resolve 5964 5965 5966/* ------------------------------ */ 5967 .balign 64 5968.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ 5969 /* (stub) */ 5970 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx 5971 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 5972 call dvmMterp_OP_IGET_WIDE_VOLATILE # do the real work 5973 mov rGLUE,%ecx 5974 LOAD_PC_FP_FROM_GLUE # retrieve updated values 5975 FETCH_INST 5976 GOTO_NEXT 5977/* ------------------------------ */ 5978 .balign 64 5979.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */ 5980 /* (stub) */ 5981 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx 5982 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 5983 call dvmMterp_OP_IPUT_WIDE_VOLATILE # do the real work 5984 mov rGLUE,%ecx 5985 LOAD_PC_FP_FROM_GLUE # retrieve updated values 5986 FETCH_INST 5987 GOTO_NEXT 5988/* ------------------------------ */ 5989 .balign 64 5990.L_OP_SGET_WIDE_VOLATILE: /* 0xea */ 5991 /* (stub) */ 5992 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx 5993 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 5994 call dvmMterp_OP_SGET_WIDE_VOLATILE # do the real work 5995 mov rGLUE,%ecx 5996 LOAD_PC_FP_FROM_GLUE # retrieve updated values 5997 FETCH_INST 5998 GOTO_NEXT 5999/* ------------------------------ */ 6000 .balign 64 6001.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */ 6002 /* (stub) */ 6003 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx 6004 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 6005 call dvmMterp_OP_SPUT_WIDE_VOLATILE # do the real work 6006 mov rGLUE,%ecx 6007 LOAD_PC_FP_FROM_GLUE # retrieve updated values 6008 FETCH_INST 6009 GOTO_NEXT 6010/* ------------------------------ */ 6011 .balign 64 6012.L_OP_BREAKPOINT: /* 0xec */ 6013/* File: x86/OP_BREAKPOINT.S */ 6014/* File: x86/unused.S */ 6015 jmp common_abort 6016 6017 6018/* ------------------------------ */ 6019 .balign 64 6020.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */ 6021/* File: x86/OP_THROW_VERIFICATION_ERROR.S */ 6022 /* 6023 * Handle a throw-verification-error instruction. This throws an 6024 * exception for an error discovered during verification. The 6025 * exception is indicated by AA, with some detail provided by BBBB. 6026 */ 6027 /* op AA, ref@BBBB */ 6028 movl rGLUE,%ecx 6029 movzwl 2(rPC),%eax # eax<- BBBB 6030 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6031 EXPORT_PC 6032 movl %eax,OUT_ARG2(%esp) # arg2<- BBBB 6033 movl rINST,OUT_ARG1(%esp) # arg1<- AA 6034 movl %ecx,OUT_ARG0(%esp) # arg0<- method 6035 call dvmThrowVerificationError # call(method, kind, ref) 6036 jmp common_exceptionThrown # handle exception 6037 6038/* ------------------------------ */ 6039 .balign 64 6040.L_OP_EXECUTE_INLINE: /* 0xee */ 6041/* File: x86/OP_EXECUTE_INLINE.S */ 6042 /* 6043 * Execute a "native inline" instruction. 6044 * 6045 * We will be calling through a function table: 6046 * 6047 * (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, pResult) 6048 * 6049 * Ignores argument count - always loads 4. 6050 * 6051 */ 6052 /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */ 6053 movl rGLUE,%ecx 6054 EXPORT_PC 6055 movzwl 2(rPC),%eax # eax<- BBBB 6056 leal offGlue_retval(%ecx),%ecx # ecx<- & glue->retval 6057 movl %ecx,OUT_ARG4(%esp) 6058 call .LOP_EXECUTE_INLINE_continue # make call; will return after 6059 testl %eax,%eax # successful? 6060 FETCH_INST_OPCODE 3 %edx 6061 je common_exceptionThrown # no, handle exception 6062 ADVANCE_PC 3 6063 GOTO_NEXT_R %edx 6064 6065/* ------------------------------ */ 6066 .balign 64 6067.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */ 6068 /* (stub) */ 6069 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx 6070 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 6071 call dvmMterp_OP_EXECUTE_INLINE_RANGE # do the real work 6072 mov rGLUE,%ecx 6073 LOAD_PC_FP_FROM_GLUE # retrieve updated values 6074 FETCH_INST 6075 GOTO_NEXT 6076/* ------------------------------ */ 6077 .balign 64 6078.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */ 6079/* File: x86/OP_INVOKE_DIRECT_EMPTY.S */ 6080 /* 6081 * invoke-direct-empty is a no-op in a "standard" interpreter. 6082 */ 6083 FETCH_INST_WORD 3 6084 ADVANCE_PC 3 6085 GOTO_NEXT 6086 6087/* ------------------------------ */ 6088 .balign 64 6089.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */ 6090 /* (stub) */ 6091 SAVE_PC_FP_TO_GLUE %ecx # leaves rGLUE in %ecx 6092 movl %ecx,OUT_ARG0(%esp) # glue is first arg to function 6093 call dvmMterp_OP_RETURN_VOID_BARRIER # do the real work 6094 mov rGLUE,%ecx 6095 LOAD_PC_FP_FROM_GLUE # retrieve updated values 6096 FETCH_INST 6097 GOTO_NEXT 6098/* ------------------------------ */ 6099 .balign 64 6100.L_OP_IGET_QUICK: /* 0xf2 */ 6101/* File: x86/OP_IGET_QUICK.S */ 6102 /* For: iget-quick, iget-object-quick */ 6103 /* op vA, vB, offset@CCCC */ 6104 movzbl rINSTbl,%ecx # ecx<- BA 6105 sarl $4,%ecx # ecx<- B 6106 GET_VREG_R %ecx %ecx # vB (object we're operating on) 6107 movzwl 2(rPC),%eax # eax<- field byte offset 6108 cmpl $0,%ecx # is object null? 6109 je common_errNullObject 6110 movl (%ecx,%eax,1),%eax 6111 FETCH_INST_OPCODE 2 %edx 6112 ADVANCE_PC 2 6113 andb $0xf,rINSTbl # rINST<- A 6114 SET_VREG %eax rINST # fp[A]<- result 6115 GOTO_NEXT_R %edx 6116 6117/* ------------------------------ */ 6118 .balign 64 6119.L_OP_IGET_WIDE_QUICK: /* 0xf3 */ 6120/* File: x86/OP_IGET_WIDE_QUICK.S */ 6121 /* For: iget-wide-quick */ 6122 /* op vA, vB, offset@CCCC */ 6123 movzbl rINSTbl,%ecx # ecx<- BA 6124 sarl $4,%ecx # ecx<- B 6125 GET_VREG_R %ecx %ecx # vB (object we're operating on) 6126 movzwl 2(rPC),%eax # eax<- field byte offset 6127 cmpl $0,%ecx # is object null? 6128 je common_errNullObject 6129 leal (%ecx,%eax,1),%eax # eax<- address of 64-bit source 6130 movl (%eax),%ecx # ecx<- lsw 6131 movl 4(%eax),%eax # eax<- msw 6132 andb $0xf,rINSTbl # rINST<- A 6133 FETCH_INST_OPCODE 2 %edx 6134 SET_VREG_WORD %ecx rINST 0 # v[A+0]<- lsw 6135 SET_VREG_WORD %eax rINST 1 # v[A+1]<- msw 6136 ADVANCE_PC 2 6137 GOTO_NEXT_R %edx 6138 6139/* ------------------------------ */ 6140 .balign 64 6141.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */ 6142/* File: x86/OP_IGET_OBJECT_QUICK.S */ 6143/* File: x86/OP_IGET_QUICK.S */ 6144 /* For: iget-quick, iget-object-quick */ 6145 /* op vA, vB, offset@CCCC */ 6146 movzbl rINSTbl,%ecx # ecx<- BA 6147 sarl $4,%ecx # ecx<- B 6148 GET_VREG_R %ecx %ecx # vB (object we're operating on) 6149 movzwl 2(rPC),%eax # eax<- field byte offset 6150 cmpl $0,%ecx # is object null? 6151 je common_errNullObject 6152 movl (%ecx,%eax,1),%eax 6153 FETCH_INST_OPCODE 2 %edx 6154 ADVANCE_PC 2 6155 andb $0xf,rINSTbl # rINST<- A 6156 SET_VREG %eax rINST # fp[A]<- result 6157 GOTO_NEXT_R %edx 6158 6159 6160/* ------------------------------ */ 6161 .balign 64 6162.L_OP_IPUT_QUICK: /* 0xf5 */ 6163/* File: x86/OP_IPUT_QUICK.S */ 6164 /* For: iput-quick */ 6165 /* op vA, vB, offset@CCCC */ 6166 movzbl rINSTbl,%ecx # ecx<- BA 6167 sarl $4,%ecx # ecx<- B 6168 GET_VREG_R %ecx %ecx # vB (object we're operating on) 6169 andb $0xf,rINSTbl # rINST<- A 6170 GET_VREG_R rINST,rINST # rINST<- v[A] 6171 movzwl 2(rPC),%eax # eax<- field byte offset 6172 testl %ecx,%ecx # is object null? 6173 FETCH_INST_OPCODE 2 %edx 6174 je common_errNullObject 6175 movl rINST,(%ecx,%eax,1) 6176 ADVANCE_PC 2 6177 GOTO_NEXT_R %edx 6178 6179/* ------------------------------ */ 6180 .balign 64 6181.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */ 6182/* File: x86/OP_IPUT_WIDE_QUICK.S */ 6183 /* For: iput-wide-quick */ 6184 /* op vA, vB, offset@CCCC */ 6185 movzbl rINSTbl,%ecx # ecx<- BA 6186 sarl $4,%ecx # ecx<- B 6187 GET_VREG_R %ecx %ecx # vB (object we're operating on) 6188 movzwl 2(rPC),%eax # eax<- field byte offset 6189 testl %ecx,%ecx # is object null? 6190 je common_errNullObject 6191 leal (%ecx,%eax,1),%ecx # ecx<- Address of 64-bit target 6192 andb $0xf,rINSTbl # rINST<- A 6193 GET_VREG_WORD %eax rINST 0 # eax<- lsw 6194 GET_VREG_WORD rINST rINST 1 # rINST<- msw 6195 FETCH_INST_OPCODE 2 %edx 6196 movl %eax,(%ecx) 6197 movl rINST,4(%ecx) 6198 ADVANCE_PC 2 6199 GOTO_NEXT_R %edx 6200 6201/* ------------------------------ */ 6202 .balign 64 6203.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */ 6204/* File: x86/OP_IPUT_OBJECT_QUICK.S */ 6205 /* For: iput-object-quick */ 6206 /* op vA, vB, offset@CCCC */ 6207 movzbl rINSTbl,%ecx # ecx<- BA 6208 sarl $4,%ecx # ecx<- B 6209 GET_VREG_R %ecx %ecx # vB (object we're operating on) 6210 andb $0xf,rINSTbl # rINST<- A 6211 GET_VREG_R rINST rINST # rINST<- v[A] 6212 movzwl 2(rPC),%eax # eax<- field byte offset 6213 testl %ecx,%ecx # is object null? 6214 je common_errNullObject 6215 movl rINST,(%ecx,%eax,1) 6216 movl rGLUE,%eax 6217 jmp .LOP_IPUT_OBJECT_QUICK_finish 6218 6219/* ------------------------------ */ 6220 .balign 64 6221.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */ 6222/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */ 6223 /* 6224 * Handle an optimized virtual method call. 6225 * 6226 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 6227 */ 6228 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6229 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6230 movzwl 4(rPC),%eax # eax<- FEDC or CCCC 6231 movzwl 2(rPC),%ecx # ecx<- BBBB 6232 .if (!0) 6233 andl $0xf,%eax # eax<- C (or stays CCCC) 6234 .endif 6235 GET_VREG_R %eax %eax # eax<- vC ("this" ptr) 6236 testl %eax,%eax # null? 6237 je common_errNullObject # yep, throw exception 6238 movl offObject_clazz(%eax),%eax # eax<- thisPtr->clazz 6239 movl offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable 6240 EXPORT_PC # might throw later - get ready 6241 movl (%eax,%ecx,4),%eax # eax<- vtable[BBBB] 6242 jmp common_invokeMethodNoRange 6243 6244/* ------------------------------ */ 6245 .balign 64 6246.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */ 6247/* File: x86/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */ 6248/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */ 6249 /* 6250 * Handle an optimized virtual method call. 6251 * 6252 * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range 6253 */ 6254 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6255 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6256 movzwl 4(rPC),%eax # eax<- FEDC or CCCC 6257 movzwl 2(rPC),%ecx # ecx<- BBBB 6258 .if (!1) 6259 andl $0xf,%eax # eax<- C (or stays CCCC) 6260 .endif 6261 GET_VREG_R %eax %eax # eax<- vC ("this" ptr) 6262 testl %eax,%eax # null? 6263 je common_errNullObject # yep, throw exception 6264 movl offObject_clazz(%eax),%eax # eax<- thisPtr->clazz 6265 movl offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable 6266 EXPORT_PC # might throw later - get ready 6267 movl (%eax,%ecx,4),%eax # eax<- vtable[BBBB] 6268 jmp common_invokeMethodRange 6269 6270 6271/* ------------------------------ */ 6272 .balign 64 6273.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */ 6274/* File: x86/OP_INVOKE_SUPER_QUICK.S */ 6275 /* 6276 * Handle an optimized "super" method call. 6277 * 6278 * for: [opt] invoke-super-quick, invoke-super-quick/range 6279 */ 6280 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6281 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6282 movl rGLUE,%ecx 6283 movzwl 4(rPC),%eax # eax<- GFED or CCCC 6284 movl offGlue_method(%ecx),%ecx # ecx<- current method 6285 .if (!0) 6286 andl $0xf,%eax # eax<- D (or stays CCCC) 6287 .endif 6288 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6289 GET_VREG_R %eax %eax # eax<- "this" 6290 movl offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super 6291 testl %eax,%eax # null "this"? 6292 je common_errNullObject # "this" is null, throw exception 6293 movzwl 2(rPC),%eax # eax<- BBBB 6294 movl offClassObject_vtable(%ecx),%ecx # ecx<- vtable 6295 EXPORT_PC 6296 movl (%ecx,%eax,4),%eax # eax<- super->vtable[BBBB] 6297 jmp common_invokeMethodNoRange 6298 6299/* ------------------------------ */ 6300 .balign 64 6301.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */ 6302/* File: x86/OP_INVOKE_SUPER_QUICK_RANGE.S */ 6303/* File: x86/OP_INVOKE_SUPER_QUICK.S */ 6304 /* 6305 * Handle an optimized "super" method call. 6306 * 6307 * for: [opt] invoke-super-quick, invoke-super-quick/range 6308 */ 6309 /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */ 6310 /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */ 6311 movl rGLUE,%ecx 6312 movzwl 4(rPC),%eax # eax<- GFED or CCCC 6313 movl offGlue_method(%ecx),%ecx # ecx<- current method 6314 .if (!1) 6315 andl $0xf,%eax # eax<- D (or stays CCCC) 6316 .endif 6317 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6318 GET_VREG_R %eax %eax # eax<- "this" 6319 movl offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super 6320 testl %eax,%eax # null "this"? 6321 je common_errNullObject # "this" is null, throw exception 6322 movzwl 2(rPC),%eax # eax<- BBBB 6323 movl offClassObject_vtable(%ecx),%ecx # ecx<- vtable 6324 EXPORT_PC 6325 movl (%ecx,%eax,4),%eax # eax<- super->vtable[BBBB] 6326 jmp common_invokeMethodRange 6327 6328 6329/* ------------------------------ */ 6330 .balign 64 6331.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ 6332/* File: x86/OP_IPUT_OBJECT_VOLATILE.S */ 6333/* File: x86/OP_IPUT_OBJECT.S */ 6334 /* 6335 * Object field put. 6336 * 6337 * for: iput-object 6338 */ 6339 /* op vA, vB, field@CCCC */ 6340 movl rGLUE,%ecx 6341 movzwl 2(rPC),%edx # edx<- 0000CCCC 6342 movl offGlue_methodClassDex(%ecx),%eax # eax<- DvmDex 6343 movzbl rINSTbl,%ecx # ecx<- BA 6344 sarl $4,%ecx # ecx<- B 6345 movl offDvmDex_pResFields(%eax),%eax # eax<- pDvmDex->pResFields 6346 andb $0xf,rINSTbl # rINST<- A 6347 GET_VREG_R %ecx %ecx # ecx<- fp[B], the object ptr 6348 movl (%eax,%edx,4),%eax # resolved entry 6349 testl %eax,%eax # is resolved entry null? 6350 jne .LOP_IPUT_OBJECT_VOLATILE_finish # no, already resolved 6351 movl %edx,OUT_ARG1(%esp) 6352 movl rGLUE,%edx 6353 jmp .LOP_IPUT_OBJECT_VOLATILE_resolve 6354 6355 6356/* ------------------------------ */ 6357 .balign 64 6358.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ 6359/* File: x86/OP_SGET_OBJECT_VOLATILE.S */ 6360/* File: x86/OP_SGET.S */ 6361 /* 6362 * General 32-bit SGET handler. 6363 * 6364 * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short 6365 */ 6366 /* op vAA, field@BBBB */ 6367 movl rGLUE,%ecx 6368 movzwl 2(rPC),%eax # eax<- field ref BBBB 6369 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 6370 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 6371 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField ptr 6372 testl %eax,%eax # resolved entry null? 6373 je .LOP_SGET_OBJECT_VOLATILE_resolve # if not, make it so 6374.LOP_SGET_OBJECT_VOLATILE_finish: # field ptr in eax 6375 movl offStaticField_value(%eax),%eax 6376 FETCH_INST_OPCODE 2 %edx 6377 ADVANCE_PC 2 6378 SET_VREG %eax rINST 6379 GOTO_NEXT_R %edx 6380 6381 6382/* ------------------------------ */ 6383 .balign 64 6384.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ 6385/* File: x86/OP_SPUT_OBJECT_VOLATILE.S */ 6386/* File: x86/OP_SPUT_OBJECT.S */ 6387 /* 6388 * SPUT object handler. 6389 */ 6390 /* op vAA, field@BBBB */ 6391 movl rGLUE,%ecx 6392 movzwl 2(rPC),%eax # eax<- field ref BBBB 6393 movl offGlue_methodClassDex(%ecx),%ecx # ecx<- DvmDex 6394 movl offDvmDex_pResFields(%ecx),%ecx # ecx<- dvmDex->pResFields 6395 movl (%ecx,%eax,4),%eax # eax<- resolved StaticField 6396 testl %eax,%eax # resolved entry null? 6397 je .LOP_SPUT_OBJECT_VOLATILE_resolve # if not, make it so 6398.LOP_SPUT_OBJECT_VOLATILE_finish: # field ptr in eax 6399 movzbl rINSTbl,%ecx # ecx<- AA 6400 GET_VREG_R %ecx %ecx 6401 jmp .LOP_SPUT_OBJECT_VOLATILE_continue 6402 6403 6404/* ------------------------------ */ 6405 .balign 64 6406.L_OP_UNUSED_FF: /* 0xff */ 6407/* File: x86/OP_UNUSED_FF.S */ 6408/* File: x86/unused.S */ 6409 jmp common_abort 6410 6411 6412 6413 .balign 64 6414 .size dvmAsmInstructionStart, .-dvmAsmInstructionStart 6415 .global dvmAsmInstructionEnd 6416dvmAsmInstructionEnd: 6417 6418/* 6419 * =========================================================================== 6420 * Sister implementations 6421 * =========================================================================== 6422 */ 6423 .global dvmAsmSisterStart 6424 .type dvmAsmSisterStart, %function 6425 .text 6426 .balign 4 6427dvmAsmSisterStart: 6428 6429/* continuation for OP_CONST_STRING */ 6430 6431/* This is the less common path, so we'll redo some work 6432 here rather than force spills on the common path */ 6433.LOP_CONST_STRING_resolve: 6434 movl rGLUE,%eax 6435 movl %ecx,rINST # rINST<- AA 6436 EXPORT_PC 6437 movl offGlue_method(%eax),%eax # eax<- glue->method 6438 movzwl 2(rPC),%ecx # ecx<- BBBB 6439 movl offMethod_clazz(%eax),%eax 6440 movl %ecx,OUT_ARG1(%esp) 6441 movl %eax,OUT_ARG0(%esp) 6442 call dvmResolveString # go resolve 6443 testl %eax,%eax # failed? 6444 je common_exceptionThrown 6445 SET_VREG %eax rINST 6446 FETCH_INST_OPCODE 2 %edx 6447 ADVANCE_PC 2 6448 GOTO_NEXT_R %edx 6449 6450/* continuation for OP_CONST_STRING_JUMBO */ 6451 6452/* This is the less common path, so we'll redo some work 6453 here rather than force spills on the common path */ 6454.LOP_CONST_STRING_JUMBO_resolve: 6455 movl rGLUE,%eax 6456 movl %ecx,rINST # rINST<- AA 6457 EXPORT_PC 6458 movl offGlue_method(%eax),%eax # eax<- glue->method 6459 movl 2(rPC),%ecx # ecx<- BBBBBBBB 6460 movl offMethod_clazz(%eax),%eax 6461 movl %ecx,OUT_ARG1(%esp) 6462 movl %eax,OUT_ARG0(%esp) 6463 call dvmResolveString # go resolve 6464 testl %eax,%eax # failed? 6465 je common_exceptionThrown 6466 SET_VREG %eax rINST 6467 FETCH_INST_OPCODE 3 %edx 6468 ADVANCE_PC 3 6469 GOTO_NEXT_R %edx 6470 6471/* continuation for OP_CONST_CLASS */ 6472 6473/* This is the less common path, so we'll redo some work 6474 here rather than force spills on the common path */ 6475.LOP_CONST_CLASS_resolve: 6476 movl rGLUE,%eax 6477 movl %ecx,rINST # rINST<- AA 6478 EXPORT_PC 6479 movl offGlue_method(%eax),%eax # eax<- glue->method 6480 movl $1,OUT_ARG2(%esp) # true 6481 movzwl 2(rPC),%ecx # ecx<- BBBB 6482 movl offMethod_clazz(%eax),%eax 6483 movl %ecx,OUT_ARG1(%esp) 6484 movl %eax,OUT_ARG0(%esp) 6485 call dvmResolveClass # go resolve 6486 testl %eax,%eax # failed? 6487 je common_exceptionThrown 6488 SET_VREG %eax rINST 6489 FETCH_INST_OPCODE 2 %edx 6490 ADVANCE_PC 2 6491 GOTO_NEXT_R %edx 6492 6493/* continuation for OP_MONITOR_ENTER */ 6494 6495.LOP_MONITOR_ENTER_continue: 6496 movl %ecx,OUT_ARG0(%esp) 6497 movl %eax,OUT_ARG1(%esp) 6498 call dvmLockObject # dvmLockObject(self,object) 6499#ifdef WITH_DEADLOCK_PREDICTION 6500 movl rGLUE,%ecx 6501 movl offGlueSelf(%ecx),%ecx # ecx<- glue->self 6502 movl offThread_exception(%ecx),%eax 6503 testl %eax,%eax 6504 jne common_exceptionThrown 6505#endif 6506 ADVANCE_PC 1 6507 GOTO_NEXT 6508 6509/* continuation for OP_MONITOR_EXIT */ 6510 6511.LOP_MONITOR_EXIT_continue: 6512 call dvmUnlockObject # unlock(self,obj) 6513 FETCH_INST_OPCODE 1 %edx 6514 testl %eax,%eax # success? 6515 ADVANCE_PC 1 6516 je common_exceptionThrown # no, exception pending 6517 GOTO_NEXT_R %edx 6518.LOP_MONITOR_EXIT_errNullObject: 6519 ADVANCE_PC 1 # advance before throw 6520 jmp common_errNullObject 6521 6522/* continuation for OP_CHECK_CAST */ 6523 6524 /* 6525 * Trivial test failed, need to perform full check. This is common. 6526 * ecx holds obj->clazz 6527 * eax holds class resolved from BBBB 6528 * rINST holds object 6529 */ 6530.LOP_CHECK_CAST_fullcheck: 6531 movl %eax,OUT_ARG1(%esp) 6532 movl %ecx,OUT_ARG0(%esp) 6533 call dvmInstanceofNonTrivial # eax<- boolean result 6534 testl %eax,%eax # failed? 6535 jne .LOP_CHECK_CAST_okay # no, success 6536 6537 # A cast has failed. We need to throw a ClassCastException with the 6538 # class of the object that failed to be cast. 6539 EXPORT_PC 6540 movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz 6541 movl $.LstrClassCastException,%eax 6542 movl offClassObject_descriptor(%ecx),%ecx 6543 movl %eax,OUT_ARG0(%esp) # arg0<- message 6544 movl %ecx,OUT_ARG1(%esp) # arg1<- obj->clazz->descriptor 6545 call dvmThrowExceptionWithClassMessage 6546 jmp common_exceptionThrown 6547 6548 /* 6549 * Resolution required. This is the least-likely path, and we're 6550 * going to have to recreate some data. 6551 * 6552 * rINST holds object 6553 */ 6554.LOP_CHECK_CAST_resolve: 6555 movl rGLUE,%ecx 6556 EXPORT_PC 6557 movzwl 2(rPC),%eax # eax<- BBBB 6558 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6559 movl %eax,OUT_ARG1(%esp) # arg1<- BBBB 6560 movl offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz 6561 movl $0,OUT_ARG2(%esp) # arg2<- false 6562 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz 6563 call dvmResolveClass # eax<- resolved ClassObject ptr 6564 testl %eax,%eax # got null? 6565 je common_exceptionThrown # yes, handle exception 6566 movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz 6567 jmp .LOP_CHECK_CAST_resolved # pick up where we left off 6568 6569/* continuation for OP_INSTANCE_OF */ 6570 6571 /* 6572 * Trivial test failed, need to perform full check. This is common. 6573 * eax holds obj->clazz 6574 * ecx holds class resolved from BBBB 6575 * rINST has BA 6576 */ 6577.LOP_INSTANCE_OF_fullcheck: 6578 movl %eax,OUT_ARG0(%esp) 6579 movl %ecx,OUT_ARG1(%esp) 6580 call dvmInstanceofNonTrivial # eax<- boolean result 6581 # fall through to OP_INSTANCE_OF_store 6582 6583 /* 6584 * eax holds boolean result 6585 * rINST holds BA 6586 */ 6587.LOP_INSTANCE_OF_store: 6588 FETCH_INST_OPCODE 2 %edx 6589 andb $0xf,rINSTbl # <- A 6590 ADVANCE_PC 2 6591 SET_VREG %eax rINST # vA<- eax 6592 GOTO_NEXT_R %edx 6593 6594 /* 6595 * Trivial test succeeded, save and bail. 6596 * r9 holds A 6597 */ 6598.LOP_INSTANCE_OF_trivial: 6599 FETCH_INST_OPCODE 2 %edx 6600 andb $0xf,rINSTbl # <- A 6601 ADVANCE_PC 2 6602 movl $1,%eax 6603 SET_VREG %eax rINST # vA<- true 6604 GOTO_NEXT_R %edx 6605 6606 /* 6607 * Resolution required. This is the least-likely path. 6608 * 6609 * edx holds BBBB 6610 * rINST holds BA 6611 */ 6612.LOP_INSTANCE_OF_resolve: 6613 movl %edx,OUT_ARG1(%esp) # arg1<- BBBB 6614 movl rGLUE,%ecx 6615 movl offGlue_method(%ecx),%ecx 6616 movl $1,OUT_ARG2(%esp) # arg2<- true 6617 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6618 EXPORT_PC 6619 movl %ecx,OUT_ARG0(%esp) # arg0<- method->clazz 6620 call dvmResolveClass # eax<- resolved ClassObject ptr 6621 testl %eax,%eax # success? 6622 je common_exceptionThrown # no, handle exception 6623/* Now, we need to sync up with fast path. We need eax to 6624 * hold the obj->clazz, and ecx to hold the resolved class 6625 */ 6626 movl %eax,%ecx # ecx<- resolved class 6627 movl rINST,%eax # eax<- BA 6628 sarl $4,%eax # eax<- B 6629 GET_VREG_R %eax %eax # eax<- vB (obj) 6630 movl offObject_clazz(%eax),%eax # eax<- obj->clazz 6631 jmp .LOP_INSTANCE_OF_resolved 6632 6633/* continuation for OP_NEW_INSTANCE */ 6634 6635.LOP_NEW_INSTANCE_initialized: # on entry, ecx<- class 6636 /* TODO: remove test for interface/abstract, now done in verifier */ 6637 testl $(ACC_INTERFACE|ACC_ABSTRACT),offClassObject_accessFlags(%ecx) 6638 movl $ALLOC_DONT_TRACK,OUT_ARG1(%esp) 6639 jne .LOP_NEW_INSTANCE_abstract 6640.LOP_NEW_INSTANCE_finish: # ecx=class 6641 movl %ecx,OUT_ARG0(%esp) 6642 call dvmAllocObject # eax<- new object 6643 FETCH_INST_OPCODE 2 %edx 6644 testl %eax,%eax # success? 6645 je common_exceptionThrown # no, bail out 6646 SET_VREG %eax rINST 6647 ADVANCE_PC 2 6648 GOTO_NEXT_R %edx 6649 6650 /* 6651 * Class initialization required. 6652 * 6653 * ecx holds class object 6654 */ 6655.LOP_NEW_INSTANCE_needinit: 6656 SPILL_TMP1(%ecx) # save object 6657 movl %ecx,OUT_ARG0(%esp) 6658 call dvmInitClass # initialize class 6659 UNSPILL_TMP1(%ecx) # restore object 6660 testl %eax,%eax # success? 6661 jne .LOP_NEW_INSTANCE_initialized # success, continue 6662 jmp common_exceptionThrown # go deal with init exception 6663 6664 /* 6665 * Resolution required. This is the least-likely path. 6666 * 6667 */ 6668.LOP_NEW_INSTANCE_resolve: 6669 movl rGLUE,%ecx 6670 movzwl 2(rPC),%eax 6671 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6672 movl %eax,OUT_ARG1(%esp) 6673 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6674 movl $0,OUT_ARG2(%esp) 6675 movl %ecx,OUT_ARG0(%esp) 6676 call dvmResolveClass # call(clazz,off,flags) 6677 movl %eax,%ecx # ecx<- resolved ClassObject ptr 6678 testl %ecx,%ecx # success? 6679 jne .LOP_NEW_INSTANCE_resolved # good to go 6680 jmp common_exceptionThrown # no, handle exception 6681 6682 /* 6683 * TODO: remove this 6684 * We can't instantiate an abstract class or interface, so throw an 6685 * InstantiationError with the class descriptor as the message. 6686 * 6687 * ecx holds class object 6688 */ 6689.LOP_NEW_INSTANCE_abstract: 6690 movl offClassObject_descriptor(%ecx),%eax 6691 movl $.LstrInstantiationError,OUT_ARG0(%esp) 6692 movl %eax,OUT_ARG1(%esp) 6693 call dvmThrowExceptionWithClassMessage 6694 jmp common_exceptionThrown 6695 6696/* continuation for OP_NEW_ARRAY */ 6697 6698 /* 6699 * Resolve class. (This is an uncommon case.) 6700 * ecx holds class (null here) 6701 * eax holds array length (vB) 6702 */ 6703.LOP_NEW_ARRAY_resolve: 6704 movl rGLUE,%ecx 6705 SPILL_TMP1(%eax) # save array length 6706 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 6707 movzwl 2(rPC),%eax # eax<- CCCC 6708 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 6709 movl %eax,OUT_ARG1(%esp) 6710 movl $0,OUT_ARG2(%esp) 6711 movl %ecx,OUT_ARG0(%esp) 6712 call dvmResolveClass # eax<- call(clazz,ref,flag) 6713 movl %eax,%ecx 6714 UNSPILL_TMP1(%eax) 6715 testl %ecx,%ecx # successful resolution? 6716 je common_exceptionThrown # no, bail. 6717# fall through to OP_NEW_ARRAY_finish 6718 6719 /* 6720 * Finish allocation 6721 * 6722 * ecx holds class 6723 * eax holds array length (vB) 6724 */ 6725.LOP_NEW_ARRAY_finish: 6726 movl %ecx,OUT_ARG0(%esp) 6727 movl %eax,OUT_ARG1(%esp) 6728 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) 6729 call dvmAllocArrayByClass # eax<- call(clazz,length,flags) 6730 FETCH_INST_OPCODE 2 %edx 6731 testl %eax,%eax # failed? 6732 je common_exceptionThrown # yup - go handle 6733 SET_VREG %eax rINST 6734 ADVANCE_PC 2 6735 GOTO_NEXT_R %edx 6736 6737/* continuation for OP_FILLED_NEW_ARRAY */ 6738 6739.LOP_FILLED_NEW_ARRAY_more: 6740 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 6741 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 6742 call dvmResolveClass # eax<- call(clazz,ref,flag) 6743 testl %eax,%eax # null? 6744 je common_exceptionThrown # yes, handle it 6745 6746 # note: fall through to .LOP_FILLED_NEW_ARRAY_continue 6747 6748 /* 6749 * On entry: 6750 * eax holds array class [r0] 6751 * rINST holds AA or BB [r10] 6752 * ecx is scratch 6753 */ 6754.LOP_FILLED_NEW_ARRAY_continue: 6755 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor 6756 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags 6757 movzbl 1(%ecx),%ecx # ecx<- descriptor[1] 6758 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass 6759 movl rGLUE,%eax 6760 cmpb $'I',%cl # supported? 6761 je 1f 6762 cmpb $'L',%cl 6763 je 1f 6764 cmpb $'[',%cl 6765 jne .LOP_FILLED_NEW_ARRAY_notimpl # no, not handled yet 67661: 6767 movl %ecx,offGlue_retval+4(%eax) # save type 6768 .if (!0) 6769 SPILL_TMP1(rINST) # save copy, need "B" later 6770 sarl $4,rINST 6771 .endif 6772 movl rINST,OUT_ARG1(%esp) # arg1<- A or AA (length) 6773 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags) 6774 movl rGLUE,%ecx 6775 testl %eax,%eax # alloc successful? 6776 je common_exceptionThrown # no, handle exception 6777 movl %eax,offGlue_retval(%ecx) # retval.l<- new array 6778 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC 6779 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents 6780 6781/* at this point: 6782 * eax is pointer to tgt 6783 * rINST is length 6784 * ecx is FEDC or CCCC 6785 * TMP_SPILL is BA 6786 * We now need to copy values from registers into the array 6787 */ 6788 6789 .if 0 6790 # set up src pointer 6791 SPILL_TMP2(%esi) 6792 SPILL_TMP3(%edi) 6793 movl %eax,%edi # set up dst ptr 6794 leal (rFP,%ecx,4),%esi # set up src ptr 6795 movl rINST,%ecx # load count register 6796 rep 6797 movsd 6798 UNSPILL_TMP2(%esi) 6799 UNSPILL_TMP3(%edi) 6800 movl rGLUE,%ecx 6801 movl offGlue_retval+4(%ecx),%eax # eax<- type 6802 FETCH_INST_OPCODE 3 %edx 6803 .else 6804 testl rINST,rINST 6805 je 4f 6806 andl $0x0f,%edx # edx<- 0000000A 6807 sall $16,%edx # edx<- 000A0000 6808 orl %ecx,%edx # edx<- 000AFEDC 68093: 6810 movl $0xf,%ecx 6811 andl %edx,%ecx # ecx<- next reg to load 6812 GET_VREG_R %ecx %ecx 6813 shrl $4,%edx 6814 leal 4(%eax),%eax 6815 movl %ecx,-4(%eax) 6816 sub $1,rINST 6817 jne 3b 68184: 6819 movl rGLUE,%ecx 6820 movl offGlue_retval+4(%ecx),%eax # eax<- type 6821 FETCH_INST_OPCODE 3 %edx 6822 .endif 6823 6824 cmpb $'I',%al # Int array? 6825 je 5f # skip card mark if so 6826 movl offGlue_retval(%ecx),%eax # eax<- object head 6827 movl offGlue_cardTable(%ecx),%ecx # card table base 6828 shrl $GC_CARD_SHIFT,%eax # convert to card num 6829 movb %cl,(%ecx,%eax) # mark card 68305: 6831 ADVANCE_PC 3 6832 GOTO_NEXT_R %edx 6833 6834 6835 /* 6836 * Throw an exception indicating that we have not implemented this 6837 * mode of filled-new-array. 6838 */ 6839.LOP_FILLED_NEW_ARRAY_notimpl: 6840 movl $.LstrInternalErrorA,%eax 6841 movl %eax,OUT_ARG0(%esp) 6842 movl $.LstrFilledNewArrayNotImplA,%eax 6843 movl %eax,OUT_ARG1(%esp) 6844 call dvmThrowException 6845 jmp common_exceptionThrown 6846 6847/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 6848 6849.LOP_FILLED_NEW_ARRAY_RANGE_more: 6850 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 6851 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 6852 call dvmResolveClass # eax<- call(clazz,ref,flag) 6853 testl %eax,%eax # null? 6854 je common_exceptionThrown # yes, handle it 6855 6856 # note: fall through to .LOP_FILLED_NEW_ARRAY_RANGE_continue 6857 6858 /* 6859 * On entry: 6860 * eax holds array class [r0] 6861 * rINST holds AA or BB [r10] 6862 * ecx is scratch 6863 */ 6864.LOP_FILLED_NEW_ARRAY_RANGE_continue: 6865 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor 6866 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags 6867 movzbl 1(%ecx),%ecx # ecx<- descriptor[1] 6868 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass 6869 movl rGLUE,%eax 6870 cmpb $'I',%cl # supported? 6871 je 1f 6872 cmpb $'L',%cl 6873 je 1f 6874 cmpb $'[',%cl 6875 jne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl # no, not handled yet 68761: 6877 movl %ecx,offGlue_retval+4(%eax) # save type 6878 .if (!1) 6879 SPILL_TMP1(rINST) # save copy, need "B" later 6880 sarl $4,rINST 6881 .endif 6882 movl rINST,OUT_ARG1(%esp) # arg1<- A or AA (length) 6883 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags) 6884 movl rGLUE,%ecx 6885 testl %eax,%eax # alloc successful? 6886 je common_exceptionThrown # no, handle exception 6887 movl %eax,offGlue_retval(%ecx) # retval.l<- new array 6888 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC 6889 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents 6890 6891/* at this point: 6892 * eax is pointer to tgt 6893 * rINST is length 6894 * ecx is FEDC or CCCC 6895 * TMP_SPILL is BA 6896 * We now need to copy values from registers into the array 6897 */ 6898 6899 .if 1 6900 # set up src pointer 6901 SPILL_TMP2(%esi) 6902 SPILL_TMP3(%edi) 6903 movl %eax,%edi # set up dst ptr 6904 leal (rFP,%ecx,4),%esi # set up src ptr 6905 movl rINST,%ecx # load count register 6906 rep 6907 movsd 6908 UNSPILL_TMP2(%esi) 6909 UNSPILL_TMP3(%edi) 6910 movl rGLUE,%ecx 6911 movl offGlue_retval+4(%ecx),%eax # eax<- type 6912 FETCH_INST_OPCODE 3 %edx 6913 .else 6914 testl rINST,rINST 6915 je 4f 6916 andl $0x0f,%edx # edx<- 0000000A 6917 sall $16,%edx # edx<- 000A0000 6918 orl %ecx,%edx # edx<- 000AFEDC 69193: 6920 movl $0xf,%ecx 6921 andl %edx,%ecx # ecx<- next reg to load 6922 GET_VREG_R %ecx %ecx 6923 shrl $4,%edx 6924 leal 4(%eax),%eax 6925 movl %ecx,-4(%eax) 6926 sub $1,rINST 6927 jne 3b 69284: 6929 movl rGLUE,%ecx 6930 movl offGlue_retval+4(%ecx),%eax # eax<- type 6931 FETCH_INST_OPCODE 3 %edx 6932 .endif 6933 6934 cmpb $'I',%al # Int array? 6935 je 5f # skip card mark if so 6936 movl offGlue_retval(%ecx),%eax # eax<- object head 6937 movl offGlue_cardTable(%ecx),%ecx # card table base 6938 shrl $GC_CARD_SHIFT,%eax # convert to card num 6939 movb %cl,(%ecx,%eax) # mark card 69405: 6941 ADVANCE_PC 3 6942 GOTO_NEXT_R %edx 6943 6944 6945 /* 6946 * Throw an exception indicating that we have not implemented this 6947 * mode of filled-new-array. 6948 */ 6949.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 6950 movl $.LstrInternalErrorA,%eax 6951 movl %eax,OUT_ARG0(%esp) 6952 movl $.LstrFilledNewArrayNotImplA,%eax 6953 movl %eax,OUT_ARG1(%esp) 6954 call dvmThrowException 6955 jmp common_exceptionThrown 6956 6957/* continuation for OP_CMPL_FLOAT */ 6958 6959.LOP_CMPL_FLOAT_isNaN: 6960 movl $-1,%ecx 6961 jmp .LOP_CMPL_FLOAT_finish 6962 6963/* continuation for OP_CMPG_FLOAT */ 6964 6965.LOP_CMPG_FLOAT_isNaN: 6966 movl $1,%ecx 6967 jmp .LOP_CMPG_FLOAT_finish 6968 6969/* continuation for OP_CMPL_DOUBLE */ 6970 6971.LOP_CMPL_DOUBLE_isNaN: 6972 movl $-1,%ecx 6973 jmp .LOP_CMPL_DOUBLE_finish 6974 6975/* continuation for OP_CMPG_DOUBLE */ 6976 6977.LOP_CMPG_DOUBLE_isNaN: 6978 movl $1,%ecx 6979 jmp .LOP_CMPG_DOUBLE_finish 6980 6981/* continuation for OP_CMP_LONG */ 6982 6983.LOP_CMP_LONG_bigger: 6984 movl $1,%ecx 6985 jmp .LOP_CMP_LONG_finish 6986.LOP_CMP_LONG_smaller: 6987 movl $-1,%ecx 6988.LOP_CMP_LONG_finish: 6989 SET_VREG %ecx rINST 6990 FETCH_INST_OPCODE 2 %edx 6991 ADVANCE_PC 2 6992 GOTO_NEXT_R %edx 6993 6994/* continuation for OP_AGET_WIDE */ 6995 6996.LOP_AGET_WIDE_finish: 6997 leal offArrayObject_contents(%eax,%ecx,8),%eax 6998 movl (%eax),%ecx 6999 movl 4(%eax),%eax 7000 SET_VREG_WORD %ecx rINST 0 7001 SET_VREG_WORD %eax rINST 1 7002 FETCH_INST_OPCODE 2 %edx 7003 ADVANCE_PC 2 7004 GOTO_NEXT_R %edx 7005 7006/* continuation for OP_APUT_WIDE */ 7007 7008.LOP_APUT_WIDE_finish: 7009 leal offArrayObject_contents(%eax,%ecx,8),%eax 7010 GET_VREG_WORD %ecx rINST 0 7011 GET_VREG_WORD rINST rINST 1 7012 movl rINST,4(%eax) 7013 FETCH_INST_OPCODE 2 %edx 7014 movl %ecx,(%eax) 7015 ADVANCE_PC 2 7016 GOTO_NEXT_R %edx 7017 7018/* continuation for OP_APUT_OBJECT */ 7019 7020 /* On entry: 7021 * eax<- array object 7022 * ecx<- index 7023 * rINST<- vAA 7024 */ 7025.LOP_APUT_OBJECT_continue: 7026 leal offArrayObject_contents(%eax,%ecx,4),%ecx 7027 testl rINST,rINST # storing null reference? 7028 je .LOP_APUT_OBJECT_skip_check 7029 SPILL_TMP1(%ecx) 7030 movl offObject_clazz(%eax),%eax # eax<- arrayObj->clazz 7031 movl offObject_clazz(rINST),%ecx # ecx<- obj->clazz 7032 movl %eax,OUT_ARG1(%esp) 7033 movl %ecx,OUT_ARG0(%esp) 7034 call dvmCanPutArrayElement # test object type vs. array type 7035 UNSPILL_TMP1(%ecx) 7036 testl %eax,%eax 7037 movl rGLUE,%eax 7038 je common_errArrayStore 7039 movl offGlue_cardTable(%eax),%eax # get card table base 7040 movl rINST,(%ecx) 7041 FETCH_INST_OPCODE 2 %edx 7042 shrl $GC_CARD_SHIFT,%ecx # convert addr to card number 7043 movb %al,(%eax,%ecx) # mark card 7044 ADVANCE_PC 2 7045 GOTO_NEXT_R %edx 7046 7047.LOP_APUT_OBJECT_skip_check: 7048 movl rINST,(%ecx) 7049 FETCH_INST_OPCODE 2 %edx 7050 ADVANCE_PC 2 7051 GOTO_NEXT_R %edx 7052 7053/* continuation for OP_IGET */ 7054 7055 7056.LOP_IGET_resolve: 7057 EXPORT_PC 7058 movl offGlue_method(%edx),%edx # edx<- current method 7059 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7060 SPILL_TMP1(%ecx) # save obj pointer across call 7061 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7062 call dvmResolveInstField # ... to dvmResolveInstField 7063 UNSPILL_TMP1(%ecx) 7064 testl %eax,%eax # returns InstrField ptr 7065 jne .LOP_IGET_finish 7066 jmp common_exceptionThrown 7067 7068.LOP_IGET_finish: 7069 /* 7070 * Currently: 7071 * eax holds resolved field 7072 * ecx holds object 7073 * rINST holds A 7074 */ 7075 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7076 testl %ecx,%ecx # object null? 7077 je common_errNullObject # object was null 7078 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7079 movl rINST,%eax # eax<- A 7080 FETCH_INST_OPCODE 2 %edx 7081 SET_VREG %ecx %eax 7082 ADVANCE_PC 2 7083 GOTO_NEXT_R %edx 7084 7085/* continuation for OP_IGET_WIDE */ 7086 7087 7088.LOP_IGET_WIDE_resolve: 7089 EXPORT_PC 7090 movl offGlue_method(%edx),%edx # edx<- current method 7091 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7092 SPILL_TMP1(%ecx) # save objpointer across call 7093 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7094 call dvmResolveInstField # ... to dvmResolveInstField 7095 UNSPILL_TMP1(%ecx) 7096 testl %eax,%eax # returns InstrField ptr 7097 jne .LOP_IGET_WIDE_finish 7098 jmp common_exceptionThrown 7099 7100.LOP_IGET_WIDE_finish: 7101 /* 7102 * Currently: 7103 * eax holds resolved field 7104 * ecx holds object 7105 * rINST holds A 7106 */ 7107 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7108 testl %ecx,%ecx # object null? 7109 je common_errNullObject # object was null 7110 leal (%ecx,%eax,1),%eax # eax<- address of field 7111 movl (%eax),%ecx # ecx<- lsw 7112 movl 4(%eax),%eax # eax<- msw 7113 FETCH_INST_OPCODE 2 %edx 7114 SET_VREG_WORD %ecx rINST 0 7115 SET_VREG_WORD %eax rINST 1 7116 ADVANCE_PC 2 7117 GOTO_NEXT_R %edx 7118 7119/* continuation for OP_IGET_OBJECT */ 7120 7121 7122.LOP_IGET_OBJECT_resolve: 7123 EXPORT_PC 7124 movl offGlue_method(%edx),%edx # edx<- current method 7125 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7126 SPILL_TMP1(%ecx) # save obj pointer across call 7127 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7128 call dvmResolveInstField # ... to dvmResolveInstField 7129 UNSPILL_TMP1(%ecx) 7130 testl %eax,%eax # returns InstrField ptr 7131 jne .LOP_IGET_OBJECT_finish 7132 jmp common_exceptionThrown 7133 7134.LOP_IGET_OBJECT_finish: 7135 /* 7136 * Currently: 7137 * eax holds resolved field 7138 * ecx holds object 7139 * rINST holds A 7140 */ 7141 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7142 testl %ecx,%ecx # object null? 7143 je common_errNullObject # object was null 7144 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7145 movl rINST,%eax # eax<- A 7146 FETCH_INST_OPCODE 2 %edx 7147 SET_VREG %ecx %eax 7148 ADVANCE_PC 2 7149 GOTO_NEXT_R %edx 7150 7151/* continuation for OP_IGET_BOOLEAN */ 7152 7153 7154.LOP_IGET_BOOLEAN_resolve: 7155 EXPORT_PC 7156 movl offGlue_method(%edx),%edx # edx<- current method 7157 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7158 SPILL_TMP1(%ecx) # save obj pointer across call 7159 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7160 call dvmResolveInstField # ... to dvmResolveInstField 7161 UNSPILL_TMP1(%ecx) 7162 testl %eax,%eax # returns InstrField ptr 7163 jne .LOP_IGET_BOOLEAN_finish 7164 jmp common_exceptionThrown 7165 7166.LOP_IGET_BOOLEAN_finish: 7167 /* 7168 * Currently: 7169 * eax holds resolved field 7170 * ecx holds object 7171 * rINST holds A 7172 */ 7173 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7174 testl %ecx,%ecx # object null? 7175 je common_errNullObject # object was null 7176 movzbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7177 movl rINST,%eax # eax<- A 7178 FETCH_INST_OPCODE 2 %edx 7179 SET_VREG %ecx %eax 7180 ADVANCE_PC 2 7181 GOTO_NEXT_R %edx 7182 7183/* continuation for OP_IGET_BYTE */ 7184 7185 7186.LOP_IGET_BYTE_resolve: 7187 EXPORT_PC 7188 movl offGlue_method(%edx),%edx # edx<- current method 7189 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7190 SPILL_TMP1(%ecx) # save obj pointer across call 7191 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7192 call dvmResolveInstField # ... to dvmResolveInstField 7193 UNSPILL_TMP1(%ecx) 7194 testl %eax,%eax # returns InstrField ptr 7195 jne .LOP_IGET_BYTE_finish 7196 jmp common_exceptionThrown 7197 7198.LOP_IGET_BYTE_finish: 7199 /* 7200 * Currently: 7201 * eax holds resolved field 7202 * ecx holds object 7203 * rINST holds A 7204 */ 7205 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7206 testl %ecx,%ecx # object null? 7207 je common_errNullObject # object was null 7208 movsbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7209 movl rINST,%eax # eax<- A 7210 FETCH_INST_OPCODE 2 %edx 7211 SET_VREG %ecx %eax 7212 ADVANCE_PC 2 7213 GOTO_NEXT_R %edx 7214 7215/* continuation for OP_IGET_CHAR */ 7216 7217 7218.LOP_IGET_CHAR_resolve: 7219 EXPORT_PC 7220 movl offGlue_method(%edx),%edx # edx<- current method 7221 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7222 SPILL_TMP1(%ecx) # save obj pointer across call 7223 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7224 call dvmResolveInstField # ... to dvmResolveInstField 7225 UNSPILL_TMP1(%ecx) 7226 testl %eax,%eax # returns InstrField ptr 7227 jne .LOP_IGET_CHAR_finish 7228 jmp common_exceptionThrown 7229 7230.LOP_IGET_CHAR_finish: 7231 /* 7232 * Currently: 7233 * eax holds resolved field 7234 * ecx holds object 7235 * rINST holds A 7236 */ 7237 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7238 testl %ecx,%ecx # object null? 7239 je common_errNullObject # object was null 7240 movzwl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7241 movl rINST,%eax # eax<- A 7242 FETCH_INST_OPCODE 2 %edx 7243 SET_VREG %ecx %eax 7244 ADVANCE_PC 2 7245 GOTO_NEXT_R %edx 7246 7247/* continuation for OP_IGET_SHORT */ 7248 7249 7250.LOP_IGET_SHORT_resolve: 7251 EXPORT_PC 7252 movl offGlue_method(%edx),%edx # edx<- current method 7253 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7254 SPILL_TMP1(%ecx) # save obj pointer across call 7255 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7256 call dvmResolveInstField # ... to dvmResolveInstField 7257 UNSPILL_TMP1(%ecx) 7258 testl %eax,%eax # returns InstrField ptr 7259 jne .LOP_IGET_SHORT_finish 7260 jmp common_exceptionThrown 7261 7262.LOP_IGET_SHORT_finish: 7263 /* 7264 * Currently: 7265 * eax holds resolved field 7266 * ecx holds object 7267 * rINST holds A 7268 */ 7269 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7270 testl %ecx,%ecx # object null? 7271 je common_errNullObject # object was null 7272 movswl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7273 movl rINST,%eax # eax<- A 7274 FETCH_INST_OPCODE 2 %edx 7275 SET_VREG %ecx %eax 7276 ADVANCE_PC 2 7277 GOTO_NEXT_R %edx 7278 7279/* continuation for OP_IPUT */ 7280 7281 7282.LOP_IPUT_resolve: 7283 EXPORT_PC 7284 movl offGlue_method(%edx),%edx # edx<- current method 7285 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7286 SPILL_TMP1(%ecx) # save obj pointer across call 7287 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7288 call dvmResolveInstField # ... to dvmResolveInstField 7289 UNSPILL_TMP1(%ecx) 7290 testl %eax,%eax # returns InstrField ptr 7291 jne .LOP_IPUT_finish 7292 jmp common_exceptionThrown 7293 7294.LOP_IPUT_finish: 7295 /* 7296 * Currently: 7297 * eax holds resolved field 7298 * ecx holds object 7299 * rINST holds A 7300 */ 7301 GET_VREG_R rINST rINST # rINST<- v[A] 7302 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7303 testl %ecx,%ecx # object null? 7304 je common_errNullObject # object was null 7305 FETCH_INST_OPCODE 2 %edx 7306 movl rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7307 ADVANCE_PC 2 7308 GOTO_NEXT_R %edx 7309 7310/* continuation for OP_IPUT_WIDE */ 7311 7312 7313.LOP_IPUT_WIDE_resolve: 7314 EXPORT_PC 7315 movl offGlue_method(%edx),%edx # edx<- current method 7316 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7317 SPILL_TMP1(%ecx) # save obj pointer across call 7318 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7319 call dvmResolveInstField # ... to dvmResolveInstField 7320 UNSPILL_TMP1(%ecx) 7321 testl %eax,%eax # ... which returns InstrField ptr 7322 jne .LOP_IPUT_WIDE_finish 7323 jmp common_exceptionThrown 7324 7325.LOP_IPUT_WIDE_finish: 7326 /* 7327 * Currently: 7328 * eax holds resolved field 7329 * ecx holds object 7330 * %edx is scratch, but needs to be unspilled 7331 * rINST holds A 7332 */ 7333 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7334 testl %ecx,%ecx # object null? 7335 je common_errNullObject # object was null 7336 leal (%ecx,%eax,1),%eax # eax<- address of field 7337 GET_VREG_WORD %ecx rINST 0 # ecx<- lsw 7338 GET_VREG_WORD rINST rINST 1 # rINST<- msw 7339 FETCH_INST_OPCODE 2 %edx 7340 movl rINST,4(%eax) 7341 movl %ecx,(%eax) 7342 ADVANCE_PC 2 7343 GOTO_NEXT_R %edx 7344 7345/* continuation for OP_IPUT_OBJECT */ 7346 7347 7348.LOP_IPUT_OBJECT_resolve: 7349 EXPORT_PC 7350 movl offGlue_method(%edx),%edx # edx<- current method 7351 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7352 SPILL_TMP1(%ecx) # save obj pointer across call 7353 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7354 call dvmResolveInstField # ... to dvmResolveInstField 7355 UNSPILL_TMP1(%ecx) 7356 testl %eax,%eax # returns InstrField ptr 7357 jne .LOP_IPUT_OBJECT_finish 7358 jmp common_exceptionThrown 7359 7360.LOP_IPUT_OBJECT_finish: 7361 /* 7362 * Currently: 7363 * eax holds resolved field 7364 * ecx holds object 7365 * %edx is scratch, but needs to be unspilled 7366 * rINST holds A 7367 */ 7368 GET_VREG_R rINST rINST # rINST<- v[A] 7369 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7370 testl %ecx,%ecx # object null? 7371 je common_errNullObject # object was null 7372 movl rINST,(%ecx,%eax) # obj.field <- v[A](8/16/32 bits) 7373 movl rGLUE,%eax 7374 testl rINST,rINST # stored a NULL? 7375 movl offGlue_cardTable(%eax),%eax # get card table base 7376 FETCH_INST_OPCODE 2 %edx 7377 je 1f # skip card mark if null store 7378 shrl $GC_CARD_SHIFT,%ecx # object head to card number 7379 movb %al,(%eax,%ecx) # mark card 73801: 7381 ADVANCE_PC 2 7382 GOTO_NEXT_R %edx 7383 7384/* continuation for OP_IPUT_BOOLEAN */ 7385 7386 7387.LOP_IPUT_BOOLEAN_resolve: 7388 EXPORT_PC 7389 movl offGlue_method(%edx),%edx # edx<- current method 7390 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7391 SPILL_TMP1(%ecx) # save obj pointer across call 7392 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7393 call dvmResolveInstField # ... to dvmResolveInstField 7394 UNSPILL_TMP1(%ecx) 7395 testl %eax,%eax # returns InstrField ptr 7396 jne .LOP_IPUT_BOOLEAN_finish 7397 jmp common_exceptionThrown 7398 7399.LOP_IPUT_BOOLEAN_finish: 7400 /* 7401 * Currently: 7402 * eax holds resolved field 7403 * ecx holds object 7404 * rINST holds A 7405 */ 7406 GET_VREG_R rINST rINST # rINST<- v[A] 7407 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7408 testl %ecx,%ecx # object null? 7409 je common_errNullObject # object was null 7410 FETCH_INST_OPCODE 2 %edx 7411 movb rINSTbl,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7412 ADVANCE_PC 2 7413 GOTO_NEXT_R %edx 7414 7415/* continuation for OP_IPUT_BYTE */ 7416 7417 7418.LOP_IPUT_BYTE_resolve: 7419 EXPORT_PC 7420 movl offGlue_method(%edx),%edx # edx<- current method 7421 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7422 SPILL_TMP1(%ecx) # save obj pointer across call 7423 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7424 call dvmResolveInstField # ... to dvmResolveInstField 7425 UNSPILL_TMP1(%ecx) 7426 testl %eax,%eax # returns InstrField ptr 7427 jne .LOP_IPUT_BYTE_finish 7428 jmp common_exceptionThrown 7429 7430.LOP_IPUT_BYTE_finish: 7431 /* 7432 * Currently: 7433 * eax holds resolved field 7434 * ecx holds object 7435 * rINST holds A 7436 */ 7437 GET_VREG_R rINST rINST # rINST<- v[A] 7438 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7439 testl %ecx,%ecx # object null? 7440 je common_errNullObject # object was null 7441 FETCH_INST_OPCODE 2 %edx 7442 movb rINSTbl,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7443 ADVANCE_PC 2 7444 GOTO_NEXT_R %edx 7445 7446/* continuation for OP_IPUT_CHAR */ 7447 7448 7449.LOP_IPUT_CHAR_resolve: 7450 EXPORT_PC 7451 movl offGlue_method(%edx),%edx # edx<- current method 7452 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7453 SPILL_TMP1(%ecx) # save obj pointer across call 7454 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7455 call dvmResolveInstField # ... to dvmResolveInstField 7456 UNSPILL_TMP1(%ecx) 7457 testl %eax,%eax # returns InstrField ptr 7458 jne .LOP_IPUT_CHAR_finish 7459 jmp common_exceptionThrown 7460 7461.LOP_IPUT_CHAR_finish: 7462 /* 7463 * Currently: 7464 * eax holds resolved field 7465 * ecx holds object 7466 * rINST holds A 7467 */ 7468 GET_VREG_R rINST rINST # rINST<- v[A] 7469 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7470 testl %ecx,%ecx # object null? 7471 je common_errNullObject # object was null 7472 FETCH_INST_OPCODE 2 %edx 7473 movw rINSTw,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7474 ADVANCE_PC 2 7475 GOTO_NEXT_R %edx 7476 7477/* continuation for OP_IPUT_SHORT */ 7478 7479 7480.LOP_IPUT_SHORT_resolve: 7481 EXPORT_PC 7482 movl offGlue_method(%edx),%edx # edx<- current method 7483 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 7484 SPILL_TMP1(%ecx) # save obj pointer across call 7485 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 7486 call dvmResolveInstField # ... to dvmResolveInstField 7487 UNSPILL_TMP1(%ecx) 7488 testl %eax,%eax # returns InstrField ptr 7489 jne .LOP_IPUT_SHORT_finish 7490 jmp common_exceptionThrown 7491 7492.LOP_IPUT_SHORT_finish: 7493 /* 7494 * Currently: 7495 * eax holds resolved field 7496 * ecx holds object 7497 * rINST holds A 7498 */ 7499 GET_VREG_R rINST rINST # rINST<- v[A] 7500 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7501 testl %ecx,%ecx # object null? 7502 je common_errNullObject # object was null 7503 FETCH_INST_OPCODE 2 %edx 7504 movw rINSTw,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7505 ADVANCE_PC 2 7506 GOTO_NEXT_R %edx 7507 7508/* continuation for OP_SGET */ 7509 7510 /* 7511 * Go resolve the field 7512 */ 7513.LOP_SGET_resolve: 7514 movl rGLUE,%ecx 7515 movzwl 2(rPC),%eax # eax<- field ref BBBB 7516 movl offGlue_method(%ecx),%ecx # ecx<- current method 7517 EXPORT_PC # could throw, need to export 7518 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7519 movl %eax,OUT_ARG1(%esp) 7520 movl %ecx,OUT_ARG0(%esp) 7521 call dvmResolveStaticField # eax<- resolved StaticField ptr 7522 testl %eax,%eax 7523 jne .LOP_SGET_finish # success, continue 7524 jmp common_exceptionThrown # no, handle exception 7525 7526/* continuation for OP_SGET_WIDE */ 7527 7528 /* 7529 * Go resolve the field 7530 */ 7531.LOP_SGET_WIDE_resolve: 7532 movl rGLUE,%ecx 7533 movzwl 2(rPC),%eax # eax<- field ref BBBB 7534 movl offGlue_method(%ecx),%ecx # ecx<- current method 7535 EXPORT_PC # could throw, need to export 7536 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7537 movl %eax,OUT_ARG1(%esp) 7538 movl %ecx,OUT_ARG0(%esp) 7539 call dvmResolveStaticField # eax<- resolved StaticField ptr 7540 testl %eax,%eax 7541 jne .LOP_SGET_WIDE_finish # success, continue 7542 jmp common_exceptionThrown # no, handle exception 7543 7544/* continuation for OP_SGET_OBJECT */ 7545 7546 /* 7547 * Go resolve the field 7548 */ 7549.LOP_SGET_OBJECT_resolve: 7550 movl rGLUE,%ecx 7551 movzwl 2(rPC),%eax # eax<- field ref BBBB 7552 movl offGlue_method(%ecx),%ecx # ecx<- current method 7553 EXPORT_PC # could throw, need to export 7554 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7555 movl %eax,OUT_ARG1(%esp) 7556 movl %ecx,OUT_ARG0(%esp) 7557 call dvmResolveStaticField # eax<- resolved StaticField ptr 7558 testl %eax,%eax 7559 jne .LOP_SGET_OBJECT_finish # success, continue 7560 jmp common_exceptionThrown # no, handle exception 7561 7562/* continuation for OP_SGET_BOOLEAN */ 7563 7564 /* 7565 * Go resolve the field 7566 */ 7567.LOP_SGET_BOOLEAN_resolve: 7568 movl rGLUE,%ecx 7569 movzwl 2(rPC),%eax # eax<- field ref BBBB 7570 movl offGlue_method(%ecx),%ecx # ecx<- current method 7571 EXPORT_PC # could throw, need to export 7572 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7573 movl %eax,OUT_ARG1(%esp) 7574 movl %ecx,OUT_ARG0(%esp) 7575 call dvmResolveStaticField # eax<- resolved StaticField ptr 7576 testl %eax,%eax 7577 jne .LOP_SGET_BOOLEAN_finish # success, continue 7578 jmp common_exceptionThrown # no, handle exception 7579 7580/* continuation for OP_SGET_BYTE */ 7581 7582 /* 7583 * Go resolve the field 7584 */ 7585.LOP_SGET_BYTE_resolve: 7586 movl rGLUE,%ecx 7587 movzwl 2(rPC),%eax # eax<- field ref BBBB 7588 movl offGlue_method(%ecx),%ecx # ecx<- current method 7589 EXPORT_PC # could throw, need to export 7590 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7591 movl %eax,OUT_ARG1(%esp) 7592 movl %ecx,OUT_ARG0(%esp) 7593 call dvmResolveStaticField # eax<- resolved StaticField ptr 7594 testl %eax,%eax 7595 jne .LOP_SGET_BYTE_finish # success, continue 7596 jmp common_exceptionThrown # no, handle exception 7597 7598/* continuation for OP_SGET_CHAR */ 7599 7600 /* 7601 * Go resolve the field 7602 */ 7603.LOP_SGET_CHAR_resolve: 7604 movl rGLUE,%ecx 7605 movzwl 2(rPC),%eax # eax<- field ref BBBB 7606 movl offGlue_method(%ecx),%ecx # ecx<- current method 7607 EXPORT_PC # could throw, need to export 7608 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7609 movl %eax,OUT_ARG1(%esp) 7610 movl %ecx,OUT_ARG0(%esp) 7611 call dvmResolveStaticField # eax<- resolved StaticField ptr 7612 testl %eax,%eax 7613 jne .LOP_SGET_CHAR_finish # success, continue 7614 jmp common_exceptionThrown # no, handle exception 7615 7616/* continuation for OP_SGET_SHORT */ 7617 7618 /* 7619 * Go resolve the field 7620 */ 7621.LOP_SGET_SHORT_resolve: 7622 movl rGLUE,%ecx 7623 movzwl 2(rPC),%eax # eax<- field ref BBBB 7624 movl offGlue_method(%ecx),%ecx # ecx<- current method 7625 EXPORT_PC # could throw, need to export 7626 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7627 movl %eax,OUT_ARG1(%esp) 7628 movl %ecx,OUT_ARG0(%esp) 7629 call dvmResolveStaticField # eax<- resolved StaticField ptr 7630 testl %eax,%eax 7631 jne .LOP_SGET_SHORT_finish # success, continue 7632 jmp common_exceptionThrown # no, handle exception 7633 7634/* continuation for OP_SPUT */ 7635 7636 /* 7637 * Go resolve the field 7638 */ 7639.LOP_SPUT_resolve: 7640 movl rGLUE,%ecx 7641 movzwl 2(rPC),%eax # eax<- field ref BBBB 7642 movl offGlue_method(%ecx),%ecx # ecx<- current method 7643 EXPORT_PC # could throw, need to export 7644 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7645 movl %eax,OUT_ARG1(%esp) 7646 movl %ecx,OUT_ARG0(%esp) 7647 call dvmResolveStaticField # eax<- resolved StaticField ptr 7648 testl %eax,%eax 7649 jne .LOP_SPUT_finish # success, continue 7650 jmp common_exceptionThrown # no, handle exception 7651 7652/* continuation for OP_SPUT_WIDE */ 7653 7654 /* 7655 * Go resolve the field 7656 */ 7657.LOP_SPUT_WIDE_resolve: 7658 movl rGLUE,%ecx 7659 movzwl 2(rPC),%eax # eax<- field ref BBBB 7660 movl offGlue_method(%ecx),%ecx # ecx<- current method 7661 EXPORT_PC # could throw, need to export 7662 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7663 movl %eax,OUT_ARG1(%esp) 7664 movl %ecx,OUT_ARG0(%esp) 7665 call dvmResolveStaticField # eax<- resolved StaticField ptr 7666 testl %eax,%eax 7667 jne .LOP_SPUT_WIDE_finish # success, continue 7668 jmp common_exceptionThrown # no, handle exception 7669 7670/* continuation for OP_SPUT_OBJECT */ 7671 7672 7673.LOP_SPUT_OBJECT_continue: 7674 movl %ecx,offStaticField_value(%eax) 7675 testl %ecx,%ecx 7676 movl rGLUE,%ecx 7677 FETCH_INST_OPCODE 2 %edx 7678 je 1f 7679 movl offGlue_cardTable(%ecx),%ecx # get card table base 7680 shrl $GC_CARD_SHIFT,%eax # head to card number 7681 movb %cl,(%ecx,%eax) # mark card 76821: 7683 ADVANCE_PC 2 7684 GOTO_NEXT_R %edx 7685 7686.LOP_SPUT_OBJECT_resolve: 7687 movl rGLUE,%ecx 7688 movzwl 2(rPC),%eax # eax<- field ref BBBB 7689 movl offGlue_method(%ecx),%ecx # ecx<- current method 7690 EXPORT_PC # could throw, need to export 7691 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7692 movl %eax,OUT_ARG1(%esp) 7693 movl %ecx,OUT_ARG0(%esp) 7694 call dvmResolveStaticField # eax<- resolved StaticField ptr 7695 testl %eax,%eax 7696 jne .LOP_SPUT_OBJECT_finish # success, continue 7697 jmp common_exceptionThrown # no, handle exception 7698 7699/* continuation for OP_SPUT_BOOLEAN */ 7700 7701 /* 7702 * Go resolve the field 7703 */ 7704.LOP_SPUT_BOOLEAN_resolve: 7705 movl rGLUE,%ecx 7706 movzwl 2(rPC),%eax # eax<- field ref BBBB 7707 movl offGlue_method(%ecx),%ecx # ecx<- current method 7708 EXPORT_PC # could throw, need to export 7709 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7710 movl %eax,OUT_ARG1(%esp) 7711 movl %ecx,OUT_ARG0(%esp) 7712 call dvmResolveStaticField # eax<- resolved StaticField ptr 7713 testl %eax,%eax 7714 jne .LOP_SPUT_BOOLEAN_finish # success, continue 7715 jmp common_exceptionThrown # no, handle exception 7716 7717/* continuation for OP_SPUT_BYTE */ 7718 7719 /* 7720 * Go resolve the field 7721 */ 7722.LOP_SPUT_BYTE_resolve: 7723 movl rGLUE,%ecx 7724 movzwl 2(rPC),%eax # eax<- field ref BBBB 7725 movl offGlue_method(%ecx),%ecx # ecx<- current method 7726 EXPORT_PC # could throw, need to export 7727 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7728 movl %eax,OUT_ARG1(%esp) 7729 movl %ecx,OUT_ARG0(%esp) 7730 call dvmResolveStaticField # eax<- resolved StaticField ptr 7731 testl %eax,%eax 7732 jne .LOP_SPUT_BYTE_finish # success, continue 7733 jmp common_exceptionThrown # no, handle exception 7734 7735/* continuation for OP_SPUT_CHAR */ 7736 7737 /* 7738 * Go resolve the field 7739 */ 7740.LOP_SPUT_CHAR_resolve: 7741 movl rGLUE,%ecx 7742 movzwl 2(rPC),%eax # eax<- field ref BBBB 7743 movl offGlue_method(%ecx),%ecx # ecx<- current method 7744 EXPORT_PC # could throw, need to export 7745 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7746 movl %eax,OUT_ARG1(%esp) 7747 movl %ecx,OUT_ARG0(%esp) 7748 call dvmResolveStaticField # eax<- resolved StaticField ptr 7749 testl %eax,%eax 7750 jne .LOP_SPUT_CHAR_finish # success, continue 7751 jmp common_exceptionThrown # no, handle exception 7752 7753/* continuation for OP_SPUT_SHORT */ 7754 7755 /* 7756 * Go resolve the field 7757 */ 7758.LOP_SPUT_SHORT_resolve: 7759 movl rGLUE,%ecx 7760 movzwl 2(rPC),%eax # eax<- field ref BBBB 7761 movl offGlue_method(%ecx),%ecx # ecx<- current method 7762 EXPORT_PC # could throw, need to export 7763 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7764 movl %eax,OUT_ARG1(%esp) 7765 movl %ecx,OUT_ARG0(%esp) 7766 call dvmResolveStaticField # eax<- resolved StaticField ptr 7767 testl %eax,%eax 7768 jne .LOP_SPUT_SHORT_finish # success, continue 7769 jmp common_exceptionThrown # no, handle exception 7770 7771/* continuation for OP_INVOKE_VIRTUAL */ 7772 7773 7774.LOP_INVOKE_VIRTUAL_more: 7775 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 7776 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 7777 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 7778 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7779 testl %eax,%eax # got null? 7780 jne .LOP_INVOKE_VIRTUAL_continue # no, continue 7781 jmp common_exceptionThrown # yes, handle exception 7782 7783 /* At this point: 7784 * eax = resolved base method 7785 * ecx = scratch 7786 */ 7787.LOP_INVOKE_VIRTUAL_continue: 7788 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 7789 .if (!0) 7790 andl $0xf,%ecx # ecx<- D (or stays CCCC) 7791 .endif 7792 GET_VREG_R %ecx %ecx # ecx<- "this" 7793 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 7794 testl %ecx,%ecx # null this? 7795 je common_errNullObject # go if so 7796 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz 7797 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable 7798 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex] 7799 jmp common_invokeMethodNoRange 7800 7801/* continuation for OP_INVOKE_SUPER */ 7802 7803 /* 7804 * At this point: 7805 * ecx = resolved base method [r0] 7806 * eax = method->clazz [r9] 7807 */ 7808.LOP_INVOKE_SUPER_continue: 7809 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super 7810 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex 7811 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount) 7812 jae .LOP_INVOKE_SUPER_nsm # method not present in superclass 7813 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable 7814 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex] 7815 jmp common_invokeMethodNoRange 7816 7817 7818 /* At this point: 7819 * ecx = null (needs to be resolved base method) 7820 * eax = method->clazz 7821 */ 7822.LOP_INVOKE_SUPER_resolve: 7823 SPILL_TMP1(%eax) # method->clazz 7824 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz 7825 movzwl 2(rPC),%ecx # ecx<- BBBB 7826 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type 7827 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 7828 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7829 testl %eax,%eax # got null? 7830 movl %eax,%ecx # ecx<- resolved base method 7831 UNSPILL_TMP1(%eax) # restore method->clazz 7832 jne .LOP_INVOKE_SUPER_continue # good to go - continue 7833 jmp common_exceptionThrown # handle exception 7834 7835 /* 7836 * Throw a NoSuchMethodError with the method name as the message. 7837 * ecx = resolved base method 7838 */ 7839.LOP_INVOKE_SUPER_nsm: 7840 movl offMethod_name(%ecx),%eax 7841 mov %eax,OUT_ARG1(%esp) 7842 jmp common_errNoSuchMethod 7843 7844/* continuation for OP_INVOKE_DIRECT */ 7845 7846 /* 7847 * On entry: 7848 * TMP_SPILL <- "this" register 7849 * Things a bit ugly on this path, but it's the less 7850 * frequent one. We'll have to do some reloading. 7851 */ 7852.LOP_INVOKE_DIRECT_resolve: 7853 SPILL_TMP1(%ecx) 7854 movl rGLUE,%ecx 7855 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 7856 movzwl 2(rPC),%eax # reference (BBBB or CCCC) 7857 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7858 movl $METHOD_DIRECT,OUT_ARG2(%esp) 7859 movl %eax,OUT_ARG1(%esp) 7860 movl %ecx,OUT_ARG0(%esp) 7861 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7862 UNSPILL_TMP1(%ecx) 7863 testl %eax,%eax 7864 jne .LOP_INVOKE_DIRECT_finish 7865 jmp common_exceptionThrown 7866 7867/* continuation for OP_INVOKE_STATIC */ 7868 7869.LOP_INVOKE_STATIC_continue: 7870 movl $METHOD_STATIC,%eax 7871 movl %eax,OUT_ARG2(%esp) # arg2<- flags 7872 call dvmResolveMethod # call(clazz,ref,flags) 7873 testl %eax,%eax # got null? 7874 jne common_invokeMethodNoRange 7875 jmp common_exceptionThrown 7876 7877/* continuation for OP_INVOKE_INTERFACE */ 7878 7879.LOP_INVOKE_INTERFACE_continue: 7880 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex) 7881 testl %eax,%eax 7882 je common_exceptionThrown 7883 jmp common_invokeMethodNoRange 7884 7885/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 7886 7887 7888.LOP_INVOKE_VIRTUAL_RANGE_more: 7889 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 7890 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 7891 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 7892 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7893 testl %eax,%eax # got null? 7894 jne .LOP_INVOKE_VIRTUAL_RANGE_continue # no, continue 7895 jmp common_exceptionThrown # yes, handle exception 7896 7897 /* At this point: 7898 * eax = resolved base method 7899 * ecx = scratch 7900 */ 7901.LOP_INVOKE_VIRTUAL_RANGE_continue: 7902 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 7903 .if (!1) 7904 andl $0xf,%ecx # ecx<- D (or stays CCCC) 7905 .endif 7906 GET_VREG_R %ecx %ecx # ecx<- "this" 7907 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 7908 testl %ecx,%ecx # null this? 7909 je common_errNullObject # go if so 7910 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz 7911 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable 7912 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex] 7913 jmp common_invokeMethodRange 7914 7915/* continuation for OP_INVOKE_SUPER_RANGE */ 7916 7917 /* 7918 * At this point: 7919 * ecx = resolved base method [r0] 7920 * eax = method->clazz [r9] 7921 */ 7922.LOP_INVOKE_SUPER_RANGE_continue: 7923 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super 7924 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex 7925 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount) 7926 jae .LOP_INVOKE_SUPER_RANGE_nsm # method not present in superclass 7927 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable 7928 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex] 7929 jmp common_invokeMethodRange 7930 7931 7932 /* At this point: 7933 * ecx = null (needs to be resolved base method) 7934 * eax = method->clazz 7935 */ 7936.LOP_INVOKE_SUPER_RANGE_resolve: 7937 SPILL_TMP1(%eax) # method->clazz 7938 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz 7939 movzwl 2(rPC),%ecx # ecx<- BBBB 7940 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type 7941 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 7942 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7943 testl %eax,%eax # got null? 7944 movl %eax,%ecx # ecx<- resolved base method 7945 UNSPILL_TMP1(%eax) # restore method->clazz 7946 jne .LOP_INVOKE_SUPER_RANGE_continue # good to go - continue 7947 jmp common_exceptionThrown # handle exception 7948 7949 /* 7950 * Throw a NoSuchMethodError with the method name as the message. 7951 * ecx = resolved base method 7952 */ 7953.LOP_INVOKE_SUPER_RANGE_nsm: 7954 movl offMethod_name(%ecx),%eax 7955 mov %eax,OUT_ARG1(%esp) 7956 jmp common_errNoSuchMethod 7957 7958/* continuation for OP_INVOKE_DIRECT_RANGE */ 7959 7960 /* 7961 * On entry: 7962 * TMP_SPILL <- "this" register 7963 * Things a bit ugly on this path, but it's the less 7964 * frequent one. We'll have to do some reloading. 7965 */ 7966.LOP_INVOKE_DIRECT_RANGE_resolve: 7967 SPILL_TMP1(%ecx) 7968 movl rGLUE,%ecx 7969 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 7970 movzwl 2(rPC),%eax # reference (BBBB or CCCC) 7971 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7972 movl $METHOD_DIRECT,OUT_ARG2(%esp) 7973 movl %eax,OUT_ARG1(%esp) 7974 movl %ecx,OUT_ARG0(%esp) 7975 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7976 UNSPILL_TMP1(%ecx) 7977 testl %eax,%eax 7978 jne .LOP_INVOKE_DIRECT_RANGE_finish 7979 jmp common_exceptionThrown 7980 7981/* continuation for OP_INVOKE_STATIC_RANGE */ 7982 7983.LOP_INVOKE_STATIC_RANGE_continue: 7984 movl $METHOD_STATIC,%eax 7985 movl %eax,OUT_ARG2(%esp) # arg2<- flags 7986 call dvmResolveMethod # call(clazz,ref,flags) 7987 testl %eax,%eax # got null? 7988 jne common_invokeMethodRange 7989 jmp common_exceptionThrown 7990 7991/* continuation for OP_INVOKE_INTERFACE_RANGE */ 7992 7993.LOP_INVOKE_INTERFACE_RANGE_continue: 7994 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex) 7995 testl %eax,%eax 7996 je common_exceptionThrown 7997 jmp common_invokeMethodRange 7998 7999/* continuation for OP_FLOAT_TO_INT */ 8000 8001 8002.LOP_FLOAT_TO_INT_continue: 8003 .if 0 8004 movl $0x80000000,%eax 8005 xorl 4(rFP,%ecx,4),%eax 8006 orl (rFP,%ecx,4),%eax 8007 .else 8008 cmpl $0x80000000,(rFP,%ecx,4) 8009 .endif 8010 je .LOP_FLOAT_TO_INT_special_case # fix up result 8011 8012.LOP_FLOAT_TO_INT_finish: 8013 ADVANCE_PC 1 8014 GOTO_NEXT_R %edx 8015 8016.LOP_FLOAT_TO_INT_special_case: 8017 fnstsw %ax 8018 sahf 8019 jp .LOP_FLOAT_TO_INT_isNaN 8020 adcl $-1,(rFP,%ecx,4) 8021 .if 0 8022 adcl $-1,4(rFP,%ecx,4) 8023 .endif 8024 jmp .LOP_FLOAT_TO_INT_finish 8025.LOP_FLOAT_TO_INT_isNaN: 8026 movl $0,(rFP,%ecx,4) 8027 .if 0 8028 movl $0,4(rFP,%ecx,4) 8029 .endif 8030 jmp .LOP_FLOAT_TO_INT_finish 8031 8032/* continuation for OP_FLOAT_TO_LONG */ 8033 8034 8035.LOP_FLOAT_TO_LONG_continue: 8036 .if 1 8037 movl $0x80000000,%eax 8038 xorl 4(rFP,%ecx,4),%eax 8039 orl (rFP,%ecx,4),%eax 8040 .else 8041 cmpl $0x80000000,(rFP,%ecx,4) 8042 .endif 8043 je .LOP_FLOAT_TO_LONG_special_case # fix up result 8044 8045.LOP_FLOAT_TO_LONG_finish: 8046 ADVANCE_PC 1 8047 GOTO_NEXT_R %edx 8048 8049.LOP_FLOAT_TO_LONG_special_case: 8050 fnstsw %ax 8051 sahf 8052 jp .LOP_FLOAT_TO_LONG_isNaN 8053 adcl $-1,(rFP,%ecx,4) 8054 .if 1 8055 adcl $-1,4(rFP,%ecx,4) 8056 .endif 8057 jmp .LOP_FLOAT_TO_LONG_finish 8058.LOP_FLOAT_TO_LONG_isNaN: 8059 movl $0,(rFP,%ecx,4) 8060 .if 1 8061 movl $0,4(rFP,%ecx,4) 8062 .endif 8063 jmp .LOP_FLOAT_TO_LONG_finish 8064 8065/* continuation for OP_DOUBLE_TO_INT */ 8066 8067 8068.LOP_DOUBLE_TO_INT_continue: 8069 .if 0 8070 movl $0x80000000,%eax 8071 xorl 4(rFP,%ecx,4),%eax 8072 orl (rFP,%ecx,4),%eax 8073 .else 8074 cmpl $0x80000000,(rFP,%ecx,4) 8075 .endif 8076 je .LOP_DOUBLE_TO_INT_special_case # fix up result 8077 8078.LOP_DOUBLE_TO_INT_finish: 8079 ADVANCE_PC 1 8080 GOTO_NEXT_R %edx 8081 8082.LOP_DOUBLE_TO_INT_special_case: 8083 fnstsw %ax 8084 sahf 8085 jp .LOP_DOUBLE_TO_INT_isNaN 8086 adcl $-1,(rFP,%ecx,4) 8087 .if 0 8088 adcl $-1,4(rFP,%ecx,4) 8089 .endif 8090 jmp .LOP_DOUBLE_TO_INT_finish 8091.LOP_DOUBLE_TO_INT_isNaN: 8092 movl $0,(rFP,%ecx,4) 8093 .if 0 8094 movl $0,4(rFP,%ecx,4) 8095 .endif 8096 jmp .LOP_DOUBLE_TO_INT_finish 8097 8098/* continuation for OP_DOUBLE_TO_LONG */ 8099 8100 8101.LOP_DOUBLE_TO_LONG_continue: 8102 .if 1 8103 movl $0x80000000,%eax 8104 xorl 4(rFP,%ecx,4),%eax 8105 orl (rFP,%ecx,4),%eax 8106 .else 8107 cmpl $0x80000000,(rFP,%ecx,4) 8108 .endif 8109 je .LOP_DOUBLE_TO_LONG_special_case # fix up result 8110 8111.LOP_DOUBLE_TO_LONG_finish: 8112 ADVANCE_PC 1 8113 GOTO_NEXT_R %edx 8114 8115.LOP_DOUBLE_TO_LONG_special_case: 8116 fnstsw %ax 8117 sahf 8118 jp .LOP_DOUBLE_TO_LONG_isNaN 8119 adcl $-1,(rFP,%ecx,4) 8120 .if 1 8121 adcl $-1,4(rFP,%ecx,4) 8122 .endif 8123 jmp .LOP_DOUBLE_TO_LONG_finish 8124.LOP_DOUBLE_TO_LONG_isNaN: 8125 movl $0,(rFP,%ecx,4) 8126 .if 1 8127 movl $0,4(rFP,%ecx,4) 8128 .endif 8129 jmp .LOP_DOUBLE_TO_LONG_finish 8130 8131/* continuation for OP_DIV_INT */ 8132.LOP_DIV_INT_continue_div: 8133 cltd 8134 idivl %ecx 8135.LOP_DIV_INT_finish_div: 8136 SET_VREG %eax rINST 8137 FETCH_INST_OPCODE 2 %edx 8138 ADVANCE_PC 2 8139 GOTO_NEXT_R %edx 8140 8141/* continuation for OP_REM_INT */ 8142.LOP_REM_INT_continue_div: 8143 cltd 8144 idivl %ecx 8145.LOP_REM_INT_finish_div: 8146 SET_VREG %edx rINST 8147 FETCH_INST_OPCODE 2 %edx 8148 ADVANCE_PC 2 8149 GOTO_NEXT_R %edx 8150 8151/* continuation for OP_MUL_LONG */ 8152 8153.LOP_MUL_LONG_continue: 8154 leal (%ecx,%edx),%edx # full result now in %edx:%eax 8155 UNSPILL_TMP2(%esi) # Restore Dalvik PC 8156 FETCH_INST_OPCODE 2 %ecx # Fetch next instruction 8157 movl %edx,4(rFP,rINST,4) # v[B+1]<- %edx 8158 movl %eax,(rFP,rINST,4) # v[B]<- %eax 8159 ADVANCE_PC 2 8160 GOTO_NEXT_R %ecx 8161 8162/* continuation for OP_DIV_LONG */ 8163 8164.LOP_DIV_LONG_continue: 8165 call __divdi3 8166.LOP_DIV_LONG_finish: 8167 SET_VREG_WORD %edx rINST 1 8168 SET_VREG_WORD %eax rINST 0 8169 FETCH_INST_OPCODE 2 %edx 8170 ADVANCE_PC 2 8171 GOTO_NEXT_R %edx 8172 8173.LOP_DIV_LONG_check_zero: 8174 testl %edx,%edx 8175 jne .LOP_DIV_LONG_notSpecial 8176 jmp common_errDivideByZero 8177.LOP_DIV_LONG_check_neg1: 8178 testl %edx,%eax 8179 jne .LOP_DIV_LONG_notSpecial 8180 GET_VREG_WORD %edx %ecx 0 8181 GET_VREG_WORD %ecx %ecx 1 8182 testl %edx,%edx 8183 jne .LOP_DIV_LONG_notSpecial1 8184 cmpl $0x80000000,%ecx 8185 jne .LOP_DIV_LONG_notSpecial1 8186 /* minint / -1, return minint on div, 0 on rem */ 8187 xorl %eax,%eax 8188 movl $0x80000000,%edx 8189 jmp .LOP_DIV_LONG_finish 8190 8191/* continuation for OP_REM_LONG */ 8192 8193.LOP_REM_LONG_continue: 8194 call __moddi3 8195.LOP_REM_LONG_finish: 8196 SET_VREG_WORD %edx rINST 1 8197 SET_VREG_WORD %eax rINST 0 8198 FETCH_INST_OPCODE 2 %edx 8199 ADVANCE_PC 2 8200 GOTO_NEXT_R %edx 8201 8202.LOP_REM_LONG_check_zero: 8203 testl %edx,%edx 8204 jne .LOP_REM_LONG_notSpecial 8205 jmp common_errDivideByZero 8206.LOP_REM_LONG_check_neg1: 8207 testl %edx,%eax 8208 jne .LOP_REM_LONG_notSpecial 8209 GET_VREG_WORD %edx %ecx 0 8210 GET_VREG_WORD %ecx %ecx 1 8211 testl %edx,%edx 8212 jne .LOP_REM_LONG_notSpecial1 8213 cmpl $0x80000000,%ecx 8214 jne .LOP_REM_LONG_notSpecial1 8215 /* minint / -1, return minint on div, 0 on rem */ 8216 xorl %eax,%eax 8217 movl $0,%edx 8218 jmp .LOP_REM_LONG_finish 8219 8220/* continuation for OP_SHL_LONG */ 8221 8222.LOP_SHL_LONG_finish: 8223 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- %eax 8224 ADVANCE_PC 2 8225 GOTO_NEXT_R %edx 8226 8227/* continuation for OP_SHR_LONG */ 8228 8229 8230.LOP_SHR_LONG_finish: 8231 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax 8232 ADVANCE_PC 2 8233 GOTO_NEXT_R %edx 8234 8235/* continuation for OP_USHR_LONG */ 8236 8237 8238.LOP_USHR_LONG_finish: 8239 SET_VREG_WORD %eax rINST 0 # v[BB+0]<- eax 8240 ADVANCE_PC 2 8241 GOTO_NEXT_R %edx 8242 8243/* continuation for OP_DIV_INT_2ADDR */ 8244.LOP_DIV_INT_2ADDR_continue_div2addr: 8245 cltd 8246 idivl %ecx 8247.LOP_DIV_INT_2ADDR_finish_div2addr: 8248 SET_VREG %eax rINST 8249 FETCH_INST_OPCODE 1 %edx 8250 ADVANCE_PC 1 8251 GOTO_NEXT_R %edx 8252 8253/* continuation for OP_REM_INT_2ADDR */ 8254.LOP_REM_INT_2ADDR_continue_div2addr: 8255 cltd 8256 idivl %ecx 8257.LOP_REM_INT_2ADDR_finish_div2addr: 8258 SET_VREG %edx rINST 8259 FETCH_INST_OPCODE 1 %edx 8260 ADVANCE_PC 1 8261 GOTO_NEXT_R %edx 8262 8263/* continuation for OP_MUL_LONG_2ADDR */ 8264 8265.LOP_MUL_LONG_2ADDR_continue: 8266 leal (%ecx,%edx),%edx # full result now in %edx:%eax 8267 movl %edx,4(%esi) # v[A+1]<- %edx 8268 movl %eax,(%esi) # v[A]<- %eax 8269 UNSPILL_TMP2(%esi) 8270 FETCH_INST_OPCODE 1 %ecx 8271 UNSPILL(rFP) 8272 ADVANCE_PC 1 8273 GOTO_NEXT_R %ecx 8274 8275/* continuation for OP_DIV_LONG_2ADDR */ 8276 8277.LOP_DIV_LONG_2ADDR_continue: 8278 movl %eax,OUT_ARG3(%esp) 8279 movl %edx,OUT_ARG0(%esp) 8280 movl %ecx,OUT_ARG1(%esp) 8281 call __divdi3 8282.LOP_DIV_LONG_2ADDR_finish: 8283 SET_VREG_WORD %edx rINST 1 8284 SET_VREG_WORD %eax rINST 0 8285 FETCH_INST_OPCODE 1 %edx 8286 ADVANCE_PC 1 8287 GOTO_NEXT_R %edx 8288 8289.LOP_DIV_LONG_2ADDR_check_zero: 8290 testl %edx,%edx 8291 jne .LOP_DIV_LONG_2ADDR_notSpecial 8292 jmp common_errDivideByZero 8293.LOP_DIV_LONG_2ADDR_check_neg1: 8294 testl %edx,%eax 8295 jne .LOP_DIV_LONG_2ADDR_notSpecial 8296 GET_VREG_WORD %edx rINST 0 8297 GET_VREG_WORD %ecx rINST 1 8298 testl %edx,%edx 8299 jne .LOP_DIV_LONG_2ADDR_notSpecial1 8300 cmpl $0x80000000,%ecx 8301 jne .LOP_DIV_LONG_2ADDR_notSpecial1 8302 /* minint / -1, return minint on div, 0 on rem */ 8303 xorl %eax,%eax 8304 movl $0x80000000,%edx 8305 jmp .LOP_DIV_LONG_2ADDR_finish 8306 8307/* continuation for OP_REM_LONG_2ADDR */ 8308 8309.LOP_REM_LONG_2ADDR_continue: 8310 movl %eax,OUT_ARG3(%esp) 8311 movl %edx,OUT_ARG0(%esp) 8312 movl %ecx,OUT_ARG1(%esp) 8313 call __moddi3 8314.LOP_REM_LONG_2ADDR_finish: 8315 SET_VREG_WORD %edx rINST 1 8316 SET_VREG_WORD %eax rINST 0 8317 FETCH_INST_OPCODE 1 %edx 8318 ADVANCE_PC 1 8319 GOTO_NEXT_R %edx 8320 8321.LOP_REM_LONG_2ADDR_check_zero: 8322 testl %edx,%edx 8323 jne .LOP_REM_LONG_2ADDR_notSpecial 8324 jmp common_errDivideByZero 8325.LOP_REM_LONG_2ADDR_check_neg1: 8326 testl %edx,%eax 8327 jne .LOP_REM_LONG_2ADDR_notSpecial 8328 GET_VREG_WORD %edx rINST 0 8329 GET_VREG_WORD %ecx rINST 1 8330 testl %edx,%edx 8331 jne .LOP_REM_LONG_2ADDR_notSpecial1 8332 cmpl $0x80000000,%ecx 8333 jne .LOP_REM_LONG_2ADDR_notSpecial1 8334 /* minint / -1, return minint on div, 0 on rem */ 8335 xorl %eax,%eax 8336 movl $0,%edx 8337 jmp .LOP_REM_LONG_2ADDR_finish 8338 8339/* continuation for OP_SHL_LONG_2ADDR */ 8340 8341 8342.LOP_SHL_LONG_2ADDR_finish: 8343 FETCH_INST_OPCODE 1 %edx 8344 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax 8345 ADVANCE_PC 1 8346 GOTO_NEXT_R %edx 8347 8348/* continuation for OP_SHR_LONG_2ADDR */ 8349 8350 8351.LOP_SHR_LONG_2ADDR_finish: 8352 FETCH_INST_OPCODE 1 %edx 8353 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax 8354 ADVANCE_PC 1 8355 GOTO_NEXT_R %edx 8356 8357/* continuation for OP_USHR_LONG_2ADDR */ 8358 8359 8360.LOP_USHR_LONG_2ADDR_finish: 8361 FETCH_INST_OPCODE 1 %edx 8362 SET_VREG_WORD %eax rINST 0 # v[AA+0]<- eax 8363 ADVANCE_PC 1 8364 GOTO_NEXT_R %edx 8365 8366/* continuation for OP_DIV_INT_LIT16 */ 8367.LOP_DIV_INT_LIT16_continue_div: 8368 cltd 8369 idivl %ecx 8370.LOP_DIV_INT_LIT16_finish_div: 8371 SET_VREG %eax rINST 8372 FETCH_INST_OPCODE 2 %edx 8373 ADVANCE_PC 2 8374 GOTO_NEXT_R %edx 8375 8376/* continuation for OP_REM_INT_LIT16 */ 8377.LOP_REM_INT_LIT16_continue_div: 8378 cltd 8379 idivl %ecx 8380.LOP_REM_INT_LIT16_finish_div: 8381 SET_VREG %edx rINST 8382 FETCH_INST_OPCODE 2 %edx 8383 ADVANCE_PC 2 8384 GOTO_NEXT_R %edx 8385 8386/* continuation for OP_DIV_INT_LIT8 */ 8387.LOP_DIV_INT_LIT8_continue_div: 8388 cltd 8389 idivl %ecx 8390.LOP_DIV_INT_LIT8_finish_div: 8391 SET_VREG %eax rINST 8392 FETCH_INST_OPCODE 2 %edx 8393 ADVANCE_PC 2 8394 GOTO_NEXT_R %edx 8395 8396/* continuation for OP_REM_INT_LIT8 */ 8397.LOP_REM_INT_LIT8_continue_div: 8398 cltd 8399 idivl %ecx 8400.LOP_REM_INT_LIT8_finish_div: 8401 SET_VREG %edx rINST 8402 FETCH_INST_OPCODE 2 %edx 8403 ADVANCE_PC 2 8404 GOTO_NEXT_R %edx 8405 8406/* continuation for OP_IGET_VOLATILE */ 8407 8408 8409.LOP_IGET_VOLATILE_resolve: 8410 EXPORT_PC 8411 movl offGlue_method(%edx),%edx # edx<- current method 8412 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 8413 SPILL_TMP1(%ecx) # save obj pointer across call 8414 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 8415 call dvmResolveInstField # ... to dvmResolveInstField 8416 UNSPILL_TMP1(%ecx) 8417 testl %eax,%eax # returns InstrField ptr 8418 jne .LOP_IGET_VOLATILE_finish 8419 jmp common_exceptionThrown 8420 8421.LOP_IGET_VOLATILE_finish: 8422 /* 8423 * Currently: 8424 * eax holds resolved field 8425 * ecx holds object 8426 * rINST holds A 8427 */ 8428 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8429 testl %ecx,%ecx # object null? 8430 je common_errNullObject # object was null 8431 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 8432 movl rINST,%eax # eax<- A 8433 FETCH_INST_OPCODE 2 %edx 8434 SET_VREG %ecx %eax 8435 ADVANCE_PC 2 8436 GOTO_NEXT_R %edx 8437 8438/* continuation for OP_IPUT_VOLATILE */ 8439 8440 8441.LOP_IPUT_VOLATILE_resolve: 8442 EXPORT_PC 8443 movl offGlue_method(%edx),%edx # edx<- current method 8444 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 8445 SPILL_TMP1(%ecx) # save obj pointer across call 8446 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 8447 call dvmResolveInstField # ... to dvmResolveInstField 8448 UNSPILL_TMP1(%ecx) 8449 testl %eax,%eax # returns InstrField ptr 8450 jne .LOP_IPUT_VOLATILE_finish 8451 jmp common_exceptionThrown 8452 8453.LOP_IPUT_VOLATILE_finish: 8454 /* 8455 * Currently: 8456 * eax holds resolved field 8457 * ecx holds object 8458 * rINST holds A 8459 */ 8460 GET_VREG_R rINST rINST # rINST<- v[A] 8461 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8462 testl %ecx,%ecx # object null? 8463 je common_errNullObject # object was null 8464 FETCH_INST_OPCODE 2 %edx 8465 movl rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 8466 ADVANCE_PC 2 8467 GOTO_NEXT_R %edx 8468 8469/* continuation for OP_SGET_VOLATILE */ 8470 8471 /* 8472 * Go resolve the field 8473 */ 8474.LOP_SGET_VOLATILE_resolve: 8475 movl rGLUE,%ecx 8476 movzwl 2(rPC),%eax # eax<- field ref BBBB 8477 movl offGlue_method(%ecx),%ecx # ecx<- current method 8478 EXPORT_PC # could throw, need to export 8479 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8480 movl %eax,OUT_ARG1(%esp) 8481 movl %ecx,OUT_ARG0(%esp) 8482 call dvmResolveStaticField # eax<- resolved StaticField ptr 8483 testl %eax,%eax 8484 jne .LOP_SGET_VOLATILE_finish # success, continue 8485 jmp common_exceptionThrown # no, handle exception 8486 8487/* continuation for OP_SPUT_VOLATILE */ 8488 8489 /* 8490 * Go resolve the field 8491 */ 8492.LOP_SPUT_VOLATILE_resolve: 8493 movl rGLUE,%ecx 8494 movzwl 2(rPC),%eax # eax<- field ref BBBB 8495 movl offGlue_method(%ecx),%ecx # ecx<- current method 8496 EXPORT_PC # could throw, need to export 8497 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8498 movl %eax,OUT_ARG1(%esp) 8499 movl %ecx,OUT_ARG0(%esp) 8500 call dvmResolveStaticField # eax<- resolved StaticField ptr 8501 testl %eax,%eax 8502 jne .LOP_SPUT_VOLATILE_finish # success, continue 8503 jmp common_exceptionThrown # no, handle exception 8504 8505/* continuation for OP_IGET_OBJECT_VOLATILE */ 8506 8507 8508.LOP_IGET_OBJECT_VOLATILE_resolve: 8509 EXPORT_PC 8510 movl offGlue_method(%edx),%edx # edx<- current method 8511 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 8512 SPILL_TMP1(%ecx) # save obj pointer across call 8513 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 8514 call dvmResolveInstField # ... to dvmResolveInstField 8515 UNSPILL_TMP1(%ecx) 8516 testl %eax,%eax # returns InstrField ptr 8517 jne .LOP_IGET_OBJECT_VOLATILE_finish 8518 jmp common_exceptionThrown 8519 8520.LOP_IGET_OBJECT_VOLATILE_finish: 8521 /* 8522 * Currently: 8523 * eax holds resolved field 8524 * ecx holds object 8525 * rINST holds A 8526 */ 8527 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8528 testl %ecx,%ecx # object null? 8529 je common_errNullObject # object was null 8530 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 8531 movl rINST,%eax # eax<- A 8532 FETCH_INST_OPCODE 2 %edx 8533 SET_VREG %ecx %eax 8534 ADVANCE_PC 2 8535 GOTO_NEXT_R %edx 8536 8537/* continuation for OP_EXECUTE_INLINE */ 8538 8539.LOP_EXECUTE_INLINE_continue: 8540 /* 8541 * Extract args, call function. 8542 * ecx = #of args (0-4) 8543 * eax = call index 8544 * @esp = return addr 8545 * esp is -4 from normal 8546 * 8547 * Go ahead and load all 4 args, even if not used. 8548 */ 8549 movzwl 4(rPC),%edx 8550 8551 movl $0xf,%ecx 8552 andl %edx,%ecx 8553 GET_VREG_R %ecx %ecx 8554 sarl $4,%edx 8555 movl %ecx,4+OUT_ARG0(%esp) 8556 8557 movl $0xf,%ecx 8558 andl %edx,%ecx 8559 GET_VREG_R %ecx %ecx 8560 sarl $4,%edx 8561 movl %ecx,4+OUT_ARG1(%esp) 8562 8563 movl $0xf,%ecx 8564 andl %edx,%ecx 8565 GET_VREG_R %ecx %ecx 8566 sarl $4,%edx 8567 movl %ecx,4+OUT_ARG2(%esp) 8568 8569 movl $0xf,%ecx 8570 andl %edx,%ecx 8571 GET_VREG_R %ecx %ecx 8572 sarl $4,%edx 8573 movl %ecx,4+OUT_ARG3(%esp) 8574 8575 sall $4,%eax # index *= sizeof(table entry) 8576 jmp *gDvmInlineOpsTable(%eax) 8577 # will return to caller of .LOP_EXECUTE_INLINE_continue 8578 8579/* continuation for OP_IPUT_OBJECT_QUICK */ 8580 8581.LOP_IPUT_OBJECT_QUICK_finish: 8582 testl rINST,rINST # did we store null? 8583 FETCH_INST_OPCODE 2 %edx 8584 movl offGlue_cardTable(%eax),%eax # get card table base 8585 je 1f # skip card mark if null store 8586 shrl $GC_CARD_SHIFT,%ecx # object head to card number 8587 movb %al,(%eax,%ecx) # mark card 85881: 8589 ADVANCE_PC 2 8590 GOTO_NEXT_R %edx 8591 8592/* continuation for OP_IPUT_OBJECT_VOLATILE */ 8593 8594 8595.LOP_IPUT_OBJECT_VOLATILE_resolve: 8596 EXPORT_PC 8597 movl offGlue_method(%edx),%edx # edx<- current method 8598 movl offMethod_clazz(%edx),%edx # edx<- method->clazz 8599 SPILL_TMP1(%ecx) # save obj pointer across call 8600 movl %edx,OUT_ARG0(%esp) # pass in method->clazz 8601 call dvmResolveInstField # ... to dvmResolveInstField 8602 UNSPILL_TMP1(%ecx) 8603 testl %eax,%eax # returns InstrField ptr 8604 jne .LOP_IPUT_OBJECT_VOLATILE_finish 8605 jmp common_exceptionThrown 8606 8607.LOP_IPUT_OBJECT_VOLATILE_finish: 8608 /* 8609 * Currently: 8610 * eax holds resolved field 8611 * ecx holds object 8612 * %edx is scratch, but needs to be unspilled 8613 * rINST holds A 8614 */ 8615 GET_VREG_R rINST rINST # rINST<- v[A] 8616 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 8617 testl %ecx,%ecx # object null? 8618 je common_errNullObject # object was null 8619 movl rINST,(%ecx,%eax) # obj.field <- v[A](8/16/32 bits) 8620 movl rGLUE,%eax 8621 testl rINST,rINST # stored a NULL? 8622 movl offGlue_cardTable(%eax),%eax # get card table base 8623 FETCH_INST_OPCODE 2 %edx 8624 je 1f # skip card mark if null store 8625 shrl $GC_CARD_SHIFT,%ecx # object head to card number 8626 movb %al,(%eax,%ecx) # mark card 86271: 8628 ADVANCE_PC 2 8629 GOTO_NEXT_R %edx 8630 8631/* continuation for OP_SGET_OBJECT_VOLATILE */ 8632 8633 /* 8634 * Go resolve the field 8635 */ 8636.LOP_SGET_OBJECT_VOLATILE_resolve: 8637 movl rGLUE,%ecx 8638 movzwl 2(rPC),%eax # eax<- field ref BBBB 8639 movl offGlue_method(%ecx),%ecx # ecx<- current method 8640 EXPORT_PC # could throw, need to export 8641 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8642 movl %eax,OUT_ARG1(%esp) 8643 movl %ecx,OUT_ARG0(%esp) 8644 call dvmResolveStaticField # eax<- resolved StaticField ptr 8645 testl %eax,%eax 8646 jne .LOP_SGET_OBJECT_VOLATILE_finish # success, continue 8647 jmp common_exceptionThrown # no, handle exception 8648 8649/* continuation for OP_SPUT_OBJECT_VOLATILE */ 8650 8651 8652.LOP_SPUT_OBJECT_VOLATILE_continue: 8653 movl %ecx,offStaticField_value(%eax) 8654 testl %ecx,%ecx 8655 movl rGLUE,%ecx 8656 FETCH_INST_OPCODE 2 %edx 8657 je 1f 8658 movl offGlue_cardTable(%ecx),%ecx # get card table base 8659 shrl $GC_CARD_SHIFT,%eax # head to card number 8660 movb %cl,(%ecx,%eax) # mark card 86611: 8662 ADVANCE_PC 2 8663 GOTO_NEXT_R %edx 8664 8665.LOP_SPUT_OBJECT_VOLATILE_resolve: 8666 movl rGLUE,%ecx 8667 movzwl 2(rPC),%eax # eax<- field ref BBBB 8668 movl offGlue_method(%ecx),%ecx # ecx<- current method 8669 EXPORT_PC # could throw, need to export 8670 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 8671 movl %eax,OUT_ARG1(%esp) 8672 movl %ecx,OUT_ARG0(%esp) 8673 call dvmResolveStaticField # eax<- resolved StaticField ptr 8674 testl %eax,%eax 8675 jne .LOP_SPUT_OBJECT_VOLATILE_finish # success, continue 8676 jmp common_exceptionThrown # no, handle exception 8677 8678 .size dvmAsmSisterStart, .-dvmAsmSisterStart 8679 .global dvmAsmSisterEnd 8680dvmAsmSisterEnd: 8681 8682/* File: x86/entry.S */ 8683/* 8684 * Copyright (C) 2008 The Android Open Source Project 8685 * 8686 * Licensed under the Apache License, Version 2.0 (the "License"); 8687 * you may not use this file except in compliance with the License. 8688 * You may obtain a copy of the License at 8689 * 8690 * http://www.apache.org/licenses/LICENSE-2.0 8691 * 8692 * Unless required by applicable law or agreed to in writing, software 8693 * distributed under the License is distributed on an "AS IS" BASIS, 8694 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8695 * See the License for the specific language governing permissions and 8696 * limitations under the License. 8697 */ 8698 8699 8700 .text 8701 .global dvmMterpStdRun 8702 .type dvmMterpStdRun, %function 8703/* 8704 * bool dvmMterpStdRun(MterpGlue* glue) 8705 * 8706 * Interpreter entry point. Returns changeInterp. 8707 * 8708 */ 8709dvmMterpStdRun: 8710 movl 4(%esp), %ecx # get incoming rGLUE 8711 push %ebp # save caller base pointer 8712 push %ecx # save rGLUE at (%ebp) 8713 movl %esp, %ebp # set our %ebp 8714/* 8715 * At this point we've allocated two slots on the stack 8716 * via push and stack is 8-byte aligned. Allocate space 8717 * for 8 spill slots, 3 local slots, 5 arg slots + 2 slots for 8718 * padding to bring us to 16-byte alignment 8719 */ 8720 subl $(FRAME_SIZE-8), %esp 8721 8722/* Spill callee save regs */ 8723 movl %edi,EDI_SPILL(%ebp) 8724 movl %esi,ESI_SPILL(%ebp) 8725 movl %ebx,EBX_SPILL(%ebp) 8726 8727/* Set up "named" registers */ 8728 movl offGlue_pc(%ecx),rPC 8729 movl offGlue_fp(%ecx),rFP 8730 8731/* Remember %esp for future "longjmp" */ 8732 movl %esp,offGlue_bailPtr(%ecx) 8733 8734/* How to start? */ 8735 movb offGlue_entryPoint(%ecx),%al 8736 8737/* Normal start? */ 8738 cmpb $kInterpEntryInstr,%al 8739 jne .Lnot_instr 8740 8741 /* Normal case: start executing the instruction at rPC */ 8742 FETCH_INST 8743 GOTO_NEXT 8744 8745.Lnot_instr: 8746 /* Reset to normal case */ 8747 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx) 8748 cmpb $kInterpEntryReturn,%al 8749 je common_returnFromMethod 8750 cmpb $kInterpEntryThrow,%al 8751 je common_exceptionThrown 8752 movzx %al,%eax 8753 movl %eax,OUT_ARG1(%esp) 8754 movl $.LstrBadEntryPoint,OUT_ARG0(%esp) 8755 call printf 8756 call dvmAbort 8757 /* Not reached */ 8758 8759 8760 .global dvmMterpStdBail 8761 .type dvmMterpStdBail, %function 8762/* 8763 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp) 8764 * 8765 * Restore the stack pointer and PC from the save point established on entry. 8766 * This is essentially the same as a longjmp, but should be cheaper. The 8767 * last instruction causes us to return to whoever called dvmMterpStdRun. 8768 * 8769 * We're not going to build a standard frame here, so the arg accesses will 8770 * look a little strange. 8771 * 8772 * On entry: 8773 * esp+4 (arg0) MterpGlue* glue 8774 * esp+8 (arg1) bool changeInterp 8775 */ 8776dvmMterpStdBail: 8777 movl 4(%esp),%ecx # grab glue 8778 movl 8(%esp),%eax # changeInterp to return reg 8779 movl offGlue_bailPtr(%ecx),%esp # Restore "setjmp" esp 8780 movl (FRAME_SIZE-8)(%esp), %ebp # Restore %ebp at point of setjmp 8781 movl EDI_SPILL(%ebp),%edi 8782 movl ESI_SPILL(%ebp),%esi 8783 movl EBX_SPILL(%ebp),%ebx 8784 movl PREV_FP(%ebp),%ebp # restore caller's ebp 8785 addl $FRAME_SIZE,%esp # strip frame 8786 ret # return to dvmMterpStdRun's caller 8787 8788 8789/* 8790 * Strings 8791 */ 8792 .section .rodata 8793.LstrBadEntryPoint: 8794 .asciz "Bad entry point %d\n" 8795 8796 8797/* 8798 * FIXME: Should have the config/rebuild mechanism generate this 8799 * for targets that need it. 8800 */ 8801 8802/* Jump table */ 8803dvmAsmInstructionJmpTable = .LdvmAsmInstructionJmpTable 8804.LdvmAsmInstructionJmpTable: 8805.long .L_OP_NOP 8806.long .L_OP_MOVE 8807.long .L_OP_MOVE_FROM16 8808.long .L_OP_MOVE_16 8809.long .L_OP_MOVE_WIDE 8810.long .L_OP_MOVE_WIDE_FROM16 8811.long .L_OP_MOVE_WIDE_16 8812.long .L_OP_MOVE_OBJECT 8813.long .L_OP_MOVE_OBJECT_FROM16 8814.long .L_OP_MOVE_OBJECT_16 8815.long .L_OP_MOVE_RESULT 8816.long .L_OP_MOVE_RESULT_WIDE 8817.long .L_OP_MOVE_RESULT_OBJECT 8818.long .L_OP_MOVE_EXCEPTION 8819.long .L_OP_RETURN_VOID 8820.long .L_OP_RETURN 8821.long .L_OP_RETURN_WIDE 8822.long .L_OP_RETURN_OBJECT 8823.long .L_OP_CONST_4 8824.long .L_OP_CONST_16 8825.long .L_OP_CONST 8826.long .L_OP_CONST_HIGH16 8827.long .L_OP_CONST_WIDE_16 8828.long .L_OP_CONST_WIDE_32 8829.long .L_OP_CONST_WIDE 8830.long .L_OP_CONST_WIDE_HIGH16 8831.long .L_OP_CONST_STRING 8832.long .L_OP_CONST_STRING_JUMBO 8833.long .L_OP_CONST_CLASS 8834.long .L_OP_MONITOR_ENTER 8835.long .L_OP_MONITOR_EXIT 8836.long .L_OP_CHECK_CAST 8837.long .L_OP_INSTANCE_OF 8838.long .L_OP_ARRAY_LENGTH 8839.long .L_OP_NEW_INSTANCE 8840.long .L_OP_NEW_ARRAY 8841.long .L_OP_FILLED_NEW_ARRAY 8842.long .L_OP_FILLED_NEW_ARRAY_RANGE 8843.long .L_OP_FILL_ARRAY_DATA 8844.long .L_OP_THROW 8845.long .L_OP_GOTO 8846.long .L_OP_GOTO_16 8847.long .L_OP_GOTO_32 8848.long .L_OP_PACKED_SWITCH 8849.long .L_OP_SPARSE_SWITCH 8850.long .L_OP_CMPL_FLOAT 8851.long .L_OP_CMPG_FLOAT 8852.long .L_OP_CMPL_DOUBLE 8853.long .L_OP_CMPG_DOUBLE 8854.long .L_OP_CMP_LONG 8855.long .L_OP_IF_EQ 8856.long .L_OP_IF_NE 8857.long .L_OP_IF_LT 8858.long .L_OP_IF_GE 8859.long .L_OP_IF_GT 8860.long .L_OP_IF_LE 8861.long .L_OP_IF_EQZ 8862.long .L_OP_IF_NEZ 8863.long .L_OP_IF_LTZ 8864.long .L_OP_IF_GEZ 8865.long .L_OP_IF_GTZ 8866.long .L_OP_IF_LEZ 8867.long .L_OP_UNUSED_3E 8868.long .L_OP_UNUSED_3F 8869.long .L_OP_UNUSED_40 8870.long .L_OP_UNUSED_41 8871.long .L_OP_UNUSED_42 8872.long .L_OP_UNUSED_43 8873.long .L_OP_AGET 8874.long .L_OP_AGET_WIDE 8875.long .L_OP_AGET_OBJECT 8876.long .L_OP_AGET_BOOLEAN 8877.long .L_OP_AGET_BYTE 8878.long .L_OP_AGET_CHAR 8879.long .L_OP_AGET_SHORT 8880.long .L_OP_APUT 8881.long .L_OP_APUT_WIDE 8882.long .L_OP_APUT_OBJECT 8883.long .L_OP_APUT_BOOLEAN 8884.long .L_OP_APUT_BYTE 8885.long .L_OP_APUT_CHAR 8886.long .L_OP_APUT_SHORT 8887.long .L_OP_IGET 8888.long .L_OP_IGET_WIDE 8889.long .L_OP_IGET_OBJECT 8890.long .L_OP_IGET_BOOLEAN 8891.long .L_OP_IGET_BYTE 8892.long .L_OP_IGET_CHAR 8893.long .L_OP_IGET_SHORT 8894.long .L_OP_IPUT 8895.long .L_OP_IPUT_WIDE 8896.long .L_OP_IPUT_OBJECT 8897.long .L_OP_IPUT_BOOLEAN 8898.long .L_OP_IPUT_BYTE 8899.long .L_OP_IPUT_CHAR 8900.long .L_OP_IPUT_SHORT 8901.long .L_OP_SGET 8902.long .L_OP_SGET_WIDE 8903.long .L_OP_SGET_OBJECT 8904.long .L_OP_SGET_BOOLEAN 8905.long .L_OP_SGET_BYTE 8906.long .L_OP_SGET_CHAR 8907.long .L_OP_SGET_SHORT 8908.long .L_OP_SPUT 8909.long .L_OP_SPUT_WIDE 8910.long .L_OP_SPUT_OBJECT 8911.long .L_OP_SPUT_BOOLEAN 8912.long .L_OP_SPUT_BYTE 8913.long .L_OP_SPUT_CHAR 8914.long .L_OP_SPUT_SHORT 8915.long .L_OP_INVOKE_VIRTUAL 8916.long .L_OP_INVOKE_SUPER 8917.long .L_OP_INVOKE_DIRECT 8918.long .L_OP_INVOKE_STATIC 8919.long .L_OP_INVOKE_INTERFACE 8920.long .L_OP_UNUSED_73 8921.long .L_OP_INVOKE_VIRTUAL_RANGE 8922.long .L_OP_INVOKE_SUPER_RANGE 8923.long .L_OP_INVOKE_DIRECT_RANGE 8924.long .L_OP_INVOKE_STATIC_RANGE 8925.long .L_OP_INVOKE_INTERFACE_RANGE 8926.long .L_OP_UNUSED_79 8927.long .L_OP_UNUSED_7A 8928.long .L_OP_NEG_INT 8929.long .L_OP_NOT_INT 8930.long .L_OP_NEG_LONG 8931.long .L_OP_NOT_LONG 8932.long .L_OP_NEG_FLOAT 8933.long .L_OP_NEG_DOUBLE 8934.long .L_OP_INT_TO_LONG 8935.long .L_OP_INT_TO_FLOAT 8936.long .L_OP_INT_TO_DOUBLE 8937.long .L_OP_LONG_TO_INT 8938.long .L_OP_LONG_TO_FLOAT 8939.long .L_OP_LONG_TO_DOUBLE 8940.long .L_OP_FLOAT_TO_INT 8941.long .L_OP_FLOAT_TO_LONG 8942.long .L_OP_FLOAT_TO_DOUBLE 8943.long .L_OP_DOUBLE_TO_INT 8944.long .L_OP_DOUBLE_TO_LONG 8945.long .L_OP_DOUBLE_TO_FLOAT 8946.long .L_OP_INT_TO_BYTE 8947.long .L_OP_INT_TO_CHAR 8948.long .L_OP_INT_TO_SHORT 8949.long .L_OP_ADD_INT 8950.long .L_OP_SUB_INT 8951.long .L_OP_MUL_INT 8952.long .L_OP_DIV_INT 8953.long .L_OP_REM_INT 8954.long .L_OP_AND_INT 8955.long .L_OP_OR_INT 8956.long .L_OP_XOR_INT 8957.long .L_OP_SHL_INT 8958.long .L_OP_SHR_INT 8959.long .L_OP_USHR_INT 8960.long .L_OP_ADD_LONG 8961.long .L_OP_SUB_LONG 8962.long .L_OP_MUL_LONG 8963.long .L_OP_DIV_LONG 8964.long .L_OP_REM_LONG 8965.long .L_OP_AND_LONG 8966.long .L_OP_OR_LONG 8967.long .L_OP_XOR_LONG 8968.long .L_OP_SHL_LONG 8969.long .L_OP_SHR_LONG 8970.long .L_OP_USHR_LONG 8971.long .L_OP_ADD_FLOAT 8972.long .L_OP_SUB_FLOAT 8973.long .L_OP_MUL_FLOAT 8974.long .L_OP_DIV_FLOAT 8975.long .L_OP_REM_FLOAT 8976.long .L_OP_ADD_DOUBLE 8977.long .L_OP_SUB_DOUBLE 8978.long .L_OP_MUL_DOUBLE 8979.long .L_OP_DIV_DOUBLE 8980.long .L_OP_REM_DOUBLE 8981.long .L_OP_ADD_INT_2ADDR 8982.long .L_OP_SUB_INT_2ADDR 8983.long .L_OP_MUL_INT_2ADDR 8984.long .L_OP_DIV_INT_2ADDR 8985.long .L_OP_REM_INT_2ADDR 8986.long .L_OP_AND_INT_2ADDR 8987.long .L_OP_OR_INT_2ADDR 8988.long .L_OP_XOR_INT_2ADDR 8989.long .L_OP_SHL_INT_2ADDR 8990.long .L_OP_SHR_INT_2ADDR 8991.long .L_OP_USHR_INT_2ADDR 8992.long .L_OP_ADD_LONG_2ADDR 8993.long .L_OP_SUB_LONG_2ADDR 8994.long .L_OP_MUL_LONG_2ADDR 8995.long .L_OP_DIV_LONG_2ADDR 8996.long .L_OP_REM_LONG_2ADDR 8997.long .L_OP_AND_LONG_2ADDR 8998.long .L_OP_OR_LONG_2ADDR 8999.long .L_OP_XOR_LONG_2ADDR 9000.long .L_OP_SHL_LONG_2ADDR 9001.long .L_OP_SHR_LONG_2ADDR 9002.long .L_OP_USHR_LONG_2ADDR 9003.long .L_OP_ADD_FLOAT_2ADDR 9004.long .L_OP_SUB_FLOAT_2ADDR 9005.long .L_OP_MUL_FLOAT_2ADDR 9006.long .L_OP_DIV_FLOAT_2ADDR 9007.long .L_OP_REM_FLOAT_2ADDR 9008.long .L_OP_ADD_DOUBLE_2ADDR 9009.long .L_OP_SUB_DOUBLE_2ADDR 9010.long .L_OP_MUL_DOUBLE_2ADDR 9011.long .L_OP_DIV_DOUBLE_2ADDR 9012.long .L_OP_REM_DOUBLE_2ADDR 9013.long .L_OP_ADD_INT_LIT16 9014.long .L_OP_RSUB_INT 9015.long .L_OP_MUL_INT_LIT16 9016.long .L_OP_DIV_INT_LIT16 9017.long .L_OP_REM_INT_LIT16 9018.long .L_OP_AND_INT_LIT16 9019.long .L_OP_OR_INT_LIT16 9020.long .L_OP_XOR_INT_LIT16 9021.long .L_OP_ADD_INT_LIT8 9022.long .L_OP_RSUB_INT_LIT8 9023.long .L_OP_MUL_INT_LIT8 9024.long .L_OP_DIV_INT_LIT8 9025.long .L_OP_REM_INT_LIT8 9026.long .L_OP_AND_INT_LIT8 9027.long .L_OP_OR_INT_LIT8 9028.long .L_OP_XOR_INT_LIT8 9029.long .L_OP_SHL_INT_LIT8 9030.long .L_OP_SHR_INT_LIT8 9031.long .L_OP_USHR_INT_LIT8 9032.long .L_OP_IGET_VOLATILE 9033.long .L_OP_IPUT_VOLATILE 9034.long .L_OP_SGET_VOLATILE 9035.long .L_OP_SPUT_VOLATILE 9036.long .L_OP_IGET_OBJECT_VOLATILE 9037.long .L_OP_IGET_WIDE_VOLATILE 9038.long .L_OP_IPUT_WIDE_VOLATILE 9039.long .L_OP_SGET_WIDE_VOLATILE 9040.long .L_OP_SPUT_WIDE_VOLATILE 9041.long .L_OP_BREAKPOINT 9042.long .L_OP_THROW_VERIFICATION_ERROR 9043.long .L_OP_EXECUTE_INLINE 9044.long .L_OP_EXECUTE_INLINE_RANGE 9045.long .L_OP_INVOKE_DIRECT_EMPTY 9046.long .L_OP_RETURN_VOID_BARRIER 9047.long .L_OP_IGET_QUICK 9048.long .L_OP_IGET_WIDE_QUICK 9049.long .L_OP_IGET_OBJECT_QUICK 9050.long .L_OP_IPUT_QUICK 9051.long .L_OP_IPUT_WIDE_QUICK 9052.long .L_OP_IPUT_OBJECT_QUICK 9053.long .L_OP_INVOKE_VIRTUAL_QUICK 9054.long .L_OP_INVOKE_VIRTUAL_QUICK_RANGE 9055.long .L_OP_INVOKE_SUPER_QUICK 9056.long .L_OP_INVOKE_SUPER_QUICK_RANGE 9057.long .L_OP_IPUT_OBJECT_VOLATILE 9058.long .L_OP_SGET_OBJECT_VOLATILE 9059.long .L_OP_SPUT_OBJECT_VOLATILE 9060.long .L_OP_UNUSED_FF 9061 9062 9063/* File: x86/footer.S */ 9064/* 9065 * Copyright (C) 2008 The Android Open Source Project 9066 * 9067 * Licensed under the Apache License, Version 2.0 (the "License"); 9068 * you may not use this file except in compliance with the License. 9069 * You may obtain a copy of the License at 9070 * 9071 * http://www.apache.org/licenses/LICENSE-2.0 9072 * 9073 * Unless required by applicable law or agreed to in writing, software 9074 * distributed under the License is distributed on an "AS IS" BASIS, 9075 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 9076 * See the License for the specific language governing permissions and 9077 * limitations under the License. 9078 */ 9079/* 9080 * Common subroutines and data. 9081 */ 9082 9083#if defined(WITH_JIT) 9084/* 9085 * Placeholder entries for x86 JIT 9086 */ 9087 .global dvmJitToInterpPunt 9088dvmJitToInterpPunt: 9089 .global dvmJitToInterpSingleStep 9090dvmJitToInterpSingleStep: 9091 .global dvmJitToInterpNoChainNoProfile 9092dvmJitToInterpNoChainNoProfile: 9093 .global dvmJitToInterpTraceSelectNoChain 9094dvmJitToInterpTraceSelectNoChain: 9095 .global dvmJitToInterpTraceSelect 9096dvmJitToInterpTraceSelect: 9097 .global dvmJitToInterpBackwardBranch 9098dvmJitToInterpBackwardBranch: 9099 .global dvmJitToInterpNormal 9100dvmJitToInterpNormal: 9101 .global dvmJitToInterpNoChain 9102dvmJitToInterpNoChain: 9103 jmp common_abort 9104#endif 9105 9106/* 9107 * Common code when a backwards branch is taken 9108 * 9109 * On entry: 9110 * ebx (a.k.a. rINST) -> PC adjustment in 16-bit words 9111 */ 9112common_backwardBranch: 9113 movl rGLUE,%ecx 9114 call common_periodicChecks # Note: expects rPC to be preserved 9115 ADVANCE_PC_INDEXED rINST 9116 FETCH_INST 9117 GOTO_NEXT 9118 9119 9120 9121/* 9122 * Common code for method invocation with range. 9123 * 9124 * On entry: 9125 * eax = Method* methodToCall 9126 * rINSTw trashed, must reload 9127 */ 9128 9129common_invokeMethodRange: 9130.LinvokeNewRange: 9131 9132 /* 9133 * prepare to copy args to "outs" area of current frame 9134 */ 9135 9136 movzbl 1(rPC),rINST # rINST<- AA 9137 movzwl 4(rPC), %ecx # %ecx<- CCCC 9138 SAVEAREA_FROM_FP %edx # %edx<- &StackSaveArea 9139 test rINST, rINST 9140 movl rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA 9141 jz .LinvokeArgsDone # no args; jump to args done 9142 9143 9144 /* 9145 * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea) 9146 * (very few methods have > 10 args; could unroll for common cases) 9147 */ 9148 9149 movl %ebx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- save %ebx 9150 lea (rFP, %ecx, 4), %ecx # %ecx<- &vCCCC 9151 shll $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 9152 subl LOCAL0_OFFSET(%ebp), %edx # %edx<- update &outs 9153 shrl $2, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- offset 91541: 9155 movl (%ecx), %ebx # %ebx<- vCCCC 9156 lea 4(%ecx), %ecx # %ecx<- &vCCCC++ 9157 subl $1, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- LOCAL0_OFFSET-- 9158 movl %ebx, (%edx) # *outs<- vCCCC 9159 lea 4(%edx), %edx # outs++ 9160 jne 1b # loop if count (LOCAL0_OFFSET(%ebp)) not zero 9161 movl LOCAL1_OFFSET(%ebp), %ebx # %ebx<- restore %ebx 9162 jmp .LinvokeArgsDone # continue 9163 9164 /* 9165 * %eax is "Method* methodToCall", the method we're trying to call 9166 * prepare to copy args to "outs" area of current frame 9167 */ 9168 9169common_invokeMethodNoRange: 9170.LinvokeNewNoRange: 9171 movzbl 1(rPC),rINST # rINST<- BA 9172 movl rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA 9173 shrl $4, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- B 9174 je .LinvokeArgsDone # no args; jump to args done 9175 movzwl 4(rPC), %ecx # %ecx<- GFED 9176 SAVEAREA_FROM_FP %edx # %edx<- &StackSaveArea 9177 9178 /* 9179 * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs 9180 */ 9181 9182.LinvokeNonRange: 9183 cmp $2, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 2 9184 movl %ecx, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- GFED 9185 jl 1f # handle 1 arg 9186 je 2f # handle 2 args 9187 cmp $4, LOCAL0_OFFSET(%ebp) # compare LOCAL0_OFFSET(%ebp) to 4 9188 jl 3f # handle 3 args 9189 je 4f # handle 4 args 91905: 9191 andl $15, rINST # rINSTw<- A 9192 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9193 movl (rFP, rINST, 4), %ecx # %ecx<- vA 9194 movl %ecx, (%edx) # *outs<- vA 9195 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 91964: 9197 shr $12, %ecx # %ecx<- G 9198 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9199 movl (rFP, %ecx, 4), %ecx # %ecx<- vG 9200 movl %ecx, (%edx) # *outs<- vG 9201 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 92023: 9203 and $0x0f00, %ecx # %ecx<- 0F00 9204 shr $8, %ecx # %ecx<- F 9205 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9206 movl (rFP, %ecx, 4), %ecx # %ecx<- vF 9207 movl %ecx, (%edx) # *outs<- vF 9208 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 92092: 9210 and $0x00f0, %ecx # %ecx<- 00E0 9211 shr $4, %ecx # %ecx<- E 9212 lea -4(%edx), %edx # %edx<- update &outs; &outs-- 9213 movl (rFP, %ecx, 4), %ecx # %ecx<- vE 9214 movl %ecx, (%edx) # *outs<- vE 9215 movl LOCAL1_OFFSET(%ebp), %ecx # %ecx<- GFED 92161: 9217 and $0x000f, %ecx # %ecx<- 000D 9218 movl (rFP, %ecx, 4), %ecx # %ecx<- vD 9219 movl %ecx, -4(%edx) # *--outs<- vD 92200: 9221 9222 /* 9223 * %eax is "Method* methodToCall", the method we're trying to call 9224 * find space for the new stack frame, check for overflow 9225 */ 9226 9227.LinvokeArgsDone: 9228 movzwl offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize 9229 movzwl offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize 9230 movl %eax, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET<- methodToCall 9231 shl $2, %edx # %edx<- update offset 9232 SAVEAREA_FROM_FP %eax # %eax<- &StackSaveArea 9233 subl %edx, %eax # %eax<- newFP; (old savearea - regsSize) 9234 movl rGLUE,%edx # %edx<- pMterpGlue 9235 movl %eax, LOCAL1_OFFSET(%ebp) # LOCAL1_OFFSET(%ebp)<- &outs 9236 subl $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP) 9237 movl offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd 9238 movl %edx, LOCAL2_OFFSET(%ebp) # LOCAL2_OFFSET<- glue->interpStackEnd 9239 shl $2, %ecx # %ecx<- update offset for outsSize 9240 movl %eax, %edx # %edx<- newSaveArea 9241 sub %ecx, %eax # %eax<- bottom; (newSaveArea - outsSize) 9242 cmp LOCAL2_OFFSET(%ebp), %eax # compare interpStackEnd and bottom 9243 movl LOCAL0_OFFSET(%ebp), %eax # %eax<- restore methodToCall 9244 jl .LstackOverflow # handle frame overflow 9245 9246 /* 9247 * set up newSaveArea 9248 */ 9249 9250#ifdef EASY_GDB 9251 SAVEAREA_FROM_FP %ecx # %ecx<- &StackSaveArea 9252 movl %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs 9253#endif 9254 movl rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP 9255 movl rPC, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC 9256 testl $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call 9257 movl %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call 9258 jne .LinvokeNative # handle native call 9259 9260 /* 9261 * Update "glue" values for the new method 9262 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp 9263 */ 9264 9265 movl offMethod_clazz(%eax), %edx # %edx<- method->clazz 9266 movl rGLUE,%ecx # %ecx<- pMterpGlue 9267 movl offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex 9268 movl %eax, offGlue_method(%ecx) # glue->method<- methodToCall 9269 movl %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex 9270 movl offMethod_insns(%eax), rPC # rPC<- methodToCall->insns 9271 movl offGlue_self(%ecx), %eax # %eax<- glue->self 9272 movl LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP 9273 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP 9274 FETCH_INST 9275 GOTO_NEXT # jump to methodToCall->insns 9276 9277 /* 9278 * Prep for the native call 9279 * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea 9280 */ 9281 9282.LinvokeNative: 9283 movl rGLUE,%ecx # %ecx<- pMterpGlue 9284 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 9285 movl offGlue_self(%ecx), %ecx # %ecx<- glue->self 9286 movl offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->... 9287 movl %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top 9288 movl %edx, OUT_ARG4(%esp) # save newSaveArea 9289 movl LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP 9290 movl %edx, offThread_curFrame(%ecx) # glue->self->curFrame<- newFP 9291 movl %ecx, OUT_ARG3(%esp) # save glue->self 9292 movl %ecx, OUT_ARG2(%esp) # push parameter glue->self 9293 movl rGLUE,%ecx # %ecx<- pMterpGlue 9294 movl OUT_ARG1(%esp), %eax # %eax<- methodToCall 9295 lea offGlue_retval(%ecx), %ecx # %ecx<- &retval 9296 movl %ecx, OUT_ARG0(%esp) # push parameter pMterpGlue 9297 push %edx # push parameter newFP 9298 9299 call *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc 9300 lea 4(%esp), %esp 9301 movl OUT_ARG4(%esp), %ecx # %ecx<- newSaveArea 9302 movl OUT_ARG3(%esp), %eax # %eax<- glue->self 9303 movl offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top 9304 cmp $0, offThread_exception(%eax) # check for exception 9305 movl rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP 9306 movl %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top 9307 jne common_exceptionThrown # handle exception 9308 FETCH_INST_OPCODE 3 %edx 9309 ADVANCE_PC 3 9310 GOTO_NEXT_R %edx # jump to next instruction 9311 9312.LstackOverflow: # eax=methodToCall 9313 movl %eax, OUT_ARG1(%esp) # push parameter methodToCall 9314 movl rGLUE,%eax # %eax<- pMterpGlue 9315 movl offGlue_self(%eax), %eax # %eax<- glue->self 9316 movl %eax, OUT_ARG0(%esp) # push parameter self 9317 call dvmHandleStackOverflow # call: (Thread* self, Method* meth) 9318 jmp common_exceptionThrown # handle exception 9319 9320 9321/* 9322 * Do we need the thread to be suspended or have debugger/profiling activity? 9323 * 9324 * On entry: 9325 * ebx -> PC adjustment in 16-bit words (must be preserved) 9326 * ecx -> GLUE pointer 9327 * reentry type, e.g. kInterpEntryInstr stored in rGLUE->entryPoint 9328 * 9329 * Note: A call will normally kill %eax and %ecx. To 9330 * streamline the normal case, this routine will preserve 9331 * %ecx in addition to the normal caller save regs. The save/restore 9332 * is a bit ugly, but will happen in the relatively uncommon path. 9333 * TODO: Basic-block style Jit will need a hook here as well. Fold it into 9334 * the suspendCount check so we can get both in 1 shot. 9335 */ 9336common_periodicChecks: 9337 movl offGlue_pSelfSuspendCount(%ecx),%eax # eax <- &suspendCount 9338 cmpl $0,(%eax) 9339 jne 1f 9340 93416: 9342 movl offGlue_pDebuggerActive(%ecx),%eax # eax <- &DebuggerActive 9343 movl offGlue_pActiveProfilers(%ecx),%ecx # ecx <- &ActiveProfilers 9344 testl %eax,%eax # debugger enabled? 9345 je 2f 9346 movzbl (%eax),%eax # get active count 93472: 9348 orl (%ecx),%eax # eax <- debuggerActive | activeProfilers 9349 movl rGLUE,%ecx # restore rGLUE 9350 jne 3f # one or both active - switch interp 9351 93525: 9353 ret 9354 9355 /* Check for suspend */ 93561: 9357 /* At this point, the return pointer to the caller of 9358 * common_periodicChecks is on the top of stack. We need to preserve 9359 * GLUE(ecx). 9360 * The outgoing profile is: 9361 * bool dvmCheckSuspendPending(Thread* self) 9362 * Because we reached here via a call, go ahead and build a new frame. 9363 */ 9364 EXPORT_PC # need for precise GC 9365 movl offGlue_self(%ecx),%eax # eax<- glue->self 9366 push %ebp 9367 movl %esp,%ebp 9368 subl $24,%esp 9369 movl %eax,OUT_ARG0(%esp) 9370 call dvmCheckSuspendPending 9371 addl $24,%esp 9372 pop %ebp 9373 movl rGLUE,%ecx 9374 9375 /* 9376 * Need to check to see if debugger or profiler flags got set 9377 * while we were suspended. 9378 */ 9379 jmp 6b 9380 9381 /* Switch interpreters */ 9382 /* Note: %ebx contains the 16-bit word offset to be applied to rPC to 9383 * "complete" the interpretation of backwards branches. In effect, we 9384 * are completing the interpretation of the branch instruction here, 9385 * and the new interpreter will resume interpretation at the branch 9386 * target. However, a switch request recognized during the handling 9387 * of a return from method instruction results in an immediate abort, 9388 * and the new interpreter will resume by re-interpreting the return 9389 * instruction. 9390 */ 93913: 9392 leal (rPC,%ebx,2),rPC # adjust pc to show target 9393 movl rGLUE,%ecx # bail expect GLUE already loaded 9394 movl $1,rINST # set changeInterp to true 9395 jmp common_gotoBail 9396 9397 9398/* 9399 * Common code for handling a return instruction 9400 */ 9401common_returnFromMethod: 9402 movl rGLUE,%ecx 9403 /* Set entry mode in case we bail */ 9404 movb $kInterpEntryReturn,offGlue_entryPoint(%ecx) 9405 xorl rINST,rINST # zero offset in case we switch interps 9406 call common_periodicChecks # Note: expects %ecx to be preserved 9407 9408 SAVEAREA_FROM_FP %eax # eax<- saveArea (old) 9409 movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame 9410 movl (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST 9411 cmpl $0,rINST # break? 9412 je common_gotoBail # break frame, bail out completely 9413 9414 movl offStackSaveArea_savedPc(%eax),rPC # pc<- saveArea->savedPC 9415 movl offGlue_self(%ecx),%eax # eax<- self 9416 movl rINST,offGlue_method(%ecx) # glue->method = newSave->meethod 9417 movl rFP,offThread_curFrame(%eax) # self->curFrame = fp 9418 movl offMethod_clazz(rINST),%eax # eax<- method->clazz 9419 FETCH_INST_OPCODE 3 %edx 9420 movl offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex 9421 ADVANCE_PC 3 9422 movl %eax,offGlue_methodClassDex(%ecx) 9423 /* not bailing - restore entry mode to default */ 9424 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx) 9425 GOTO_NEXT_R %edx 9426 9427/* 9428 * Prepare to strip the current frame and "longjump" back to caller of 9429 * dvmMterpStdRun. 9430 * 9431 * on entry: 9432 * rINST holds changeInterp 9433 * ecx holds glue pointer 9434 * 9435 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp) 9436 */ 9437common_gotoBail: 9438 movl rPC,offGlue_pc(%ecx) # export state to glue 9439 movl rFP,offGlue_fp(%ecx) 9440 movl %ecx,OUT_ARG0(%esp) # glue in arg0 9441 movl rINST,OUT_ARG1(%esp) # changeInterp in arg1 9442 call dvmMterpStdBail # bail out.... 9443 9444 9445/* 9446 * After returning from a "glued" function, pull out the updated values 9447 * and start executing at the next instruction. 9448 */ 9449 common_resumeAfterGlueCall: 9450 LOAD_PC_FP_FROM_GLUE 9451 FETCH_INST 9452 GOTO_NEXT 9453 9454/* 9455 * Integer divide or mod by zero 9456 */ 9457common_errDivideByZero: 9458 EXPORT_PC 9459 movl $.LstrArithmeticException,%eax 9460 movl %eax,OUT_ARG0(%esp) 9461 movl $.LstrDivideByZero,%eax 9462 movl %eax,OUT_ARG1(%esp) 9463 call dvmThrowException 9464 jmp common_exceptionThrown 9465 9466/* 9467 * Attempt to allocate an array with a negative size. 9468 */ 9469common_errNegativeArraySize: 9470 EXPORT_PC 9471 movl $.LstrNegativeArraySizeException,%eax 9472 movl %eax,OUT_ARG0(%esp) 9473 xorl %eax,%eax 9474 movl %eax,OUT_ARG1(%esp) 9475 call dvmThrowException 9476 jmp common_exceptionThrown 9477 9478/* 9479 * Attempt to allocate an array with a negative size. 9480 */ 9481common_errNoSuchMethod: 9482 9483 EXPORT_PC 9484 movl $.LstrNoSuchMethodError,%eax 9485 movl %eax,OUT_ARG0(%esp) 9486 xorl %eax,%eax 9487 movl %eax,OUT_ARG1(%esp) 9488 call dvmThrowException 9489 jmp common_exceptionThrown 9490 9491/* 9492 * Hit a null object when we weren't expecting one. Export the PC, throw a 9493 * NullPointerException and goto the exception processing code. 9494 */ 9495common_errNullObject: 9496 EXPORT_PC 9497 movl $.LstrNullPointerException,%eax 9498 movl %eax,OUT_ARG0(%esp) 9499 xorl %eax,%eax 9500 movl %eax,OUT_ARG1(%esp) 9501 call dvmThrowException 9502 jmp common_exceptionThrown 9503 9504/* 9505 * Array index exceeds max. 9506 */ 9507common_errArrayIndex: 9508 EXPORT_PC 9509 movl $.LstrArrayIndexException,%eax 9510 movl %eax,OUT_ARG0(%esp) 9511 xorl %eax,%eax 9512 movl %eax,OUT_ARG1(%esp) 9513 call dvmThrowException 9514 jmp common_exceptionThrown 9515/* 9516 * Invalid array value. 9517 */ 9518common_errArrayStore: 9519 EXPORT_PC 9520 movl $.LstrArrayStoreException,%eax 9521 movl %eax,OUT_ARG0(%esp) 9522 xorl %eax,%eax 9523 movl %eax,OUT_ARG1(%esp) 9524 call dvmThrowException 9525 jmp common_exceptionThrown 9526 9527/* 9528 * Somebody has thrown an exception. Handle it. 9529 * 9530 * If the exception processing code returns to us (instead of falling 9531 * out of the interpreter), continue with whatever the next instruction 9532 * now happens to be. 9533 * 9534 * This does not return. 9535 */ 9536common_exceptionThrown: 9537 movl rGLUE,%ecx 9538 movl rPC,offGlue_pc(%ecx) 9539 movl rFP,offGlue_fp(%ecx) 9540 movl %ecx,OUT_ARG0(%esp) 9541 call dvmMterp_exceptionThrown 9542 jmp common_resumeAfterGlueCall 9543 9544common_abort: 9545 movl $0xdeadf00d,%eax 9546 call *%eax 9547 9548 9549/* 9550 * Strings 9551 */ 9552 9553 .section .rodata 9554.LstrNullPointerException: 9555 .asciz "Ljava/lang/NullPointerException;" 9556.LstrArithmeticException: 9557 .asciz "Ljava/lang/ArithmeticException;" 9558.LstrDivideByZero: 9559 .asciz "divide by zero" 9560.LstrArrayIndexException: 9561 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 9562.LstrArrayStoreException: 9563 .asciz "Ljava/lang/ArrayStoreException;" 9564.LstrNegativeArraySizeException: 9565 .asciz "Ljava/lang/NegativeArraySizeException;" 9566.LstrInstantiationError: 9567 .asciz "Ljava/lang/InstantiationError;" 9568.LstrClassCastException: 9569 .asciz "Ljava/lang/ClassCastException;" 9570.LstrNoSuchMethodError: 9571 .asciz "Ljava/lang/NoSuchMethodError;" 9572.LstrInternalErrorA: 9573 .asciz "Ljava/lang/InternalError;" 9574.LstrFilledNewArrayNotImplA: 9575 .asciz "filled-new-array only implemented for 'int'" 9576 9577