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