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 %eax,OUT_ARG0(%esp) # arg0<- arrayClass 6547 cmpb $'I',%cl # supported? 6548 je 1f 6549 cmpb $'L',%cl 6550 je 1f 6551 cmpb $'[',%cl 6552 jne .LOP_FILLED_NEW_ARRAY_notimpl # no, not handled yet 65531: 6554 .if (!0) 6555 SPILL_TMP(rINST_FULL) # save copy, need "B" later 6556 sarl $4,rINST_FULL 6557 .endif 6558 movl rINST_FULL,OUT_ARG1(%esp) # arg1<- A or AA (length) 6559 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags) 6560 UNSPILL(rPC) 6561 GET_GLUE(%ecx) 6562 testl %eax,%eax # alloc successful? 6563 je common_exceptionThrown # no, handle exception 6564 movl %eax,offGlue_retval(%ecx) # retval.l<- new array 6565 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC 6566 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents 6567 6568/* at this point: 6569 * eax is pointer to tgt 6570 * rINST_FULL is length 6571 * ecx is FEDC or CCCC 6572 * TMP_SPILL is BA 6573 * rPC is valid, but spilled 6574 * We now need to copy values from registers into the array 6575 */ 6576 6577 .if 0 6578 # set up src pointer 6579 SPILL(rFP) # esi 6580 SPILL(rIBASE) # edi 6581 movl %eax,%edi # set up dst ptr 6582 leal (rFP,%ecx,4),%esi # set up src ptr 6583 movl rINST_FULL,%ecx # load count register 6584 FETCH_INST_WORD(3) 6585 rep 6586 movsd 6587 UNSPILL(rIBASE) 6588 UNSPILL(rFP) 6589 .else 6590 testl rINST_FULL,rINST_FULL 6591 je 4f 6592 UNSPILL_TMP(rPC) 6593 andl $0x0f,rPC # rPC<- 0000000A 6594 sall $16,rPC # rPC<- 000A0000 6595 orl %ecx,rPC # rpc<- 000AFEDC 65963: 6597 movl $0xf,%ecx 6598 andl rPC,%ecx # ecx<- next reg to load 6599 GET_VREG(%ecx,%ecx) 6600 shrl $4,rPC 6601 leal 4(%eax),%eax 6602 movl %ecx,-4(%eax) 6603 sub $1,rINST_FULL 6604 jne 3b 66054: 6606 UNSPILL(rPC) 6607 FETCH_INST_WORD(3) 6608 .endif 6609 6610 ADVANCE_PC(3) 6611 GOTO_NEXT 6612 6613 6614 /* 6615 * Throw an exception indicating that we have not implemented this 6616 * mode of filled-new-array. 6617 */ 6618.LOP_FILLED_NEW_ARRAY_notimpl: 6619 movl $.LstrInternalError,%eax 6620 movl %eax,OUT_ARG0(%esp) 6621 movl $.LstrFilledNewArrayNotImpl,%eax 6622 movl %eax,OUT_ARG1(%esp) 6623 call dvmThrowException 6624 UNSPILL(rPC) 6625 jmp common_exceptionThrown 6626 6627 6628/* continuation for OP_FILLED_NEW_ARRAY_RANGE */ 6629 6630.LOP_FILLED_NEW_ARRAY_RANGE_more: 6631 movl offMethod_clazz(%eax),%eax # eax<- method->clazz 6632 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 6633 call dvmResolveClass # eax<- call(clazz,ref,flag) 6634 UNSPILL(rPC) 6635 testl %eax,%eax # null? 6636 je common_exceptionThrown # yes, handle it 6637 6638 # note: fall through to .LOP_FILLED_NEW_ARRAY_RANGE_continue 6639 6640 /* 6641 * On entry: 6642 * eax holds array class [r0] 6643 * rINST_FULL holds AA or BB [r10] 6644 * ecx is scratch 6645 * rPC is valid, but has been spilled 6646 */ 6647.LOP_FILLED_NEW_ARRAY_RANGE_continue: 6648 movl offClassObject_descriptor(%eax),%ecx # ecx<- arrayClass->descriptor 6649 movl $ALLOC_DONT_TRACK,OUT_ARG2(%esp) # arg2<- flags 6650 movzbl 1(%ecx),%ecx # ecx<- descriptor[1] 6651 movl %eax,OUT_ARG0(%esp) # arg0<- arrayClass 6652 cmpb $'I',%cl # supported? 6653 je 1f 6654 cmpb $'L',%cl 6655 je 1f 6656 cmpb $'[',%cl 6657 jne .LOP_FILLED_NEW_ARRAY_RANGE_notimpl # no, not handled yet 66581: 6659 .if (!1) 6660 SPILL_TMP(rINST_FULL) # save copy, need "B" later 6661 sarl $4,rINST_FULL 6662 .endif 6663 movl rINST_FULL,OUT_ARG1(%esp) # arg1<- A or AA (length) 6664 call dvmAllocArrayByClass # eax<- call(arrayClass, length, flags) 6665 UNSPILL(rPC) 6666 GET_GLUE(%ecx) 6667 testl %eax,%eax # alloc successful? 6668 je common_exceptionThrown # no, handle exception 6669 movl %eax,offGlue_retval(%ecx) # retval.l<- new array 6670 movzwl 4(rPC),%ecx # ecx<- FEDC or CCCC 6671 leal offArrayObject_contents(%eax),%eax # eax<- newArray->contents 6672 6673/* at this point: 6674 * eax is pointer to tgt 6675 * rINST_FULL is length 6676 * ecx is FEDC or CCCC 6677 * TMP_SPILL is BA 6678 * rPC is valid, but spilled 6679 * We now need to copy values from registers into the array 6680 */ 6681 6682 .if 1 6683 # set up src pointer 6684 SPILL(rFP) # esi 6685 SPILL(rIBASE) # edi 6686 movl %eax,%edi # set up dst ptr 6687 leal (rFP,%ecx,4),%esi # set up src ptr 6688 movl rINST_FULL,%ecx # load count register 6689 FETCH_INST_WORD(3) 6690 rep 6691 movsd 6692 UNSPILL(rIBASE) 6693 UNSPILL(rFP) 6694 .else 6695 testl rINST_FULL,rINST_FULL 6696 je 4f 6697 UNSPILL_TMP(rPC) 6698 andl $0x0f,rPC # rPC<- 0000000A 6699 sall $16,rPC # rPC<- 000A0000 6700 orl %ecx,rPC # rpc<- 000AFEDC 67013: 6702 movl $0xf,%ecx 6703 andl rPC,%ecx # ecx<- next reg to load 6704 GET_VREG(%ecx,%ecx) 6705 shrl $4,rPC 6706 leal 4(%eax),%eax 6707 movl %ecx,-4(%eax) 6708 sub $1,rINST_FULL 6709 jne 3b 67104: 6711 UNSPILL(rPC) 6712 FETCH_INST_WORD(3) 6713 .endif 6714 6715 ADVANCE_PC(3) 6716 GOTO_NEXT 6717 6718 6719 /* 6720 * Throw an exception indicating that we have not implemented this 6721 * mode of filled-new-array. 6722 */ 6723.LOP_FILLED_NEW_ARRAY_RANGE_notimpl: 6724 movl $.LstrInternalError,%eax 6725 movl %eax,OUT_ARG0(%esp) 6726 movl $.LstrFilledNewArrayNotImpl,%eax 6727 movl %eax,OUT_ARG1(%esp) 6728 call dvmThrowException 6729 UNSPILL(rPC) 6730 jmp common_exceptionThrown 6731 6732 6733/* continuation for OP_CMPL_FLOAT */ 6734 6735.LOP_CMPL_FLOAT_isNaN: 6736 movl $-1,%ecx 6737 jmp .LOP_CMPL_FLOAT_finish 6738 6739/* continuation for OP_CMPG_FLOAT */ 6740 6741.LOP_CMPG_FLOAT_isNaN: 6742 movl $1,%ecx 6743 jmp .LOP_CMPG_FLOAT_finish 6744 6745/* continuation for OP_CMPL_DOUBLE */ 6746 6747.LOP_CMPL_DOUBLE_isNaN: 6748 movl $-1,%ecx 6749 jmp .LOP_CMPL_DOUBLE_finish 6750 6751/* continuation for OP_CMPG_DOUBLE */ 6752 6753.LOP_CMPG_DOUBLE_isNaN: 6754 movl $1,%ecx 6755 jmp .LOP_CMPG_DOUBLE_finish 6756 6757/* continuation for OP_CMP_LONG */ 6758 6759.LOP_CMP_LONG_bigger: 6760 UNSPILL(rPC) 6761 movl $1,%ecx 6762 jmp .LOP_CMP_LONG_finish 6763.LOP_CMP_LONG_smaller: 6764 UNSPILL(rPC) 6765 movl $-1,%ecx 6766.LOP_CMP_LONG_finish: 6767 SET_VREG(%ecx,rINST_FULL) 6768 FETCH_INST_WORD(2) 6769 ADVANCE_PC(2) 6770 GOTO_NEXT 6771 6772/* continuation for OP_AGET_WIDE */ 6773 6774.LOP_AGET_WIDE_finish: 6775 leal offArrayObject_contents(%eax,%ecx,8),%eax 6776 movl (%eax),%ecx 6777 movl 4(%eax),%eax 6778 SET_VREG_WORD(%ecx,rINST_FULL,0) 6779 SET_VREG_WORD(%eax,rINST_FULL,1) 6780 FETCH_INST_WORD(2) 6781 ADVANCE_PC(2) 6782 GOTO_NEXT 6783 6784 6785/* continuation for OP_APUT_WIDE */ 6786 6787.LOP_APUT_WIDE_finish: 6788 leal offArrayObject_contents(%eax,%ecx,8),%eax 6789 GET_VREG_WORD(%ecx,rINST_FULL,0) 6790 GET_VREG_WORD(rINST_FULL,rINST_FULL,1) 6791 movl rINST_FULL,4(%eax) 6792 FETCH_INST_WORD(2) 6793 movl %ecx,(%eax) 6794 ADVANCE_PC(2) 6795 GOTO_NEXT 6796 6797 6798/* continuation for OP_APUT_OBJECT */ 6799 6800 /* On entry: 6801 * eax<- array object 6802 * ecx<- index 6803 * rINST_FULL<- vAA 6804 */ 6805.LOP_APUT_OBJECT_continue: 6806 leal offArrayObject_contents(%eax,%ecx,4),%ecx 6807 testl rINST_FULL,rINST_FULL # storing null reference? 6808 je .LOP_APUT_OBJECT_skip_check 6809 SPILL(rPC) 6810 SPILL_TMP(%ecx) 6811 movl offObject_clazz(%eax),%eax # eax<- arrayObj->clazz 6812 movl offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz 6813 movl %eax,OUT_ARG1(%esp) 6814 movl %ecx,OUT_ARG0(%esp) 6815 call dvmCanPutArrayElement # test object type vs. array type 6816 UNSPILL(rPC) 6817 UNSPILL_TMP(%ecx) 6818 testl %eax,%eax 6819 je common_errArrayStore 6820 6821.LOP_APUT_OBJECT_skip_check: 6822 movl rINST_FULL,(%ecx) 6823 FETCH_INST_WORD(2) 6824 ADVANCE_PC(2) 6825 GOTO_NEXT 6826 6827 6828/* continuation for OP_IGET */ 6829 6830 6831.LOP_IGET_resolve: 6832 EXPORT_PC() 6833 SPILL(rPC) 6834 movl offGlue_method(rIBASE),rPC # rPC<- current method 6835 UNSPILL(rIBASE) 6836 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 6837 SPILL_TMP(%ecx) # save object pointer across call 6838 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 6839 call dvmResolveInstField # ... to dvmResolveInstField 6840 UNSPILL_TMP(%ecx) 6841 UNSPILL(rPC) 6842 testl %eax,%eax # ... which returns InstrField ptr 6843 jne .LOP_IGET_finish 6844 jmp common_exceptionThrown 6845 6846.LOP_IGET_finish: 6847 /* 6848 * Currently: 6849 * eax holds resolved field 6850 * ecx holds object 6851 * rIBASE is scratch, but needs to be unspilled 6852 * rINST_FULL holds A 6853 */ 6854 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 6855 UNSPILL(rIBASE) 6856 testl %ecx,%ecx # object null? 6857 je common_errNullObject # object was null 6858 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 6859 movl rINST_FULL,%eax # eax<- A 6860 FETCH_INST_WORD(2) 6861 SET_VREG(%ecx,%eax) 6862 ADVANCE_PC(2) 6863 GOTO_NEXT 6864 6865 6866/* continuation for OP_IGET_WIDE */ 6867 6868 6869.LOP_IGET_WIDE_resolve: 6870 EXPORT_PC() 6871 SPILL(rPC) 6872 movl offGlue_method(rIBASE),rPC # rPC<- current method 6873 UNSPILL(rIBASE) 6874 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 6875 SPILL_TMP(%ecx) # save object pointer across call 6876 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 6877 call dvmResolveInstField # ... to dvmResolveInstField 6878 UNSPILL_TMP(%ecx) 6879 UNSPILL(rPC) 6880 testl %eax,%eax # ... which returns InstrField ptr 6881 jne .LOP_IGET_WIDE_finish 6882 jmp common_exceptionThrown 6883 6884.LOP_IGET_WIDE_finish: 6885 /* 6886 * Currently: 6887 * eax holds resolved field 6888 * ecx holds object 6889 * rIBASE is scratch, but needs to be unspilled 6890 * rINST_FULL holds A 6891 */ 6892 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 6893 UNSPILL(rIBASE) 6894 testl %ecx,%ecx # object null? 6895 je common_errNullObject # object was null 6896 leal (%ecx,%eax,1),%eax # eax<- address of field 6897 movl (%eax),%ecx # ecx<- lsw 6898 movl 4(%eax),%eax # eax<- msw 6899 SET_VREG_WORD(%ecx,rINST_FULL,0) 6900 SET_VREG_WORD(%eax,rINST_FULL,1) 6901 FETCH_INST_WORD(2) 6902 ADVANCE_PC(2) 6903 GOTO_NEXT 6904 6905 6906/* continuation for OP_IGET_OBJECT */ 6907 6908 6909.LOP_IGET_OBJECT_resolve: 6910 EXPORT_PC() 6911 SPILL(rPC) 6912 movl offGlue_method(rIBASE),rPC # rPC<- current method 6913 UNSPILL(rIBASE) 6914 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 6915 SPILL_TMP(%ecx) # save object pointer across call 6916 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 6917 call dvmResolveInstField # ... to dvmResolveInstField 6918 UNSPILL_TMP(%ecx) 6919 UNSPILL(rPC) 6920 testl %eax,%eax # ... which returns InstrField ptr 6921 jne .LOP_IGET_OBJECT_finish 6922 jmp common_exceptionThrown 6923 6924.LOP_IGET_OBJECT_finish: 6925 /* 6926 * Currently: 6927 * eax holds resolved field 6928 * ecx holds object 6929 * rIBASE is scratch, but needs to be unspilled 6930 * rINST_FULL holds A 6931 */ 6932 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 6933 UNSPILL(rIBASE) 6934 testl %ecx,%ecx # object null? 6935 je common_errNullObject # object was null 6936 movl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 6937 movl rINST_FULL,%eax # eax<- A 6938 FETCH_INST_WORD(2) 6939 SET_VREG(%ecx,%eax) 6940 ADVANCE_PC(2) 6941 GOTO_NEXT 6942 6943 6944/* continuation for OP_IGET_BOOLEAN */ 6945 6946 6947.LOP_IGET_BOOLEAN_resolve: 6948 EXPORT_PC() 6949 SPILL(rPC) 6950 movl offGlue_method(rIBASE),rPC # rPC<- current method 6951 UNSPILL(rIBASE) 6952 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 6953 SPILL_TMP(%ecx) # save object pointer across call 6954 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 6955 call dvmResolveInstField # ... to dvmResolveInstField 6956 UNSPILL_TMP(%ecx) 6957 UNSPILL(rPC) 6958 testl %eax,%eax # ... which returns InstrField ptr 6959 jne .LOP_IGET_BOOLEAN_finish 6960 jmp common_exceptionThrown 6961 6962.LOP_IGET_BOOLEAN_finish: 6963 /* 6964 * Currently: 6965 * eax holds resolved field 6966 * ecx holds object 6967 * rIBASE is scratch, but needs to be unspilled 6968 * rINST_FULL holds A 6969 */ 6970 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 6971 UNSPILL(rIBASE) 6972 testl %ecx,%ecx # object null? 6973 je common_errNullObject # object was null 6974 movzbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 6975 movl rINST_FULL,%eax # eax<- A 6976 FETCH_INST_WORD(2) 6977 SET_VREG(%ecx,%eax) 6978 ADVANCE_PC(2) 6979 GOTO_NEXT 6980 6981 6982/* continuation for OP_IGET_BYTE */ 6983 6984 6985.LOP_IGET_BYTE_resolve: 6986 EXPORT_PC() 6987 SPILL(rPC) 6988 movl offGlue_method(rIBASE),rPC # rPC<- current method 6989 UNSPILL(rIBASE) 6990 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 6991 SPILL_TMP(%ecx) # save object pointer across call 6992 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 6993 call dvmResolveInstField # ... to dvmResolveInstField 6994 UNSPILL_TMP(%ecx) 6995 UNSPILL(rPC) 6996 testl %eax,%eax # ... which returns InstrField ptr 6997 jne .LOP_IGET_BYTE_finish 6998 jmp common_exceptionThrown 6999 7000.LOP_IGET_BYTE_finish: 7001 /* 7002 * Currently: 7003 * eax holds resolved field 7004 * ecx holds object 7005 * rIBASE is scratch, but needs to be unspilled 7006 * rINST_FULL holds A 7007 */ 7008 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7009 UNSPILL(rIBASE) 7010 testl %ecx,%ecx # object null? 7011 je common_errNullObject # object was null 7012 movsbl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7013 movl rINST_FULL,%eax # eax<- A 7014 FETCH_INST_WORD(2) 7015 SET_VREG(%ecx,%eax) 7016 ADVANCE_PC(2) 7017 GOTO_NEXT 7018 7019 7020/* continuation for OP_IGET_CHAR */ 7021 7022 7023.LOP_IGET_CHAR_resolve: 7024 EXPORT_PC() 7025 SPILL(rPC) 7026 movl offGlue_method(rIBASE),rPC # rPC<- current method 7027 UNSPILL(rIBASE) 7028 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7029 SPILL_TMP(%ecx) # save object pointer across call 7030 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7031 call dvmResolveInstField # ... to dvmResolveInstField 7032 UNSPILL_TMP(%ecx) 7033 UNSPILL(rPC) 7034 testl %eax,%eax # ... which returns InstrField ptr 7035 jne .LOP_IGET_CHAR_finish 7036 jmp common_exceptionThrown 7037 7038.LOP_IGET_CHAR_finish: 7039 /* 7040 * Currently: 7041 * eax holds resolved field 7042 * ecx holds object 7043 * rIBASE is scratch, but needs to be unspilled 7044 * rINST_FULL holds A 7045 */ 7046 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7047 UNSPILL(rIBASE) 7048 testl %ecx,%ecx # object null? 7049 je common_errNullObject # object was null 7050 movzwl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7051 movl rINST_FULL,%eax # eax<- A 7052 FETCH_INST_WORD(2) 7053 SET_VREG(%ecx,%eax) 7054 ADVANCE_PC(2) 7055 GOTO_NEXT 7056 7057 7058/* continuation for OP_IGET_SHORT */ 7059 7060 7061.LOP_IGET_SHORT_resolve: 7062 EXPORT_PC() 7063 SPILL(rPC) 7064 movl offGlue_method(rIBASE),rPC # rPC<- current method 7065 UNSPILL(rIBASE) 7066 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7067 SPILL_TMP(%ecx) # save object pointer across call 7068 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7069 call dvmResolveInstField # ... to dvmResolveInstField 7070 UNSPILL_TMP(%ecx) 7071 UNSPILL(rPC) 7072 testl %eax,%eax # ... which returns InstrField ptr 7073 jne .LOP_IGET_SHORT_finish 7074 jmp common_exceptionThrown 7075 7076.LOP_IGET_SHORT_finish: 7077 /* 7078 * Currently: 7079 * eax holds resolved field 7080 * ecx holds object 7081 * rIBASE is scratch, but needs to be unspilled 7082 * rINST_FULL holds A 7083 */ 7084 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7085 UNSPILL(rIBASE) 7086 testl %ecx,%ecx # object null? 7087 je common_errNullObject # object was null 7088 movswl (%ecx,%eax,1),%ecx # ecx<- obj.field (8/16/32 bits) 7089 movl rINST_FULL,%eax # eax<- A 7090 FETCH_INST_WORD(2) 7091 SET_VREG(%ecx,%eax) 7092 ADVANCE_PC(2) 7093 GOTO_NEXT 7094 7095 7096/* continuation for OP_IPUT */ 7097 7098 7099.LOP_IPUT_resolve: 7100 EXPORT_PC() 7101 SPILL(rPC) 7102 movl offGlue_method(rIBASE),rPC # rPC<- current method 7103 UNSPILL(rIBASE) 7104 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7105 SPILL_TMP(%ecx) # save object pointer across call 7106 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7107 call dvmResolveInstField # ... to dvmResolveInstField 7108 UNSPILL_TMP(%ecx) 7109 UNSPILL(rPC) 7110 testl %eax,%eax # ... which returns InstrField ptr 7111 jne .LOP_IPUT_finish 7112 jmp common_exceptionThrown 7113 7114.LOP_IPUT_finish: 7115 /* 7116 * Currently: 7117 * eax holds resolved field 7118 * ecx holds object 7119 * rIBASE is scratch, but needs to be unspilled 7120 * rINST_FULL holds A 7121 */ 7122 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7123 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7124 UNSPILL(rIBASE) 7125 testl %ecx,%ecx # object null? 7126 je common_errNullObject # object was null 7127 movl rINST_FULL,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7128 FETCH_INST_WORD(2) 7129 ADVANCE_PC(2) 7130 GOTO_NEXT 7131 7132/* continuation for OP_IPUT_WIDE */ 7133 7134 7135.LOP_IPUT_WIDE_resolve: 7136 EXPORT_PC() 7137 SPILL(rPC) 7138 movl offGlue_method(rIBASE),rPC # rPC<- current method 7139 UNSPILL(rIBASE) 7140 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7141 SPILL_TMP(%ecx) # save object pointer across call 7142 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7143 call dvmResolveInstField # ... to dvmResolveInstField 7144 UNSPILL_TMP(%ecx) 7145 UNSPILL(rPC) 7146 testl %eax,%eax # ... which returns InstrField ptr 7147 jne .LOP_IPUT_WIDE_finish 7148 jmp common_exceptionThrown 7149 7150.LOP_IPUT_WIDE_finish: 7151 /* 7152 * Currently: 7153 * eax holds resolved field 7154 * ecx holds object 7155 * rIBASE is scratch, but needs to be unspilled 7156 * rINST_FULL holds A 7157 */ 7158 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7159 UNSPILL(rIBASE) 7160 testl %ecx,%ecx # object null? 7161 je common_errNullObject # object was null 7162 leal (%ecx,%eax,1),%eax # eax<- address of field 7163 GET_VREG_WORD(%ecx,rINST_FULL,0) # ecx<- lsw 7164 GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- msw 7165 movl rINST_FULL,4(%eax) 7166 FETCH_INST_WORD(2) 7167 movl %ecx,(%eax) 7168 ADVANCE_PC(2) 7169 GOTO_NEXT 7170 7171/* continuation for OP_IPUT_OBJECT */ 7172 7173 7174.LOP_IPUT_OBJECT_resolve: 7175 EXPORT_PC() 7176 SPILL(rPC) 7177 movl offGlue_method(rIBASE),rPC # rPC<- current method 7178 UNSPILL(rIBASE) 7179 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7180 SPILL_TMP(%ecx) # save object pointer across call 7181 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7182 call dvmResolveInstField # ... to dvmResolveInstField 7183 UNSPILL_TMP(%ecx) 7184 UNSPILL(rPC) 7185 testl %eax,%eax # ... which returns InstrField ptr 7186 jne .LOP_IPUT_OBJECT_finish 7187 jmp common_exceptionThrown 7188 7189.LOP_IPUT_OBJECT_finish: 7190 /* 7191 * Currently: 7192 * eax holds resolved field 7193 * ecx holds object 7194 * rIBASE is scratch, but needs to be unspilled 7195 * rINST_FULL holds A 7196 */ 7197 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7198 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7199 UNSPILL(rIBASE) 7200 testl %ecx,%ecx # object null? 7201 je common_errNullObject # object was null 7202 movl rINST_FULL,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7203 FETCH_INST_WORD(2) 7204 ADVANCE_PC(2) 7205 GOTO_NEXT 7206 7207/* continuation for OP_IPUT_BOOLEAN */ 7208 7209 7210.LOP_IPUT_BOOLEAN_resolve: 7211 EXPORT_PC() 7212 SPILL(rPC) 7213 movl offGlue_method(rIBASE),rPC # rPC<- current method 7214 UNSPILL(rIBASE) 7215 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7216 SPILL_TMP(%ecx) # save object pointer across call 7217 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7218 call dvmResolveInstField # ... to dvmResolveInstField 7219 UNSPILL_TMP(%ecx) 7220 UNSPILL(rPC) 7221 testl %eax,%eax # ... which returns InstrField ptr 7222 jne .LOP_IPUT_BOOLEAN_finish 7223 jmp common_exceptionThrown 7224 7225.LOP_IPUT_BOOLEAN_finish: 7226 /* 7227 * Currently: 7228 * eax holds resolved field 7229 * ecx holds object 7230 * rIBASE is scratch, but needs to be unspilled 7231 * rINST_FULL holds A 7232 */ 7233 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7234 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7235 UNSPILL(rIBASE) 7236 testl %ecx,%ecx # object null? 7237 je common_errNullObject # object was null 7238 movb rINST_LO,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7239 FETCH_INST_WORD(2) 7240 ADVANCE_PC(2) 7241 GOTO_NEXT 7242 7243/* continuation for OP_IPUT_BYTE */ 7244 7245 7246.LOP_IPUT_BYTE_resolve: 7247 EXPORT_PC() 7248 SPILL(rPC) 7249 movl offGlue_method(rIBASE),rPC # rPC<- current method 7250 UNSPILL(rIBASE) 7251 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7252 SPILL_TMP(%ecx) # save object pointer across call 7253 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7254 call dvmResolveInstField # ... to dvmResolveInstField 7255 UNSPILL_TMP(%ecx) 7256 UNSPILL(rPC) 7257 testl %eax,%eax # ... which returns InstrField ptr 7258 jne .LOP_IPUT_BYTE_finish 7259 jmp common_exceptionThrown 7260 7261.LOP_IPUT_BYTE_finish: 7262 /* 7263 * Currently: 7264 * eax holds resolved field 7265 * ecx holds object 7266 * rIBASE is scratch, but needs to be unspilled 7267 * rINST_FULL holds A 7268 */ 7269 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7270 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7271 UNSPILL(rIBASE) 7272 testl %ecx,%ecx # object null? 7273 je common_errNullObject # object was null 7274 movb rINST_LO,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7275 FETCH_INST_WORD(2) 7276 ADVANCE_PC(2) 7277 GOTO_NEXT 7278 7279/* continuation for OP_IPUT_CHAR */ 7280 7281 7282.LOP_IPUT_CHAR_resolve: 7283 EXPORT_PC() 7284 SPILL(rPC) 7285 movl offGlue_method(rIBASE),rPC # rPC<- current method 7286 UNSPILL(rIBASE) 7287 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7288 SPILL_TMP(%ecx) # save object pointer across call 7289 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7290 call dvmResolveInstField # ... to dvmResolveInstField 7291 UNSPILL_TMP(%ecx) 7292 UNSPILL(rPC) 7293 testl %eax,%eax # ... which returns InstrField ptr 7294 jne .LOP_IPUT_CHAR_finish 7295 jmp common_exceptionThrown 7296 7297.LOP_IPUT_CHAR_finish: 7298 /* 7299 * Currently: 7300 * eax holds resolved field 7301 * ecx holds object 7302 * rIBASE is scratch, but needs to be unspilled 7303 * rINST_FULL holds A 7304 */ 7305 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7306 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7307 UNSPILL(rIBASE) 7308 testl %ecx,%ecx # object null? 7309 je common_errNullObject # object was null 7310 movw rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7311 FETCH_INST_WORD(2) 7312 ADVANCE_PC(2) 7313 GOTO_NEXT 7314 7315/* continuation for OP_IPUT_SHORT */ 7316 7317 7318.LOP_IPUT_SHORT_resolve: 7319 EXPORT_PC() 7320 SPILL(rPC) 7321 movl offGlue_method(rIBASE),rPC # rPC<- current method 7322 UNSPILL(rIBASE) 7323 movl offMethod_clazz(rPC),rPC # rPC<- method->clazz 7324 SPILL_TMP(%ecx) # save object pointer across call 7325 movl rPC,OUT_ARG0(%esp) # pass in method->clazz 7326 call dvmResolveInstField # ... to dvmResolveInstField 7327 UNSPILL_TMP(%ecx) 7328 UNSPILL(rPC) 7329 testl %eax,%eax # ... which returns InstrField ptr 7330 jne .LOP_IPUT_SHORT_finish 7331 jmp common_exceptionThrown 7332 7333.LOP_IPUT_SHORT_finish: 7334 /* 7335 * Currently: 7336 * eax holds resolved field 7337 * ecx holds object 7338 * rIBASE is scratch, but needs to be unspilled 7339 * rINST_FULL holds A 7340 */ 7341 GET_VREG(rINST_FULL,rINST_FULL) # rINST_FULL<- v[A] 7342 movl offInstField_byteOffset(%eax),%eax # eax<- byte offset of field 7343 UNSPILL(rIBASE) 7344 testl %ecx,%ecx # object null? 7345 je common_errNullObject # object was null 7346 movw rINST,(%ecx,%eax,1) # obj.field <- v[A](8/16/32 bits) 7347 FETCH_INST_WORD(2) 7348 ADVANCE_PC(2) 7349 GOTO_NEXT 7350 7351/* continuation for OP_SGET */ 7352 7353 /* 7354 * Go resolve the field 7355 */ 7356.LOP_SGET_resolve: 7357 GET_GLUE(%ecx) 7358 movzwl 2(rPC),%eax # eax<- field ref BBBB 7359 movl offGlue_method(%ecx),%ecx # ecx<- current method 7360 EXPORT_PC() # could throw, need to export 7361 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7362 SPILL(rPC) 7363 movl %eax,OUT_ARG1(%esp) 7364 movl %ecx,OUT_ARG0(%esp) 7365 call dvmResolveStaticField # eax<- resolved StaticField ptr 7366 UNSPILL(rPC) 7367 testl %eax,%eax 7368 jne .LOP_SGET_finish # success, continue 7369 jmp common_exceptionThrown # no, handle exception 7370 7371 7372/* continuation for OP_SGET_WIDE */ 7373 7374 /* 7375 * Go resolve the field 7376 */ 7377.LOP_SGET_WIDE_resolve: 7378 GET_GLUE(%ecx) 7379 movzwl 2(rPC),%eax # eax<- field ref BBBB 7380 movl offGlue_method(%ecx),%ecx # ecx<- current method 7381 EXPORT_PC() # could throw, need to export 7382 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7383 SPILL(rPC) 7384 movl %eax,OUT_ARG1(%esp) 7385 movl %ecx,OUT_ARG0(%esp) 7386 call dvmResolveStaticField # eax<- resolved StaticField ptr 7387 UNSPILL(rPC) 7388 testl %eax,%eax 7389 jne .LOP_SGET_WIDE_finish # success, continue 7390 jmp common_exceptionThrown # no, handle exception 7391 7392 7393/* continuation for OP_SGET_OBJECT */ 7394 7395 /* 7396 * Go resolve the field 7397 */ 7398.LOP_SGET_OBJECT_resolve: 7399 GET_GLUE(%ecx) 7400 movzwl 2(rPC),%eax # eax<- field ref BBBB 7401 movl offGlue_method(%ecx),%ecx # ecx<- current method 7402 EXPORT_PC() # could throw, need to export 7403 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7404 SPILL(rPC) 7405 movl %eax,OUT_ARG1(%esp) 7406 movl %ecx,OUT_ARG0(%esp) 7407 call dvmResolveStaticField # eax<- resolved StaticField ptr 7408 UNSPILL(rPC) 7409 testl %eax,%eax 7410 jne .LOP_SGET_OBJECT_finish # success, continue 7411 jmp common_exceptionThrown # no, handle exception 7412 7413 7414/* continuation for OP_SGET_BOOLEAN */ 7415 7416 /* 7417 * Go resolve the field 7418 */ 7419.LOP_SGET_BOOLEAN_resolve: 7420 GET_GLUE(%ecx) 7421 movzwl 2(rPC),%eax # eax<- field ref BBBB 7422 movl offGlue_method(%ecx),%ecx # ecx<- current method 7423 EXPORT_PC() # could throw, need to export 7424 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7425 SPILL(rPC) 7426 movl %eax,OUT_ARG1(%esp) 7427 movl %ecx,OUT_ARG0(%esp) 7428 call dvmResolveStaticField # eax<- resolved StaticField ptr 7429 UNSPILL(rPC) 7430 testl %eax,%eax 7431 jne .LOP_SGET_BOOLEAN_finish # success, continue 7432 jmp common_exceptionThrown # no, handle exception 7433 7434 7435/* continuation for OP_SGET_BYTE */ 7436 7437 /* 7438 * Go resolve the field 7439 */ 7440.LOP_SGET_BYTE_resolve: 7441 GET_GLUE(%ecx) 7442 movzwl 2(rPC),%eax # eax<- field ref BBBB 7443 movl offGlue_method(%ecx),%ecx # ecx<- current method 7444 EXPORT_PC() # could throw, need to export 7445 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7446 SPILL(rPC) 7447 movl %eax,OUT_ARG1(%esp) 7448 movl %ecx,OUT_ARG0(%esp) 7449 call dvmResolveStaticField # eax<- resolved StaticField ptr 7450 UNSPILL(rPC) 7451 testl %eax,%eax 7452 jne .LOP_SGET_BYTE_finish # success, continue 7453 jmp common_exceptionThrown # no, handle exception 7454 7455 7456/* continuation for OP_SGET_CHAR */ 7457 7458 /* 7459 * Go resolve the field 7460 */ 7461.LOP_SGET_CHAR_resolve: 7462 GET_GLUE(%ecx) 7463 movzwl 2(rPC),%eax # eax<- field ref BBBB 7464 movl offGlue_method(%ecx),%ecx # ecx<- current method 7465 EXPORT_PC() # could throw, need to export 7466 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7467 SPILL(rPC) 7468 movl %eax,OUT_ARG1(%esp) 7469 movl %ecx,OUT_ARG0(%esp) 7470 call dvmResolveStaticField # eax<- resolved StaticField ptr 7471 UNSPILL(rPC) 7472 testl %eax,%eax 7473 jne .LOP_SGET_CHAR_finish # success, continue 7474 jmp common_exceptionThrown # no, handle exception 7475 7476 7477/* continuation for OP_SGET_SHORT */ 7478 7479 /* 7480 * Go resolve the field 7481 */ 7482.LOP_SGET_SHORT_resolve: 7483 GET_GLUE(%ecx) 7484 movzwl 2(rPC),%eax # eax<- field ref BBBB 7485 movl offGlue_method(%ecx),%ecx # ecx<- current method 7486 EXPORT_PC() # could throw, need to export 7487 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7488 SPILL(rPC) 7489 movl %eax,OUT_ARG1(%esp) 7490 movl %ecx,OUT_ARG0(%esp) 7491 call dvmResolveStaticField # eax<- resolved StaticField ptr 7492 UNSPILL(rPC) 7493 testl %eax,%eax 7494 jne .LOP_SGET_SHORT_finish # success, continue 7495 jmp common_exceptionThrown # no, handle exception 7496 7497 7498/* continuation for OP_SPUT */ 7499 7500 /* 7501 * Go resolve the field 7502 */ 7503.LOP_SPUT_resolve: 7504 GET_GLUE(%ecx) 7505 movzwl 2(rPC),%eax # eax<- field ref BBBB 7506 movl offGlue_method(%ecx),%ecx # ecx<- current method 7507 EXPORT_PC() # could throw, need to export 7508 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7509 SPILL(rPC) 7510 movl %eax,OUT_ARG1(%esp) 7511 movl %ecx,OUT_ARG0(%esp) 7512 call dvmResolveStaticField # eax<- resolved StaticField ptr 7513 UNSPILL(rPC) 7514 testl %eax,%eax 7515 jne .LOP_SPUT_finish # success, continue 7516 jmp common_exceptionThrown # no, handle exception 7517 7518 7519/* continuation for OP_SPUT_WIDE */ 7520 7521 /* 7522 * Go resolve the field 7523 */ 7524.LOP_SPUT_WIDE_resolve: 7525 GET_GLUE(%ecx) 7526 movzwl 2(rPC),%eax # eax<- field ref BBBB 7527 movl offGlue_method(%ecx),%ecx # ecx<- current method 7528 EXPORT_PC() # could throw, need to export 7529 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7530 SPILL(rPC) 7531 movl %eax,OUT_ARG1(%esp) 7532 movl %ecx,OUT_ARG0(%esp) 7533 call dvmResolveStaticField # eax<- resolved StaticField ptr 7534 UNSPILL(rPC) 7535 testl %eax,%eax 7536 jne .LOP_SPUT_WIDE_finish # success, continue 7537 jmp common_exceptionThrown # no, handle exception 7538 7539 7540/* continuation for OP_SPUT_OBJECT */ 7541 7542 /* 7543 * Go resolve the field 7544 */ 7545.LOP_SPUT_OBJECT_resolve: 7546 GET_GLUE(%ecx) 7547 movzwl 2(rPC),%eax # eax<- field ref BBBB 7548 movl offGlue_method(%ecx),%ecx # ecx<- current method 7549 EXPORT_PC() # could throw, need to export 7550 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7551 SPILL(rPC) 7552 movl %eax,OUT_ARG1(%esp) 7553 movl %ecx,OUT_ARG0(%esp) 7554 call dvmResolveStaticField # eax<- resolved StaticField ptr 7555 UNSPILL(rPC) 7556 testl %eax,%eax 7557 jne .LOP_SPUT_OBJECT_finish # success, continue 7558 jmp common_exceptionThrown # no, handle exception 7559 7560 7561/* continuation for OP_SPUT_BOOLEAN */ 7562 7563 /* 7564 * Go resolve the field 7565 */ 7566.LOP_SPUT_BOOLEAN_resolve: 7567 GET_GLUE(%ecx) 7568 movzwl 2(rPC),%eax # eax<- field ref BBBB 7569 movl offGlue_method(%ecx),%ecx # ecx<- current method 7570 EXPORT_PC() # could throw, need to export 7571 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7572 SPILL(rPC) 7573 movl %eax,OUT_ARG1(%esp) 7574 movl %ecx,OUT_ARG0(%esp) 7575 call dvmResolveStaticField # eax<- resolved StaticField ptr 7576 UNSPILL(rPC) 7577 testl %eax,%eax 7578 jne .LOP_SPUT_BOOLEAN_finish # success, continue 7579 jmp common_exceptionThrown # no, handle exception 7580 7581 7582/* continuation for OP_SPUT_BYTE */ 7583 7584 /* 7585 * Go resolve the field 7586 */ 7587.LOP_SPUT_BYTE_resolve: 7588 GET_GLUE(%ecx) 7589 movzwl 2(rPC),%eax # eax<- field ref BBBB 7590 movl offGlue_method(%ecx),%ecx # ecx<- current method 7591 EXPORT_PC() # could throw, need to export 7592 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7593 SPILL(rPC) 7594 movl %eax,OUT_ARG1(%esp) 7595 movl %ecx,OUT_ARG0(%esp) 7596 call dvmResolveStaticField # eax<- resolved StaticField ptr 7597 UNSPILL(rPC) 7598 testl %eax,%eax 7599 jne .LOP_SPUT_BYTE_finish # success, continue 7600 jmp common_exceptionThrown # no, handle exception 7601 7602 7603/* continuation for OP_SPUT_CHAR */ 7604 7605 /* 7606 * Go resolve the field 7607 */ 7608.LOP_SPUT_CHAR_resolve: 7609 GET_GLUE(%ecx) 7610 movzwl 2(rPC),%eax # eax<- field ref BBBB 7611 movl offGlue_method(%ecx),%ecx # ecx<- current method 7612 EXPORT_PC() # could throw, need to export 7613 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7614 SPILL(rPC) 7615 movl %eax,OUT_ARG1(%esp) 7616 movl %ecx,OUT_ARG0(%esp) 7617 call dvmResolveStaticField # eax<- resolved StaticField ptr 7618 UNSPILL(rPC) 7619 testl %eax,%eax 7620 jne .LOP_SPUT_CHAR_finish # success, continue 7621 jmp common_exceptionThrown # no, handle exception 7622 7623 7624/* continuation for OP_SPUT_SHORT */ 7625 7626 /* 7627 * Go resolve the field 7628 */ 7629.LOP_SPUT_SHORT_resolve: 7630 GET_GLUE(%ecx) 7631 movzwl 2(rPC),%eax # eax<- field ref BBBB 7632 movl offGlue_method(%ecx),%ecx # ecx<- current method 7633 EXPORT_PC() # could throw, need to export 7634 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7635 SPILL(rPC) 7636 movl %eax,OUT_ARG1(%esp) 7637 movl %ecx,OUT_ARG0(%esp) 7638 call dvmResolveStaticField # eax<- resolved StaticField ptr 7639 UNSPILL(rPC) 7640 testl %eax,%eax 7641 jne .LOP_SPUT_SHORT_finish # success, continue 7642 jmp common_exceptionThrown # no, handle exception 7643 7644 7645/* continuation for OP_INVOKE_VIRTUAL */ 7646 7647 7648.LOP_INVOKE_VIRTUAL_more: 7649 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 7650 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 7651 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 7652 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7653 UNSPILL(rPC) 7654 testl %eax,%eax # got null? 7655 jne .LOP_INVOKE_VIRTUAL_continue # no, continue 7656 jmp common_exceptionThrown # yes, handle exception 7657 7658 /* At this point: 7659 * eax = resolved base method 7660 * ecx = scratch 7661 */ 7662.LOP_INVOKE_VIRTUAL_continue: 7663 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 7664 .if (!0) 7665 andl $0xf,%ecx # ecx<- D (or stays CCCC) 7666 .endif 7667 GET_VREG(%ecx,%ecx) # ecx<- "this" 7668 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 7669 testl %ecx,%ecx # null this? 7670 je common_errNullObject # go if so 7671 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz 7672 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable 7673 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex] 7674 movl $0,%ecx # needed for common_invokeOld 7675 #jmp common_invokeMethodNoRange 7676 jmp common_invokeOld 7677 7678 7679/* continuation for OP_INVOKE_SUPER */ 7680 7681 /* 7682 * At this point: 7683 * ecx = resolved base method [r0] 7684 * eax = method->clazz [r9] 7685 */ 7686.LOP_INVOKE_SUPER_continue: 7687 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super 7688 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex 7689 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount) 7690 jae .LOP_INVOKE_SUPER_nsm # method not present in superclass 7691 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable 7692 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex] 7693 movl $0,%ecx 7694 #jmp common_invokeMethodNoRange 7695 jmp common_invokeOld 7696 7697 /* At this point: 7698 * ecx = null (needs to be resolved base method) 7699 * eax = method->clazz 7700 */ 7701.LOP_INVOKE_SUPER_resolve: 7702 SPILL_TMP(%eax) # method->clazz 7703 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz 7704 movzwl 2(rPC),%ecx # ecx<- BBBB 7705 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type 7706 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 7707 SPILL(rPC) 7708 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7709 UNSPILL(rPC) 7710 testl %eax,%eax # got null? 7711 movl %eax,%ecx # ecx<- resolved base method 7712 UNSPILL_TMP(%eax) # restore method->clazz 7713 jne .LOP_INVOKE_SUPER_continue # good to go - continue 7714 jmp common_exceptionThrown # handle exception 7715 7716 /* 7717 * Throw a NoSuchMethodError with the method name as the message. 7718 * ecx = resolved base method 7719 */ 7720.LOP_INVOKE_SUPER_nsm: 7721 movl offMethod_name(%ecx),%eax 7722 mov %eax,OUT_ARG1(%esp) 7723 jmp common_errNoSuchMethod 7724 7725/* continuation for OP_INVOKE_DIRECT */ 7726 7727 /* 7728 * On entry: 7729 * TMP_SPILL <- "this" register 7730 * Things a bit ugly on this path, but it's the less 7731 * frequent one. We'll have to do some reloading. 7732 */ 7733.LOP_INVOKE_DIRECT_resolve: 7734 SPILL_TMP(%ecx) 7735 GET_GLUE(%ecx) 7736 UNSPILL(rPC) 7737 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 7738 movzwl 2(rPC),%eax # reference (BBBB or CCCC) 7739 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7740 movl $METHOD_DIRECT,OUT_ARG2(%esp) 7741 movl %eax,OUT_ARG1(%esp) 7742 movl %ecx,OUT_ARG0(%esp) 7743 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7744 UNSPILL_TMP(%ecx) 7745 testl %eax,%eax 7746 jne .LOP_INVOKE_DIRECT_finish 7747 UNSPILL(rPC) 7748 jmp common_exceptionThrown 7749 7750/* continuation for OP_INVOKE_STATIC */ 7751 7752.LOP_INVOKE_STATIC_continue: 7753 movl $METHOD_STATIC,%eax 7754 movl %eax,OUT_ARG2(%esp) # arg2<- flags 7755 SPILL(rPC) 7756 call dvmResolveMethod # call(clazz,ref,flags) 7757 UNSPILL(rPC) 7758 movl $0,%ecx 7759 testl %eax,%eax # got null? 7760 #jne common_invokeMethodNoRange 7761 jne common_invokeOld 7762 jmp common_exceptionThrown 7763 7764 7765/* continuation for OP_INVOKE_INTERFACE */ 7766 7767.LOP_INVOKE_INTERFACE_continue: 7768 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex) 7769 UNSPILL(rPC) 7770 testl %eax,%eax 7771 je common_exceptionThrown 7772 movl $0,%ecx 7773 #jmp common_invokeMethodNoRange 7774 jmp common_invokeOld 7775 7776 7777/* continuation for OP_INVOKE_VIRTUAL_RANGE */ 7778 7779 7780.LOP_INVOKE_VIRTUAL_RANGE_more: 7781 movl offMethod_clazz(%eax),%eax # ecx<- method->clazz 7782 movl %eax,OUT_ARG0(%esp) # arg0<- clazz 7783 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags 7784 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7785 UNSPILL(rPC) 7786 testl %eax,%eax # got null? 7787 jne .LOP_INVOKE_VIRTUAL_RANGE_continue # no, continue 7788 jmp common_exceptionThrown # yes, handle exception 7789 7790 /* At this point: 7791 * eax = resolved base method 7792 * ecx = scratch 7793 */ 7794.LOP_INVOKE_VIRTUAL_RANGE_continue: 7795 movzwl 4(rPC),%ecx # ecx<- GFED or CCCC 7796 .if (!1) 7797 andl $0xf,%ecx # ecx<- D (or stays CCCC) 7798 .endif 7799 GET_VREG(%ecx,%ecx) # ecx<- "this" 7800 movzwl offMethod_methodIndex(%eax),%eax # eax<- baseMethod->methodIndex 7801 testl %ecx,%ecx # null this? 7802 je common_errNullObject # go if so 7803 movl offObject_clazz(%ecx),%ecx # ecx<- thisPtr->clazz 7804 movl offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable 7805 movl (%ecx,%eax,4),%eax # eax<- vtable[methodIndex] 7806 movl $1,%ecx # needed for common_invokeOld 7807 #jmp common_invokeMethodRange 7808 jmp common_invokeOld 7809 7810 7811/* continuation for OP_INVOKE_SUPER_RANGE */ 7812 7813 /* 7814 * At this point: 7815 * ecx = resolved base method [r0] 7816 * eax = method->clazz [r9] 7817 */ 7818.LOP_INVOKE_SUPER_RANGE_continue: 7819 movl offClassObject_super(%eax),%eax # eax<- method->clazz->super 7820 movzwl offMethod_methodIndex(%ecx),%ecx # ecx<- baseMthod->methodIndex 7821 cmpl offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount) 7822 jae .LOP_INVOKE_SUPER_RANGE_nsm # method not present in superclass 7823 movl offClassObject_vtable(%eax),%eax # eax<- ...clazz->super->vtable 7824 movl (%eax,%ecx,4),%eax # eax<- vtable[methodIndex] 7825 movl $1,%ecx 7826 #jmp common_invokeMethodRange 7827 jmp common_invokeOld 7828 7829 /* At this point: 7830 * ecx = null (needs to be resolved base method) 7831 * eax = method->clazz 7832 */ 7833.LOP_INVOKE_SUPER_RANGE_resolve: 7834 SPILL_TMP(%eax) # method->clazz 7835 movl %eax,OUT_ARG0(%esp) # arg0<- method->clazz 7836 movzwl 2(rPC),%ecx # ecx<- BBBB 7837 movl $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- resolver method type 7838 movl %ecx,OUT_ARG1(%esp) # arg1<- ref 7839 SPILL(rPC) 7840 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7841 UNSPILL(rPC) 7842 testl %eax,%eax # got null? 7843 movl %eax,%ecx # ecx<- resolved base method 7844 UNSPILL_TMP(%eax) # restore method->clazz 7845 jne .LOP_INVOKE_SUPER_RANGE_continue # good to go - continue 7846 jmp common_exceptionThrown # handle exception 7847 7848 /* 7849 * Throw a NoSuchMethodError with the method name as the message. 7850 * ecx = resolved base method 7851 */ 7852.LOP_INVOKE_SUPER_RANGE_nsm: 7853 movl offMethod_name(%ecx),%eax 7854 mov %eax,OUT_ARG1(%esp) 7855 jmp common_errNoSuchMethod 7856 7857/* continuation for OP_INVOKE_DIRECT_RANGE */ 7858 7859 /* 7860 * On entry: 7861 * TMP_SPILL <- "this" register 7862 * Things a bit ugly on this path, but it's the less 7863 * frequent one. We'll have to do some reloading. 7864 */ 7865.LOP_INVOKE_DIRECT_RANGE_resolve: 7866 SPILL_TMP(%ecx) 7867 GET_GLUE(%ecx) 7868 UNSPILL(rPC) 7869 movl offGlue_method(%ecx),%ecx # ecx<- glue->method 7870 movzwl 2(rPC),%eax # reference (BBBB or CCCC) 7871 movl offMethod_clazz(%ecx),%ecx # ecx<- method->clazz 7872 movl $METHOD_DIRECT,OUT_ARG2(%esp) 7873 movl %eax,OUT_ARG1(%esp) 7874 movl %ecx,OUT_ARG0(%esp) 7875 call dvmResolveMethod # eax<- call(clazz, ref, flags) 7876 UNSPILL_TMP(%ecx) 7877 testl %eax,%eax 7878 jne .LOP_INVOKE_DIRECT_RANGE_finish 7879 UNSPILL(rPC) 7880 jmp common_exceptionThrown 7881 7882/* continuation for OP_INVOKE_STATIC_RANGE */ 7883 7884.LOP_INVOKE_STATIC_RANGE_continue: 7885 movl $METHOD_STATIC,%eax 7886 movl %eax,OUT_ARG2(%esp) # arg2<- flags 7887 SPILL(rPC) 7888 call dvmResolveMethod # call(clazz,ref,flags) 7889 UNSPILL(rPC) 7890 movl $1,%ecx 7891 testl %eax,%eax # got null? 7892 #jne common_invokeMethodRange 7893 jne common_invokeOld 7894 jmp common_exceptionThrown 7895 7896 7897/* continuation for OP_INVOKE_INTERFACE_RANGE */ 7898 7899.LOP_INVOKE_INTERFACE_RANGE_continue: 7900 call dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex) 7901 UNSPILL(rPC) 7902 testl %eax,%eax 7903 je common_exceptionThrown 7904 movl $1,%ecx 7905 #jmp common_invokeMethodRange 7906 jmp common_invokeOld 7907 7908 7909/* continuation for OP_FLOAT_TO_INT */ 7910 7911 7912.LOP_FLOAT_TO_INT_continue: 7913 .if 0 7914 movl $0x80000000,%eax 7915 xorl 4(rFP,%ecx,4),%eax 7916 orl (rFP,%ecx,4),%eax 7917 .else 7918 cmpl $0x80000000,(rFP,%ecx,4) 7919 .endif 7920 je .LOP_FLOAT_TO_INT_special_case # fix up result 7921 7922.LOP_FLOAT_TO_INT_finish: 7923 ADVANCE_PC(1) 7924 GOTO_NEXT 7925 7926.LOP_FLOAT_TO_INT_special_case: 7927 fnstsw %ax 7928 sahf 7929 jp .LOP_FLOAT_TO_INT_isNaN 7930 adcl $-1,(rFP,%ecx,4) 7931 .if 0 7932 adcl $-1,4(rFP,%ecx,4) 7933 .endif 7934 jmp .LOP_FLOAT_TO_INT_finish 7935.LOP_FLOAT_TO_INT_isNaN: 7936 movl $0,(rFP,%ecx,4) 7937 .if 0 7938 movl $0,4(rFP,%ecx,4) 7939 .endif 7940 jmp .LOP_FLOAT_TO_INT_finish 7941 7942/* continuation for OP_FLOAT_TO_LONG */ 7943 7944 7945.LOP_FLOAT_TO_LONG_continue: 7946 .if 1 7947 movl $0x80000000,%eax 7948 xorl 4(rFP,%ecx,4),%eax 7949 orl (rFP,%ecx,4),%eax 7950 .else 7951 cmpl $0x80000000,(rFP,%ecx,4) 7952 .endif 7953 je .LOP_FLOAT_TO_LONG_special_case # fix up result 7954 7955.LOP_FLOAT_TO_LONG_finish: 7956 ADVANCE_PC(1) 7957 GOTO_NEXT 7958 7959.LOP_FLOAT_TO_LONG_special_case: 7960 fnstsw %ax 7961 sahf 7962 jp .LOP_FLOAT_TO_LONG_isNaN 7963 adcl $-1,(rFP,%ecx,4) 7964 .if 1 7965 adcl $-1,4(rFP,%ecx,4) 7966 .endif 7967 jmp .LOP_FLOAT_TO_LONG_finish 7968.LOP_FLOAT_TO_LONG_isNaN: 7969 movl $0,(rFP,%ecx,4) 7970 .if 1 7971 movl $0,4(rFP,%ecx,4) 7972 .endif 7973 jmp .LOP_FLOAT_TO_LONG_finish 7974 7975/* continuation for OP_DOUBLE_TO_INT */ 7976 7977 7978.LOP_DOUBLE_TO_INT_continue: 7979 .if 0 7980 movl $0x80000000,%eax 7981 xorl 4(rFP,%ecx,4),%eax 7982 orl (rFP,%ecx,4),%eax 7983 .else 7984 cmpl $0x80000000,(rFP,%ecx,4) 7985 .endif 7986 je .LOP_DOUBLE_TO_INT_special_case # fix up result 7987 7988.LOP_DOUBLE_TO_INT_finish: 7989 ADVANCE_PC(1) 7990 GOTO_NEXT 7991 7992.LOP_DOUBLE_TO_INT_special_case: 7993 fnstsw %ax 7994 sahf 7995 jp .LOP_DOUBLE_TO_INT_isNaN 7996 adcl $-1,(rFP,%ecx,4) 7997 .if 0 7998 adcl $-1,4(rFP,%ecx,4) 7999 .endif 8000 jmp .LOP_DOUBLE_TO_INT_finish 8001.LOP_DOUBLE_TO_INT_isNaN: 8002 movl $0,(rFP,%ecx,4) 8003 .if 0 8004 movl $0,4(rFP,%ecx,4) 8005 .endif 8006 jmp .LOP_DOUBLE_TO_INT_finish 8007 8008/* continuation for OP_DOUBLE_TO_LONG */ 8009 8010 8011.LOP_DOUBLE_TO_LONG_continue: 8012 .if 1 8013 movl $0x80000000,%eax 8014 xorl 4(rFP,%ecx,4),%eax 8015 orl (rFP,%ecx,4),%eax 8016 .else 8017 cmpl $0x80000000,(rFP,%ecx,4) 8018 .endif 8019 je .LOP_DOUBLE_TO_LONG_special_case # fix up result 8020 8021.LOP_DOUBLE_TO_LONG_finish: 8022 ADVANCE_PC(1) 8023 GOTO_NEXT 8024 8025.LOP_DOUBLE_TO_LONG_special_case: 8026 fnstsw %ax 8027 sahf 8028 jp .LOP_DOUBLE_TO_LONG_isNaN 8029 adcl $-1,(rFP,%ecx,4) 8030 .if 1 8031 adcl $-1,4(rFP,%ecx,4) 8032 .endif 8033 jmp .LOP_DOUBLE_TO_LONG_finish 8034.LOP_DOUBLE_TO_LONG_isNaN: 8035 movl $0,(rFP,%ecx,4) 8036 .if 1 8037 movl $0,4(rFP,%ecx,4) 8038 .endif 8039 jmp .LOP_DOUBLE_TO_LONG_finish 8040 8041/* continuation for OP_DIV_INT */ 8042.LOP_DIV_INT_continue_div: 8043 cltd 8044 idivl %ecx 8045.LOP_DIV_INT_finish_div: 8046 movzbl rINST_HI,%ecx # ecl<- AA 8047 SET_VREG(%eax,%ecx) 8048 UNSPILL(rPC) 8049 FETCH_INST_WORD(2) 8050 ADVANCE_PC(2) 8051 GOTO_NEXT 8052 8053/* continuation for OP_REM_INT */ 8054.LOP_REM_INT_continue_div: 8055 cltd 8056 idivl %ecx 8057.LOP_REM_INT_finish_div: 8058 movzbl rINST_HI,%ecx # ecl<- AA 8059 SET_VREG(%edx,%ecx) 8060 UNSPILL(rPC) 8061 FETCH_INST_WORD(2) 8062 ADVANCE_PC(2) 8063 GOTO_NEXT 8064 8065/* continuation for OP_MUL_LONG */ 8066 8067.LOP_MUL_LONG_continue: 8068 leal (%ecx,%edx),%edx # full result now in %edx:%eax 8069 movzbl rINST_HI,%ecx # ecx<- A 8070 movl %edx,4(rFP,%ecx,4) # v[B+1]<- %edx 8071 UNSPILL(rPC) # restore rPC/%edx 8072 FETCH_INST_WORD(2) 8073 UNSPILL(rIBASE) 8074 movl %eax,(rFP,%ecx,4) # v[B]<- %eax 8075 ADVANCE_PC(2) 8076 GOTO_NEXT 8077 8078 8079/* continuation for OP_DIV_LONG */ 8080 8081.LOP_DIV_LONG_continue: 8082 call __divdi3 8083.LOP_DIV_LONG_finish: 8084 movzbl rINST_HI,%ecx 8085 SET_VREG_WORD(rPC,%ecx,1) 8086 UNSPILL(rPC) 8087 SET_VREG_WORD(%eax,%ecx,0) 8088 FETCH_INST_WORD(2) 8089 ADVANCE_PC(2) 8090 GOTO_NEXT 8091 8092.LOP_DIV_LONG_check_zero: 8093 testl rPC,rPC 8094 jne .LOP_DIV_LONG_notSpecial 8095 UNSPILL(rPC) 8096 jmp common_errDivideByZero 8097.LOP_DIV_LONG_check_neg1: 8098 testl rPC,%eax 8099 jne .LOP_DIV_LONG_notSpecial 8100 GET_VREG_WORD(rPC,%ecx,0) 8101 GET_VREG_WORD(%ecx,%ecx,1) 8102 testl rPC,rPC 8103 jne .LOP_DIV_LONG_notSpecial1 8104 cmpl $0x80000000,%ecx 8105 jne .LOP_DIV_LONG_notSpecial1 8106 /* minint / -1, return minint on div, 0 on rem */ 8107 xorl %eax,%eax 8108 movl $0x80000000,%edx 8109 jmp .LOP_DIV_LONG_finish 8110 8111 8112 8113 8114/* continuation for OP_REM_LONG */ 8115 8116.LOP_REM_LONG_continue: 8117 call __moddi3 8118.LOP_REM_LONG_finish: 8119 movzbl rINST_HI,%ecx 8120 SET_VREG_WORD(rPC,%ecx,1) 8121 UNSPILL(rPC) 8122 SET_VREG_WORD(%eax,%ecx,0) 8123 FETCH_INST_WORD(2) 8124 ADVANCE_PC(2) 8125 GOTO_NEXT 8126 8127.LOP_REM_LONG_check_zero: 8128 testl rPC,rPC 8129 jne .LOP_REM_LONG_notSpecial 8130 UNSPILL(rPC) 8131 jmp common_errDivideByZero 8132.LOP_REM_LONG_check_neg1: 8133 testl rPC,%eax 8134 jne .LOP_REM_LONG_notSpecial 8135 GET_VREG_WORD(rPC,%ecx,0) 8136 GET_VREG_WORD(%ecx,%ecx,1) 8137 testl rPC,rPC 8138 jne .LOP_REM_LONG_notSpecial1 8139 cmpl $0x80000000,%ecx 8140 jne .LOP_REM_LONG_notSpecial1 8141 /* minint / -1, return minint on div, 0 on rem */ 8142 xorl %eax,%eax 8143 movl $0,%edx 8144 jmp .LOP_REM_LONG_finish 8145 8146 8147 8148 8149/* continuation for OP_SHL_LONG */ 8150 8151.LOP_SHL_LONG_finish: 8152 SET_VREG_WORD(%eax,%ecx,0) # v[AA+0]<- %eax 8153 ADVANCE_PC(2) 8154 GOTO_NEXT 8155 8156/* continuation for OP_SHR_LONG */ 8157 8158 8159.LOP_SHR_LONG_finish: 8160 SET_VREG_WORD(%eax,%ecx,0) # v[AA+0]<- eax 8161 ADVANCE_PC(2) 8162 GOTO_NEXT 8163 8164/* continuation for OP_USHR_LONG */ 8165 8166 8167.LOP_USHR_LONG_finish: 8168 SET_VREG_WORD(%eax,%ecx,0) # v[BB+0]<- eax 8169 FETCH_INST_WORD(2) 8170 ADVANCE_PC(2) 8171 GOTO_NEXT 8172 8173/* continuation for OP_DIV_INT_2ADDR */ 8174.LOP_DIV_INT_2ADDR_continue_div2addr: 8175 cltd 8176 idivl %ecx 8177.LOP_DIV_INT_2ADDR_finish_div2addr: 8178 SET_VREG(%eax,rINST_FULL) 8179 UNSPILL(rPC) 8180 FETCH_INST_WORD(1) 8181 ADVANCE_PC(1) 8182 GOTO_NEXT 8183 8184/* continuation for OP_REM_INT_2ADDR */ 8185.LOP_REM_INT_2ADDR_continue_div2addr: 8186 cltd 8187 idivl %ecx 8188.LOP_REM_INT_2ADDR_finish_div2addr: 8189 SET_VREG(%edx,rINST_FULL) 8190 UNSPILL(rPC) 8191 FETCH_INST_WORD(1) 8192 ADVANCE_PC(1) 8193 GOTO_NEXT 8194 8195/* continuation for OP_MUL_LONG_2ADDR */ 8196 8197.LOP_MUL_LONG_2ADDR_continue: 8198 leal (%ecx,%edx),%edx # full result now in %edx:%eax 8199 movl %edx,4(rIBASE) # v[A+1]<- %edx 8200 UNSPILL(rPC) # restore rPC/%edx 8201 FETCH_INST_WORD(1) 8202 movl %eax,(rIBASE) # v[A]<- %eax 8203 UNSPILL(rFP) 8204 UNSPILL(rIBASE) 8205 ADVANCE_PC(1) 8206 GOTO_NEXT 8207 8208 8209/* continuation for OP_DIV_LONG_2ADDR */ 8210 8211.LOP_DIV_LONG_2ADDR_continue: 8212 movl %eax,OUT_ARG3(%esp) 8213 movl rPC,OUT_ARG0(%esp) 8214 movl %ecx,OUT_ARG1(%esp) 8215 call __divdi3 8216.LOP_DIV_LONG_2ADDR_finish: 8217 movl rINST_FULL,%ecx 8218 SET_VREG_WORD(rPC,%ecx,1) 8219 UNSPILL(rPC) 8220 SET_VREG_WORD(%eax,%ecx,0) 8221 FETCH_INST_WORD(1) 8222 ADVANCE_PC(1) 8223 GOTO_NEXT 8224 8225.LOP_DIV_LONG_2ADDR_check_zero: 8226 testl rPC,rPC 8227 jne .LOP_DIV_LONG_2ADDR_notSpecial 8228 UNSPILL(rPC) 8229 jmp common_errDivideByZero 8230.LOP_DIV_LONG_2ADDR_check_neg1: 8231 testl rPC,%eax 8232 jne .LOP_DIV_LONG_2ADDR_notSpecial 8233 GET_VREG_WORD(rPC,rINST_FULL,0) 8234 GET_VREG_WORD(%ecx,rINST_FULL,1) 8235 testl rPC,rPC 8236 jne .LOP_DIV_LONG_2ADDR_notSpecial1 8237 cmpl $0x80000000,%ecx 8238 jne .LOP_DIV_LONG_2ADDR_notSpecial1 8239 /* minint / -1, return minint on div, 0 on rem */ 8240 xorl %eax,%eax 8241 movl $0x80000000,%edx 8242 jmp .LOP_DIV_LONG_2ADDR_finish 8243 8244 8245/* continuation for OP_REM_LONG_2ADDR */ 8246 8247.LOP_REM_LONG_2ADDR_continue: 8248 movl %eax,OUT_ARG3(%esp) 8249 movl rPC,OUT_ARG0(%esp) 8250 movl %ecx,OUT_ARG1(%esp) 8251 call __moddi3 8252.LOP_REM_LONG_2ADDR_finish: 8253 movl rINST_FULL,%ecx 8254 SET_VREG_WORD(rPC,%ecx,1) 8255 UNSPILL(rPC) 8256 SET_VREG_WORD(%eax,%ecx,0) 8257 FETCH_INST_WORD(1) 8258 ADVANCE_PC(1) 8259 GOTO_NEXT 8260 8261.LOP_REM_LONG_2ADDR_check_zero: 8262 testl rPC,rPC 8263 jne .LOP_REM_LONG_2ADDR_notSpecial 8264 UNSPILL(rPC) 8265 jmp common_errDivideByZero 8266.LOP_REM_LONG_2ADDR_check_neg1: 8267 testl rPC,%eax 8268 jne .LOP_REM_LONG_2ADDR_notSpecial 8269 GET_VREG_WORD(rPC,rINST_FULL,0) 8270 GET_VREG_WORD(%ecx,rINST_FULL,1) 8271 testl rPC,rPC 8272 jne .LOP_REM_LONG_2ADDR_notSpecial1 8273 cmpl $0x80000000,%ecx 8274 jne .LOP_REM_LONG_2ADDR_notSpecial1 8275 /* minint / -1, return minint on div, 0 on rem */ 8276 xorl %eax,%eax 8277 movl $0,%edx 8278 jmp .LOP_REM_LONG_2ADDR_finish 8279 8280 8281/* continuation for OP_SHL_LONG_2ADDR */ 8282 8283 8284.LOP_SHL_LONG_2ADDR_finish: 8285 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax 8286 FETCH_INST_WORD(1) 8287 ADVANCE_PC(1) 8288 GOTO_NEXT 8289 8290/* continuation for OP_SHR_LONG_2ADDR */ 8291 8292 8293.LOP_SHR_LONG_2ADDR_finish: 8294 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax 8295 FETCH_INST_WORD(1) 8296 ADVANCE_PC(1) 8297 GOTO_NEXT 8298 8299/* continuation for OP_USHR_LONG_2ADDR */ 8300 8301 8302.LOP_USHR_LONG_2ADDR_finish: 8303 SET_VREG_WORD(%eax,rINST_FULL,0) # v[AA+0]<- eax 8304 FETCH_INST_WORD(1) 8305 ADVANCE_PC(1) 8306 GOTO_NEXT 8307 8308/* continuation for OP_DIV_INT_LIT16 */ 8309.LOP_DIV_INT_LIT16_continue_div: 8310 cltd 8311 idivl %ecx 8312.LOP_DIV_INT_LIT16_finish_div: 8313 SET_VREG(%eax,rINST_FULL) 8314 UNSPILL(rPC) 8315 FETCH_INST_WORD(2) 8316 ADVANCE_PC(2) 8317 GOTO_NEXT 8318 8319/* continuation for OP_REM_INT_LIT16 */ 8320.LOP_REM_INT_LIT16_continue_div: 8321 cltd 8322 idivl %ecx 8323.LOP_REM_INT_LIT16_finish_div: 8324 SET_VREG(%edx,rINST_FULL) 8325 UNSPILL(rPC) 8326 FETCH_INST_WORD(2) 8327 ADVANCE_PC(2) 8328 GOTO_NEXT 8329 8330/* continuation for OP_DIV_INT_LIT8 */ 8331.LOP_DIV_INT_LIT8_continue_div: 8332 cltd 8333 idivl %ecx 8334.LOP_DIV_INT_LIT8_finish_div: 8335 SET_VREG(%eax,rINST_FULL) 8336 UNSPILL(rPC) 8337 FETCH_INST_WORD(2) 8338 ADVANCE_PC(2) 8339 GOTO_NEXT 8340 8341/* continuation for OP_REM_INT_LIT8 */ 8342.LOP_REM_INT_LIT8_continue_div: 8343 cltd 8344 idivl %ecx 8345.LOP_REM_INT_LIT8_finish_div: 8346 SET_VREG(%edx,rINST_FULL) 8347 UNSPILL(rPC) 8348 FETCH_INST_WORD(2) 8349 ADVANCE_PC(2) 8350 GOTO_NEXT 8351 8352/* continuation for OP_EXECUTE_INLINE */ 8353 8354.LOP_EXECUTE_INLINE_continue: 8355 /* 8356 * Extract args, call function. 8357 * ecx = #of args (0-4) 8358 * eax = call index 8359 * @esp = return addr 8360 * esp is -4 from normal 8361 * 8362 * Go ahead and load all 4 args, even if not used. 8363 */ 8364 movzwl 4(rPC),rPC 8365 8366 movl $0xf,%ecx 8367 andl rPC,%ecx 8368 GET_VREG(%ecx,%ecx) 8369 sarl $4,rPC 8370 movl %ecx,4+OUT_ARG0(%esp) 8371 8372 movl $0xf,%ecx 8373 andl rPC,%ecx 8374 GET_VREG(%ecx,%ecx) 8375 sarl $4,rPC 8376 movl %ecx,4+OUT_ARG1(%esp) 8377 8378 movl $0xf,%ecx 8379 andl rPC,%ecx 8380 GET_VREG(%ecx,%ecx) 8381 sarl $4,rPC 8382 movl %ecx,4+OUT_ARG2(%esp) 8383 8384 movl $0xf,%ecx 8385 andl rPC,%ecx 8386 GET_VREG(%ecx,%ecx) 8387 sarl $4,rPC 8388 movl %ecx,4+OUT_ARG3(%esp) 8389 8390 sall $4,%eax # index *= sizeof(table entry) 8391 jmp *gDvmInlineOpsTable(%eax) 8392 # will return to caller of .LOP_EXECUTE_INLINE_continue 8393 8394 8395 .size dvmAsmSisterStart, .-dvmAsmSisterStart 8396 .global dvmAsmSisterEnd 8397dvmAsmSisterEnd: 8398 8399/* File: x86/entry.S */ 8400/* 8401 * Copyright (C) 2008 The Android Open Source Project 8402 * 8403 * Licensed under the Apache License, Version 2.0 (the "License"); 8404 * you may not use this file except in compliance with the License. 8405 * You may obtain a copy of the License at 8406 * 8407 * http://www.apache.org/licenses/LICENSE-2.0 8408 * 8409 * Unless required by applicable law or agreed to in writing, software 8410 * distributed under the License is distributed on an "AS IS" BASIS, 8411 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8412 * See the License for the specific language governing permissions and 8413 * limitations under the License. 8414 */ 8415 8416 8417 .text 8418 .global dvmMterpStdRun 8419 .type dvmMterpStdRun, %function 8420/* 8421 * bool dvmMterpStdRun(MterpGlue* glue) 8422 * 8423 * Interpreter entry point. Returns changeInterp. 8424 * 8425 */ 8426dvmMterpStdRun: 8427 push %ebp 8428 movl %esp,%ebp 8429 push %edi 8430 push %esi 8431 push %ebx 8432 8433/* at this point, stack is misaligned by 1 word 8434 We're allocating spill space for 6 words, plus 8435 outgoing argument (5 words) and local variables 8436 (4 words) - 15 words or 60 bytes total. See 8437 diagram in header.S 8438*/ 8439 subl $60,%esp 8440 8441/* Set up "named" registers */ 8442 movl IN_ARG0(%ebp),%ecx 8443 movl %ecx,rGLUE_SPILL(%ebp) 8444 LOAD_PC_FROM_GLUE(%ecx) 8445 LOAD_FP_FROM_GLUE(%ecx) 8446 movl $dvmAsmInstructionStart,rIBASE 8447 8448/* Remember %esp for future "longjmp" */ 8449 movl %esp,offGlue_bailPtr(%ecx) 8450 8451/* How to start? */ 8452 movb offGlue_entryPoint(%ecx),%al 8453 8454/* Normal start? */ 8455 cmpb $kInterpEntryInstr,%al 8456 jne .Lnot_instr 8457 8458 /* Normal case: start executing the instruction at rPC */ 8459 FETCH_INST() 8460 GOTO_NEXT 8461 8462.Lnot_instr: 8463 /* Reset to normal case */ 8464 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx) 8465 cmpb $kInterpEntryReturn,%al 8466 je common_returnFromMethod 8467 cmpb $kInterpEntryThrow,%al 8468 je common_exceptionThrown 8469 movzx %al,%eax 8470 movl %eax,OUT_ARG1(%esp) 8471 movl $.LstrBadEntryPoint,OUT_ARG0(%esp) 8472 call printf 8473 call dvmAbort 8474 /* Not reached */ 8475 8476 8477 .global dvmMterpStdBail 8478 .type dvmMterpStdBail, %function 8479/* 8480 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp) 8481 * 8482 * Restore the stack pointer and PC from the save point established on entry. 8483 * This is essentially the same as a longjmp, but should be cheaper. The 8484 * last instruction causes us to return to whoever called dvmMterpStdRun. 8485 * 8486 * We're not going to build a standard frame here, so the arg accesses will 8487 * look a little strange. 8488 * 8489 * On entry: 8490 * esp+4 (arg0) MterpGlue* glue 8491 * esp+8 (arg1) bool changeInterp 8492 */ 8493dvmMterpStdBail: 8494 movl 4(%esp),%ecx # grab glue 8495 movl 8(%esp),%eax # changeInterp to return reg 8496 movl offGlue_bailPtr(%ecx),%esp # Stack back to normal 8497 addl $60,%esp # Strip dvmMterpStdRun's frame 8498 pop %ebx 8499 pop %esi 8500 pop %edi 8501 pop %ebp 8502 ret # return to dvmMterpStdRun's caller 8503 8504 8505/* 8506 * Strings 8507 */ 8508 .section .rodata 8509.LstrBadEntryPoint: 8510 .asciz "Bad entry point %d\n" 8511 8512/* File: x86/footer.S */ 8513/* 8514 * Copyright (C) 2008 The Android Open Source Project 8515 * 8516 * Licensed under the Apache License, Version 2.0 (the "License"); 8517 * you may not use this file except in compliance with the License. 8518 * You may obtain a copy of the License at 8519 * 8520 * http://www.apache.org/licenses/LICENSE-2.0 8521 * 8522 * Unless required by applicable law or agreed to in writing, software 8523 * distributed under the License is distributed on an "AS IS" BASIS, 8524 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 8525 * See the License for the specific language governing permissions and 8526 * limitations under the License. 8527 */ 8528/* 8529 * Common subroutines and data. 8530 */ 8531 8532/* 8533 * Common code when a backwards branch is taken 8534 * 8535 * On entry: 8536 * ebx (a.k.a. rINST_FULL) -> PC adjustment in 16-bit words 8537 */ 8538common_backwardBranch: 8539 GET_GLUE(%ecx) 8540 call common_periodicChecks # Note: expects rPC to be preserved 8541 ADVANCE_PC_INDEXED(rINST_FULL) 8542 FETCH_INST() 8543 GOTO_NEXT 8544 8545/* 8546 * Common invoke code (old-style). 8547 * TUNING: Rewrite along lines of new armv5 code? 8548 * 8549 * On entry: 8550 * eax = Method* methodToCall 8551 * ecx = bool methodCallRange 8552 * rINST trashed, must reload 8553 */ 8554common_invokeOld: 8555 movl %ecx,OUT_ARG1(%esp) # arg1<- methodCallRange 8556 GET_GLUE(%ecx) 8557 movzwl (rPC),rINST_FULL # recover rINST 8558 movl %eax,OUT_ARG2(%esp) # arg2<- method 8559 movzwl 4(rPC),%eax # eax<- GFED or CCCC 8560 SAVE_PC_TO_GLUE(%ecx) 8561 SAVE_FP_TO_GLUE(%ecx) 8562 movzbl rINST_HI,rINST_FULL 8563 movl rINST_FULL,OUT_ARG3(%esp)# arg3<- AA 8564 movl %ecx,OUT_ARG0(%esp) # arg0<- GLUE 8565 movl %eax,OUT_ARG4(%esp) # arg4<- GFED/CCCC 8566 call dvmMterp_invokeMethod 8567 jmp common_resumeAfterGlueCall 8568 8569 8570/* 8571 * Do we need the thread to be suspended or have debugger/profiling activity? 8572 * 8573 * On entry: 8574 * ebx -> PC adjustment in 16-bit words (must be preserved) 8575 * ecx -> GLUE pointer 8576 * 8577 * Note: A call will normally kill %eax, rPC/%edx and %ecx. To 8578 * streamline the normal case, this routine will preserve rPC and 8579 * %ecx in addition to the normal caller save regs. The save/restore 8580 * is a bit ugly, but will happen in the relatively uncommon path. 8581 * TUNING: Might be worthwhile to inline this. 8582 * TODO: Basic-block style Jit will need a hook here as well. Fold it into 8583 * the suspendCount check so we can get both in 1 shot. 8584 */ 8585common_periodicChecks: 8586 movl offGlue_pSelfSuspendCount(%ecx),%eax # eax <- &suspendCount 8587 cmpl $0,(%eax) 8588 jne 1f 8589 8590#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER) 8591#if defined(WITH_DEBUGGER) 8592 movl offGlue_pDebuggerActive(%ecx),%eax # eax <- &DebuggerActive 8593#endif 8594#if defined(WITH_PROFILER) 8595 movl offGlue_pActiveProfilers(%ecx),%ecx # ecx <- &ActiveProfilers 8596#endif 8597#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER) 8598 movzbl (%eax),%eax # eax <- debuggerActive (boolean) 8599 orl (%ecx),%eax # eax <- debuggerActive || activeProfilers 8600#elif defined(WITH_DEBUGGER) 8601 movzbl (%eax),%eax # eax <- debuggerActive (boolean) 8602#elif defined(WITH_PROFILER) 8603 movl (%ecx),%eax # eax <= activeProfilers 8604#endif 8605 GET_GLUE(%ecx) # restore rGLUE 8606 testl %eax,%eax 8607 jne 3f # one or both active - switch interp 8608#endif 8609 8610 ret 8611 8612 /* Check for suspend */ 86131: 8614 /* At this point, the return pointer to the caller of 8615 * common_periodicChecks is on the top of stack. We need to preserve 8616 * rPC(edx) and GLUE(ecx). We'll spill rPC, and reload GLUE. 8617 * The outgoing profile is: 8618 * bool dvmCheckSuspendPending(Thread* self) 8619 * Because we reached here via a call, go ahead and build a new frame. 8620 */ 8621 movl offGlue_self(%ecx),%eax # eax<- glue->self 8622 SPILL(rPC) # save edx 8623 push %ebp 8624 movl %esp,%ebp 8625 subl $24,%esp 8626 movl %eax,OUT_ARG0(%esp) 8627 call dvmCheckSuspendPending 8628 addl $24,%esp 8629 pop %ebp 8630 UNSPILL(rPC) 8631 GET_GLUE(%ecx) 8632 ret 8633 8634 /* Switch interpreters */ 8635 /* Note: %ebx contains the 16-bit word offset to be applied to rPC to 8636 * "complete" the interpretation of backwards branches. In effect, we 8637 * are completing the interpretation of the branch instruction here, 8638 * and the new interpreter will resume interpretation at the branch 8639 * target. However, a switch request recognized during the handling 8640 * of a return from method instruction results in an immediate abort, 8641 * and the new interpreter will resume by re-interpreting the return 8642 * instruction. 8643 */ 86443: 8645 leal (rPC,%ebx,2),rPC # adjust pc to show target 8646 GET_GLUE(%ecx) # bail expect GLUE already loaded 8647 movl $1,rINST_FULL # set changeInterp to true 8648 jmp common_gotoBail 8649 8650 8651/* 8652 * Common code for handling a return instruction 8653 */ 8654common_returnFromMethod: 8655 GET_GLUE(%ecx) 8656 /* Set entry mode in case we bail */ 8657 movb $kInterpEntryReturn,offGlue_entryPoint(%ecx) 8658 xorl rINST_FULL,rINST_FULL # zero offset in case we switch interps 8659 call common_periodicChecks # Note: expects %ecx to be preserved 8660 8661 SAVEAREA_FROM_FP(%eax,rFP) # eax<- saveArea (old) 8662 movl offStackSaveArea_prevFrame(%eax),rFP # rFP<- prevFrame 8663 movl (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST_FULL 8664 cmpl $0,rINST_FULL # break? 8665 je common_gotoBail # break frame, bail out completely 8666 8667 movl offStackSaveArea_savedPc(%eax),rPC # pc<- saveArea->savedPC 8668 movl offGlue_self(%ecx),%eax # eax<- self 8669 movl rINST_FULL,offGlue_method(%ecx) # glue->method = newSave->meethod 8670 movl rFP,offThread_curFrame(%eax) # self->curFrame = fp 8671 movl offMethod_clazz(rINST_FULL),%eax # eax<- method->clazz 8672 FETCH_INST_WORD(3) 8673 movl offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex 8674 ADVANCE_PC(3) 8675 movl %eax,offGlue_methodClassDex(%ecx) 8676 /* not bailing - restore entry mode to default */ 8677 movb $kInterpEntryInstr,offGlue_entryPoint(%ecx) 8678 GOTO_NEXT 8679 8680/* 8681 * Prepare to strip the current frame and "longjump" back to caller of 8682 * dvmMterpStdRun. 8683 * 8684 * on entry: 8685 * rINST_FULL holds changeInterp 8686 * ecx holds glue pointer 8687 * 8688 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp) 8689 */ 8690common_gotoBail: 8691 SAVE_PC_TO_GLUE(%ecx) # export state to glue 8692 SAVE_FP_TO_GLUE(%ecx) 8693 movl %ecx,OUT_ARG0(%esp) # glue in arg0 8694 movl rINST_FULL,OUT_ARG1(%esp) # changeInterp in arg1 8695 call dvmMterpStdBail # bail out.... 8696 8697 8698/* 8699 * After returning from a "glued" function, pull out the updated values 8700 * and start executing at the next instruction. 8701 */ 8702 common_resumeAfterGlueCall: 8703 GET_GLUE(%ecx) 8704 LOAD_PC_FROM_GLUE(%ecx) 8705 LOAD_FP_FROM_GLUE(%ecx) 8706 FETCH_INST() 8707 GOTO_NEXT 8708 8709/* 8710 * Integer divide or mod by zero 8711 */ 8712common_errDivideByZero: 8713 EXPORT_PC() 8714 movl $.LstrArithmeticException,%eax 8715 movl %eax,OUT_ARG0(%esp) 8716 movl $.LstrDivideByZero,%eax 8717 movl %eax,OUT_ARG1(%esp) 8718 SPILL(rPC) 8719 call dvmThrowException 8720 UNSPILL(rPC) 8721 jmp common_exceptionThrown 8722 8723/* 8724 * Attempt to allocate an array with a negative size. 8725 */ 8726common_errNegativeArraySize: 8727 EXPORT_PC() 8728 movl $.LstrNegativeArraySizeException,%eax 8729 movl %eax,OUT_ARG0(%esp) 8730 xorl %eax,%eax 8731 movl %eax,OUT_ARG1(%esp) 8732 SPILL(rPC) 8733 call dvmThrowException 8734 UNSPILL(rPC) 8735 jmp common_exceptionThrown 8736 8737/* 8738 * Attempt to allocate an array with a negative size. 8739 */ 8740common_errNoSuchMethod: 8741 8742 EXPORT_PC() 8743 movl $.LstrNoSuchMethodError,%eax 8744 movl %eax,OUT_ARG0(%esp) 8745 xorl %eax,%eax 8746 movl %eax,OUT_ARG1(%esp) 8747 SPILL(rPC) 8748 call dvmThrowException 8749 UNSPILL(rPC) 8750 jmp common_exceptionThrown 8751 8752/* 8753 * Hit a null object when we weren't expecting one. Export the PC, throw a 8754 * NullPointerException and goto the exception processing code. 8755 */ 8756common_errNullObject: 8757 EXPORT_PC() 8758 movl $.LstrNullPointerException,%eax 8759 movl %eax,OUT_ARG0(%esp) 8760 xorl %eax,%eax 8761 movl %eax,OUT_ARG1(%esp) 8762 SPILL(rPC) 8763 call dvmThrowException 8764 UNSPILL(rPC) 8765 jmp common_exceptionThrown 8766 8767/* 8768 * Array index exceeds max. 8769 */ 8770common_errArrayIndex: 8771 EXPORT_PC() 8772 movl $.LstrArrayIndexException,%eax 8773 movl %eax,OUT_ARG0(%esp) 8774 xorl %eax,%eax 8775 movl %eax,OUT_ARG1(%esp) 8776 SPILL(rPC) 8777 call dvmThrowException 8778 UNSPILL(rPC) 8779 jmp common_exceptionThrown 8780/* 8781 * Invalid array value. 8782 */ 8783common_errArrayStore: 8784 EXPORT_PC() 8785 movl $.LstrArrayStoreException,%eax 8786 movl %eax,OUT_ARG0(%esp) 8787 xorl %eax,%eax 8788 movl %eax,OUT_ARG1(%esp) 8789 SPILL(rPC) 8790 call dvmThrowException 8791 UNSPILL(rPC) 8792 jmp common_exceptionThrown 8793 8794/* 8795 * Somebody has thrown an exception. Handle it. 8796 * 8797 * If the exception processing code returns to us (instead of falling 8798 * out of the interpreter), continue with whatever the next instruction 8799 * now happens to be. 8800 * 8801 * This does not return. 8802 */ 8803common_exceptionThrown: 8804 GET_GLUE(%ecx) 8805 SAVE_PC_TO_GLUE(%ecx) 8806 SAVE_FP_TO_GLUE(%ecx) 8807 movl %ecx,OUT_ARG0(%esp) 8808 call dvmMterp_exceptionThrown 8809 jmp common_resumeAfterGlueCall 8810 8811common_abort: 8812 movl $0xdeadf00d,%eax 8813 call *%eax 8814 8815 8816/* 8817 * Strings 8818 */ 8819 8820 .section .rodata 8821.LstrNullPointerException: 8822 .asciz "Ljava/lang/NullPointerException;" 8823.LstrArithmeticException: 8824 .asciz "Ljava/lang/ArithmeticException;" 8825.LstrDivideByZero: 8826 .asciz "divide by zero" 8827.LstrArrayIndexException: 8828 .asciz "Ljava/lang/ArrayIndexOutOfBoundsException;" 8829.LstrArrayStoreException: 8830 .asciz "Ljava/lang/ArrayStoreException;" 8831.LstrNegativeArraySizeException: 8832 .asciz "Ljava/lang/NegativeArraySizeException;" 8833.LstrInstantiationError: 8834 .asciz "Ljava/lang/InstantiationError;" 8835.LstrClassCastException: 8836 .asciz "Ljava/lang/ClassCastException;" 8837.LstrNoSuchMethodError: 8838 .asciz "Ljava/lang/NoSuchMethodError;" 8839.LstrInternalError: 8840 .asciz "Ljava/lang/InternalError;" 8841.LstrFilledNewArrayNotImpl: 8842 .asciz "filled-new-array only implemented for 'int'" 8843 8844 8845