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