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