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