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